changeset 62:cd0742ba123c

Merge
author kamg
date Thu, 20 Mar 2008 09:17:30 -0500
parents 75b0f3cb1943 (diff) 5a76ab815e34 (current diff)
children d6fe2e4959d6
files src/os/linux/vm/os_linux.cpp src/os/windows/vm/os_windows.cpp src/share/vm/code/dependencies.cpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/globals.hpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/thread.cpp
diffstat 152 files changed, 3026 insertions(+), 1236 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/os/linux/ps_core.c	Wed Mar 19 09:58:01 2008 -0400
+++ b/agent/src/os/linux/ps_core.c	Thu Mar 20 09:17:30 2008 -0500
@@ -518,10 +518,10 @@
 }
 
 static ps_prochandle_ops core_ops = {
-   release:  core_release,
-   p_pread:  core_read_data,
-   p_pwrite: core_write_data,
-   get_lwp_regs: core_get_lwp_regs
+   .release=  core_release,
+   .p_pread=  core_read_data,
+   .p_pwrite= core_write_data,
+   .get_lwp_regs= core_get_lwp_regs
 };
 
 // read regs and create thread from NT_PRSTATUS entries from core file
--- a/agent/src/os/linux/ps_proc.c	Wed Mar 19 09:58:01 2008 -0400
+++ b/agent/src/os/linux/ps_proc.c	Thu Mar 20 09:17:30 2008 -0500
@@ -291,10 +291,10 @@
 }
 
 static ps_prochandle_ops process_ops = {
-  release:  process_cleanup,
-  p_pread:  process_read_data,
-  p_pwrite: process_write_data,
-  get_lwp_regs: process_get_lwp_regs
+  .release=  process_cleanup,
+  .p_pread=  process_read_data,
+  .p_pwrite= process_write_data,
+  .get_lwp_regs= process_get_lwp_regs
 };
 
 // attach to the process. One and only one exposed stuff
--- a/build/linux/Makefile	Wed Mar 19 09:58:01 2008 -0400
+++ b/build/linux/Makefile	Thu Mar 20 09:17:30 2008 -0500
@@ -80,6 +80,11 @@
   MFLAGS += " LP64=1 "
 endif
 
+# pass USE_SUNCC further, through MFLAGS
+ifdef USE_SUNCC
+  MFLAGS += " USE_SUNCC=1 "
+endif
+
 # The following renders pathnames in generated Makefiles valid on
 # machines other than the machine containing the build tree.
 #
--- a/build/linux/makefiles/amd64.make	Wed Mar 19 09:58:01 2008 -0400
+++ b/build/linux/makefiles/amd64.make	Thu Mar 20 09:17:30 2008 -0500
@@ -35,6 +35,8 @@
 CFLAGS += -D_LP64=1
 
 # The serviceability agent relies on frame pointer (%rbp) to walk thread stack
-CFLAGS += -fno-omit-frame-pointer
+ifndef USE_SUNCC
+  CFLAGS += -fno-omit-frame-pointer
+endif
 
 OPT_CFLAGS/compactingPermGenGen.o = -O1
--- a/build/linux/makefiles/buildtree.make	Wed Mar 19 09:58:01 2008 -0400
+++ b/build/linux/makefiles/buildtree.make	Thu Mar 20 09:17:30 2008 -0500
@@ -63,7 +63,11 @@
 # For now, until the compiler is less wobbly:
 TESTFLAGS	= -Xbatch -showversion
 
-PLATFORM_FILE	= $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH)
+ifdef USE_SUNCC
+PLATFORM_FILE	= $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH).suncc
+else
+PLATFORM_FILE   = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH)
+endif
 
 ifdef FORCE_TIERED
 ifeq		($(VARIANT),tiered)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/linux/makefiles/sparcWorks.make	Thu Mar 20 09:17:30 2008 -0500
@@ -0,0 +1,93 @@
+#
+# Copyright 1999-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.
+#  
+#
+
+#------------------------------------------------------------------------
+# CC, CPP & AS
+
+CPP = CC
+CC  = cc
+AS  = $(CC) -c
+
+ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
+ARCHFLAG/i486    = -m32
+ARCHFLAG/amd64   = -m64
+
+CFLAGS     += $(ARCHFLAG)
+AOUT_FLAGS += $(ARCHFLAG)
+LFLAGS     += $(ARCHFLAG)
+ASFLAGS    += $(ARCHFLAG)
+
+#------------------------------------------------------------------------
+# Compiler flags
+
+# position-independent code
+PICFLAG = -KPIC
+
+CFLAGS += $(PICFLAG)
+# no more exceptions
+CFLAGS += -features=no%except
+# Reduce code bloat by reverting back to 5.0 behavior for static initializers
+CFLAGS += -features=no%split_init
+# allow zero sized arrays
+CFLAGS += -features=zla
+
+# Use C++ Interpreter
+ifdef CC_INTERP
+  CFLAGS += -DCC_INTERP
+endif
+
+# We don't need libCstd.so and librwtools7.so, only libCrun.so
+CFLAGS += -library=Crun
+LIBS += -lCrun
+
+CFLAGS += -mt
+LFLAGS += -mt
+
+# Compiler warnings are treated as errors
+#WARNINGS_ARE_ERRORS = -errwarn=%all
+CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) 
+# Special cases
+CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@)) 
+
+# The flags to use for an Optimized build
+OPT_CFLAGS+=-xO4
+OPT_CFLAGS/NOOPT=-xO0
+
+#------------------------------------------------------------------------
+# Linker flags
+
+# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
+MAPFLAG = -Wl,--version-script=FILENAME
+
+# Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj
+SONAMEFLAG = -h SONAME
+
+# Build shared library
+SHARED_FLAG = -G
+
+#------------------------------------------------------------------------
+# Debug flags
+DEBUG_CFLAGS += -g
+FASTDEBUG_CFLAGS = -g0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/linux/platform_amd64.suncc	Thu Mar 20 09:17:30 2008 -0500
@@ -0,0 +1,17 @@
+os_family = linux
+
+arch = x86
+
+arch_model = x86_64
+
+os_arch = linux_x86
+
+os_arch_model = linux_x86_64
+
+lib_arch = amd64
+
+compiler = sparcWorks
+
+gnu_dis_arch = amd64
+
+sysdefs = -DLINUX -DSPARC_WORKS -D_GNU_SOURCE -DAMD64
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/linux/platform_i486.suncc	Thu Mar 20 09:17:30 2008 -0500
@@ -0,0 +1,17 @@
+os_family = linux
+
+arch = x86
+
+arch_model = x86_32
+
+os_arch = linux_x86
+
+os_arch_model = linux_x86_32
+
+lib_arch = i386
+
+compiler = sparcWorks
+
+gnu_dis_arch = i386
+
+sysdefs = -DLINUX -DSPARC_WORKS -D_GNU_SOURCE -DIA32
--- a/build/solaris/makefiles/amd64.make	Wed Mar 19 09:58:01 2008 -0400
+++ b/build/solaris/makefiles/amd64.make	Thu Mar 20 09:17:30 2008 -0500
@@ -19,7 +19,7 @@
 # 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.
-#  
+#
 #
 
 # Must also specify if CPU is little endian
@@ -45,6 +45,10 @@
 OPT_CFLAGS/generateOptoStub.o = -xO2
 OPT_CFLAGS/thread.o = -xO2
 
+# Work around for 6624782
+OPT_CFLAGS/instanceKlass.o = -Qoption ube -no_a2lf
+OPT_CFLAGS/objArrayKlass.o = -Qoption ube -no_a2lf
+
 else
 
 ifeq ("${Platform_compiler}", "gcc")
@@ -58,6 +62,6 @@
 # error
 _JUNK2_ := $(shell echo >&2 \
        "*** ERROR: this compiler is not yet supported by this code base!")
-	@exit 1
+       @exit 1
 endif
 endif
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -2037,7 +2037,7 @@
 
 
 int LIR_Assembler::shift_amount(BasicType t) {
-  int elem_size = type2aelembytes[t];
+  int elem_size = type2aelembytes(t);
   switch (elem_size) {
     case 1 : return 0;
     case 2 : return 1;
@@ -2360,7 +2360,7 @@
                       op->tmp2()->as_register(),
                       op->tmp3()->as_register(),
                       arrayOopDesc::header_size(op->type()),
-                      type2aelembytes[op->type()],
+                      type2aelembytes(op->type()),
                       op->klass()->as_register(),
                       *op->stub()->entry());
   }
--- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -179,7 +179,7 @@
 
 LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr,
                                               BasicType type, bool needs_card_mark) {
-  int elem_size = type2aelembytes[type];
+  int elem_size = type2aelembytes(type);
   int shift = exact_log2(elem_size);
 
   LIR_Opr base_opr;
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -2911,6 +2911,7 @@
 
     // These entry points require SharedInfo::stack0 to be set up in non-core builds
     StubRoutines::_throw_AbstractMethodError_entry         = generate_throw_exception("AbstractMethodError throw_exception",          CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError),  false);
+    StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError),  false);
     StubRoutines::_throw_ArithmeticException_entry         = generate_throw_exception("ArithmeticException throw_exception",          CAST_FROM_FN_PTR(address, SharedRuntime::throw_ArithmeticException),  true);
     StubRoutines::_throw_NullPointerException_entry        = generate_throw_exception("NullPointerException throw_exception",         CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException), true);
     StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -28,6 +28,12 @@
 int VM_Version::_features = VM_Version::unknown_m;
 const char* VM_Version::_features_str = "";
 
+bool VM_Version::is_niagara1_plus() {
+  // This is a placeholder until the real test is determined.
+  return is_niagara1() &&
+    (os::processor_count() > maximum_niagara1_processor_count());
+}
+
 void VM_Version::initialize() {
   _features = determine_features();
   PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
@@ -160,3 +166,13 @@
 void VM_Version::revert() {
   _features = saved_features;
 }
+
+unsigned int VM_Version::calc_parallel_worker_threads() {
+  unsigned int result;
+  if (is_niagara1_plus()) {
+    result = nof_parallel_worker_threads(5, 16, 8);
+  } else {
+    result = nof_parallel_worker_threads(5, 8, 8);
+  }
+  return result;
+}
--- a/src/cpu/sparc/vm/vm_version_sparc.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/sparc/vm/vm_version_sparc.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -64,6 +64,11 @@
 
   static bool is_niagara1(int features) { return (features & niagara1_m) == niagara1_m; }
 
+  static int maximum_niagara1_processor_count() { return 32; }
+  // Returns true if the platform is in the niagara line and
+  // newer than the niagara1.
+  static bool is_niagara1_plus();
+
 public:
   // Initialization
   static void initialize();
@@ -129,4 +134,7 @@
 
   // Override the Abstract_VM_Version implementation.
   static uint page_size_count() { return is_sun4v() ? 4 : 2; }
+
+  // Calculates the number of parallel threads
+  static unsigned int calc_parallel_worker_threads();
 };
--- a/src/cpu/sparc/vm/vtableStubs_sparc.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/sparc/vm/vtableStubs_sparc.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -175,17 +175,12 @@
   // %%%% Could load both offset and interface in one ldx, if they were
   // in the opposite order.  This would save a load.
   __ ld_ptr(L0, base + itableOffsetEntry::interface_offset_in_bytes(), L1);
-#ifdef ASSERT
-  Label ok;
-  // Check that entry is non-null and an Oop
-  __ bpr(Assembler::rc_nz, false, Assembler::pt, L1, ok);
-  __ delayed()->nop();
-  __ stop("null entry point found in itable's offset table");
-  __ bind(ok);
-  __ verify_oop(L1);
-#endif // ASSERT
 
-  __ cmp(G5_interface, L1);
+  // If the entry is NULL then we've reached the end of the table
+  // without finding the expected interface, so throw an exception
+  Label throw_icce;
+  __ bpr(Assembler::rc_z, false, Assembler::pn, L1, throw_icce);
+  __ delayed()->cmp(G5_interface, L1);
   __ brx(Assembler::notEqual, true, Assembler::pn, search);
   __ delayed()->add(L0, itableOffsetEntry::size() * wordSize, L0);
 
@@ -223,24 +218,30 @@
   __ JMP(G3_scratch, 0);
   __ delayed()->nop();
 
+  __ bind(throw_icce);
+  Address icce(G3_scratch, StubRoutines::throw_IncompatibleClassChangeError_entry());
+  __ jump_to(icce, 0);
+  __ delayed()->restore();
+
   masm->flush();
+
+  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
+
   s->set_exception_points(npe_addr, ame_addr);
   return s;
 }
 
 
 int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
-  if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) return 999;
+  if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) return 1000;
   else {
     const int slop = 2*BytesPerInstWord; // sethi;add  (needed for long offsets)
     if (is_vtable_stub) {
       const int basic = 5*BytesPerInstWord; // ld;ld;ld,jmp,nop
       return basic + slop;
     } else {
-#ifdef ASSERT
-      return 999;
-#endif // ASSERT
-      const int basic = 17*BytesPerInstWord; // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore
+      // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore
+      const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord;
       return (basic + slop);
     }
   }
@@ -252,29 +253,3 @@
   const unsigned int icache_line_size = 32;
   return icache_line_size;
 }
-
-
-//Reconciliation History
-// 1.2 97/12/09 17:13:31 vtableStubs_i486.cpp
-// 1.4 98/01/21 19:18:37 vtableStubs_i486.cpp
-// 1.5 98/02/13 16:33:55 vtableStubs_i486.cpp
-// 1.7 98/03/05 17:17:28 vtableStubs_i486.cpp
-// 1.9 98/05/18 09:26:17 vtableStubs_i486.cpp
-// 1.10 98/05/26 16:28:13 vtableStubs_i486.cpp
-// 1.11 98/05/27 08:51:35 vtableStubs_i486.cpp
-// 1.12 98/06/15 15:04:12 vtableStubs_i486.cpp
-// 1.13 98/07/28 18:44:22 vtableStubs_i486.cpp
-// 1.15 98/08/28 11:31:19 vtableStubs_i486.cpp
-// 1.16 98/09/02 12:58:31 vtableStubs_i486.cpp
-// 1.17 98/09/04 12:15:52 vtableStubs_i486.cpp
-// 1.18 98/11/19 11:55:24 vtableStubs_i486.cpp
-// 1.19 99/01/12 14:57:56 vtableStubs_i486.cpp
-// 1.20 99/01/19 17:42:52 vtableStubs_i486.cpp
-// 1.22 99/01/21 10:29:25 vtableStubs_i486.cpp
-// 1.30 99/06/02 15:27:39 vtableStubs_i486.cpp
-// 1.26 99/06/24 14:25:07 vtableStubs_i486.cpp
-// 1.23 99/02/22 14:37:52 vtableStubs_i486.cpp
-// 1.28 99/06/29 18:06:17 vtableStubs_i486.cpp
-// 1.29 99/07/22 17:03:44 vtableStubs_i486.cpp
-// 1.30 99/08/11 09:33:27 vtableStubs_i486.cpp
-//End
--- a/src/cpu/x86/vm/assembler_x86_64.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/x86/vm/assembler_x86_64.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1304,7 +1304,7 @@
   emit_operand(src, dst);
 }
 
-void Assembler::mov64(Register dst, int64_t imm64) {
+void Assembler::mov64(Register dst, intptr_t imm64) {
   InstructionMark im(this);
   int encode = prefixq_and_encode(dst->encoding());
   emit_byte(0xB8 | encode);
@@ -1331,7 +1331,7 @@
   emit_operand(dst, src);
 }
 
-void Assembler::mov64(Address dst, int64_t imm32) {
+void Assembler::mov64(Address dst, intptr_t imm32) {
   assert(is_simm32(imm32), "lost bits");
   InstructionMark im(this);
   prefixq(dst);
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -546,8 +546,8 @@
   // set rsi.edi to the end of the arrays (arrays have same length)
   // negate the index
 
-  __ leal(rsi, Address(rsi, rax, Address::times_2, type2aelembytes[T_CHAR]));
-  __ leal(rdi, Address(rdi, rax, Address::times_2, type2aelembytes[T_CHAR]));
+  __ leal(rsi, Address(rsi, rax, Address::times_2, type2aelembytes(T_CHAR)));
+  __ leal(rdi, Address(rdi, rax, Address::times_2, type2aelembytes(T_CHAR)));
   __ negl(rax);
 
   // compare the strings in a loop
@@ -1232,7 +1232,7 @@
 
 NEEDS_CLEANUP; // This could be static?
 Address::ScaleFactor LIR_Assembler::array_element_size(BasicType type) const {
-  int elem_size = type2aelembytes[type];
+  int elem_size = type2aelembytes(type);
   switch (elem_size) {
     case 1: return Address::times_1;
     case 2: return Address::times_2;
@@ -2739,7 +2739,7 @@
 
   assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point");
 
-  int elem_size = type2aelembytes[basic_type];
+  int elem_size = type2aelembytes(basic_type);
   int shift_amount;
   Address::ScaleFactor scale;
 
--- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -151,7 +151,7 @@
 
   LIR_Address* addr;
   if (index_opr->is_constant()) {
-    int elem_size = type2aelembytes[type];
+    int elem_size = type2aelembytes(type);
     addr = new LIR_Address(array_opr,
                            offset_in_bytes + index_opr->as_jint() * elem_size, type);
   } else {
--- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1416,8 +1416,8 @@
     // ======== end loop ========
 
     // It was a real error; we must depend on the caller to finish the job.
-    // Register rdx = -1 * number of *remaining* oops, r14 = *total* oops.
-    // Emit GC store barriers for the oops we have copied (r14 + rdx),
+    // Register "count" = -1 * number of *remaining* oops, length_arg = *total* oops.
+    // Emit GC store barriers for the oops we have copied (length_arg + count),
     // and report their number to the caller.
     __ addl(count, length_arg);         // transfers = (length - remaining)
     __ movl(rax, count);                // save the value
@@ -1430,6 +1430,7 @@
     // Come here on success only.
     __ BIND(L_do_card_marks);
     __ movl(count, length_arg);
+    __ movl(to, to_arg);                // reload
     gen_write_ref_array_post_barrier(to, count);
     __ xorl(rax, rax);                  // return 0 on success
 
@@ -2151,6 +2152,7 @@
     // These entry points require SharedInfo::stack0 to be set up in non-core builds
     // and need to be relocatable, so they each fabricate a RuntimeStub internally.
     StubRoutines::_throw_AbstractMethodError_entry         = generate_throw_exception("AbstractMethodError throw_exception",          CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError),  false);
+    StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError),  false);
     StubRoutines::_throw_ArithmeticException_entry         = generate_throw_exception("ArithmeticException throw_exception",          CAST_FROM_FN_PTR(address, SharedRuntime::throw_ArithmeticException),  true);
     StubRoutines::_throw_NullPointerException_entry        = generate_throw_exception("NullPointerException throw_exception",         CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException), true);
     StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -2832,6 +2832,13 @@
                                                 throw_AbstractMethodError),
                                false);
 
+    StubRoutines::_throw_IncompatibleClassChangeError_entry =
+      generate_throw_exception("IncompatibleClassChangeError throw_exception",
+                               CAST_FROM_FN_PTR(address,
+                                                SharedRuntime::
+                                                throw_IncompatibleClassChangeError),
+                               false);
+
     StubRoutines::_throw_ArithmeticException_entry =
       generate_throw_exception("ArithmeticException throw_exception",
                                CAST_FROM_FN_PTR(address,
--- a/src/cpu/x86/vm/vtableStubs_x86_32.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/x86/vm/vtableStubs_x86_32.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -138,29 +138,21 @@
     __ round_to(rbx, BytesPerLong);
   }
 
-  Label hit, next, entry;
+  Label hit, next, entry, throw_icce;
 
-  __ jmp(entry);
+  __ jmpb(entry);
 
   __ bind(next);
   __ addl(rbx, itableOffsetEntry::size() * wordSize);
 
   __ bind(entry);
 
-#ifdef ASSERT
-    // Check that the entry is non-null
-  if (DebugVtables) {
-    Label L;
-    __ pushl(rbx);
-    __ movl(rbx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
-    __ testl(rbx, rbx);
-    __ jcc(Assembler::notZero, L);
-    __ stop("null entry point found in itable's offset table");
-    __ bind(L);
-    __ popl(rbx);
-  }
-#endif
-  __ cmpl(rax, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
+  // If the entry is NULL then we've reached the end of the table
+  // without finding the expected interface, so throw an exception
+  __ movl(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
+  __ testl(rdx, rdx);
+  __ jcc(Assembler::zero, throw_icce);
+  __ cmpl(rax, rdx);
   __ jcc(Assembler::notEqual, next);
 
   // We found a hit, move offset into rbx,
@@ -194,7 +186,15 @@
   address ame_addr = __ pc();
   __ jmp(Address(method, methodOopDesc::from_compiled_offset()));
 
+  __ bind(throw_icce);
+  // Restore saved register
+  __ popl(rdx);
+  __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
+
   masm->flush();
+
+  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
+
   s->set_exception_points(npe_addr, ame_addr);
   return s;
 }
@@ -207,7 +207,7 @@
     return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
   } else {
     // Itable stub size
-    return (DebugVtables ? 140 : 55) + (CountCompiledCalls ? 6 : 0);
+    return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0);
   }
 }
 
--- a/src/cpu/x86/vm/vtableStubs_x86_64.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/cpu/x86/vm/vtableStubs_x86_64.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -153,7 +153,7 @@
     // Round up to align_object_offset boundary
     __ round_to_q(rbx, BytesPerLong);
   }
-  Label hit, next, entry;
+  Label hit, next, entry, throw_icce;
 
   __ jmpb(entry);
 
@@ -162,22 +162,13 @@
 
   __ bind(entry);
 
-#ifdef ASSERT
-    // Check that the entry is non-null
-  if (DebugVtables) {
-    Label L;
-    __ pushq(rbx);
-    __ movq(rbx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
-    __ testq(rbx, rbx);
-    __ jcc(Assembler::notZero, L);
-    __ stop("null entry point found in itable's offset table");
-    __ bind(L);
-    __ popq(rbx);
-  }
-#endif
-
-  __ cmpq(rax, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
-  __ jcc(Assembler::notEqual, next);
+  // If the entry is NULL then we've reached the end of the table
+  // without finding the expected interface, so throw an exception
+  __ movq(j_rarg1, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
+  __ testq(j_rarg1, j_rarg1);
+  __ jcc(Assembler::zero, throw_icce);
+  __ cmpq(rax, j_rarg1);
+  __ jccb(Assembler::notEqual, next);
 
   // We found a hit, move offset into j_rarg1
   __ movl(j_rarg1, Address(rbx, itableOffsetEntry::offset_offset_in_bytes()));
@@ -203,23 +194,31 @@
 
 
 #ifdef ASSERT
-    if (DebugVtables) {
-      Label L2;
-      __ cmpq(method, (int)NULL);
-      __ jcc(Assembler::equal, L2);
-      __ cmpq(Address(method, methodOopDesc::from_compiled_offset()), (int)NULL_WORD);
-      __ jcc(Assembler::notZero, L2);
-      __ stop("compiler entrypoint is null");
-      __ bind(L2);
-    }
+  if (DebugVtables) {
+    Label L2;
+    __ cmpq(method, (int)NULL);
+    __ jcc(Assembler::equal, L2);
+    __ cmpq(Address(method, methodOopDesc::from_compiled_offset()), (int)NULL_WORD);
+    __ jcc(Assembler::notZero, L2);
+    __ stop("compiler entrypoint is null");
+    __ bind(L2);
+  }
 #endif // ASSERT
 
-    // rbx: methodOop
-    // j_rarg0: receiver
-    address ame_addr = __ pc();
-    __ jmp(Address(method, methodOopDesc::from_compiled_offset()));
+  // rbx: methodOop
+  // j_rarg0: receiver
+  address ame_addr = __ pc();
+  __ jmp(Address(method, methodOopDesc::from_compiled_offset()));
+
+  __ bind(throw_icce);
+  // Restore saved register
+  __ popq(j_rarg1);
+  __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
 
   __ flush();
+
+  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
+
   s->set_exception_points(npe_addr, ame_addr);
   return s;
 }
@@ -230,7 +229,7 @@
     return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0);
   } else {
     // Itable stub size
-    return (DebugVtables ? 636 : 64) + (CountCompiledCalls ? 13 : 0);
+    return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0);
   }
 }
 
--- a/src/os/linux/vm/attachListener_linux.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/os/linux/vm/attachListener_linux.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -232,7 +232,7 @@
   // where <ver> is the protocol version (1), <cmd> is the command
   // name ("load", "datadump", ...), and <arg> is an argument
   int expected_str_count = 2 + AttachOperation::arg_count_max;
-  int max_len = (strlen(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
+  const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
     AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);
 
   char buf[max_len];
--- a/src/os/linux/vm/os_linux.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/os/linux/vm/os_linux.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -116,6 +116,20 @@
   return Linux::physical_memory();
 }
 
+julong os::allocatable_physical_memory(julong size) {
+#ifdef _LP64
+  return size;
+#else
+  julong result = MIN2(size, (julong)3800*M);
+   if (!is_allocatable(result)) {
+     // See comments under solaris for alignment considerations
+     julong reasonable_size = (julong)2*G - 2 * os::vm_page_size();
+     result =  MIN2(size, reasonable_size);
+   }
+   return result;
+#endif // _LP64
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // environment support
 
--- a/src/os/windows/vm/os_windows.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/os/windows/vm/os_windows.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -621,7 +621,12 @@
 }
 
 julong os::allocatable_physical_memory(julong size) {
+#ifdef _LP64
+  return size;
+#else
+  // Limit to 1400m because of the 2gb address space wall
   return MIN2(size, (julong)1400*M);
+#endif
 }
 
 // VC6 lacks DWORD_PTR
--- a/src/os_cpu/linux_x86/vm/bytes_linux_x86.inline.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/os_cpu/linux_x86/vm/bytes_linux_x86.inline.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -60,7 +60,18 @@
 
 #ifdef AMD64
 inline u8 Bytes::swap_u8(u8 x) {
+#ifdef SPARC_WORKS
+  // workaround for SunStudio12 CR6615391
+  __asm__ __volatile__ (
+    "bswapq %0"
+    :"=r" (x)        // output : register 0 => x
+    :"0"  (x)        // input  : x => register 0
+    :"0"             // clobbered register
+  );
+  return x;
+#else
   return bswap_64(x);
+#endif
 }
 #else
 // Helper function for swap_u8
--- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -62,8 +62,14 @@
 #endif // AMD64
 
 address os::current_stack_pointer() {
+#ifdef SPARC_WORKS
+  register void *esp;
+  __asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp));
+  return (address) ((char*)esp + sizeof(long)*2);
+#else
   register void *esp __asm__ (SPELL_REG_SP);
   return (address) esp;
+#endif
 }
 
 char* os::non_memory_address_word() {
@@ -139,7 +145,12 @@
 }
 
 intptr_t* _get_previous_fp() {
+#ifdef SPARC_WORKS
+  register intptr_t **ebp;
+  __asm__("mov %%"SPELL_REG_FP", %0":"=r"(ebp));
+#else
   register intptr_t **ebp __asm__ (SPELL_REG_FP);
+#endif
   return (intptr_t*) *ebp;   // we want what it points to.
 }
 
@@ -157,23 +168,8 @@
   }
 }
 
-
 // Utility functions
 
-julong os::allocatable_physical_memory(julong size) {
-#ifdef AMD64
-  return size;
-#else
-  julong result = MIN2(size, (julong)3800*M);
-   if (!is_allocatable(result)) {
-     // See comments under solaris for alignment considerations
-     julong reasonable_size = (julong)2*G - 2 * os::vm_page_size();
-     result =  MIN2(size, reasonable_size);
-   }
-   return result;
-#endif // AMD64
-}
-
 // From IA32 System Programming Guide
 enum {
   trap_page_fault = 0xE
@@ -575,7 +571,9 @@
 #else
 size_t os::Linux::min_stack_allowed  =  (48 DEBUG_ONLY(+4))*K;
 
+#ifdef __GNUC__
 #define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
+#endif
 
 // Test if pthread library can support variable thread stack size. LinuxThreads
 // in fixed stack mode allocates 2M fixed slot for each thread. LinuxThreads
@@ -606,7 +604,11 @@
     // return true and skip _thread_safety_check(), so we may not be able to
     // detect stack-heap collisions. But otherwise it's harmless.
     //
+#ifdef __GNUC__
     return (GET_GS() != 0);
+#else
+    return false;
+#endif
   }
 }
 #endif // AMD64
--- a/src/share/vm/c1/c1_LIR.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/c1/c1_LIR.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -105,7 +105,7 @@
 
 
 LIR_Address::Scale LIR_Address::scale(BasicType type) {
-  int elem_size = type2aelembytes[type];
+  int elem_size = type2aelembytes(type);
   switch (elem_size) {
   case 1: return LIR_Address::times_1;
   case 2: return LIR_Address::times_2;
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -104,7 +104,7 @@
 };
 
 void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
-  for (int i = 0; i <= _arg_size; i++) {
+  for (int i = 0; i < _arg_size; i++) {
     if (vars.contains(i))
       _arg_returned.set_bit(i);
   }
@@ -112,10 +112,9 @@
   _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
 }
 
-
 // return true if any element of vars is an argument
 bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) {
-  for (int i = 0; i <= _arg_size; i++) {
+  for (int i = 0; i < _arg_size; i++) {
     if (vars.contains(i))
       return true;
   }
@@ -126,7 +125,7 @@
 bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){
   if (_conservative)
     return true;
-  for (int i = 0; i <= _arg_size; i++) {
+  for (int i = 0; i < _arg_size; i++) {
     if (vars.contains(i) && _arg_stack.at(i))
       return true;
   }
@@ -134,12 +133,13 @@
 }
 
 void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) {
-  for (int i = 0; i <= _arg_size; i++) {
+  for (int i = 0; i < _arg_size; i++) {
     if (vars.contains(i)) {
       bm.clear_bit(i);
     }
   }
 }
+
 void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) {
   clear_bits(vars, _arg_local);
 }
@@ -155,6 +155,17 @@
   clear_bits(vars, _dirty);
 }
 
+void BCEscapeAnalyzer::set_modified(ArgumentMap vars, int offs, int size) {
+
+  for (int i = 0; i < _arg_size; i++) {
+    if (vars.contains(i)) {
+      set_arg_modified(i, offs, size);
+    }
+  }
+  if (vars.contains_unknown())
+    _unknown_modified = true;
+}
+
 bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) {
   for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) {
     if (scope->method() == callee) {
@@ -164,6 +175,40 @@
   return false;
 }
 
+bool BCEscapeAnalyzer::is_arg_modified(int arg, int offset, int size_in_bytes) {
+  if (offset == OFFSET_ANY)
+    return _arg_modified[arg] != 0;
+  assert(arg >= 0 && arg < _arg_size, "must be an argument.");
+  bool modified = false;
+  int l = offset / HeapWordSize;
+  int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;
+  if (l > ARG_OFFSET_MAX)
+    l = ARG_OFFSET_MAX;
+  if (h > ARG_OFFSET_MAX+1)
+    h = ARG_OFFSET_MAX + 1;
+  for (int i = l; i < h; i++) {
+    modified = modified || (_arg_modified[arg] & (1 << i)) != 0;
+  }
+  return modified;
+}
+
+void BCEscapeAnalyzer::set_arg_modified(int arg, int offset, int size_in_bytes) {
+  if (offset == OFFSET_ANY) {
+    _arg_modified[arg] =  (uint) -1;
+    return;
+  }
+  assert(arg >= 0 && arg < _arg_size, "must be an argument.");
+  int l = offset / HeapWordSize;
+  int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;
+  if (l > ARG_OFFSET_MAX)
+    l = ARG_OFFSET_MAX;
+  if (h > ARG_OFFSET_MAX+1)
+    h = ARG_OFFSET_MAX + 1;
+  for (int i = l; i < h; i++) {
+    _arg_modified[arg] |= (1 << i);
+  }
+}
+
 void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) {
   int i;
 
@@ -197,6 +242,7 @@
     for (i = 0; i < arg_size; i++) {
       set_method_escape(state.raw_pop());
     }
+    _unknown_modified = true;  // assume the worst since we don't analyze the called method
     return;
   }
 
@@ -224,6 +270,11 @@
       ArgumentMap arg = state.raw_pop();
       if (!is_argument(arg))
         continue;
+      for (int j = 0; j < _arg_size; j++) {
+        if (arg.contains(j)) {
+          _arg_modified[j] |= analyzer._arg_modified[i];
+        }
+      }
       if (!is_arg_stack(arg)) {
         // arguments have already been recognized as escaping
       } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) {
@@ -233,6 +284,7 @@
         set_global_escape(arg);
       }
     }
+    _unknown_modified = _unknown_modified || analyzer.has_non_arg_side_affects();
 
     // record dependencies if at least one parameter retained stack-allocatable
     if (must_record_dependencies) {
@@ -250,8 +302,10 @@
       ArgumentMap arg = state.raw_pop();
       if (!is_argument(arg))
         continue;
+      set_modified(arg, OFFSET_ANY, type2size[T_INT]*HeapWordSize);
       set_global_escape(arg);
     }
+    _unknown_modified = true;  // assume the worst since we don't know the called method
   }
 }
 
@@ -421,6 +475,7 @@
         state.spop();
         ArgumentMap arr = state.apop();
         set_method_escape(arr);
+        set_modified(arr, OFFSET_ANY, type2size[T_INT]*HeapWordSize);
         break;
       }
       case Bytecodes::_lastore:
@@ -430,6 +485,7 @@
         state.spop();
         ArgumentMap arr = state.apop();
         set_method_escape(arr);
+        set_modified(arr, OFFSET_ANY, type2size[T_LONG]*HeapWordSize);
         break;
       }
       case Bytecodes::_aastore:
@@ -437,6 +493,7 @@
         set_global_escape(state.apop());
         state.spop();
         ArgumentMap arr = state.apop();
+        set_modified(arr, OFFSET_ANY, type2size[T_OBJECT]*HeapWordSize);
         break;
       }
       case Bytecodes::_pop:
@@ -762,6 +819,7 @@
           if (s.cur_bc() != Bytecodes::_putstatic) {
             ArgumentMap p = state.apop();
             set_method_escape(p);
+            set_modified(p, will_link ? field->offset() : OFFSET_ANY, type2size[field_type]*HeapWordSize);
           }
         }
         break;
@@ -872,7 +930,7 @@
 }
 
 void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) {
-  StateInfo *d_state = blockstates+dest->index();
+  StateInfo *d_state = blockstates + dest->index();
   int nlocals = _method->max_locals();
 
   // exceptions may cause transfer of control to handlers in the middle of a
@@ -916,6 +974,7 @@
     }
     for (int i = 0; i < s_state->_stack_height; i++) {
       ArgumentMap t;
+      //extra_vars |= !d_state->_vars[i] & s_state->_vars[i];
       t.clear();
       t = s_state->_stack[i];
       t.set_difference(d_state->_stack[i]);
@@ -933,7 +992,7 @@
 
   int datacount = (numblocks + 1) * (stkSize + numLocals);
   int datasize = datacount * sizeof(ArgumentMap);
-  StateInfo *blockstates = (StateInfo *) arena->Amalloc(_methodBlocks->num_blocks() * sizeof(StateInfo));
+  StateInfo *blockstates = (StateInfo *) arena->Amalloc(numblocks * sizeof(StateInfo));
   ArgumentMap *statedata  = (ArgumentMap *) arena->Amalloc(datasize);
   for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap();
   ArgumentMap *dp = statedata;
@@ -961,33 +1020,35 @@
   ArgumentMap allVars;   // all oop arguments to method
   ciSignature* sig = method()->signature();
   int j = 0;
+  ciBlock* first_blk = _methodBlocks->block_containing(0);
+  int fb_i = first_blk->index();
   if (!method()->is_static()) {
     // record information for "this"
-    blockstates[0]._vars[j].set(j);
+    blockstates[fb_i]._vars[j].set(j);
     allVars.add(j);
     j++;
   }
   for (int i = 0; i < sig->count(); i++) {
     ciType* t = sig->type_at(i);
     if (!t->is_primitive_type()) {
-      blockstates[0]._vars[j].set(j);
+      blockstates[fb_i]._vars[j].set(j);
       allVars.add(j);
     }
     j += t->size();
   }
-  blockstates[0]._initialized = true;
+  blockstates[fb_i]._initialized = true;
   assert(j == _arg_size, "just checking");
 
   ArgumentMap unknown_map;
   unknown_map.add_unknown();
 
-  worklist.push(_methodBlocks->block_containing(0));
+  worklist.push(first_blk);
   while(worklist.length() > 0) {
     ciBlock *blk = worklist.pop();
-    StateInfo *blkState = blockstates+blk->index();
+    StateInfo *blkState = blockstates + blk->index();
     if (blk->is_handler() || blk->is_ret_target()) {
       // for an exception handler or a target of a ret instruction, we assume the worst case,
-      // that any variable or stack slot could contain any argument
+      // that any variable could contain any argument
       for (int i = 0; i < numLocals; i++) {
         state._vars[i] = allVars;
       }
@@ -997,6 +1058,7 @@
         state._stack_height = blkState->_stack_height;
       }
       for (int i = 0; i < state._stack_height; i++) {
+// ??? should this be unknown_map ???
         state._stack[i] = allVars;
       }
     } else {
@@ -1053,6 +1115,7 @@
   vmIntrinsics::ID iid = method()->intrinsic_id();
 
   if (iid == vmIntrinsics::_getClass ||
+      iid ==  vmIntrinsics::_fillInStackTrace ||
       iid == vmIntrinsics::_hashCode)
     return iid;
   else
@@ -1060,12 +1123,16 @@
 }
 
 bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {
-  ArgumentMap empty;
-  empty.clear();
+  ArgumentMap arg;
+  arg.clear();
   switch (iid) {
   case vmIntrinsics::_getClass:
     _return_local = false;
     break;
+  case vmIntrinsics::_fillInStackTrace:
+    arg.set(0); // 'this'
+    set_returned(arg);
+    break;
   case vmIntrinsics::_hashCode:
     // initialized state is correct
     break;
@@ -1109,15 +1176,21 @@
     _return_allocated = true;
   }
   _allocated_escapes = false;
+  _unknown_modified = false;
 }
 
 void BCEscapeAnalyzer::clear_escape_info() {
   ciSignature* sig = method()->signature();
   int arg_count = sig->count();
   ArgumentMap var;
+  if (!method()->is_static()) {
+    arg_count++;  // allow for "this"
+  }
   for (int i = 0; i < arg_count; i++) {
+    set_arg_modified(i, OFFSET_ANY, 4);
     var.clear();
     var.set(i);
+    set_modified(var, OFFSET_ANY, 4);
     set_global_escape(var);
   }
   _arg_local.clear();
@@ -1126,6 +1199,7 @@
   _return_local = false;
   _return_allocated = false;
   _allocated_escapes = true;
+  _unknown_modified = true;
 }
 
 
@@ -1205,8 +1279,17 @@
     } else {
       tty->print_cr("     non-local return values");
     }
+    tty->print("     modified args: ");
+    for (int i = 0; i < _arg_size; i++) {
+      if (_arg_modified[i] == 0)
+        tty->print("    0");
+      else
+        tty->print("    0x%x", _arg_modified[i]);
+    }
     tty->cr();
     tty->print("     flags: ");
+    if (_unknown_modified)
+      tty->print(" unknown_modified");
     if (_return_allocated)
       tty->print(" return_allocated");
     tty->cr();
@@ -1228,6 +1311,7 @@
       if (_arg_returned.at(i)) {
         methodData()->set_arg_returned(i);
       }
+      methodData()->set_arg_modified(i, _arg_modified[i]);
     }
     if (_return_local) {
       methodData()->set_eflag(methodDataOopDesc::return_local);
@@ -1244,6 +1328,7 @@
     _arg_local.at_put(i, methodData()->is_arg_local(i));
     _arg_stack.at_put(i, methodData()->is_arg_stack(i));
     _arg_returned.at_put(i, methodData()->is_arg_returned(i));
+    _arg_modified[i] = methodData()->arg_modified(i);
   }
   _return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
 
@@ -1261,6 +1346,12 @@
       tty->print_cr("     non-local return values");
     }
     tty->print("     modified args: ");
+    for (int i = 0; i < _arg_size; i++) {
+      if (_arg_modified[i] == 0)
+        tty->print("    0");
+      else
+        tty->print("    0x%x", _arg_modified[i]);
+    }
     tty->cr();
   }
 #endif
@@ -1281,6 +1372,7 @@
     , _return_local(false)
     , _return_allocated(false)
     , _allocated_escapes(false)
+    , _unknown_modified(false)
     , _dependencies()
     , _parent(parent)
     , _level(parent == NULL ? 0 : parent->level() + 1) {
@@ -1290,6 +1382,8 @@
     _arg_returned.clear();
     _dirty.clear();
     Arena* arena = CURRENT_ENV->arena();
+    _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
+    Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
 
     if (methodData() == NULL)
       return;
--- a/src/share/vm/ci/bcEscapeAnalyzer.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/bcEscapeAnalyzer.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -46,9 +46,12 @@
   BitMap            _arg_stack;
   BitMap            _arg_returned;
   BitMap            _dirty;
+  enum{ ARG_OFFSET_MAX = 31};
+  uint              *_arg_modified;
 
   bool              _return_local;
   bool              _allocated_escapes;
+  bool              _unknown_modified;
   bool              _return_allocated;
 
   ciObjectList     _dependencies;
@@ -80,6 +83,7 @@
   void set_method_escape(ArgumentMap vars);
   void set_global_escape(ArgumentMap vars);
   void set_dirty(ArgumentMap vars);
+  void set_modified(ArgumentMap vars, int offs, int size);
 
   bool is_recursive_call(ciMethod* callee);
   void add_dependence(ciKlass *klass, ciMethod *meth);
@@ -140,6 +144,13 @@
     return !_conservative && _return_allocated && !_allocated_escapes;
   }
 
+  // Tracking of argument modification
+
+  enum {OFFSET_ANY = -1};
+  bool is_arg_modified(int arg, int offset, int size_in_bytes);
+  void set_arg_modified(int arg, int offset, int size_in_bytes);
+  bool has_non_arg_side_affects()    { return _unknown_modified; }
+
   // Copy dependencies from this analysis into "deps"
   void copy_dependencies(Dependencies *deps);
 };
--- a/src/share/vm/ci/ciField.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/ciField.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -102,7 +102,7 @@
   BasicType layout_type() { return type2field[(_type == NULL) ? T_OBJECT : _type->basic_type()]; }
 
   // How big is this field in memory?
-  int size_in_bytes() { return type2aelembytes[layout_type()]; }
+  int size_in_bytes() { return type2aelembytes(layout_type()); }
 
   // What is the offset of this field?
   int offset() {
--- a/src/share/vm/ci/ciInstanceKlass.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/ciInstanceKlass.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -34,7 +34,9 @@
 // ciInstanceKlass::ciInstanceKlass
 //
 // Loaded instance klass.
-ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : ciKlass(h_k) {
+ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
+  ciKlass(h_k), _non_static_fields(NULL)
+{
   assert(get_Klass()->oop_is_instance(), "wrong type");
   instanceKlass* ik = get_instanceKlass();
 
@@ -335,6 +337,37 @@
   return field;
 }
 
+// ------------------------------------------------------------------
+// ciInstanceKlass::non_static_fields.
+
+class NonStaticFieldFiller: public FieldClosure {
+  GrowableArray<ciField*>* _arr;
+  ciEnv* _curEnv;
+public:
+  NonStaticFieldFiller(ciEnv* curEnv, GrowableArray<ciField*>* arr) :
+    _curEnv(curEnv), _arr(arr)
+  {}
+  void do_field(fieldDescriptor* fd) {
+    ciField* field = new (_curEnv->arena()) ciField(fd);
+    _arr->append(field);
+  }
+};
+
+GrowableArray<ciField*>* ciInstanceKlass::non_static_fields() {
+  if (_non_static_fields == NULL) {
+    VM_ENTRY_MARK;
+    ciEnv* curEnv = ciEnv::current();
+    instanceKlass* ik = get_instanceKlass();
+    int max_n_fields = ik->fields()->length()/instanceKlass::next_offset;
+
+    _non_static_fields =
+      new (curEnv->arena()) GrowableArray<ciField*>(max_n_fields);
+    NonStaticFieldFiller filler(curEnv, _non_static_fields);
+    ik->do_nonstatic_fields(&filler);
+  }
+  return _non_static_fields;
+}
+
 static int sort_field_by_offset(ciField** a, ciField** b) {
   return (*a)->offset_in_bytes() - (*b)->offset_in_bytes();
   // (no worries about 32-bit overflow...)
--- a/src/share/vm/ci/ciInstanceKlass.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/ciInstanceKlass.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -46,6 +46,7 @@
   bool                   _has_subklass;
   ciFlags                _flags;
   jint                   _nonstatic_field_size;
+  jint                   _nonstatic_oop_map_size;
 
   // Lazy fields get filled in only upon request.
   ciInstanceKlass*       _super;
@@ -58,6 +59,8 @@
   ciInstanceKlass*       _implementors[implementors_limit];
   jint                   _nof_implementors;
 
+  GrowableArray<ciField*>* _non_static_fields;
+
 protected:
   ciInstanceKlass(KlassHandle h_k);
   ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain);
@@ -129,6 +132,9 @@
   jint                   nonstatic_field_size()  {
     assert(is_loaded(), "must be loaded");
     return _nonstatic_field_size; }
+  jint                   nonstatic_oop_map_size()  {
+    assert(is_loaded(), "must be loaded");
+    return _nonstatic_oop_map_size; }
   ciInstanceKlass*       super();
   jint                   nof_implementors()  {
     assert(is_loaded(), "must be loaded");
@@ -138,6 +144,9 @@
 
   ciInstanceKlass* get_canonical_holder(int offset);
   ciField* get_field_by_offset(int field_offset, bool is_static);
+
+  GrowableArray<ciField*>* non_static_fields();
+
   // total number of nonstatic fields (including inherited):
   int nof_nonstatic_fields() {
     if (_nonstatic_fields == NULL)
--- a/src/share/vm/ci/ciMethod.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/ciMethod.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -146,7 +146,7 @@
   memcpy(_code, me->code_base(), code_size());
 
   // Revert any breakpoint bytecodes in ci's copy
-  if (_is_compilable && me->number_of_breakpoints() > 0) {
+  if (me->number_of_breakpoints() > 0) {
     BreakpointInfo* bp = instanceKlass::cast(me->method_holder())->breakpoints();
     for (; bp != NULL; bp = bp->next()) {
       if (bp->match(me)) {
--- a/src/share/vm/ci/ciMethodBlocks.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/ciMethodBlocks.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -67,6 +67,14 @@
       break;
     }
   }
+  // Move an exception handler information if needed.
+  if (former_block->is_handler()) {
+    int ex_start = former_block->ex_start_bci();
+    int ex_end = former_block->ex_limit_bci();
+    new_block->set_exception_range(ex_start, ex_end);
+    // Clear information in former_block.
+    former_block->clear_exception_handler();
+  }
   return former_block;
 }
 
@@ -102,7 +110,7 @@
     // one and end the old one.
     assert(cur_block != NULL, "must always have a current block");
     ciBlock *new_block = block_containing(bci);
-    if (new_block == NULL) {
+    if (new_block == NULL || new_block == cur_block) {
       // We have not marked this bci as the start of a new block.
       // Keep interpreting the current_range.
       _bci_to_block[bci] = cur_block;
@@ -254,9 +262,33 @@
     for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) {
       ciExceptionHandler* handler = str.handler();
       ciBlock *eb = make_block_at(handler->handler_bci());
-      eb->set_handler();
+      //
+      // Several exception handlers can have the same handler_bci:
+      //
+      //  try {
+      //    if (a.foo(b) < 0) {
+      //      return a.error();
+      //    }
+      //    return CoderResult.UNDERFLOW;
+      //  } finally {
+      //      a.position(b);
+      //  }
+      //
+      //  The try block above is divided into 2 exception blocks
+      //  separated by 'areturn' bci.
+      //
       int ex_start = handler->start();
       int ex_end = handler->limit();
+      if (eb->is_handler()) {
+        // Extend old handler exception range to cover additional range.
+        int old_ex_start = eb->ex_start_bci();
+        int old_ex_end   = eb->ex_limit_bci();
+        if (ex_start > old_ex_start)
+          ex_start = old_ex_start;
+        if (ex_end < old_ex_end)
+          ex_end = old_ex_end;
+        eb->clear_exception_handler(); // Reset exception information
+      }
       eb->set_exception_range(ex_start, ex_end);
       // ensure a block at the start of exception range and start of following code
       (void) make_block_at(ex_start);
@@ -312,9 +344,10 @@
 
 void ciBlock::set_exception_range(int start_bci, int limit_bci)  {
    assert(limit_bci >= start_bci, "valid range");
-   assert(is_handler(), "must be handler");
+   assert(!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1, "must not be handler");
    _ex_start_bci = start_bci;
    _ex_limit_bci = limit_bci;
+   set_handler();
 }
 
 #ifndef PRODUCT
--- a/src/share/vm/ci/ciMethodBlocks.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/ciMethodBlocks.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -110,9 +110,10 @@
   void  set_does_jsr()              { _flags |= DoesJsr; }
   void  clear_does_jsr()            { _flags &= ~DoesJsr; }
   void  set_does_ret()              { _flags |= DoesRet; }
-  void  clear_does_ret()            { _flags |= DoesRet; }
+  void  clear_does_ret()            { _flags &= ~DoesRet; }
   void  set_is_ret_target()         { _flags |= RetTarget; }
   void  set_has_handler()           { _flags |= HasHandler; }
+  void  clear_exception_handler()   { _flags &= ~Handler; _ex_start_bci = -1; _ex_limit_bci = -1; }
 #ifndef PRODUCT
   ciMethod *method() const          { return _method; }
   void dump();
--- a/src/share/vm/ci/ciMethodData.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/ciMethodData.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -42,6 +42,8 @@
   // Set an initial hint. Don't use set_hint_di() because
   // first_di() may be out of bounds if data_size is 0.
   _hint_di = first_di();
+  // Initialize the escape information (to "don't know.");
+  _eflags = _arg_local = _arg_stack = _arg_returned = 0;
 }
 
 // ------------------------------------------------------------------
@@ -59,6 +61,8 @@
   // Set an initial hint. Don't use set_hint_di() because
   // first_di() may be out of bounds if data_size is 0.
   _hint_di = first_di();
+  // Initialize the escape information (to "don't know.");
+  _eflags = _arg_local = _arg_stack = _arg_returned = 0;
 }
 
 void ciMethodData::load_data() {
@@ -142,6 +146,8 @@
     return new ciBranchData(data_layout);
   case DataLayout::multi_branch_data_tag:
     return new ciMultiBranchData(data_layout);
+  case DataLayout::arg_info_data_tag:
+    return new ciArgInfoData(data_layout);
   };
 }
 
@@ -172,6 +178,9 @@
       _saw_free_extra_data = true;  // observed an empty slot (common case)
       return NULL;
     }
+    if (dp->tag() == DataLayout::arg_info_data_tag) {
+      break; // ArgInfoData is at the end of extra data section.
+    }
     if (dp->bci() == bci) {
       assert(dp->tag() == DataLayout::bit_data_tag, "sane");
       return new ciBitData(dp);
@@ -217,8 +226,14 @@
 void ciMethodData::clear_escape_info() {
   VM_ENTRY_MARK;
   methodDataOop mdo = get_methodDataOop();
-  if (mdo != NULL)
+  if (mdo != NULL) {
     mdo->clear_escape_info();
+    ArgInfoData *aid = arg_info();
+    int arg_count = (aid == NULL) ? 0 : aid->number_of_args();
+    for (int i = 0; i < arg_count; i++) {
+      set_arg_modified(i, 0);
+    }
+  }
   _eflags = _arg_local = _arg_stack = _arg_returned = 0;
 }
 
@@ -231,6 +246,10 @@
     mdo->set_arg_local(_arg_local);
     mdo->set_arg_stack(_arg_stack);
     mdo->set_arg_returned(_arg_returned);
+    int arg_count = mdo->method()->size_of_parameters();
+    for (int i = 0; i < arg_count; i++) {
+      mdo->set_arg_modified(i, arg_modified(i));
+    }
   }
 }
 
@@ -262,6 +281,14 @@
   set_nth_bit(_arg_returned, i);
 }
 
+void ciMethodData::set_arg_modified(int arg, uint val) {
+  ArgInfoData *aid = arg_info();
+  if (aid == NULL)
+    return;
+  assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
+  aid->set_arg_modified(arg, val);
+}
+
 bool ciMethodData::is_arg_local(int i) const {
   return is_set_nth_bit(_arg_local, i);
 }
@@ -274,6 +301,14 @@
   return is_set_nth_bit(_arg_returned, i);
 }
 
+uint ciMethodData::arg_modified(int arg) const {
+  ArgInfoData *aid = arg_info();
+  if (aid == NULL)
+    return 0;
+  assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
+  return aid->arg_modified(arg);
+}
+
 ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) {
   // Get offset within methodDataOop of the data array
   ByteSize data_offset = methodDataOopDesc::data_offset();
@@ -287,6 +322,18 @@
   return in_ByteSize(offset);
 }
 
+ciArgInfoData *ciMethodData::arg_info() const {
+  // Should be last, have to skip all traps.
+  DataLayout* dp  = data_layout_at(data_size());
+  DataLayout* end = data_layout_at(data_size() + extra_data_size());
+  for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) {
+    if (dp->tag() == DataLayout::arg_info_data_tag)
+      return new ciArgInfoData(dp);
+  }
+  return NULL;
+}
+
+
 // Implementation of the print method.
 void ciMethodData::print_impl(outputStream* st) {
   ciObject::print_impl(st);
@@ -305,6 +352,22 @@
     st->fill_to(6);
     data->print_data_on(st);
   }
+  st->print_cr("--- Extra data:");
+  DataLayout* dp  = data_layout_at(data_size());
+  DataLayout* end = data_layout_at(data_size() + extra_data_size());
+  for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) {
+    if (dp->tag() == DataLayout::no_tag)  continue;
+    if (dp->tag() == DataLayout::bit_data_tag) {
+      data = new BitData(dp);
+    } else {
+      assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo");
+      data = new ciArgInfoData(dp);
+      dp = end; // ArgInfoData is at the end of extra data section.
+    }
+    st->print("%d", dp_to_di(data->dp()));
+    st->fill_to(6);
+    data->print_data_on(st);
+  }
 }
 
 void ciReceiverTypeData::print_receiver_data_on(outputStream* st) {
--- a/src/share/vm/ci/ciMethodData.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/ciMethodData.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -30,6 +30,7 @@
 class ciBranchData;
 class ciArrayData;
 class ciMultiBranchData;
+class ciArgInfoData;
 
 typedef ProfileData ciProfileData;
 
@@ -121,6 +122,11 @@
   ciMultiBranchData(DataLayout* layout) : MultiBranchData(layout) {};
 };
 
+class ciArgInfoData : public ArgInfoData {
+public:
+  ciArgInfoData(DataLayout* layout) : ArgInfoData(layout) {};
+};
+
 // ciMethodData
 //
 // This class represents a methodDataOop in the HotSpot virtual
@@ -163,9 +169,9 @@
   ciMethodData();
 
   // Accessors
-  int data_size() { return _data_size; }
-  int extra_data_size() { return _extra_data_size; }
-  intptr_t * data() { return _data; }
+  int data_size() const { return _data_size; }
+  int extra_data_size() const { return _extra_data_size; }
+  intptr_t * data() const { return _data; }
 
   methodDataOop get_methodDataOop() const {
     if (handle() == NULL) return NULL;
@@ -178,7 +184,7 @@
 
   void print_impl(outputStream* st);
 
-  DataLayout* data_layout_at(int data_index) {
+  DataLayout* data_layout_at(int data_index) const {
     assert(data_index % sizeof(intptr_t) == 0, "unaligned");
     return (DataLayout*) (((address)_data) + data_index);
   }
@@ -207,6 +213,8 @@
   // What is the index of the first data entry?
   int first_di() { return 0; }
 
+  ciArgInfoData *arg_info() const;
+
 public:
   bool is_method_data()  { return true; }
   bool is_empty() { return _state == empty_state; }
@@ -270,10 +278,12 @@
   void set_arg_local(int i);
   void set_arg_stack(int i);
   void set_arg_returned(int i);
+  void set_arg_modified(int arg, uint val);
 
   bool is_arg_local(int i) const;
   bool is_arg_stack(int i) const;
   bool is_arg_returned(int i) const;
+  uint arg_modified(int arg) const;
 
   // Code generation helper
   ByteSize offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/ci/ciObjArray.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1999-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.
+ *
+ */
+
+#include "incls/_precompiled.incl"
+#include "incls/_ciObjArray.cpp.incl"
+
+// ciObjArray
+//
+// This class represents an objArrayOop in the HotSpot virtual
+// machine.
+
+ciObject* ciObjArray::obj_at(int index) {
+  VM_ENTRY_MARK;
+  objArrayOop array = get_objArrayOop();
+  if (index < 0 || index >= array->length()) return NULL;
+  oop o = array->obj_at(index);
+  if (o == NULL) {
+    return ciNullObject::make();
+  } else {
+    return CURRENT_ENV->get_object(o);
+  }
+}
--- a/src/share/vm/ci/ciObjArray.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/ci/ciObjArray.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -43,4 +43,6 @@
 public:
   // What kind of ciObject is this?
   bool is_obj_array() { return true; }
+
+  ciObject* obj_at(int index);
 };
--- a/src/share/vm/classfile/dictionary.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/classfile/dictionary.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -155,8 +155,8 @@
         for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) {
           // check the previous versions array for GC'ed weak refs
           PreviousVersionNode * pv_node = ik->previous_versions()->at(i);
-          jweak cp_ref = pv_node->prev_constant_pool();
-          assert(cp_ref != NULL, "weak cp ref was unexpectedly cleared");
+          jobject cp_ref = pv_node->prev_constant_pool();
+          assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
           if (cp_ref == NULL) {
             delete pv_node;
             ik->previous_versions()->remove_at(i);
--- a/src/share/vm/classfile/javaClasses.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/classfile/javaClasses.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -143,13 +143,43 @@
   jstring js = NULL;
   { JavaThread* thread = (JavaThread*)THREAD;
     assert(thread->is_Java_thread(), "must be java thread");
+    HandleMark hm(thread);
     ThreadToNativeFromVM ttn(thread);
-    HandleMark hm(thread);
     js = (_to_java_string_fn)(thread->jni_environment(), str);
   }
   return Handle(THREAD, JNIHandles::resolve(js));
 }
 
+// Converts a Java String to a native C string that can be used for
+// native OS calls.
+char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) {
+
+  typedef char* (*to_platform_string_fn_t)(JNIEnv*, jstring, bool*);
+  static to_platform_string_fn_t _to_platform_string_fn = NULL;
+
+  if (_to_platform_string_fn == NULL) {
+    void *lib_handle = os::native_java_library();
+    _to_platform_string_fn = CAST_TO_FN_PTR(to_platform_string_fn_t, hpi::dll_lookup(lib_handle, "GetStringPlatformChars"));
+    if (_to_platform_string_fn == NULL) {
+      fatal("GetStringPlatformChars missing");
+    }
+  }
+
+  char *native_platform_string;
+  { JavaThread* thread = (JavaThread*)THREAD;
+    assert(thread->is_Java_thread(), "must be java thread");
+    JNIEnv *env = thread->jni_environment();
+    jstring js = (jstring) JNIHandles::make_local(env, java_string());
+    bool is_copy;
+    HandleMark hm(thread);
+    ThreadToNativeFromVM ttn(thread);
+    native_platform_string = (_to_platform_string_fn)(env, js, &is_copy);
+    assert(is_copy == JNI_TRUE, "is_copy value changed");
+    JNIHandles::destroy_local(js);
+  }
+  return native_platform_string;
+}
+
 Handle java_lang_String::char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS) {
   oop          obj    = java_string();
   // Typical usage is to convert all '/' to '.' in string.
--- a/src/share/vm/classfile/javaClasses.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/classfile/javaClasses.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -96,6 +96,7 @@
   // String converters
   static char*  as_utf8_string(oop java_string);
   static char*  as_utf8_string(oop java_string, int start, int len);
+  static char*  as_platform_dependent_str(Handle java_string, TRAPS);
   static jchar* as_unicode_string(oop java_string, int& length);
 
   static bool equals(oop java_string, jchar* chars, int len);
--- a/src/share/vm/classfile/systemDictionary.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/classfile/systemDictionary.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1242,7 +1242,9 @@
     oop obj = (oop) result.get_jobject();
     if (obj == NULL) { return nk; }
 
-    char* new_class_name = java_lang_String::as_utf8_string(obj);
+    Handle h_obj(THREAD, obj);
+    char* new_class_name = java_lang_String::as_platform_dependent_str(h_obj,
+                                                                  CHECK_(nk));
 
     // lock the loader
     // we use this lock because JVMTI does.
--- a/src/share/vm/classfile/vmSymbols.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/classfile/vmSymbols.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -318,6 +318,11 @@
   const int neg = JVM_ACC_SYNCHRONIZED;
   return (flags & (req | neg)) == req;
 }
+inline bool match_F_RNY(jshort flags) {
+  const int req = JVM_ACC_NATIVE | JVM_ACC_SYNCHRONIZED;
+  const int neg = JVM_ACC_STATIC;
+  return (flags & (req | neg)) == req;
+}
 
 // These are for forming case labels:
 #define ID3(x, y, z) (( jint)(z) +                                  \
@@ -359,6 +364,7 @@
   case F_RN: fname = "native ";        break;
   case F_SN: fname = "native static "; break;
   case F_S:  fname = "static ";        break;
+  case F_RNY:fname = "native synchronized "; break;
   }
   const char* kptr = strrchr(kname, '/');
   if (kptr != NULL)  kname = kptr + 1;
@@ -485,7 +491,7 @@
   if (PrintMiscellaneous && (WizardMode || Verbose)) {
     tty->print_cr("*** misidentified method; %s(%d) should be %s(%d):",
                   declared_name, declared_id, actual_name, actual_id);
-    m->print_short_name(tty);
+    mh()->print_short_name(tty);
     tty->cr();
   }
 }
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -58,12 +58,17 @@
   template(java_lang_ThreadDeath,                     "java/lang/ThreadDeath")                    \
   template(java_lang_Boolean,                         "java/lang/Boolean")                        \
   template(java_lang_Character,                       "java/lang/Character")                      \
+  template(java_lang_Character_CharacterCache,        "java/lang/Character$CharacterCache")       \
   template(java_lang_Float,                           "java/lang/Float")                          \
   template(java_lang_Double,                          "java/lang/Double")                         \
   template(java_lang_Byte,                            "java/lang/Byte")                           \
+  template(java_lang_Byte_Cache,                      "java/lang/Byte$ByteCache")                 \
   template(java_lang_Short,                           "java/lang/Short")                          \
+  template(java_lang_Short_ShortCache,                "java/lang/Short$ShortCache")               \
   template(java_lang_Integer,                         "java/lang/Integer")                        \
+  template(java_lang_Integer_IntegerCache,            "java/lang/Integer$IntegerCache")           \
   template(java_lang_Long,                            "java/lang/Long")                           \
+  template(java_lang_Long_LongCache,                  "java/lang/Long$LongCache")                 \
   template(java_lang_Shutdown,                        "java/lang/Shutdown")                       \
   template(java_lang_ref_Reference,                   "java/lang/ref/Reference")                  \
   template(java_lang_ref_SoftReference,               "java/lang/ref/SoftReference")              \
@@ -91,10 +96,11 @@
   template(java_util_Vector,                          "java/util/Vector")                         \
   template(java_util_AbstractList,                    "java/util/AbstractList")                   \
   template(java_util_Hashtable,                       "java/util/Hashtable")                      \
+  template(java_util_HashMap,                         "java/util/HashMap")                        \
   template(java_lang_Compiler,                        "java/lang/Compiler")                       \
   template(sun_misc_Signal,                           "sun/misc/Signal")                          \
   template(java_lang_AssertionStatusDirectives,       "java/lang/AssertionStatusDirectives")      \
-  template(sun_jkernel_DownloadManager,               "sun/jkernel/DownloadManager")                 \
+  template(sun_jkernel_DownloadManager,               "sun/jkernel/DownloadManager")              \
   template(getBootClassPathEntryForClass_name,        "getBootClassPathEntryForClass")            \
                                                                                                   \
   /* class file format tags */                                                                    \
@@ -274,7 +280,9 @@
   template(exclusive_owner_thread_name,               "exclusiveOwnerThread")                     \
   template(park_blocker_name,                         "parkBlocker")                              \
   template(park_event_name,                           "nativeParkEventPointer")                   \
+  template(cache_field_name,                          "cache")                                    \
   template(value_name,                                "value")                                    \
+  template(frontCacheEnabled_name,                    "frontCacheEnabled")                        \
                                                                                                   \
   /* non-intrinsic name/signature pairs: */                                                       \
   template(register_method_name,                      "register")                                 \
@@ -576,6 +584,8 @@
    do_name(     attemptUpdate_name,                                 "attemptUpdate")                                    \
    do_signature(attemptUpdate_signature,                            "(JJ)Z")                                            \
                                                                                                                         \
+  do_intrinsic(_fillInStackTrace,         java_lang_Throwable, fillInStackTrace_name, void_throwable_signature,  F_RNY) \
+                                                                                                                        \
   /* support for sun.misc.Unsafe */                                                                                     \
   do_class(sun_misc_Unsafe,               "sun/misc/Unsafe")                                                            \
                                                                                                                         \
@@ -863,7 +873,8 @@
     F_R,                        // !static        !synchronized (R="regular")
     F_S,                        //  static        !synchronized
     F_RN,                       // !static native !synchronized
-    F_SN                        //  static native !synchronized
+    F_SN,                       //  static native !synchronized
+    F_RNY                       // !static native  synchronized
   };
 
 public:
--- a/src/share/vm/code/debugInfo.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/code/debugInfo.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -47,7 +47,8 @@
   }
 #endif
   ObjectValue* result = new ObjectValue(id);
-  _obj_pool->append(result);
+  // Cache the object since an object field could reference it.
+  _obj_pool->push(result);
   result->read_object(this);
   return result;
 }
@@ -56,9 +57,9 @@
   int id = read_int();
   assert(_obj_pool != NULL, "object pool does not exist");
   for (int i = _obj_pool->length() - 1; i >= 0; i--) {
-    ObjectValue* sv = (ObjectValue*) _obj_pool->at(i);
-    if (sv->id() == id) {
-      return sv;
+    ObjectValue* ov = (ObjectValue*) _obj_pool->at(i);
+    if (ov->id() == id) {
+      return ov;
     }
   }
   ShouldNotReachHere();
--- a/src/share/vm/code/dependencies.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/code/dependencies.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -882,6 +882,14 @@
   // Must not move the class hierarchy during this check:
   assert_locked_or_safepoint(Compile_lock);
 
+  int nof_impls = instanceKlass::cast(context_type)->nof_implementors();
+  if (nof_impls > 1) {
+    // Avoid this case: *I.m > { A.m, C }; B.m > C
+    // %%% Until this is fixed more systematically, bail out.
+    // See corresponding comment in find_witness_anywhere.
+    return context_type;
+  }
+
   assert(!is_participant(new_type), "only old classes are participants");
   if (participants_hide_witnesses) {
     // If the new type is a subtype of a participant, we are done.
--- a/src/share/vm/code/nmethod.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/code/nmethod.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1971,7 +1971,7 @@
     if (ctxk != NULL) {
       Klass* k = Klass::cast(ctxk);
       if (k->oop_is_instance() && ((instanceKlass*)k)->is_dependent_nmethod(this)) {
-        tty->print("   [nmethod<=klass]%s", k->external_name());
+        tty->print_cr("   [nmethod<=klass]%s", k->external_name());
       }
     }
     deps.log_dependency();  // put it into the xml log also
--- a/src/share/vm/code/scopeDesc.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/code/scopeDesc.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -91,7 +91,9 @@
   DebugInfoReadStream* stream = new DebugInfoReadStream(_code, decode_offset, result);
   int length = stream->read_int();
   for (int index = 0; index < length; index++) {
-    result->push(ScopeValue::read_from(stream));
+    // Objects values are pushed to 'result' array during read so that
+    // object's fields could reference it (OBJECT_ID_CODE).
+    (void)ScopeValue::read_from(stream);
   }
   assert(result->length() == length, "inconsistent debug information");
   return result;
--- a/src/share/vm/code/vmreg.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/code/vmreg.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -36,16 +36,16 @@
 // Register names
 const char *VMRegImpl::regName[ConcreteRegisterImpl::number_of_registers];
 
-void VMRegImpl::print() {
 #ifndef PRODUCT
+void VMRegImpl::print_on(outputStream* st) const {
   if( is_reg() ) {
     assert( VMRegImpl::regName[value()], "" );
-    tty->print("%s",VMRegImpl::regName[value()]);
+    st->print("%s",VMRegImpl::regName[value()]);
   } else if (is_stack()) {
     int stk = value() - stack0->value();
-    tty->print("[%d]", stk*4);
+    st->print("[%d]", stk*4);
   } else {
-    tty->print("BAD!");
+    st->print("BAD!");
   }
+}
 #endif // PRODUCT
-}
--- a/src/share/vm/code/vmreg.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/code/vmreg.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -66,9 +66,9 @@
     }
   }
   static VMReg Bad() { return (VMReg) (intptr_t) BAD; }
-  bool is_valid() { return ((intptr_t) this) != BAD; }
-  bool is_stack() { return (intptr_t) this >= (intptr_t) stack0; }
-  bool is_reg() { return is_valid() && !is_stack(); }
+  bool is_valid() const { return ((intptr_t) this) != BAD; }
+  bool is_stack() const { return (intptr_t) this >= (intptr_t) stack0; }
+  bool is_reg()   const { return is_valid() && !is_stack(); }
 
   // A concrete register is a value that returns true for is_reg() and is
   // also a register you could use in the assembler. On machines with
@@ -96,7 +96,8 @@
 
   intptr_t value() const         {return (intptr_t) this; }
 
-  void print();
+  void print_on(outputStream* st) const PRODUCT_RETURN;
+  void print() const { print_on(tty); }
 
   // bias a stack slot.
   // Typically used to adjust a virtual frame slots by amounts that are offset by
--- a/src/share/vm/compiler/oopMap.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/compiler/oopMap.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -506,27 +506,27 @@
 }
 
 
-void print_register_type(OopMapValue::oop_types x, VMReg optional) {
+static void print_register_type(OopMapValue::oop_types x, VMReg optional, outputStream* st) {
   switch( x ) {
   case OopMapValue::oop_value:
-    tty->print("Oop");
+    st->print("Oop");
     break;
   case OopMapValue::value_value:
-    tty->print("Value" );
+    st->print("Value" );
     break;
   case OopMapValue::dead_value:
-    tty->print("Dead" );
+    st->print("Dead" );
     break;
   case OopMapValue::callee_saved_value:
-    tty->print("Callers_" );
-    optional->print();
+    st->print("Callers_" );
+    optional->print_on(st);
     break;
   case OopMapValue::derived_oop_value:
-    tty->print("Derived_oop_" );
-    optional->print();
+    st->print("Derived_oop_" );
+    optional->print_on(st);
     break;
   case OopMapValue::stack_obj:
-    tty->print("Stack");
+    st->print("Stack");
     break;
   default:
     ShouldNotReachHere();
@@ -534,11 +534,11 @@
 }
 
 
-void OopMapValue::print() const {
-  reg()->print();
-  tty->print("=");
-  print_register_type(type(),content_reg());
-  tty->print(" ");
+void OopMapValue::print_on(outputStream* st) const {
+  reg()->print_on(st);
+  st->print("=");
+  print_register_type(type(),content_reg(),st);
+  st->print(" ");
 }
 
 
--- a/src/share/vm/compiler/oopMap.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/compiler/oopMap.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -129,7 +129,8 @@
     return reg()->reg2stack();
   }
 
-  void print( ) const PRODUCT_RETURN;
+  void print_on(outputStream* st) const PRODUCT_RETURN;
+  void print() const { print_on(tty); }
 };
 
 
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1071,85 +1071,56 @@
 // for each list in the tree.  Also print some summary
 // information.
 class printTreeCensusClosure : public AscendTreeCensusClosure {
+  int _print_line;
   size_t _totalFree;
-  AllocationStats _totals;
-  size_t _count;
+  FreeList _total;
 
  public:
   printTreeCensusClosure() {
+    _print_line = 0;
     _totalFree = 0;
-    _count = 0;
-    _totals.initialize();
   }
-  AllocationStats* totals() { return &_totals; }
-  size_t count() { return _count; }
-  void increment_count_by(size_t v) { _count += v; }
+  FreeList* total() { return &_total; }
   size_t totalFree() { return _totalFree; }
-  void increment_totalFree_by(size_t v) { _totalFree += v; }
   void do_list(FreeList* fl) {
-    bool nl = false; // "maybe this is not needed" isNearLargestChunk(fl->head());
-
-    gclog_or_tty->print("%c %4d\t\t" "%7d\t" "%7d\t"
-               "%7d\t"      "%7d\t" "%7d\t" "%7d\t"
-               "%7d\t"      "%7d\t" "%7d\t"
-               "%7d\t" "\n",
-               " n"[nl], fl->size(), fl->bfrSurp(), fl->surplus(),
-               fl->desired(), fl->prevSweep(), fl->beforeSweep(), fl->count(),
-               fl->coalBirths(), fl->coalDeaths(), fl->splitBirths(),
-               fl->splitDeaths());
-
-    increment_totalFree_by(fl->count() * fl->size());
-    increment_count_by(fl->count());
-    totals()->set_bfrSurp(totals()->bfrSurp() + fl->bfrSurp());
-    totals()->set_surplus(totals()->splitDeaths()     + fl->surplus());
-    totals()->set_prevSweep(totals()->prevSweep()   + fl->prevSweep());
-    totals()->set_beforeSweep(totals()->beforeSweep() + fl->beforeSweep());
-    totals()->set_coalBirths(totals()->coalBirths()  + fl->coalBirths());
-    totals()->set_coalDeaths(totals()->coalDeaths()  + fl->coalDeaths());
-    totals()->set_splitBirths(totals()->splitBirths() + fl->splitBirths());
-    totals()->set_splitDeaths(totals()->splitDeaths() + fl->splitDeaths());
+    if (++_print_line >= 40) {
+      FreeList::print_labels_on(gclog_or_tty, "size");
+      _print_line = 0;
+    }
+    fl->print_on(gclog_or_tty);
+    _totalFree +=            fl->count()            * fl->size()        ;
+    total()->set_count(      total()->count()       + fl->count()      );
+    total()->set_bfrSurp(    total()->bfrSurp()     + fl->bfrSurp()    );
+    total()->set_surplus(    total()->splitDeaths() + fl->surplus()    );
+    total()->set_desired(    total()->desired()     + fl->desired()    );
+    total()->set_prevSweep(  total()->prevSweep()   + fl->prevSweep()  );
+    total()->set_beforeSweep(total()->beforeSweep() + fl->beforeSweep());
+    total()->set_coalBirths( total()->coalBirths()  + fl->coalBirths() );
+    total()->set_coalDeaths( total()->coalDeaths()  + fl->coalDeaths() );
+    total()->set_splitBirths(total()->splitBirths() + fl->splitBirths());
+    total()->set_splitDeaths(total()->splitDeaths() + fl->splitDeaths());
   }
 };
 
 void BinaryTreeDictionary::printDictCensus(void) const {
 
   gclog_or_tty->print("\nBinaryTree\n");
-  gclog_or_tty->print(
-             "%4s\t\t" "%7s\t"   "%7s\t"    "%7s\t"    "%7s\t"    "%7s\t"
-             "%7s\t"   "%7s\t"   "%7s\t"    "%7s\t"    "%7s\t"     "\n",
-             "size",  "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
-             "count", "cBirths", "cDeaths", "sBirths", "sDeaths");
-
+  FreeList::print_labels_on(gclog_or_tty, "size");
   printTreeCensusClosure ptc;
   ptc.do_tree(root());
 
-  gclog_or_tty->print(
-             "\t\t"    "%7s\t"    "%7s\t"    "%7s\t"    "%7s\t"
-             "%7s\t"   "%7s\t"    "%7s\t"    "%7s\t"    "%7s\t"     "\n",
-                       "bfrsurp", "surplus", "prvSwep", "bfrSwep",
-             "count",  "cBirths", "cDeaths", "sBirths", "sDeaths");
+  FreeList* total = ptc.total();
+  FreeList::print_labels_on(gclog_or_tty, " ");
+  total->print_on(gclog_or_tty, "TOTAL\t");
   gclog_or_tty->print(
-             "%s\t\t"  "%7d\t"    "%7d\t"     "%7d\t"    "%7d\t"
-             "%7d\t"   "%7d\t"    "%7d\t"     "%7d\t"    "%7d\t"    "\n",
-             "totl",
-             ptc.totals()->bfrSurp(),
-             ptc.totals()->surplus(),
-             ptc.totals()->prevSweep(),
-             ptc.totals()->beforeSweep(),
-             ptc.count(),
-             ptc.totals()->coalBirths(),
-             ptc.totals()->coalDeaths(),
-             ptc.totals()->splitBirths(),
-             ptc.totals()->splitDeaths());
-  gclog_or_tty->print("totalFree(words): %7d growth: %8.5f  deficit: %8.5f\n",
+              "totalFree(words): " SIZE_FORMAT_W(16)
+              " growth: %8.5f  deficit: %8.5f\n",
               ptc.totalFree(),
-              (double)(ptc.totals()->splitBirths()+ptc.totals()->coalBirths()
-                       -ptc.totals()->splitDeaths()-ptc.totals()->coalDeaths())
-              /(ptc.totals()->prevSweep() != 0 ?
-                (double)ptc.totals()->prevSweep() : 1.0),
-             (double)(ptc.totals()->desired() - ptc.count())
-             /(ptc.totals()->desired() != 0 ?
-               (double)ptc.totals()->desired() : 1.0));
+              (double)(total->splitBirths() + total->coalBirths()
+                     - total->splitDeaths() - total->coalDeaths())
+              /(total->prevSweep() != 0 ? (double)total->prevSweep() : 1.0),
+             (double)(total->desired() - total->count())
+             /(total->desired() != 0 ? (double)total->desired() : 1.0));
 }
 
 // Verify the following tree invariants:
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1835,7 +1835,7 @@
   guarantee(false, "NYI");
 }
 
-bool CompactibleFreeListSpace::linearAllocationWouldFail() {
+bool CompactibleFreeListSpace::linearAllocationWouldFail() const {
   return _smallLinearAllocBlock._word_size == 0;
 }
 
@@ -1906,6 +1906,13 @@
   }
 }
 
+// Support for concurrent collection policy decisions.
+bool CompactibleFreeListSpace::should_concurrent_collect() const {
+  // In the future we might want to add in frgamentation stats --
+  // including erosion of the "mountain" into this decision as well.
+  return !adaptive_freelists() && linearAllocationWouldFail();
+}
+
 // Support for compaction
 
 void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) {
@@ -2013,11 +2020,11 @@
   }
 }
 
-void CompactibleFreeListSpace::endSweepFLCensus(int sweepCt) {
+void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
   setFLSurplus();
   setFLHints();
   if (PrintGC && PrintFLSCensus > 0) {
-    printFLCensus(sweepCt);
+    printFLCensus(sweep_count);
   }
   clearFLCensus();
   assert_locked();
@@ -2293,59 +2300,37 @@
 }
 #endif
 
-void CompactibleFreeListSpace::printFLCensus(int sweepCt) const {
+void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
   assert_lock_strong(&_freelistLock);
-  ssize_t bfrSurp     = 0;
-  ssize_t surplus     = 0;
-  ssize_t desired     = 0;
-  ssize_t prevSweep   = 0;
-  ssize_t beforeSweep = 0;
-  ssize_t count       = 0;
-  ssize_t coalBirths  = 0;
-  ssize_t coalDeaths  = 0;
-  ssize_t splitBirths = 0;
-  ssize_t splitDeaths = 0;
-  gclog_or_tty->print("end sweep# %d\n", sweepCt);
-  gclog_or_tty->print("%4s\t"    "%7s\t"      "%7s\t"      "%7s\t"      "%7s\t"
-             "%7s\t"    "%7s\t"      "%7s\t"      "%7s\t"      "%7s\t"
-             "%7s\t"    "\n",
-             "size",    "bfrsurp",   "surplus",   "desired",   "prvSwep",
-             "bfrSwep", "count",     "cBirths",   "cDeaths",   "sBirths",
-             "sDeaths");
-
+  FreeList total;
+  gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
+  FreeList::print_labels_on(gclog_or_tty, "size");
   size_t totalFree = 0;
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
     const FreeList *fl = &_indexedFreeList[i];
-        totalFree += fl->count() * fl->size();
-
-    gclog_or_tty->print("%4d\t"          "%7d\t"             "%7d\t"        "%7d\t"
-               "%7d\t"          "%7d\t"             "%7d\t"        "%7d\t"
-               "%7d\t"          "%7d\t"             "%7d\t"        "\n",
-               fl->size(),       fl->bfrSurp(),     fl->surplus(), fl->desired(),
-               fl->prevSweep(),  fl->beforeSweep(), fl->count(),   fl->coalBirths(),
-               fl->coalDeaths(), fl->splitBirths(), fl->splitDeaths());
-    bfrSurp     += fl->bfrSurp();
-    surplus     += fl->surplus();
-    desired     += fl->desired();
-    prevSweep   += fl->prevSweep();
-    beforeSweep += fl->beforeSweep();
-    count       += fl->count();
-    coalBirths  += fl->coalBirths();
-    coalDeaths  += fl->coalDeaths();
-    splitBirths += fl->splitBirths();
-    splitDeaths += fl->splitDeaths();
+    totalFree += fl->count() * fl->size();
+    if (i % (40*IndexSetStride) == 0) {
+      FreeList::print_labels_on(gclog_or_tty, "size");
+    }
+    fl->print_on(gclog_or_tty);
+    total.set_bfrSurp(    total.bfrSurp()     + fl->bfrSurp()    );
+    total.set_surplus(    total.surplus()     + fl->surplus()    );
+    total.set_desired(    total.desired()     + fl->desired()    );
+    total.set_prevSweep(  total.prevSweep()   + fl->prevSweep()  );
+    total.set_beforeSweep(total.beforeSweep() + fl->beforeSweep());
+    total.set_count(      total.count()       + fl->count()      );
+    total.set_coalBirths( total.coalBirths()  + fl->coalBirths() );
+    total.set_coalDeaths( total.coalDeaths()  + fl->coalDeaths() );
+    total.set_splitBirths(total.splitBirths() + fl->splitBirths());
+    total.set_splitDeaths(total.splitDeaths() + fl->splitDeaths());
   }
-  gclog_or_tty->print("%4s\t"
-            "%7d\t"      "%7d\t"     "%7d\t"        "%7d\t"       "%7d\t"
-            "%7d\t"      "%7d\t"     "%7d\t"        "%7d\t"       "%7d\t" "\n",
-            "totl",
-            bfrSurp,     surplus,     desired,     prevSweep,     beforeSweep,
-            count,       coalBirths,  coalDeaths,  splitBirths,   splitDeaths);
-  gclog_or_tty->print_cr("Total free in indexed lists %d words", totalFree);
+  total.print_on(gclog_or_tty, "TOTAL");
+  gclog_or_tty->print_cr("Total free in indexed lists "
+                         SIZE_FORMAT " words", totalFree);
   gclog_or_tty->print("growth: %8.5f  deficit: %8.5f\n",
-    (double)(splitBirths+coalBirths-splitDeaths-coalDeaths)/
-            (prevSweep != 0 ? (double)prevSweep : 1.0),
-    (double)(desired - count)/(desired != 0 ? (double)desired : 1.0));
+    (double)(total.splitBirths()+total.coalBirths()-total.splitDeaths()-total.coalDeaths())/
+            (total.prevSweep() != 0 ? (double)total.prevSweep() : 1.0),
+    (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
   _dictionary->printDictCensus();
 }
 
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -418,7 +418,7 @@
   // chunk exists, return NULL.
   FreeChunk* find_chunk_at_end();
 
-  bool adaptive_freelists() { return _adaptive_freelists; }
+  bool adaptive_freelists() const { return _adaptive_freelists; }
 
   void set_collector(CMSCollector* collector) { _collector = collector; }
 
@@ -566,7 +566,7 @@
   FreeChunk* allocateScratch(size_t size);
 
   // returns true if either the small or large linear allocation buffer is empty.
-  bool       linearAllocationWouldFail();
+  bool       linearAllocationWouldFail() const;
 
   // Adjust the chunk for the minimum size.  This version is called in
   // most cases in CompactibleFreeListSpace methods.
@@ -585,6 +585,9 @@
   void      addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size,
               bool coalesced);
 
+  // Support for decisions regarding concurrent collection policy
+  bool should_concurrent_collect() const;
+
   // Support for compaction
   void prepare_for_compaction(CompactPoint* cp);
   void adjust_pointers();
@@ -622,7 +625,7 @@
   // coalescing of chunks during the sweep of garbage.
 
   // Print the statistics for the free lists.
-  void printFLCensus(int sweepCt)         const;
+  void printFLCensus(size_t sweep_count) const;
 
   // Statistics functions
   // Initialize census for lists before the sweep.
@@ -635,12 +638,11 @@
   // Clear the census for each of the free lists.
   void clearFLCensus();
   // Perform functions for the census after the end of the sweep.
-  void endSweepFLCensus(int sweepCt);
+  void endSweepFLCensus(size_t sweep_count);
   // Return true if the count of free chunks is greater
   // than the desired number of free chunks.
   bool coalOverPopulated(size_t size);
 
-
 // Record (for each size):
 //
 //   split-births = #chunks added due to splits in (prev-sweep-end,
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -3121,12 +3121,7 @@
   if (GCExpandToAllocateDelayMillis > 0) {
     os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false);
   }
-  size_t adj_word_sz = CompactibleFreeListSpace::adjustObjectSize(word_size);
-  if (parallel) {
-    return cmsSpace()->par_allocate(adj_word_sz);
-  } else {
-    return cmsSpace()->allocate(adj_word_sz);
-  }
+  return have_lock_and_allocate(word_size, tlab);
 }
 
 // YSR: All of this generation expansion/shrinking stuff is an exact copy of
@@ -5732,13 +5727,19 @@
   // in the perm_gen_verify_bit_map. In order to do that we traverse
   // all blocks in perm gen and mark all dead objects.
   if (verifying() && !cms_should_unload_classes()) {
-    CMSTokenSyncWithLocks ts(true, _permGen->freelistLock(),
-                             bitMapLock());
     assert(perm_gen_verify_bit_map()->sizeInBits() != 0,
            "Should have already been allocated");
     MarkDeadObjectsClosure mdo(this, _permGen->cmsSpace(),
                                markBitMap(), perm_gen_verify_bit_map());
-    _permGen->cmsSpace()->blk_iterate(&mdo);
+    if (asynch) {
+      CMSTokenSyncWithLocks ts(true, _permGen->freelistLock(),
+                               bitMapLock());
+      _permGen->cmsSpace()->blk_iterate(&mdo);
+    } else {
+      // In the case of synchronous sweep, we already have
+      // the requisite locks/tokens.
+      _permGen->cmsSpace()->blk_iterate(&mdo);
+    }
   }
 
   if (asynch) {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -302,3 +302,29 @@
 #endif
 }
 #endif
+
+// Print the "label line" for free list stats.
+void FreeList::print_labels_on(outputStream* st, const char* c) {
+  st->print("%16s\t", c);
+  st->print("%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"
+            "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "\n",
+            "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
+            "count",   "cBirths", "cDeaths", "sBirths", "sDeaths");
+}
+
+// Print the AllocationStats for the given free list. If the second argument
+// to the call is a non-null string, it is printed in the first column;
+// otherwise, if the argument is null (the default), then the size of the
+// (free list) block is printed in the first column.
+void FreeList::print_on(outputStream* st, const char* c) const {
+  if (c != NULL) {
+    st->print("%16s", c);
+  } else {
+    st->print(SIZE_FORMAT_W(16), size());
+  }
+  st->print("\t"
+           SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t"
+           SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\n",
+           bfrSurp(),             surplus(),             desired(),             prevSweep(),           beforeSweep(),
+           count(),               coalBirths(),          coalDeaths(),          splitBirths(),         splitDeaths());
+}
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -38,6 +38,7 @@
 
 class FreeList VALUE_OBJ_CLASS_SPEC {
   friend class CompactibleFreeListSpace;
+  friend class printTreeCensusClosure;
   FreeChunk*    _head;          // List of free chunks
   FreeChunk*    _tail;          // Tail of list of free chunks
   size_t        _size;          // Size in Heap words of each chunks
@@ -63,10 +64,11 @@
  protected:
   void init_statistics();
   void set_count(ssize_t v) { _count = v;}
-  void increment_count() { _count++; }
+  void increment_count()    { _count++; }
   void decrement_count() {
     _count--;
-    assert(_count >= 0, "Count should not be negative"); }
+    assert(_count >= 0, "Count should not be negative");
+  }
 
  public:
   // Constructor
@@ -159,6 +161,10 @@
   ssize_t desired() const {
     return _allocation_stats.desired();
   }
+  void set_desired(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_desired(v);
+  }
   void compute_desired(float inter_sweep_current,
                        float inter_sweep_estimate) {
     assert_proper_lock_protection();
@@ -298,4 +304,8 @@
   // Verify that the chunk is in the list.
   // found.  Return NULL if "fc" is not found.
   bool verifyChunkInFreeLists(FreeChunk* fc) const;
+
+  // Printing support
+  static void print_labels_on(outputStream* st, const char* c);
+  void print_on(outputStream* st, const char* c = NULL) const;
 };
--- a/src/share/vm/gc_implementation/includeDB_gc_shared	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/includeDB_gc_shared	Thu Mar 20 09:17:30 2008 -0500
@@ -19,15 +19,22 @@
 // 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.
-//  
+//
 //
 
 // NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps!
 
-gcAdaptivePolicyCounters.hpp		adaptiveSizePolicy.hpp
-gcAdaptivePolicyCounters.hpp		gcPolicyCounters.hpp
+allocationStats.cpp                     allocationStats.hpp
+allocationStats.cpp                     ostream.hpp
 
-gcAdaptivePolicyCounters.cpp		resourceArea.hpp
+allocationStats.hpp                     allocation.hpp
+allocationStats.hpp                     gcUtil.hpp
+allocationStats.hpp                     globalDefinitions.hpp
+
+gcAdaptivePolicyCounters.hpp            adaptiveSizePolicy.hpp
+gcAdaptivePolicyCounters.hpp            gcPolicyCounters.hpp
+
+gcAdaptivePolicyCounters.cpp            resourceArea.hpp
 gcAdaptivePolicyCounters.cpp            gcAdaptivePolicyCounters.hpp
 
 gSpaceCounters.cpp                      generation.hpp
@@ -44,7 +51,7 @@
 
 isGCActiveMark.hpp                      parallelScavengeHeap.hpp
 
-markSweep.inline.hpp			psParallelCompact.hpp
+markSweep.inline.hpp                    psParallelCompact.hpp
 
 mutableNUMASpace.cpp                    mutableNUMASpace.hpp
 mutableNUMASpace.cpp                    sharedHeap.hpp
--- a/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/parNew/asParNewGeneration.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -74,8 +74,8 @@
 #ifdef SHRINKS_AT_END_OF_EDEN
   size_t delta_in_survivor = 0;
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t space_alignment = heap->intra_generation_alignment();
-  const size_t gen_alignment = heap->generation_alignment();
+  const size_t space_alignment = heap->intra_heap_alignment();
+  const size_t gen_alignment = heap->object_heap_alignment();
 
   MutableSpace* space_shrinking = NULL;
   if (from_space()->end() > to_space()->end()) {
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -785,6 +785,9 @@
     swap_spaces();  // Make life simpler for CMS || rescan; see 6483690.
     from()->set_next_compaction_space(to());
     gch->set_incremental_collection_will_fail();
+
+    // Reset the PromotionFailureALot counters.
+    NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
   }
   // set new iteration safe limit for the survivor spaces
   from()->set_concurrent_iteration_safe_limit(from()->top());
--- a/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/parallelScavenge/asPSYoungGen.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -86,7 +86,7 @@
   if (eden_space()->is_empty()) {
     // Respect the minimum size for eden and for the young gen as a whole.
     ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-    const size_t eden_alignment = heap->intra_generation_alignment();
+    const size_t eden_alignment = heap->intra_heap_alignment();
     const size_t gen_alignment = heap->young_gen_alignment();
 
     assert(eden_space()->capacity_in_bytes() >= eden_alignment,
@@ -124,7 +124,7 @@
 // to_space can be.
 size_t ASPSYoungGen::available_to_live() {
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t alignment = heap->intra_generation_alignment();
+  const size_t alignment = heap->intra_heap_alignment();
 
   // Include any space that is committed but is not in eden.
   size_t available = pointer_delta(eden_space()->bottom(),
@@ -275,7 +275,7 @@
   assert(eden_start < from_start, "Cannot push into from_space");
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t alignment = heap->intra_generation_alignment();
+  const size_t alignment = heap->intra_heap_alignment();
 
   // Check whether from space is below to space
   if (from_start < to_start) {
--- a/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -39,10 +39,10 @@
 
     // If the user hasn't explicitly set the number of worker
     // threads, set the count.
-    if (ParallelGCThreads == 0) {
-      assert(UseParallelGC, "Setting ParallelGCThreads without UseParallelGC");
-      ParallelGCThreads = os::active_processor_count();
-    }
+    assert(UseSerialGC ||
+           !FLAG_IS_DEFAULT(ParallelGCThreads) ||
+           (ParallelGCThreads > 0),
+           "ParallelGCThreads should be set before flag initialization");
 
     // The survivor ratio's are calculated "raw", unlike the
     // default gc, which adds 2 to the ratio value. We need to
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -173,7 +173,7 @@
     new PSAdaptiveSizePolicy(eden_capacity,
                              initial_promo_size,
                              young_gen()->to_space()->capacity_in_bytes(),
-                             intra_generation_alignment(),
+                             intra_heap_alignment(),
                              max_gc_pause_sec,
                              max_gc_minor_pause_sec,
                              GCTimeRatio
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -58,9 +58,9 @@
 
  public:
   ParallelScavengeHeap() : CollectedHeap() {
-    set_alignment(_perm_gen_alignment, intra_generation_alignment());
-    set_alignment(_young_gen_alignment, intra_generation_alignment());
-    set_alignment(_old_gen_alignment, intra_generation_alignment());
+    set_alignment(_perm_gen_alignment, intra_heap_alignment());
+    set_alignment(_young_gen_alignment, intra_heap_alignment());
+    set_alignment(_old_gen_alignment, intra_heap_alignment());
   }
 
   // For use by VM operations
@@ -92,14 +92,14 @@
 
   void post_initialize();
   void update_counters();
-
   // The alignment used for the various generations.
   size_t perm_gen_alignment()  const { return _perm_gen_alignment; }
   size_t young_gen_alignment() const { return _young_gen_alignment; }
   size_t old_gen_alignment()  const { return _old_gen_alignment; }
 
-  // The alignment used for eden and survivors within the young gen.
-  size_t intra_generation_alignment() const { return 64 * K; }
+  // The alignment used for eden and survivors within the young gen
+  // and for boundary between young gen and old gen.
+  size_t intra_heap_alignment() const { return 64 * K; }
 
   size_t capacity() const;
   size_t used() const;
@@ -217,6 +217,6 @@
 inline size_t ParallelScavengeHeap::set_alignment(size_t& var, size_t val)
 {
   assert(is_power_of_2((intptr_t)val), "must be a power of 2");
-  var = round_to(val, intra_generation_alignment());
+  var = round_to(val, intra_heap_alignment());
   return var;
 }
--- a/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -88,7 +88,7 @@
 
   // Compute maximum space sizes for performance counters
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  size_t alignment = heap->intra_generation_alignment();
+  size_t alignment = heap->intra_heap_alignment();
   size_t size = _virtual_space->reserved_size();
 
   size_t max_survivor_size;
@@ -141,7 +141,7 @@
   assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
 
   // Compute sizes
-  size_t alignment = heap->intra_generation_alignment();
+  size_t alignment = heap->intra_heap_alignment();
   size_t size = _virtual_space->committed_size();
 
   size_t survivor_size = size / InitialSurvivorRatio;
@@ -192,7 +192,7 @@
 #ifndef PRODUCT
 void PSYoungGen::space_invariants() {
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t alignment = heap->intra_generation_alignment();
+  const size_t alignment = heap->intra_heap_alignment();
 
   // Currently, our eden size cannot shrink to zero
   guarantee(eden_space()->capacity_in_bytes() >= alignment, "eden too small");
@@ -392,7 +392,7 @@
   char* to_end     = (char*)to_space()->end();
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t alignment = heap->intra_generation_alignment();
+  const size_t alignment = heap->intra_heap_alignment();
   const bool maintain_minimum =
     (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size();
 
@@ -708,7 +708,7 @@
 size_t PSYoungGen::available_to_live() {
   size_t delta_in_survivor = 0;
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
-  const size_t space_alignment = heap->intra_generation_alignment();
+  const size_t space_alignment = heap->intra_heap_alignment();
   const size_t gen_alignment = heap->young_gen_alignment();
 
   MutableSpace* space_shrinking = NULL;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/shared/allocationStats.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2005 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.
+ *
+ */
+
+# include "incls/_precompiled.incl"
+# include "incls/_allocationStats.cpp.incl"
+
+// Technically this should be derived from machine speed, and
+// ideally it would be dynamically adjusted.
+float AllocationStats::_threshold = ((float)CMS_SweepTimerThresholdMillis)/1000;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/shared/allocationStats.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2001-2005 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.
+ *
+ */
+
+class AllocationStats VALUE_OBJ_CLASS_SPEC {
+  // A duration threshold (in ms) used to filter
+  // possibly unreliable samples.
+  static float _threshold;
+
+  // We measure the demand between the end of the previous sweep and
+  // beginning of this sweep:
+  //   Count(end_last_sweep) - Count(start_this_sweep)
+  //     + splitBirths(between) - splitDeaths(between)
+  // The above number divided by the time since the start [END???] of the
+  // previous sweep gives us a time rate of demand for blocks
+  // of this size. We compute a padded average of this rate as
+  // our current estimate for the time rate of demand for blocks
+  // of this size. Similarly, we keep a padded average for the time
+  // between sweeps. Our current estimate for demand for blocks of
+  // this size is then simply computed as the product of these two
+  // estimates.
+  AdaptivePaddedAverage _demand_rate_estimate;
+
+  ssize_t     _desired;          // Estimate computed as described above
+  ssize_t     _coalDesired;     // desired +/- small-percent for tuning coalescing
+
+  ssize_t     _surplus;         // count - (desired +/- small-percent),
+                                // used to tune splitting in best fit
+  ssize_t     _bfrSurp;         // surplus at start of current sweep
+  ssize_t     _prevSweep;       // count from end of previous sweep
+  ssize_t     _beforeSweep;     // count from before current sweep
+  ssize_t     _coalBirths;      // additional chunks from coalescing
+  ssize_t     _coalDeaths;      // loss from coalescing
+  ssize_t     _splitBirths;     // additional chunks from splitting
+  ssize_t     _splitDeaths;     // loss from splitting
+  size_t     _returnedBytes;    // number of bytes returned to list.
+ public:
+  void initialize() {
+    AdaptivePaddedAverage* dummy =
+      new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight,
+                                                         CMS_FLSPadding);
+    _desired = 0;
+    _coalDesired = 0;
+    _surplus = 0;
+    _bfrSurp = 0;
+    _prevSweep = 0;
+    _beforeSweep = 0;
+    _coalBirths = 0;
+    _coalDeaths = 0;
+    _splitBirths = 0;
+    _splitDeaths = 0;
+    _returnedBytes = 0;
+  }
+
+  AllocationStats() {
+    initialize();
+  }
+  // The rate estimate is in blocks per second.
+  void compute_desired(size_t count,
+                       float inter_sweep_current,
+                       float inter_sweep_estimate) {
+    // If the latest inter-sweep time is below our granularity
+    // of measurement, we may call in here with
+    // inter_sweep_current == 0. However, even for suitably small
+    // but non-zero inter-sweep durations, we may not trust the accuracy
+    // of accumulated data, since it has not been "integrated"
+    // (read "low-pass-filtered") long enough, and would be
+    // vulnerable to noisy glitches. In such cases, we
+    // ignore the current sample and use currently available
+    // historical estimates.
+    if (inter_sweep_current > _threshold) {
+      ssize_t demand = prevSweep() - count + splitBirths() - splitDeaths();
+      float rate = ((float)demand)/inter_sweep_current;
+      _demand_rate_estimate.sample(rate);
+      _desired = (ssize_t)(_demand_rate_estimate.padded_average()
+                           *inter_sweep_estimate);
+    }
+  }
+
+  ssize_t desired() const { return _desired; }
+  void set_desired(ssize_t v) { _desired = v; }
+
+  ssize_t coalDesired() const { return _coalDesired; }
+  void set_coalDesired(ssize_t v) { _coalDesired = v; }
+
+  ssize_t surplus() const { return _surplus; }
+  void set_surplus(ssize_t v) { _surplus = v; }
+  void increment_surplus() { _surplus++; }
+  void decrement_surplus() { _surplus--; }
+
+  ssize_t bfrSurp() const { return _bfrSurp; }
+  void set_bfrSurp(ssize_t v) { _bfrSurp = v; }
+  ssize_t prevSweep() const { return _prevSweep; }
+  void set_prevSweep(ssize_t v) { _prevSweep = v; }
+  ssize_t beforeSweep() const { return _beforeSweep; }
+  void set_beforeSweep(ssize_t v) { _beforeSweep = v; }
+
+  ssize_t coalBirths() const { return _coalBirths; }
+  void set_coalBirths(ssize_t v) { _coalBirths = v; }
+  void increment_coalBirths() { _coalBirths++; }
+
+  ssize_t coalDeaths() const { return _coalDeaths; }
+  void set_coalDeaths(ssize_t v) { _coalDeaths = v; }
+  void increment_coalDeaths() { _coalDeaths++; }
+
+  ssize_t splitBirths() const { return _splitBirths; }
+  void set_splitBirths(ssize_t v) { _splitBirths = v; }
+  void increment_splitBirths() { _splitBirths++; }
+
+  ssize_t splitDeaths() const { return _splitDeaths; }
+  void set_splitDeaths(ssize_t v) { _splitDeaths = v; }
+  void increment_splitDeaths() { _splitDeaths++; }
+
+  NOT_PRODUCT(
+    size_t returnedBytes() const { return _returnedBytes; }
+    void set_returnedBytes(size_t v) { _returnedBytes = v; }
+  )
+};
--- a/src/share/vm/includeDB_compiler2	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/includeDB_compiler2	Thu Mar 20 09:17:30 2008 -0500
@@ -19,7 +19,7 @@
 // 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.
-//  
+//
 //
 
 ad_<arch_model>.cpp                     adGlobals_<arch_model>.hpp
@@ -410,6 +410,7 @@
 
 escape.cpp                              allocation.hpp
 escape.cpp                              bcEscapeAnalyzer.hpp
+escape.cpp                              c2compiler.hpp
 escape.cpp                              callnode.hpp
 escape.cpp                              cfgnode.hpp
 escape.cpp                              compile.hpp
@@ -990,6 +991,7 @@
 
 subnode.cpp                             addnode.hpp
 subnode.cpp                             allocation.inline.hpp
+subnode.cpp                             callnode.hpp
 subnode.cpp                             cfgnode.hpp
 subnode.cpp                             compileLog.hpp
 subnode.cpp                             connode.hpp
@@ -1086,7 +1088,7 @@
 idealGraphPrinter.hpp                   ostream.hpp
 
 idealGraphPrinter.cpp                   idealGraphPrinter.hpp
-idealGraphPrinter.cpp			chaitin.hpp
+idealGraphPrinter.cpp                   chaitin.hpp
 idealGraphPrinter.cpp                   machnode.hpp
 idealGraphPrinter.cpp                   parse.hpp
 idealGraphPrinter.cpp                   threadCritical.hpp
@@ -1098,4 +1100,4 @@
 parse1.cpp                              idealGraphPrinter.hpp
 matcher.cpp                             idealGraphPrinter.hpp
 loopnode.cpp                            idealGraphPrinter.hpp
-chaitin.cpp				idealGraphPrinter.hpp
+chaitin.cpp                             idealGraphPrinter.hpp
--- a/src/share/vm/includeDB_core	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/includeDB_core	Thu Mar 20 09:17:30 2008 -0500
@@ -19,7 +19,7 @@
 // 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.
-//  
+//
 //
 
 // NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps!
@@ -46,13 +46,13 @@
 // as dependencies.  Header files named H.inline.hpp generally contain
 // bodies for inline functions declared in H.hpp.
 //
-// NOTE: Files that use the token "generate_platform_dependent_include" 
+// NOTE: Files that use the token "generate_platform_dependent_include"
 // are expected to contain macro references like <os>, <arch_model>, ... and
 // makedeps has a dependency on these platform files looking like:
-// foo_<macro>.trailing_string 
+// foo_<macro>.trailing_string
 // (where "trailing_string" can be any legal filename strings but typically
 // is "hpp" or "inline.hpp").
-// 
+//
 // The dependency in makedeps (and enforced) is that an underscore
 // will precedure the macro invocation. Note that this restriction
 // is only enforced on filenames that have the dependency token
@@ -148,12 +148,6 @@
 
 allocation.inline.hpp                   os.hpp
 
-allocationStats.cpp                     allocationStats.hpp
-
-allocationStats.hpp                     allocation.hpp
-allocationStats.hpp                     gcUtil.hpp
-allocationStats.hpp                     globalDefinitions.hpp
-
 aprofiler.cpp                           aprofiler.hpp
 aprofiler.cpp                           collectedHeap.inline.hpp
 aprofiler.cpp                           oop.inline.hpp
@@ -720,6 +714,11 @@
 ciObjArray.hpp                          ciClassList.hpp
 ciObjArray.hpp                          objArrayOop.hpp
 
+ciObjArray.cpp                          ciObjArray.hpp
+ciObjArray.cpp                          ciNullObject.hpp
+ciObjArray.cpp                          ciUtilities.hpp
+ciObjArray.cpp                          objArrayOop.hpp
+
 ciObjArrayKlass.cpp                     ciInstanceKlass.hpp
 ciObjArrayKlass.cpp                     ciObjArrayKlass.hpp
 ciObjArrayKlass.cpp                     ciObjArrayKlassKlass.hpp
@@ -1935,7 +1934,7 @@
 
 init.cpp                                bytecodes.hpp
 init.cpp                                collectedHeap.hpp
-init.cpp				handles.inline.hpp
+init.cpp                                handles.inline.hpp
 init.cpp                                icBuffer.hpp
 init.cpp                                icache.hpp
 init.cpp                                init.hpp
@@ -3068,6 +3067,7 @@
 
 oopMapCache.cpp                         allocation.inline.hpp
 oopMapCache.cpp                         handles.inline.hpp
+oopMapCache.cpp                         jvmtiRedefineClassesTrace.hpp
 oopMapCache.cpp                         oop.inline.hpp
 oopMapCache.cpp                         oopMapCache.hpp
 oopMapCache.cpp                         resourceArea.hpp
--- a/src/share/vm/interpreter/oopMapCache.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/interpreter/oopMapCache.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -532,6 +532,10 @@
     if (!_array[i].is_empty() && _array[i].method()->is_old()) {
       // Cache entry is occupied by an old redefined method and we don't want
       // to pin it down so flush the entry.
+      RC_TRACE(0x08000000, ("flush: %s(%s): cached entry @%d",
+        _array[i].method()->name()->as_C_string(),
+        _array[i].method()->signature()->as_C_string(), i));
+
       _array[i].flush();
     }
 }
@@ -577,6 +581,15 @@
   // Entry is not in hashtable.
   // Compute entry and return it
 
+  if (method->should_not_be_cached()) {
+    // It is either not safe or not a good idea to cache this methodOop
+    // at this time. We give the caller of lookup() a copy of the
+    // interesting info via parameter entry_for, but we don't add it to
+    // the cache. See the gory details in methodOop.cpp.
+    compute_one_oop_map(method, bci, entry_for);
+    return;
+  }
+
   // First search for an empty slot
   for(i = 0; i < _probe_depth; i++) {
     entry  = entry_at(probe + i);
@@ -584,12 +597,6 @@
       entry->fill(method, bci);
       entry_for->resource_copy(entry);
       assert(!entry_for->is_empty(), "A non-empty oop map should be returned");
-      if (method->is_old()) {
-        // The caller of lookup() will receive a copy of the interesting
-        // info via entry_for, but we don't keep an old redefined method in
-        // the cache to avoid pinning down the method.
-        entry->flush();
-      }
       return;
     }
   }
@@ -623,13 +630,6 @@
   }
   assert(!entry_for->is_empty(), "A non-empty oop map should be returned");
 
-  if (method->is_old()) {
-    // The caller of lookup() will receive a copy of the interesting
-    // info via entry_for, but we don't keep an old redefined method in
-    // the cache to avoid pinning down the method.
-    entry->flush();
-  }
-
   return;
 }
 
--- a/src/share/vm/memory/allocationStats.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright 2005 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.
- *
- */
-
-# include "incls/_precompiled.incl"
-# include "incls/_allocationStats.cpp.incl"
-
-// Technically this should be derived from machine speed, and
-// ideally it would be dynamically adjusted.
-float AllocationStats::_threshold = ((float)CMS_SweepTimerThresholdMillis)/1000;
--- a/src/share/vm/memory/allocationStats.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright 2001-2005 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.
- *
- */
-
-class AllocationStats VALUE_OBJ_CLASS_SPEC {
-  // A duration threshold (in ms) used to filter
-  // possibly unreliable samples.
-  static float _threshold;
-
-  // We measure the demand between the end of the previous sweep and
-  // beginning of this sweep:
-  //   Count(end_last_sweep) - Count(start_this_sweep)
-  //     + splitBirths(between) - splitDeaths(between)
-  // The above number divided by the time since the start [END???] of the
-  // previous sweep gives us a time rate of demand for blocks
-  // of this size. We compute a padded average of this rate as
-  // our current estimate for the time rate of demand for blocks
-  // of this size. Similarly, we keep a padded average for the time
-  // between sweeps. Our current estimate for demand for blocks of
-  // this size is then simply computed as the product of these two
-  // estimates.
-  AdaptivePaddedAverage _demand_rate_estimate;
-
-  ssize_t     _desired;          // Estimate computed as described above
-  ssize_t     _coalDesired;     // desired +/- small-percent for tuning coalescing
-
-  ssize_t     _surplus;         // count - (desired +/- small-percent),
-                                // used to tune splitting in best fit
-  ssize_t     _bfrSurp;         // surplus at start of current sweep
-  ssize_t     _prevSweep;       // count from end of previous sweep
-  ssize_t     _beforeSweep;     // count from before current sweep
-  ssize_t     _coalBirths;      // additional chunks from coalescing
-  ssize_t     _coalDeaths;      // loss from coalescing
-  ssize_t     _splitBirths;     // additional chunks from splitting
-  ssize_t     _splitDeaths;     // loss from splitting
-  size_t     _returnedBytes;    // number of bytes returned to list.
- public:
-  void initialize() {
-    AdaptivePaddedAverage* dummy =
-      new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight,
-                                                         CMS_FLSPadding);
-    _desired = 0;
-    _coalDesired = 0;
-    _surplus = 0;
-    _bfrSurp = 0;
-    _prevSweep = 0;
-    _beforeSweep = 0;
-    _coalBirths = 0;
-    _coalDeaths = 0;
-    _splitBirths = 0;
-    _splitDeaths = 0;
-    _returnedBytes = 0;
-  }
-
-  AllocationStats() {
-    initialize();
-  }
-  // The rate estimate is in blocks per second.
-  void compute_desired(size_t count,
-                       float inter_sweep_current,
-                       float inter_sweep_estimate) {
-    // If the latest inter-sweep time is below our granularity
-    // of measurement, we may call in here with
-    // inter_sweep_current == 0. However, even for suitably small
-    // but non-zero inter-sweep durations, we may not trust the accuracy
-    // of accumulated data, since it has not been "integrated"
-    // (read "low-pass-filtered") long enough, and would be
-    // vulnerable to noisy glitches. In such cases, we
-    // ignore the current sample and use currently available
-    // historical estimates.
-    if (inter_sweep_current > _threshold) {
-      ssize_t demand = prevSweep() - count + splitBirths() - splitDeaths();
-      float rate = ((float)demand)/inter_sweep_current;
-      _demand_rate_estimate.sample(rate);
-      _desired = (ssize_t)(_demand_rate_estimate.padded_average()
-                           *inter_sweep_estimate);
-    }
-  }
-
-  ssize_t desired() const { return _desired; }
-  ssize_t coalDesired() const { return _coalDesired; }
-  void set_coalDesired(ssize_t v) { _coalDesired = v; }
-
-  ssize_t surplus() const { return _surplus; }
-  void set_surplus(ssize_t v) { _surplus = v; }
-  void increment_surplus() { _surplus++; }
-  void decrement_surplus() { _surplus--; }
-
-  ssize_t bfrSurp() const { return _bfrSurp; }
-  void set_bfrSurp(ssize_t v) { _bfrSurp = v; }
-  ssize_t prevSweep() const { return _prevSweep; }
-  void set_prevSweep(ssize_t v) { _prevSweep = v; }
-  ssize_t beforeSweep() const { return _beforeSweep; }
-  void set_beforeSweep(ssize_t v) { _beforeSweep = v; }
-
-  ssize_t coalBirths() const { return _coalBirths; }
-  void set_coalBirths(ssize_t v) { _coalBirths = v; }
-  void increment_coalBirths() { _coalBirths++; }
-
-  ssize_t coalDeaths() const { return _coalDeaths; }
-  void set_coalDeaths(ssize_t v) { _coalDeaths = v; }
-  void increment_coalDeaths() { _coalDeaths++; }
-
-  ssize_t splitBirths() const { return _splitBirths; }
-  void set_splitBirths(ssize_t v) { _splitBirths = v; }
-  void increment_splitBirths() { _splitBirths++; }
-
-  ssize_t splitDeaths() const { return _splitDeaths; }
-  void set_splitDeaths(ssize_t v) { _splitDeaths = v; }
-  void increment_splitDeaths() { _splitDeaths++; }
-
-  NOT_PRODUCT(
-    size_t returnedBytes() const { return _returnedBytes; }
-    void set_returnedBytes(size_t v) { _returnedBytes = v; }
-  )
-};
--- a/src/share/vm/memory/cardTableModRefBS.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/cardTableModRefBS.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -51,7 +51,7 @@
   _whole_heap(whole_heap),
   _guard_index(cards_required(whole_heap.word_size()) - 1),
   _last_valid_index(_guard_index - 1),
-  _page_size(os::page_size_for_region(_guard_index + 1, _guard_index + 1, 1)),
+  _page_size(os::vm_page_size()),
   _byte_map_size(compute_byte_map_size())
 {
   _kind = BarrierSet::CardTableModRef;
@@ -196,8 +196,8 @@
   assert(_whole_heap.contains(new_region),
            "attempt to cover area not in reserved area");
   debug_only(verify_guard();)
-  int ind = find_covering_region_by_base(new_region.start());
-  MemRegion old_region = _covered[ind];
+  int const ind = find_covering_region_by_base(new_region.start());
+  MemRegion const old_region = _covered[ind];
   assert(old_region.start() == new_region.start(), "just checking");
   if (new_region.word_size() != old_region.word_size()) {
     // Commit new or uncommit old pages, if necessary.
@@ -205,21 +205,21 @@
     // Extend the end of this _commited region
     // to cover the end of any lower _committed regions.
     // This forms overlapping regions, but never interior regions.
-    HeapWord* max_prev_end = largest_prev_committed_end(ind);
+    HeapWord* const max_prev_end = largest_prev_committed_end(ind);
     if (max_prev_end > cur_committed.end()) {
       cur_committed.set_end(max_prev_end);
     }
     // Align the end up to a page size (starts are already aligned).
-    jbyte* new_end = byte_after(new_region.last());
-    HeapWord* new_end_aligned =
-      (HeapWord*)align_size_up((uintptr_t)new_end, _page_size);
+    jbyte* const new_end = byte_after(new_region.last());
+    HeapWord* const new_end_aligned =
+      (HeapWord*) align_size_up((uintptr_t)new_end, _page_size);
     assert(new_end_aligned >= (HeapWord*) new_end,
            "align up, but less");
     // The guard page is always committed and should not be committed over.
-    HeapWord* new_end_for_commit = MIN2(new_end_aligned, _guard_region.start());
+    HeapWord* const new_end_for_commit = MIN2(new_end_aligned, _guard_region.start());
     if (new_end_for_commit > cur_committed.end()) {
       // Must commit new pages.
-      MemRegion new_committed =
+      MemRegion const new_committed =
         MemRegion(cur_committed.end(), new_end_for_commit);
 
       assert(!new_committed.is_empty(), "Region should not be empty here");
@@ -233,7 +233,7 @@
     // the cur_committed region may include the guard region.
     } else if (new_end_aligned < cur_committed.end()) {
       // Must uncommit pages.
-      MemRegion uncommit_region =
+      MemRegion const uncommit_region =
         committed_unique_to_self(ind, MemRegion(new_end_aligned,
                                                 cur_committed.end()));
       if (!uncommit_region.is_empty()) {
@@ -257,7 +257,7 @@
     }
     assert(index_for(new_region.last()) < (int) _guard_index,
       "The guard card will be overwritten");
-    jbyte* end = byte_after(new_region.last());
+    jbyte* const end = byte_after(new_region.last());
     // do nothing if we resized downward.
     if (entry < end) {
       memset(entry, clean_card, pointer_delta(end, entry, sizeof(jbyte)));
--- a/src/share/vm/memory/cardTableRS.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/cardTableRS.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -556,10 +556,16 @@
 }
 
 
-void CardTableRS::verify_empty(MemRegion mr) {
+void CardTableRS::verify_aligned_region_empty(MemRegion mr) {
   if (!mr.is_empty()) {
     jbyte* cur_entry = byte_for(mr.start());
     jbyte* limit = byte_after(mr.last());
+    // The region mr may not start on a card boundary so
+    // the first card may reflect a write to the space
+    // just prior to mr.
+    if (!is_aligned(mr.start())) {
+      cur_entry++;
+    }
     for (;cur_entry < limit; cur_entry++) {
       guarantee(*cur_entry == CardTableModRefBS::clean_card,
                 "Unexpected dirty card found");
--- a/src/share/vm/memory/cardTableRS.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/cardTableRS.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -126,7 +126,7 @@
   }
 
   void verify();
-  void verify_empty(MemRegion mr);
+  void verify_aligned_region_empty(MemRegion mr);
 
   void clear(MemRegion mr) { _ct_bs.clear(mr); }
   void clear_into_younger(Generation* gen, bool clear_perm);
--- a/src/share/vm/memory/collectorPolicy.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/collectorPolicy.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -57,45 +57,51 @@
   // User inputs from -mx and ms are aligned
   _initial_heap_byte_size = align_size_up(Arguments::initial_heap_size(),
                                           min_alignment());
-  _min_heap_byte_size = align_size_up(Arguments::min_heap_size(),
-                                          min_alignment());
-  _max_heap_byte_size = align_size_up(MaxHeapSize, max_alignment());
+  set_min_heap_byte_size(align_size_up(Arguments::min_heap_size(),
+                                          min_alignment()));
+  set_max_heap_byte_size(align_size_up(MaxHeapSize, max_alignment()));
 
   // Check validity of heap parameters from launcher
-  if (_initial_heap_byte_size == 0) {
-    _initial_heap_byte_size = NewSize + OldSize;
+  if (initial_heap_byte_size() == 0) {
+    set_initial_heap_byte_size(NewSize + OldSize);
   } else {
-    Universe::check_alignment(_initial_heap_byte_size, min_alignment(),
+    Universe::check_alignment(initial_heap_byte_size(), min_alignment(),
                             "initial heap");
   }
-  if (_min_heap_byte_size == 0) {
-    _min_heap_byte_size = NewSize + OldSize;
+  if (min_heap_byte_size() == 0) {
+    set_min_heap_byte_size(NewSize + OldSize);
   } else {
-    Universe::check_alignment(_min_heap_byte_size, min_alignment(),
+    Universe::check_alignment(min_heap_byte_size(), min_alignment(),
                             "initial heap");
   }
 
   // Check heap parameter properties
-  if (_initial_heap_byte_size < M) {
+  if (initial_heap_byte_size() < M) {
     vm_exit_during_initialization("Too small initial heap");
   }
   // Check heap parameter properties
-  if (_min_heap_byte_size < M) {
+  if (min_heap_byte_size() < M) {
     vm_exit_during_initialization("Too small minimum heap");
   }
-  if (_initial_heap_byte_size <= NewSize) {
+  if (initial_heap_byte_size() <= NewSize) {
      // make sure there is at least some room in old space
     vm_exit_during_initialization("Too small initial heap for new size specified");
   }
-  if (_max_heap_byte_size < _min_heap_byte_size) {
+  if (max_heap_byte_size() < min_heap_byte_size()) {
     vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
   }
-  if (_initial_heap_byte_size < _min_heap_byte_size) {
+  if (initial_heap_byte_size() < min_heap_byte_size()) {
     vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
   }
-  if (_max_heap_byte_size < _initial_heap_byte_size) {
+  if (max_heap_byte_size() < initial_heap_byte_size()) {
     vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
   }
+
+  if (PrintGCDetails && Verbose) {
+    gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT "  Initial heap "
+      SIZE_FORMAT "  Maximum heap " SIZE_FORMAT,
+      min_heap_byte_size(), initial_heap_byte_size(), max_heap_byte_size());
+  }
 }
 
 void CollectorPolicy::initialize_perm_generation(PermGen::Name pgnm) {
@@ -128,10 +134,26 @@
 
 // GenCollectorPolicy methods.
 
+size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
+  size_t x = base_size / (NewRatio+1);
+  size_t new_gen_size = x > min_alignment() ?
+                     align_size_down(x, min_alignment()) :
+                     min_alignment();
+  return new_gen_size;
+}
+
+size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
+                                                 size_t maximum_size) {
+  size_t alignment = min_alignment();
+  size_t max_minus = maximum_size - alignment;
+  return desired_size < max_minus ? desired_size : max_minus;
+}
+
+
 void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size,
                                                 size_t init_promo_size,
                                                 size_t init_survivor_size) {
-  double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
+  const double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
   _size_policy = new AdaptiveSizePolicy(init_eden_size,
                                         init_promo_size,
                                         init_survivor_size,
@@ -210,74 +232,260 @@
   assert(MaxHeapSize % max_alignment() == 0, "maximum heap alignment");
 }
 
+// Values set on the command line win over any ergonomically
+// set command line parameters.
+// Ergonomic choice of parameters are done before this
+// method is called.  Values for command line parameters such as NewSize
+// and MaxNewSize feed those ergonomic choices into this method.
+// This method makes the final generation sizings consistent with
+// themselves and with overall heap sizings.
+// In the absence of explicitly set command line flags, policies
+// such as the use of NewRatio are used to size the generation.
 void GenCollectorPolicy::initialize_size_info() {
   CollectorPolicy::initialize_size_info();
 
-  // Minimum sizes of the generations may be different than
-  // the initial sizes.
-  if (!FLAG_IS_DEFAULT(NewSize)) {
-    _min_gen0_size = NewSize;
+  // min_alignment() is used for alignment within a generation.
+  // There is additional alignment done down stream for some
+  // collectors that sometimes causes unwanted rounding up of
+  // generations sizes.
+
+  // Determine maximum size of gen0
+
+  size_t max_new_size = 0;
+  if (FLAG_IS_CMDLINE(MaxNewSize)) {
+    if (MaxNewSize < min_alignment()) {
+      max_new_size = min_alignment();
+    } else if (MaxNewSize >= max_heap_byte_size()) {
+      max_new_size = align_size_down(max_heap_byte_size() - min_alignment(),
+                                     min_alignment());
+      warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or "
+        "greater than the entire heap (" SIZE_FORMAT "k).  A "
+        "new generation size of " SIZE_FORMAT "k will be used.",
+        MaxNewSize/K, max_heap_byte_size()/K, max_new_size/K);
+    } else {
+      max_new_size = align_size_down(MaxNewSize, min_alignment());
+    }
+
+  // The case for FLAG_IS_ERGO(MaxNewSize) could be treated
+  // specially at this point to just use an ergonomically set
+  // MaxNewSize to set max_new_size.  For cases with small
+  // heaps such a policy often did not work because the MaxNewSize
+  // was larger than the entire heap.  The interpretation given
+  // to ergonomically set flags is that the flags are set
+  // by different collectors for their own special needs but
+  // are not allowed to badly shape the heap.  This allows the
+  // different collectors to decide what's best for themselves
+  // without having to factor in the overall heap shape.  It
+  // can be the case in the future that the collectors would
+  // only make "wise" ergonomics choices and this policy could
+  // just accept those choices.  The choices currently made are
+  // not always "wise".
   } else {
-    _min_gen0_size = align_size_down(_min_heap_byte_size / (NewRatio+1),
-                                     min_alignment());
-    // We bound the minimum size by NewSize below (since it historically
+    max_new_size = scale_by_NewRatio_aligned(max_heap_byte_size());
+    // Bound the maximum size by NewSize below (since it historically
     // would have been NewSize and because the NewRatio calculation could
     // yield a size that is too small) and bound it by MaxNewSize above.
-    // This is not always best.  The NewSize calculated by CMS (which has
-    // a fixed minimum of 16m) can sometimes be "too" large.  Consider
-    // the case where -Xmx32m.  The CMS calculated NewSize would be about
-    // half the entire heap which seems too large.  But the counter
-    // example is seen when the client defaults for NewRatio are used.
-    // An initial young generation size of 640k was observed
-    // with -Xmx128m -XX:MaxNewSize=32m when NewSize was not used
-    // as a lower bound as with
-    // _min_gen0_size = MIN2(_min_gen0_size, MaxNewSize);
-    // and 640k seemed too small a young generation.
-    _min_gen0_size = MIN2(MAX2(_min_gen0_size, NewSize), MaxNewSize);
+    // Ergonomics plays here by previously calculating the desired
+    // NewSize and MaxNewSize.
+    max_new_size = MIN2(MAX2(max_new_size, NewSize), MaxNewSize);
+  }
+  assert(max_new_size > 0, "All paths should set max_new_size");
+
+  // Given the maximum gen0 size, determine the initial and
+  // minimum sizes.
+
+  if (max_heap_byte_size() == min_heap_byte_size()) {
+    // The maximum and minimum heap sizes are the same so
+    // the generations minimum and initial must be the
+    // same as its maximum.
+    set_min_gen0_size(max_new_size);
+    set_initial_gen0_size(max_new_size);
+    set_max_gen0_size(max_new_size);
+  } else {
+    size_t desired_new_size = 0;
+    if (!FLAG_IS_DEFAULT(NewSize)) {
+      // If NewSize is set ergonomically (for example by cms), it
+      // would make sense to use it.  If it is used, also use it
+      // to set the initial size.  Although there is no reason
+      // the minimum size and the initial size have to be the same,
+      // the current implementation gets into trouble during the calculation
+      // of the tenured generation sizes if they are different.
+      // Note that this makes the initial size and the minimum size
+      // generally small compared to the NewRatio calculation.
+      _min_gen0_size = NewSize;
+      desired_new_size = NewSize;
+      max_new_size = MAX2(max_new_size, NewSize);
+    } else {
+      // For the case where NewSize is the default, use NewRatio
+      // to size the minimum and initial generation sizes.
+      // Use the default NewSize as the floor for these values.  If
+      // NewRatio is overly large, the resulting sizes can be too
+      // small.
+      _min_gen0_size = MAX2(scale_by_NewRatio_aligned(min_heap_byte_size()),
+                          NewSize);
+      desired_new_size =
+        MAX2(scale_by_NewRatio_aligned(initial_heap_byte_size()),
+             NewSize);
+    }
+
+    assert(_min_gen0_size > 0, "Sanity check");
+    set_initial_gen0_size(desired_new_size);
+    set_max_gen0_size(max_new_size);
+
+    // At this point the desirable initial and minimum sizes have been
+    // determined without regard to the maximum sizes.
+
+    // Bound the sizes by the corresponding overall heap sizes.
+    set_min_gen0_size(
+      bound_minus_alignment(_min_gen0_size, min_heap_byte_size()));
+    set_initial_gen0_size(
+      bound_minus_alignment(_initial_gen0_size, initial_heap_byte_size()));
+    set_max_gen0_size(
+      bound_minus_alignment(_max_gen0_size, max_heap_byte_size()));
+
+    // At this point all three sizes have been checked against the
+    // maximum sizes but have not been checked for consistency
+    // amoung the three.
+
+    // Final check min <= initial <= max
+    set_min_gen0_size(MIN2(_min_gen0_size, _max_gen0_size));
+    set_initial_gen0_size(
+      MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size));
+    set_min_gen0_size(MIN2(_min_gen0_size, _initial_gen0_size));
   }
 
-  // Parameters are valid, compute area sizes.
-  size_t max_new_size = align_size_down(_max_heap_byte_size / (NewRatio+1),
-                                        min_alignment());
-  max_new_size = MIN2(MAX2(max_new_size, _min_gen0_size), MaxNewSize);
+  if (PrintGCDetails && Verbose) {
+    gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
+      SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
+      min_gen0_size(), initial_gen0_size(), max_gen0_size());
+  }
+}
 
-  // desired_new_size is used to set the initial size.  The
-  // initial size must be greater than the minimum size.
-  size_t desired_new_size =
-    align_size_down(_initial_heap_byte_size / (NewRatio+1),
-                  min_alignment());
+// Call this method during the sizing of the gen1 to make
+// adjustments to gen0 because of gen1 sizing policy.  gen0 initially has
+// the most freedom in sizing because it is done before the
+// policy for gen1 is applied.  Once gen1 policies have been applied,
+// there may be conflicts in the shape of the heap and this method
+// is used to make the needed adjustments.  The application of the
+// policies could be more sophisticated (iterative for example) but
+// keeping it simple also seems a worthwhile goal.
+bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr,
+                                                     size_t* gen1_size_ptr,
+                                                     size_t heap_size,
+                                                     size_t min_gen0_size) {
+  bool result = false;
+  if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) {
+    if (((*gen0_size_ptr + OldSize) > heap_size) &&
+       (heap_size - min_gen0_size) >= min_alignment()) {
+      // Adjust gen0 down to accomodate OldSize
+      *gen0_size_ptr = heap_size - min_gen0_size;
+      *gen0_size_ptr =
+        MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()),
+             min_alignment());
+      assert(*gen0_size_ptr > 0, "Min gen0 is too large");
+      result = true;
+    } else {
+      *gen1_size_ptr = heap_size - *gen0_size_ptr;
+      *gen1_size_ptr =
+        MAX2((uintx)align_size_down(*gen1_size_ptr, min_alignment()),
+                       min_alignment());
+    }
+  }
+  return result;
+}
 
-  size_t new_size = MIN2(MAX2(desired_new_size, _min_gen0_size), max_new_size);
-
-  _initial_gen0_size = new_size;
-  _max_gen0_size = max_new_size;
-}
+// Minimum sizes of the generations may be different than
+// the initial sizes.  An inconsistently is permitted here
+// in the total size that can be specified explicitly by
+// command line specification of OldSize and NewSize and
+// also a command line specification of -Xms.  Issue a warning
+// but allow the values to pass.
 
 void TwoGenerationCollectorPolicy::initialize_size_info() {
   GenCollectorPolicy::initialize_size_info();
 
-  // Minimum sizes of the generations may be different than
-  // the initial sizes.  An inconsistently is permitted here
-  // in the total size that can be specified explicitly by
-  // command line specification of OldSize and NewSize and
-  // also a command line specification of -Xms.  Issue a warning
-  // but allow the values to pass.
-  if (!FLAG_IS_DEFAULT(OldSize)) {
-    _min_gen1_size = OldSize;
+  // At this point the minimum, initial and maximum sizes
+  // of the overall heap and of gen0 have been determined.
+  // The maximum gen1 size can be determined from the maximum gen0
+  // and maximum heap size since not explicit flags exits
+  // for setting the gen1 maximum.
+  _max_gen1_size = max_heap_byte_size() - _max_gen0_size;
+  _max_gen1_size =
+    MAX2((uintx)align_size_down(_max_gen1_size, min_alignment()),
+         min_alignment());
+  // If no explicit command line flag has been set for the
+  // gen1 size, use what is left for gen1.
+  if (FLAG_IS_DEFAULT(OldSize) || FLAG_IS_ERGO(OldSize)) {
+    // The user has not specified any value or ergonomics
+    // has chosen a value (which may or may not be consistent
+    // with the overall heap size).  In either case make
+    // the minimum, maximum and initial sizes consistent
+    // with the gen0 sizes and the overall heap sizes.
+    assert(min_heap_byte_size() > _min_gen0_size,
+      "gen0 has an unexpected minimum size");
+    set_min_gen1_size(min_heap_byte_size() - min_gen0_size());
+    set_min_gen1_size(
+      MAX2((uintx)align_size_down(_min_gen1_size, min_alignment()),
+           min_alignment()));
+    set_initial_gen1_size(initial_heap_byte_size() - initial_gen0_size());
+    set_initial_gen1_size(
+      MAX2((uintx)align_size_down(_initial_gen1_size, min_alignment()),
+           min_alignment()));
+
+  } else {
+    // It's been explicitly set on the command line.  Use the
+    // OldSize and then determine the consequences.
+    set_min_gen1_size(OldSize);
+    set_initial_gen1_size(OldSize);
+
+    // If the user has explicitly set an OldSize that is inconsistent
+    // with other command line flags, issue a warning.
     // The generation minimums and the overall heap mimimum should
     // be within one heap alignment.
-    if ((_min_gen1_size + _min_gen0_size + max_alignment()) <
-         _min_heap_byte_size) {
+    if ((_min_gen1_size + _min_gen0_size + min_alignment()) <
+           min_heap_byte_size()) {
       warning("Inconsistency between minimum heap size and minimum "
-        "generation sizes: using min heap = " SIZE_FORMAT,
-        _min_heap_byte_size);
+          "generation sizes: using minimum heap = " SIZE_FORMAT,
+          min_heap_byte_size());
+    }
+    if ((OldSize > _max_gen1_size)) {
+      warning("Inconsistency between maximum heap size and maximum "
+          "generation sizes: using maximum heap = " SIZE_FORMAT
+          " -XX:OldSize flag is being ignored",
+          max_heap_byte_size());
+  }
+    // If there is an inconsistency between the OldSize and the minimum and/or
+    // initial size of gen0, since OldSize was explicitly set, OldSize wins.
+    if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size,
+                          min_heap_byte_size(), OldSize)) {
+      if (PrintGCDetails && Verbose) {
+        gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
+              SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
+              min_gen0_size(), initial_gen0_size(), max_gen0_size());
+      }
     }
-  } else {
-    _min_gen1_size = _min_heap_byte_size - _min_gen0_size;
+    // Initial size
+    if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size,
+                         initial_heap_byte_size(), OldSize)) {
+      if (PrintGCDetails && Verbose) {
+        gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
+          SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
+          min_gen0_size(), initial_gen0_size(), max_gen0_size());
+      }
+    }
   }
+  // Enforce the maximum gen1 size.
+  set_min_gen1_size(MIN2(_min_gen1_size, _max_gen1_size));
 
-  _initial_gen1_size = _initial_heap_byte_size - _initial_gen0_size;
-  _max_gen1_size = _max_heap_byte_size - _max_gen0_size;
+  // Check that min gen1 <= initial gen1 <= max gen1
+  set_initial_gen1_size(MAX2(_initial_gen1_size, _min_gen1_size));
+  set_initial_gen1_size(MIN2(_initial_gen1_size, _max_gen1_size));
+
+  if (PrintGCDetails && Verbose) {
+    gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT "  Initial gen1 "
+      SIZE_FORMAT "  Maximum gen1 " SIZE_FORMAT,
+      min_gen1_size(), initial_gen1_size(), max_gen1_size());
+  }
 }
 
 HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,
--- a/src/share/vm/memory/collectorPolicy.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/collectorPolicy.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -82,8 +82,11 @@
   size_t max_alignment()                       { return _max_alignment; }
 
   size_t initial_heap_byte_size() { return _initial_heap_byte_size; }
+  void set_initial_heap_byte_size(size_t v) { _initial_heap_byte_size = v; }
   size_t max_heap_byte_size()     { return _max_heap_byte_size; }
+  void set_max_heap_byte_size(size_t v) { _max_heap_byte_size = v; }
   size_t min_heap_byte_size()     { return _min_heap_byte_size; }
+  void set_min_heap_byte_size(size_t v) { _min_heap_byte_size = v; }
 
   enum Name {
     CollectorPolicyKind,
@@ -182,8 +185,24 @@
   // compute max heap alignment
   size_t compute_max_alignment();
 
+ // Scale the base_size by NewRation according to
+ //     result = base_size / (NewRatio + 1)
+ // and align by min_alignment()
+ size_t scale_by_NewRatio_aligned(size_t base_size);
+
+ // Bound the value by the given maximum minus the
+ // min_alignment.
+ size_t bound_minus_alignment(size_t desired_size, size_t maximum_size);
 
  public:
+  // Accessors
+  size_t min_gen0_size() { return _min_gen0_size; }
+  void set_min_gen0_size(size_t v) { _min_gen0_size = v; }
+  size_t initial_gen0_size() { return _initial_gen0_size; }
+  void set_initial_gen0_size(size_t v) { _initial_gen0_size = v; }
+  size_t max_gen0_size() { return _max_gen0_size; }
+  void set_max_gen0_size(size_t v) { _max_gen0_size = v; }
+
   virtual int number_of_generations() = 0;
 
   virtual GenerationSpec **generations()       {
@@ -236,6 +255,14 @@
   void initialize_generations()                { ShouldNotReachHere(); }
 
  public:
+  // Accessors
+  size_t min_gen1_size() { return _min_gen1_size; }
+  void set_min_gen1_size(size_t v) { _min_gen1_size = v; }
+  size_t initial_gen1_size() { return _initial_gen1_size; }
+  void set_initial_gen1_size(size_t v) { _initial_gen1_size = v; }
+  size_t max_gen1_size() { return _max_gen1_size; }
+  void set_max_gen1_size(size_t v) { _max_gen1_size = v; }
+
   // Inherited methods
   TwoGenerationCollectorPolicy* as_two_generation_policy() { return this; }
 
@@ -246,6 +273,10 @@
   virtual CollectorPolicy::Name kind() {
     return CollectorPolicy::TwoGenerationCollectorPolicyKind;
   }
+
+  // Returns true is gen0 sizes were adjusted
+  bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr,
+                               size_t heap_size, size_t min_gen1_size);
 };
 
 class MarkSweepPolicy : public TwoGenerationCollectorPolicy {
--- a/src/share/vm/memory/compactingPermGenGen.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/compactingPermGenGen.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -26,9 +26,27 @@
 #include "incls/_compactingPermGenGen.cpp.incl"
 
 
-// Recursively adjust all pointers in an object and all objects by
-// referenced it.  Clear marks on objects in order to prevent visiting
-// any object twice.
+// An ObjectClosure helper: Recursively adjust all pointers in an object
+// and all objects by referenced it. Clear marks on objects in order to
+// prevent visiting any object twice. This helper is used when the
+// RedefineClasses() API has been called.
+
+class AdjustSharedObjectClosure : public ObjectClosure {
+public:
+  void do_object(oop obj) {
+    if (obj->is_shared_readwrite()) {
+      if (obj->mark()->is_marked()) {
+        obj->init_mark();         // Don't revisit this object.
+        obj->adjust_pointers();   // Adjust this object's references.
+      }
+    }
+  }
+};
+
+
+// An OopClosure helper: Recursively adjust all pointers in an object
+// and all objects by referenced it. Clear marks on objects in order
+// to prevent visiting any object twice.
 
 class RecursiveAdjustSharedObjectClosure : public OopClosure {
 public:
@@ -274,15 +292,34 @@
 // objects in the space will page in more objects than we need.
 // Instead, use the system dictionary as strong roots into the read
 // write space.
+//
+// If a RedefineClasses() call has been made, then we have to iterate
+// over the entire shared read-write space in order to find all the
+// objects that need to be forwarded. For example, it is possible for
+// an nmethod to be found and marked in GC phase-1 only for the nmethod
+// to be freed by the time we reach GC phase-3. The underlying method
+// is still marked, but we can't (easily) find it in GC phase-3 so we
+// blow up in GC phase-4. With RedefineClasses() we want replaced code
+// (EMCP or obsolete) to go away (i.e., be collectible) once it is no
+// longer being executed by any thread so we keep minimal attachments
+// to the replaced code. However, we can't guarantee when those EMCP
+// or obsolete methods will be collected so they may still be out there
+// even after we've severed our minimal attachments.
 
 void CompactingPermGenGen::pre_adjust_pointers() {
   if (spec()->enable_shared_spaces()) {
-    RecursiveAdjustSharedObjectClosure blk;
-    Universe::oops_do(&blk);
-    StringTable::oops_do(&blk);
-    SystemDictionary::always_strong_classes_do(&blk);
-    TraversePlaceholdersClosure tpc;
-    SystemDictionary::placeholders_do(&tpc);
+    if (JvmtiExport::has_redefined_a_class()) {
+      // RedefineClasses() requires a brute force approach
+      AdjustSharedObjectClosure blk;
+      rw_space()->object_iterate(&blk);
+    } else {
+      RecursiveAdjustSharedObjectClosure blk;
+      Universe::oops_do(&blk);
+      StringTable::oops_do(&blk);
+      SystemDictionary::always_strong_classes_do(&blk);
+      TraversePlaceholdersClosure tpc;
+      SystemDictionary::placeholders_do(&tpc);
+    }
   }
 }
 
--- a/src/share/vm/memory/genRemSet.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/genRemSet.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -91,8 +91,15 @@
   virtual void verify() = 0;
 
   // Verify that the remembered set has no entries for
-  // the heap interval denoted by mr.
-  virtual void verify_empty(MemRegion mr) = 0;
+  // the heap interval denoted by mr.  If there are any
+  // alignment constraints on the remembered set, only the
+  // part of the region that is aligned is checked.
+  //
+  //   alignment boundaries
+  //   +--------+-------+--------+-------+
+  //         [ region mr              )
+  //            [ part checked   )
+  virtual void verify_aligned_region_empty(MemRegion mr) = 0;
 
   // If appropriate, print some information about the remset on "tty".
   virtual void print() {}
--- a/src/share/vm/memory/heapInspection.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/heapInspection.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -65,7 +65,7 @@
       name = "<no name>";
   }
   // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit
-  st->print_cr("%13" FORMAT64_MODIFIER "d  %13" FORMAT64_MODIFIER "u  %s",
+  st->print_cr(INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13) "  %s",
                (jlong)  _instance_count,
                (julong) _instance_words * HeapWordSize,
                name);
@@ -80,7 +80,10 @@
     elt = elt->next();
   }
   elt = new KlassInfoEntry(k, list());
-  set_list(elt);
+  // We may be out of space to allocate the new entry.
+  if (elt != NULL) {
+    set_list(elt);
+  }
   return elt;
 }
 
@@ -103,21 +106,25 @@
 }
 
 KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) {
-  _size = size;
+  _size = 0;
   _ref = ref;
-  _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, _size);
-
-  for (int index = 0; index < _size; index++) {
-    _buckets[index].initialize();
+  _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size);
+  if (_buckets != NULL) {
+    _size = size;
+    for (int index = 0; index < _size; index++) {
+      _buckets[index].initialize();
+    }
   }
 }
 
 KlassInfoTable::~KlassInfoTable() {
-  for (int index = 0; index < _size; index++) {
-    _buckets[index].empty();
+  if (_buckets != NULL) {
+    for (int index = 0; index < _size; index++) {
+      _buckets[index].empty();
+    }
+    FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
+    _size = 0;
   }
-  FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
-  _size = 0;
 }
 
 uint KlassInfoTable::hash(klassOop p) {
@@ -127,19 +134,32 @@
 
 KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) {
   uint         idx = hash(k) % _size;
+  assert(_buckets != NULL, "Allocation failure should have been caught");
   KlassInfoEntry*  e   = _buckets[idx].lookup(k);
-  assert(k == e->klass(), "must be equal");
+  // Lookup may fail if this is a new klass for which we
+  // could not allocate space for an new entry.
+  assert(e == NULL || k == e->klass(), "must be equal");
   return e;
 }
 
-void KlassInfoTable::record_instance(const oop obj) {
+// Return false if the entry could not be recorded on account
+// of running out of space required to create a new entry.
+bool KlassInfoTable::record_instance(const oop obj) {
   klassOop      k = obj->klass();
   KlassInfoEntry* elt = lookup(k);
-  elt->set_count(elt->count() + 1);
-  elt->set_words(elt->words() + obj->size());
+  // elt may be NULL if it's a new klass for which we
+  // could not allocate space for a new entry in the hashtable.
+  if (elt != NULL) {
+    elt->set_count(elt->count() + 1);
+    elt->set_words(elt->words() + obj->size());
+    return true;
+  } else {
+    return false;
+  }
 }
 
 void KlassInfoTable::iterate(KlassInfoClosure* cic) {
+  assert(_size == 0 || _buckets != NULL, "Allocation failure should have been caught");
   for (int index = 0; index < _size; index++) {
     _buckets[index].iterate(cic);
   }
@@ -176,7 +196,7 @@
     total += elements()->at(i)->count();
     totalw += elements()->at(i)->words();
   }
-  st->print_cr("Total %13" FORMAT64_MODIFIER "d  %13" FORMAT64_MODIFIER "u",
+  st->print_cr("Total " INT64_FORMAT_W(13) "  " UINT64_FORMAT_W(13),
                total, totalw * HeapWordSize);
 }
 
@@ -199,12 +219,18 @@
 class RecordInstanceClosure : public ObjectClosure {
  private:
   KlassInfoTable* _cit;
+  size_t _missed_count;
  public:
-  RecordInstanceClosure(KlassInfoTable* cit) : _cit(cit) {}
+  RecordInstanceClosure(KlassInfoTable* cit) :
+    _cit(cit), _missed_count(0) {}
 
   void do_object(oop obj) {
-    _cit->record_instance(obj);
+    if (!_cit->record_instance(obj)) {
+      _missed_count++;
+    }
   }
+
+  size_t missed_count() { return _missed_count; }
 };
 
 void HeapInspection::heap_inspection(outputStream* st) {
@@ -230,21 +256,32 @@
       ShouldNotReachHere(); // Unexpected heap kind for this op
   }
   // Collect klass instance info
-
-  // Iterate over objects in the heap
   KlassInfoTable cit(KlassInfoTable::cit_size, ref);
-  RecordInstanceClosure ric(&cit);
-  Universe::heap()->object_iterate(&ric);
+  if (!cit.allocation_failed()) {
+    // Iterate over objects in the heap
+    RecordInstanceClosure ric(&cit);
+    Universe::heap()->object_iterate(&ric);
 
-  // Sort and print klass instance info
-  KlassInfoHisto histo("\n"
-                   " num     #instances         #bytes  class name\n"
-                   "----------------------------------------------",
-                   KlassInfoHisto::histo_initial_size);
-  HistoClosure hc(&histo);
-  cit.iterate(&hc);
-  histo.sort();
-  histo.print_on(st);
+    // Report if certain classes are not counted because of
+    // running out of C-heap for the histogram.
+    size_t missed_count = ric.missed_count();
+    if (missed_count != 0) {
+      st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT
+                   " total instances in data below",
+                   missed_count);
+    }
+    // Sort and print klass instance info
+    KlassInfoHisto histo("\n"
+                     " num     #instances         #bytes  class name\n"
+                     "----------------------------------------------",
+                     KlassInfoHisto::histo_initial_size);
+    HistoClosure hc(&histo);
+    cit.iterate(&hc);
+    histo.sort();
+    histo.print_on(st);
+  } else {
+    st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
+  }
   st->flush();
 
   if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) {
--- a/src/share/vm/memory/heapInspection.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/heapInspection.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -98,8 +98,9 @@
   };
   KlassInfoTable(int size, HeapWord* ref);
   ~KlassInfoTable();
-  void record_instance(const oop obj);
+  bool record_instance(const oop obj);
   void iterate(KlassInfoClosure* cic);
+  bool allocation_failed() { return _buckets == NULL; }
 };
 
 class KlassInfoHisto : public StackObj {
--- a/src/share/vm/memory/referenceProcessor.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/referenceProcessor.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -85,7 +85,7 @@
   ReferenceProcessor* rp =
     new ReferenceProcessor(span, atomic_discovery,
                            mt_discovery, mt_degree,
-                           mt_processing);
+                           mt_processing && (parallel_gc_threads > 0));
   if (rp == NULL) {
     vm_exit_during_initialization("Could not allocate ReferenceProcessor object");
   }
--- a/src/share/vm/memory/tenuredGeneration.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/memory/tenuredGeneration.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -409,10 +409,11 @@
 void TenuredGeneration::verify_alloc_buffers_clean() {
   if (UseParNewGC) {
     for (uint i = 0; i < ParallelGCThreads; i++) {
-      _rs->verify_empty(_alloc_buffers[i]->range());
+      _rs->verify_aligned_region_empty(_alloc_buffers[i]->range());
     }
   }
 }
+
 #else  // SERIALGC
 void TenuredGeneration::retire_alloc_buffers_before_full_gc() {}
 void TenuredGeneration::verify_alloc_buffers_clean() {}
--- a/src/share/vm/oops/arrayOop.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/arrayOop.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -58,11 +58,11 @@
   // alignments.  It gets the scale from the type2aelembytes array.
   static int32_t max_array_length(BasicType type) {
     assert(type >= 0 && type < T_CONFLICT, "wrong type");
-    assert(type2aelembytes[type] != 0, "wrong type");
+    assert(type2aelembytes(type) != 0, "wrong type");
     // We use max_jint, since object_size is internally represented by an 'int'
     // This gives us an upper bound of max_jint words for the size of the oop.
     int32_t max_words = (max_jint - header_size(type) - 2);
-    int elembytes = (type == T_OBJECT) ? T_OBJECT_aelem_bytes : type2aelembytes[type];
+    int elembytes = (type == T_OBJECT) ? T_OBJECT_aelem_bytes : type2aelembytes(type);
     jlong len = ((jlong)max_words * HeapWordSize) / elembytes;
     return (len > max_jint) ? max_jint : (int32_t)len;
   }
--- a/src/share/vm/oops/instanceKlass.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/instanceKlass.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -791,17 +791,39 @@
 }
 
 
+static int compare_fields_by_offset(int* a, int* b) {
+  return a[0] - b[0];
+}
+
 void instanceKlass::do_nonstatic_fields(FieldClosure* cl) {
-  fieldDescriptor fd;
   instanceKlass* super = superklass();
   if (super != NULL) {
     super->do_nonstatic_fields(cl);
   }
+  fieldDescriptor fd;
   int length = fields()->length();
+  // In DebugInfo nonstatic fields are sorted by offset.
+  int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1));
+  int j = 0;
   for (int i = 0; i < length; i += next_offset) {
     fd.initialize(as_klassOop(), i);
-    if (!(fd.is_static())) cl->do_field(&fd);
+    if (!fd.is_static()) {
+      fields_sorted[j + 0] = fd.offset();
+      fields_sorted[j + 1] = i;
+      j += 2;
+    }
   }
+  if (j > 0) {
+    length = j;
+    // _sort_Fn is defined in growableArray.hpp.
+    qsort(fields_sorted, length/2, 2*sizeof(int), (_sort_Fn)compare_fields_by_offset);
+    for (int i = 0; i < length; i += 2) {
+      fd.initialize(as_klassOop(), fields_sorted[i + 1]);
+      assert(!fd.is_static() && fd.offset() == fields_sorted[i], "only nonstatic fields");
+      cl->do_field(&fd);
+    }
+  }
+  FREE_C_HEAP_ARRAY(int, fields_sorted);
 }
 
 
@@ -950,7 +972,6 @@
     // These allocations will have to be freed if they are unused.
 
     // Allocate a new array of methods.
-    jmethodID* to_dealloc_jmeths = NULL;
     jmethodID* new_jmeths = NULL;
     if (length <= idnum) {
       // A new array will be needed (unless some other thread beats us to it)
@@ -961,7 +982,6 @@
     }
 
     // Allocate a new method ID.
-    jmethodID to_dealloc_id = NULL;
     jmethodID new_id = NULL;
     if (method_h->is_old() && !method_h->is_obsolete()) {
       // The method passed in is old (but not obsolete), we need to use the current version
@@ -975,40 +995,51 @@
       new_id = JNIHandles::make_jmethod_id(method_h);
     }
 
-    {
+    if (Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint()) {
+      // No need and unsafe to lock the JmethodIdCreation_lock at safepoint.
+      id = get_jmethod_id(ik_h, idnum, new_id, new_jmeths);
+    } else {
       MutexLocker ml(JmethodIdCreation_lock);
+      id = get_jmethod_id(ik_h, idnum, new_id, new_jmeths);
+    }
+  }
+  return id;
+}
 
-      // We must not go to a safepoint while holding this lock.
-      debug_only(No_Safepoint_Verifier nosafepoints;)
+
+jmethodID instanceKlass::get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
+                                        jmethodID new_id, jmethodID* new_jmeths) {
+  // Retry lookup after we got the lock or ensured we are at safepoint
+  jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire();
+  jmethodID  id                = NULL;
+  jmethodID  to_dealloc_id     = NULL;
+  jmethodID* to_dealloc_jmeths = NULL;
+  size_t     length;
 
-      // Retry lookup after we got the lock
-      jmeths = ik_h->methods_jmethod_ids_acquire();
-      if (jmeths == NULL || (length = (size_t)jmeths[0]) <= idnum) {
-        if (jmeths != NULL) {
-          // We have grown the array: copy the existing entries, and delete the old array
-          for (size_t index = 0; index < length; index++) {
-            new_jmeths[index+1] = jmeths[index+1];
-          }
-          to_dealloc_jmeths = jmeths; // using the new jmeths, deallocate the old one
-        }
-        ik_h->release_set_methods_jmethod_ids(jmeths = new_jmeths);
-      } else {
-        id = jmeths[idnum+1];
-        to_dealloc_jmeths = new_jmeths; // using the old jmeths, deallocate the new one
+  if (jmeths == NULL || (length = (size_t)jmeths[0]) <= idnum) {
+    if (jmeths != NULL) {
+      // We have grown the array: copy the existing entries, and delete the old array
+      for (size_t index = 0; index < length; index++) {
+        new_jmeths[index+1] = jmeths[index+1];
       }
-      if (id == NULL) {
-        id = new_id;
-        jmeths[idnum+1] = id;  // install the new method ID
-      } else {
-        to_dealloc_id = new_id; // the new id wasn't used, mark it for deallocation
-      }
+      to_dealloc_jmeths = jmeths; // using the new jmeths, deallocate the old one
     }
+    ik_h->release_set_methods_jmethod_ids(jmeths = new_jmeths);
+  } else {
+    id = jmeths[idnum+1];
+    to_dealloc_jmeths = new_jmeths; // using the old jmeths, deallocate the new one
+  }
+  if (id == NULL) {
+    id = new_id;
+    jmeths[idnum+1] = id;  // install the new method ID
+  } else {
+    to_dealloc_id = new_id; // the new id wasn't used, mark it for deallocation
+  }
 
-    // Free up unneeded or no longer needed resources
-    FreeHeap(to_dealloc_jmeths);
-    if (to_dealloc_id != NULL) {
-      JNIHandles::destroy_jmethod_id(to_dealloc_id);
-    }
+  // Free up unneeded or no longer needed resources
+  FreeHeap(to_dealloc_jmeths);
+  if (to_dealloc_id != NULL) {
+    JNIHandles::destroy_jmethod_id(to_dealloc_id);
   }
   return id;
 }
@@ -2165,12 +2196,20 @@
   RC_TRACE(0x00000100, ("adding previous version ref for %s @%d, EMCP_cnt=%d",
     ikh->external_name(), _previous_versions->length(), emcp_method_count));
   constantPoolHandle cp_h(ikh->constants());
-  jweak cp_ref = JNIHandles::make_weak_global(cp_h);
+  jobject cp_ref;
+  if (cp_h->is_shared()) {
+    // a shared ConstantPool requires a regular reference; a weak
+    // reference would be collectible
+    cp_ref = JNIHandles::make_global(cp_h);
+  } else {
+    cp_ref = JNIHandles::make_weak_global(cp_h);
+  }
   PreviousVersionNode * pv_node = NULL;
   objArrayOop old_methods = ikh->methods();
 
   if (emcp_method_count == 0) {
-    pv_node = new PreviousVersionNode(cp_ref, NULL);
+    // non-shared ConstantPool gets a weak reference
+    pv_node = new PreviousVersionNode(cp_ref, !cp_h->is_shared(), NULL);
     RC_TRACE(0x00000400,
       ("add: all methods are obsolete; flushing any EMCP weak refs"));
   } else {
@@ -2190,7 +2229,8 @@
         }
       }
     }
-    pv_node = new PreviousVersionNode(cp_ref, method_refs);
+    // non-shared ConstantPool gets a weak reference
+    pv_node = new PreviousVersionNode(cp_ref, !cp_h->is_shared(), method_refs);
   }
 
   _previous_versions->append(pv_node);
@@ -2208,7 +2248,7 @@
     // check the previous versions array for a GC'ed weak refs
     pv_node = _previous_versions->at(i);
     cp_ref = pv_node->prev_constant_pool();
-    assert(cp_ref != NULL, "weak cp ref was unexpectedly cleared");
+    assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
     if (cp_ref == NULL) {
       delete pv_node;
       _previous_versions->remove_at(i);
@@ -2281,7 +2321,7 @@
           // check the previous versions array for a GC'ed weak refs
           pv_node = _previous_versions->at(j);
           cp_ref = pv_node->prev_constant_pool();
-          assert(cp_ref != NULL, "weak cp ref was unexpectedly cleared");
+          assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
           if (cp_ref == NULL) {
             delete pv_node;
             _previous_versions->remove_at(j);
@@ -2379,8 +2419,8 @@
     // been GC'ed
     PreviousVersionNode * pv_node = _previous_versions->at(i);
 
-    jweak cp_ref = pv_node->prev_constant_pool();
-    assert(cp_ref != NULL, "weak reference was unexpectedly cleared");
+    jobject cp_ref = pv_node->prev_constant_pool();
+    assert(cp_ref != NULL, "cp reference was unexpectedly cleared");
     if (cp_ref == NULL) {
       continue;  // robustness
     }
@@ -2440,10 +2480,11 @@
 
 // Construct a PreviousVersionNode entry for the array hung off
 // the instanceKlass.
-PreviousVersionNode::PreviousVersionNode(jweak prev_constant_pool,
-  GrowableArray<jweak>* prev_EMCP_methods) {
+PreviousVersionNode::PreviousVersionNode(jobject prev_constant_pool,
+  bool prev_cp_is_weak, GrowableArray<jweak>* prev_EMCP_methods) {
 
   _prev_constant_pool = prev_constant_pool;
+  _prev_cp_is_weak = prev_cp_is_weak;
   _prev_EMCP_methods = prev_EMCP_methods;
 }
 
@@ -2451,7 +2492,11 @@
 // Destroy a PreviousVersionNode
 PreviousVersionNode::~PreviousVersionNode() {
   if (_prev_constant_pool != NULL) {
-    JNIHandles::destroy_weak_global(_prev_constant_pool);
+    if (_prev_cp_is_weak) {
+      JNIHandles::destroy_weak_global(_prev_constant_pool);
+    } else {
+      JNIHandles::destroy_global(_prev_constant_pool);
+    }
   }
 
   if (_prev_EMCP_methods != NULL) {
@@ -2471,8 +2516,8 @@
   _prev_constant_pool_handle = constantPoolHandle();  // NULL handle
   _prev_EMCP_method_handles = NULL;
 
-  jweak cp_ref = pv_node->prev_constant_pool();
-  assert(cp_ref != NULL, "weak constant pool ref was unexpectedly cleared");
+  jobject cp_ref = pv_node->prev_constant_pool();
+  assert(cp_ref != NULL, "constant pool ref was unexpectedly cleared");
   if (cp_ref == NULL) {
     return;  // robustness
   }
--- a/src/share/vm/oops/instanceKlass.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/instanceKlass.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -432,6 +432,8 @@
                                                         _enclosing_method_method_index = method_index; }
 
   // jmethodID support
+  static jmethodID get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
+                                  jmethodID new_id, jmethodID* new_jmeths);
   static jmethodID jmethod_id_for_impl(instanceKlassHandle ik_h, methodHandle method_h);
   jmethodID jmethod_id_or_null(methodOop method);
 
@@ -838,11 +840,20 @@
 // A collection point for interesting information about the previous
 // version(s) of an instanceKlass. This class uses weak references to
 // the information so that the information may be collected as needed
-// by the system. A GrowableArray of PreviousVersionNodes is attached
+// by the system. If the information is shared, then a regular
+// reference must be used because a weak reference would be seen as
+// collectible. A GrowableArray of PreviousVersionNodes is attached
 // to the instanceKlass as needed. See PreviousVersionWalker below.
 class PreviousVersionNode : public CHeapObj {
  private:
-  jweak _prev_constant_pool;
+  // A shared ConstantPool is never collected so we'll always have
+  // a reference to it so we can update items in the cache. We'll
+  // have a weak reference to a non-shared ConstantPool until all
+  // of the methods (EMCP or obsolete) have been collected; the
+  // non-shared ConstantPool becomes collectible at that point.
+  jobject _prev_constant_pool;  // regular or weak reference
+  bool    _prev_cp_is_weak;     // true if not a shared ConstantPool
+
   // If the previous version of the instanceKlass doesn't have any
   // EMCP methods, then _prev_EMCP_methods will be NULL. If all the
   // EMCP methods have been collected, then _prev_EMCP_methods can
@@ -850,10 +861,10 @@
   GrowableArray<jweak>* _prev_EMCP_methods;
 
 public:
-  PreviousVersionNode(jweak prev_constant_pool,
+  PreviousVersionNode(jobject prev_constant_pool, bool prev_cp_is_weak,
     GrowableArray<jweak>* prev_EMCP_methods);
   ~PreviousVersionNode();
-  jweak prev_constant_pool() const {
+  jobject prev_constant_pool() const {
     return _prev_constant_pool;
   }
   GrowableArray<jweak>* prev_EMCP_methods() const {
--- a/src/share/vm/oops/klass.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/klass.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -182,7 +182,7 @@
   assert(etype >= T_BOOLEAN && etype <= T_OBJECT, "valid etype");
   // Note that T_ARRAY is not allowed here.
   int  hsize = arrayOopDesc::base_offset_in_bytes(etype);
-  int  esize = type2aelembytes[etype];
+  int  esize = type2aelembytes(etype);
   bool isobj = (etype == T_OBJECT);
   int  tag   =  isobj ? _lh_array_tag_obj_value : _lh_array_tag_type_value;
   int lh = array_layout_helper(tag, hsize, etype, exact_log2(esize));
--- a/src/share/vm/oops/klassVtable.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/klassVtable.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -735,7 +735,7 @@
     }
   }
 
-  // This lenght of the itable was either zero, or it has not yet been initialized.
+  // The length of the itable was either zero, or it has not yet been initialized.
   _table_offset      = 0;
   _size_offset_table = 0;
   _size_method_table = 0;
@@ -870,16 +870,19 @@
 
 // Initialization
 void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
-  // Cannot be setup doing bootstrapping
-  if (Universe::is_bootstrapping()) return;
+  // Cannot be setup doing bootstrapping, interfaces don't have
+  // itables, and klass with only ones entry have empty itables
+  if (Universe::is_bootstrapping() ||
+      _klass->is_interface() ||
+      _klass->itable_length() == itableOffsetEntry::size()) return;
 
-  int num_interfaces = nof_interfaces();
+  // There's alway an extra itable entry so we can null-terminate it.
+  guarantee(size_offset_table() >= 1, "too small");
+  int num_interfaces = size_offset_table() - 1;
   if (num_interfaces > 0) {
-    if (TraceItables) tty->print_cr("%3d: Initializing itables for %s", ++initialize_count, _klass->name()->as_C_string());
+    if (TraceItables) tty->print_cr("%3d: Initializing itables for %s", ++initialize_count,
+                                    _klass->name()->as_C_string());
 
-    // In debug mode, we got an extra NULL/NULL entry
-    debug_only(num_interfaces--);
-    assert(num_interfaces > 0, "to few interfaces in offset itable");
 
     // Interate through all interfaces
     int i;
@@ -890,12 +893,10 @@
       initialize_itable_for_interface(ioe->offset(), interf_h, checkconstraints, CHECK);
     }
 
-#ifdef ASSERT
-    // Check that the last entry is empty
-    itableOffsetEntry* ioe = offset_entry(i);
-    assert(ioe->interface_klass() == NULL && ioe->offset() == 0, "terminator entry missing");
-#endif
   }
+  // Check that the last entry is empty
+  itableOffsetEntry* ioe = offset_entry(size_offset_table() - 1);
+  guarantee(ioe->interface_klass() == NULL && ioe->offset() == 0, "terminator entry missing");
 }
 
 
@@ -972,7 +973,7 @@
   }
 }
 
-// Update entry for specic methodOop
+// Update entry for specific methodOop
 void klassItable::initialize_with_method(methodOop m) {
   itableMethodEntry* ime = method_entry(0);
   for(int i = 0; i < _size_method_table; i++) {
@@ -1085,12 +1086,8 @@
   CountInterfacesClosure cic;
   visit_all_interfaces(transitive_interfaces(), &cic);
 
-  // Add one extra entry in debug mode, so we can null-terminate the table
-  int nof_methods    = cic.nof_methods();
-  int nof_interfaces = cic.nof_interfaces();
-  debug_only(if (nof_interfaces > 0) nof_interfaces++);
-
-  int itable_size = calc_itable_size(nof_interfaces, nof_methods);
+  // There's alway an extra itable entry so we can null-terminate it.
+  int itable_size = calc_itable_size(cic.nof_interfaces() + 1, cic.nof_methods());
 
   // Statistics
   update_stats(itable_size * HeapWordSize);
@@ -1110,8 +1107,8 @@
   int nof_methods    = cic.nof_methods();
   int nof_interfaces = cic.nof_interfaces();
 
-  // Add one extra entry in debug mode, so we can null-terminate the table
-  debug_only(if (nof_interfaces > 0) nof_interfaces++);
+  // Add one extra entry so we can null-terminate the table
+  nof_interfaces++;
 
   assert(compute_itable_size(objArrayHandle(klass->transitive_interfaces())) ==
          calc_itable_size(nof_interfaces, nof_methods),
--- a/src/share/vm/oops/klassVtable.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/klassVtable.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -259,7 +259,7 @@
   itableMethodEntry* method_entry(int i) { assert(0 <= i && i <= _size_method_table, "index out of bounds");
                                            return &((itableMethodEntry*)method_start())[i]; }
 
-  int nof_interfaces()                   { return _size_offset_table; }
+  int size_offset_table()                { return _size_offset_table; }
 
   // Initialization
   void initialize_itable(bool checkconstraints, TRAPS);
--- a/src/share/vm/oops/markOop.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/markOop.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -37,3 +37,32 @@
     st->print("age %d)", age());
   }
 }
+
+
+// Give advice about whether the oop that contains this markOop
+// should be cached or not.
+bool markOopDesc::should_not_be_cached() const {
+  // the cast is because decode_pointer() isn't marked const
+  if (is_marked() && ((markOopDesc *)this)->decode_pointer() != NULL) {
+    // If the oop containing this markOop is being forwarded, then
+    // we are in the middle of GC and we do not want the containing
+    // oop to be added to a cache. We have no way of knowing whether
+    // the cache has already been visited by the current GC phase so
+    // we don't know whether the forwarded oop will be properly
+    // processed in this phase. If the forwarded oop is not properly
+    // processed, then we'll see strange crashes or asserts during
+    // the next GC run because the markOop will contain an unexpected
+    // value.
+    //
+    // This situation has been seen when we are GC'ing a methodOop
+    // because we use the methodOop while we're GC'ing it. Scary
+    // stuff. Some of the uses the methodOop cause the methodOop to
+    // be added to the OopMapCache in the instanceKlass as a side
+    // effect. This check lets the cache maintainer know when a
+    // cache addition would not be safe.
+    return true;
+  }
+
+  // caching the containing oop should be just fine
+  return false;
+}
--- a/src/share/vm/oops/markOop.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/markOop.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -357,4 +357,7 @@
 
   // Recover address of oop from encoded form used in mark
   inline void* decode_pointer() { if (UseBiasedLocking && has_bias_pattern()) return NULL; return clear_lock_bits(); }
+
+  // see the definition in markOop.cpp for the gory details
+  bool should_not_be_cached() const;
 };
--- a/src/share/vm/oops/methodDataOop.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/methodDataOop.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -32,7 +32,7 @@
 
 // Some types of data layouts need a length field.
 bool DataLayout::needs_array_len(u1 tag) {
-  return (tag == multi_branch_data_tag);
+  return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag);
 }
 
 // Perform generic initialization of the data.  More specific
@@ -404,6 +404,17 @@
 }
 #endif
 
+#ifndef PRODUCT
+void ArgInfoData::print_data_on(outputStream* st) {
+  print_shared(st, "ArgInfoData");
+  int nargs = number_of_args();
+  for (int i = 0; i < nargs; i++) {
+    st->print("  0x%x", arg_modified(i));
+  }
+  st->cr();
+}
+
+#endif
 // ==================================================================
 // methodDataOop
 //
@@ -508,6 +519,9 @@
   int extra_data_count = compute_extra_data_count(data_size, empty_bc_count);
   object_size += extra_data_count * DataLayout::compute_size_in_bytes(0);
 
+  // Add a cell to record information about modified arguments.
+  int arg_size = method->size_of_parameters();
+  object_size += DataLayout::compute_size_in_bytes(arg_size+1);
   return object_size;
 }
 
@@ -626,6 +640,8 @@
     return new BranchData(data_layout);
   case DataLayout::multi_branch_data_tag:
     return new MultiBranchData(data_layout);
+  case DataLayout::arg_info_data_tag:
+    return new ArgInfoData(data_layout);
   };
 }
 
@@ -681,7 +697,17 @@
 
   // Add some extra DataLayout cells (at least one) to track stray traps.
   int extra_data_count = compute_extra_data_count(data_size, empty_bc_count);
-  object_size += extra_data_count * DataLayout::compute_size_in_bytes(0);
+  int extra_size = extra_data_count * DataLayout::compute_size_in_bytes(0);
+
+  // Add a cell to record information about modified arguments.
+  // Set up _args_modified array after traps cells so that
+  // the code for traps cells works.
+  DataLayout *dp = data_layout_at(data_size + extra_size);
+
+  int arg_size = method->size_of_parameters();
+  dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
+
+  object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1);
 
   // Set an initial hint. Don't use set_hint_di() because
   // first_di() may be out of bounds if data_size is 0.
@@ -764,6 +790,10 @@
     // No need for "OrderAccess::load_acquire" ops,
     // since the data structure is monotonic.
     if (dp->tag() == DataLayout::no_tag)  break;
+    if (dp->tag() == DataLayout::arg_info_data_tag) {
+      dp = end; // ArgInfoData is at the end of extra data section.
+      break;
+    }
     if (dp->bci() == bci) {
       assert(dp->tag() == DataLayout::bit_data_tag, "sane");
       return new BitData(dp);
@@ -785,6 +815,16 @@
   return NULL;
 }
 
+ArgInfoData *methodDataOopDesc::arg_info() {
+  DataLayout* dp    = extra_data_base();
+  DataLayout* end   = extra_data_limit();
+  for (; dp < end; dp = next_extra(dp)) {
+    if (dp->tag() == DataLayout::arg_info_data_tag)
+      return new ArgInfoData(dp);
+  }
+  return NULL;
+}
+
 #ifndef PRODUCT
 void methodDataOopDesc::print_data_on(outputStream* st) {
   ResourceMark rm;
@@ -794,15 +834,20 @@
     st->fill_to(6);
     data->print_data_on(st);
   }
+  st->print_cr("--- Extra data:");
   DataLayout* dp    = extra_data_base();
   DataLayout* end   = extra_data_limit();
   for (; dp < end; dp = next_extra(dp)) {
     // No need for "OrderAccess::load_acquire" ops,
     // since the data structure is monotonic.
-    if (dp->tag() == DataLayout::no_tag)  break;
-    if (dp == extra_data_base())
-      st->print_cr("--- Extra data:");
-    data = new BitData(dp);
+    if (dp->tag() == DataLayout::no_tag)  continue;
+    if (dp->tag() == DataLayout::bit_data_tag) {
+      data = new BitData(dp);
+    } else {
+      assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo");
+      data = new ArgInfoData(dp);
+      dp = end; // ArgInfoData is at the end of extra data section.
+    }
     st->print("%d", dp_to_di(data->dp()));
     st->fill_to(6);
     data->print_data_on(st);
--- a/src/share/vm/oops/methodDataOop.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/methodDataOop.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -101,7 +101,8 @@
     virtual_call_data_tag,
     ret_data_tag,
     branch_data_tag,
-    multi_branch_data_tag
+    multi_branch_data_tag,
+    arg_info_data_tag
   };
 
   enum {
@@ -245,6 +246,7 @@
 class     BranchData;
 class   ArrayData;
 class     MultiBranchData;
+class     ArgInfoData;
 
 
 // ProfileData
@@ -376,6 +378,8 @@
   virtual bool is_BranchData()      { return false; }
   virtual bool is_ArrayData()       { return false; }
   virtual bool is_MultiBranchData() { return false; }
+  virtual bool is_ArgInfoData()     { return false; }
+
 
   BitData* as_BitData() {
     assert(is_BitData(), "wrong type");
@@ -413,6 +417,10 @@
     assert(is_MultiBranchData(), "wrong type");
     return is_MultiBranchData() ? (MultiBranchData*)this : NULL;
   }
+  ArgInfoData* as_ArgInfoData() {
+    assert(is_ArgInfoData(), "wrong type");
+    return is_ArgInfoData() ? (ArgInfoData*)this : NULL;
+  }
 
 
   // Subclass specific initialization
@@ -1047,6 +1055,33 @@
 #endif
 };
 
+class ArgInfoData : public ArrayData {
+
+public:
+  ArgInfoData(DataLayout* layout) : ArrayData(layout) {
+    assert(layout->tag() == DataLayout::arg_info_data_tag, "wrong type");
+  }
+
+  virtual bool is_ArgInfoData() { return true; }
+
+
+  int number_of_args() {
+    return array_len();
+  }
+
+  uint arg_modified(int arg) {
+    return array_uint_at(arg);
+  }
+
+  void set_arg_modified(int arg, uint val) {
+    array_set_int_at(arg, val);
+  }
+
+#ifndef PRODUCT
+  void print_data_on(outputStream* st);
+#endif
+};
+
 // methodDataOop
 //
 // A methodDataOop holds information which has been collected about
@@ -1183,6 +1218,9 @@
   // Find or create an extra ProfileData:
   ProfileData* bci_to_extra_data(int bci, bool create_if_missing);
 
+  // return the argument info cell
+  ArgInfoData *arg_info();
+
 public:
   static int header_size() {
     return sizeof(methodDataOopDesc)/wordSize;
@@ -1222,11 +1260,18 @@
   intx arg_local()                               { return _arg_local; }
   intx arg_stack()                               { return _arg_stack; }
   intx arg_returned()                            { return _arg_returned; }
+  uint arg_modified(int a)                       { ArgInfoData *aid = arg_info();
+                                                   assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
+                                                   return aid->arg_modified(a); }
 
   void set_eflags(intx v)                        { _eflags = v; }
   void set_arg_local(intx v)                     { _arg_local = v; }
   void set_arg_stack(intx v)                     { _arg_stack = v; }
   void set_arg_returned(intx v)                  { _arg_returned = v; }
+  void set_arg_modified(int a, uint v)           { ArgInfoData *aid = arg_info();
+                                                   assert(a >= 0 && a < aid->number_of_args(), "valid argument number");
+
+                                                   aid->set_arg_modified(a, v); }
 
   void clear_escape_info()                       { _eflags = _arg_local = _arg_stack = _arg_returned = 0; }
 
--- a/src/share/vm/oops/methodOop.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/methodOop.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -765,6 +765,28 @@
 }
 
 
+// give advice about whether this methodOop should be cached or not
+bool methodOopDesc::should_not_be_cached() const {
+  if (is_old()) {
+    // This method has been redefined. It is either EMCP or obsolete
+    // and we don't want to cache it because that would pin the method
+    // down and prevent it from being collectible if and when it
+    // finishes executing.
+    return true;
+  }
+
+  if (mark()->should_not_be_cached()) {
+    // It is either not safe or not a good idea to cache this
+    // method at this time because of the state of the embedded
+    // markOop. See markOop.cpp for the gory details.
+    return true;
+  }
+
+  // caching this method should be just fine
+  return false;
+}
+
+
 methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
                                                 u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) {
   // Code below does not work for native methods - they should never get rewritten anyway
--- a/src/share/vm/oops/methodOop.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/oops/methodOop.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -524,6 +524,8 @@
   void set_is_old()                                 { _access_flags.set_is_old(); }
   bool is_obsolete() const                          { return access_flags().is_obsolete(); }
   void set_is_obsolete()                            { _access_flags.set_is_obsolete(); }
+  // see the definition in methodOop.cpp for the gory details
+  bool should_not_be_cached() const;
 
   // JVMTI Native method prefixing support:
   bool is_prefixed_native() const                   { return access_flags().is_prefixed_native(); }
--- a/src/share/vm/opto/addnode.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/addnode.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -505,15 +505,25 @@
       const Type *temp_t2 = phase->type( in(Offset) );
       if( temp_t2 == Type::TOP ) return NULL;
       const TypeX *t2 = temp_t2->is_intptr_t();
+      Node* address;
+      Node* offset;
       if( t2->is_con() ) {
         // The Add of the flattened expression
-        set_req(Address, addp->in(Address));
-        set_req(Offset , phase->MakeConX(t2->get_con() + t12->get_con()));
-        return this;                    // Made progress
+        address = addp->in(Address);
+        offset  = phase->MakeConX(t2->get_con() + t12->get_con());
+      } else {
+        // Else move the constant to the right.  ((A+con)+B) into ((A+B)+con)
+        address = phase->transform(new (phase->C, 4) AddPNode(in(Base),addp->in(Address),in(Offset)));
+        offset  = addp->in(Offset);
       }
-      // Else move the constant to the right.  ((A+con)+B) into ((A+B)+con)
-      set_req(Address, phase->transform(new (phase->C, 4) AddPNode(in(Base),addp->in(Address),in(Offset))));
-      set_req(Offset , addp->in(Offset));
+      PhaseIterGVN *igvn = phase->is_IterGVN();
+      if( igvn ) {
+        set_req_X(Address,address,igvn);
+        set_req_X(Offset,offset,igvn);
+      } else {
+        set_req(Address,address);
+        set_req(Offset,offset);
+      }
       return this;
     }
   }
@@ -608,6 +618,28 @@
   return NULL;
 }
 
+//------------------------------unpack_offsets----------------------------------
+// Collect the AddP offset values into the elements array, giving up
+// if there are more than length.
+int AddPNode::unpack_offsets(Node* elements[], int length) {
+  int count = 0;
+  Node* addr = this;
+  Node* base = addr->in(AddPNode::Base);
+  while (addr->is_AddP()) {
+    if (addr->in(AddPNode::Base) != base) {
+      // give up
+      return -1;
+    }
+    elements[count++] = addr->in(AddPNode::Offset);
+    if (count == length) {
+      // give up
+      return -1;
+    }
+    addr = addr->in(AddPNode::Address);
+  }
+  return count;
+}
+
 //------------------------------match_edge-------------------------------------
 // Do we Match on this edge index or not?  Do not match base pointer edge
 uint AddPNode::match_edge(uint idx) const {
--- a/src/share/vm/opto/addnode.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/addnode.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -144,6 +144,11 @@
   static Node* Ideal_base_and_offset(Node* ptr, PhaseTransform* phase,
                                      // second return value:
                                      intptr_t& offset);
+
+  // Collect the AddP offset values into the elements array, giving up
+  // if there are more than length.
+  int unpack_offsets(Node* elements[], int length);
+
   // Do not match base-ptr edge
   virtual uint match_edge(uint idx) const;
   static const Type *mach_bottom_type(const MachNode* n);  // used by ad_<arch>.hpp
--- a/src/share/vm/opto/bytecodeInfo.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/bytecodeInfo.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -79,8 +79,20 @@
   for (int i = depth; i != 0; --i) tty->print("  ");
 }
 
+static bool is_init_with_ea(ciMethod* callee_method,
+                            ciMethod* caller_method, Compile* C) {
+  // True when EA is ON and a java constructor is called or
+  // a super constructor is called from an inlined java constructor.
+  return DoEscapeAnalysis && EliminateAllocations &&
+         ( callee_method->is_initializer() ||
+           (caller_method->is_initializer() &&
+            caller_method != C->method() &&
+            caller_method->holder()->is_subclass_of(callee_method->holder()))
+         );
+}
+
 // positive filter: should send be inlined?  returns NULL, if yes, or rejection msg
-const char* InlineTree::shouldInline(ciMethod* callee_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const {
+const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const {
   // Allows targeted inlining
   if(callee_method->should_inline()) {
     *wci_result = *(WarmCallInfo::always_hot());
@@ -97,7 +109,8 @@
   int size     = callee_method->code_size();
 
   // Check for too many throws (and not too huge)
-  if(callee_method->interpreter_throwout_count() > InlineThrowCount && size < InlineThrowMaxSize ) {
+  if(callee_method->interpreter_throwout_count() > InlineThrowCount &&
+     size < InlineThrowMaxSize ) {
     wci_result->set_profit(wci_result->profit() * 100);
     if (PrintInlining && Verbose) {
       print_indent(inline_depth());
@@ -114,8 +127,12 @@
   int invoke_count     = method()->interpreter_invocation_count();
   assert( invoke_count != 0, "Require invokation count greater than zero");
   int freq = call_site_count/invoke_count;
+
   // bump the max size if the call is frequent
-  if ((freq >= InlineFrequencyRatio) || (call_site_count >= InlineFrequencyCount)) {
+  if ((freq >= InlineFrequencyRatio) ||
+      (call_site_count >= InlineFrequencyCount) ||
+      is_init_with_ea(callee_method, caller_method, C)) {
+
     max_size = C->freq_inline_size();
     if (size <= max_size && TraceFrequencyInlining) {
       print_indent(inline_depth());
@@ -126,7 +143,8 @@
     }
   } else {
     // Not hot.  Check for medium-sized pre-existing nmethod at cold sites.
-    if (callee_method->has_compiled_code() && callee_method->instructions_size() > InlineSmallCode/4)
+    if (callee_method->has_compiled_code() &&
+        callee_method->instructions_size() > InlineSmallCode/4)
       return "already compiled into a medium method";
   }
   if (size > max_size) {
@@ -139,7 +157,7 @@
 
 
 // negative filter: should send NOT be inlined?  returns NULL, ok to inline, or rejection msg
-const char* InlineTree::shouldNotInline(ciMethod *callee_method, WarmCallInfo* wci_result) const {
+const char* InlineTree::shouldNotInline(ciMethod *callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const {
   // negative filter: should send NOT be inlined?  returns NULL (--> inline) or rejection msg
   if (!UseOldInlining) {
     const char* fail = NULL;
@@ -204,9 +222,23 @@
 
   // use frequency-based objections only for non-trivial methods
   if (callee_method->code_size() <= MaxTrivialSize) return NULL;
-  if (UseInterpreter && !CompileTheWorld) { // don't use counts with -Xcomp or CTW
-    if (!callee_method->has_compiled_code() && !callee_method->was_executed_more_than(0)) return "never executed";
-    if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold, CompileThreshold >> 1))) return "executed < MinInliningThreshold times";
+
+  // don't use counts with -Xcomp or CTW
+  if (UseInterpreter && !CompileTheWorld) {
+
+    if (!callee_method->has_compiled_code() &&
+        !callee_method->was_executed_more_than(0)) {
+      return "never executed";
+    }
+
+    if (is_init_with_ea(callee_method, caller_method, C)) {
+
+      // Escape Analysis: inline all executed constructors
+
+    } else if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold,
+                                                           CompileThreshold >> 1))) {
+      return "executed < MinInliningThreshold times";
+    }
   }
 
   if (callee_method->should_not_inline()) {
@@ -219,8 +251,7 @@
 //-----------------------------try_to_inline-----------------------------------
 // return NULL if ok, reason for not inlining otherwise
 // Relocated from "InliningClosure::try_to_inline"
-const char* InlineTree::try_to_inline(ciMethod* callee_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) {
-  ciMethod* caller_method = method();
+const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) {
 
   // Old algorithm had funny accumulating BC-size counters
   if (UseOldInlining && ClipInlining
@@ -229,25 +260,47 @@
   }
 
   const char *msg = NULL;
-  if ((msg = shouldInline(callee_method, caller_bci, profile, wci_result)) != NULL) return msg;
-  if ((msg = shouldNotInline(callee_method,                   wci_result)) != NULL) return msg;
+  if ((msg = shouldInline(callee_method, caller_method, caller_bci,
+                          profile, wci_result)) != NULL) {
+    return msg;
+  }
+  if ((msg = shouldNotInline(callee_method, caller_method,
+                             wci_result)) != NULL) {
+    return msg;
+  }
 
   bool is_accessor = InlineAccessors && callee_method->is_accessor();
 
   // suppress a few checks for accessors and trivial methods
   if (!is_accessor && callee_method->code_size() > MaxTrivialSize) {
+
     // don't inline into giant methods
-    if (C->unique() > (uint)NodeCountInliningCutoff) return "NodeCountInliningCutoff";
+    if (C->unique() > (uint)NodeCountInliningCutoff) {
+      return "NodeCountInliningCutoff";
+    }
 
-    // don't inline unreached call sites
-    if (profile.count() == 0)                        return "call site not reached";
+    if ((!UseInterpreter || CompileTheWorld) &&
+        is_init_with_ea(callee_method, caller_method, C)) {
+
+      // Escape Analysis stress testing when running Xcomp or CTW:
+      // inline constructors even if they are not reached.
+
+    } else if (profile.count() == 0) {
+      // don't inline unreached call sites
+      return "call site not reached";
+    }
   }
 
-  if (!C->do_inlining() && InlineAccessors && !is_accessor) return "not an accessor";
-
-  if( inline_depth() > MaxInlineLevel )           return "inlining too deep";
+  if (!C->do_inlining() && InlineAccessors && !is_accessor) {
+    return "not an accessor";
+  }
+  if( inline_depth() > MaxInlineLevel ) {
+    return "inlining too deep";
+  }
   if( method() == callee_method &&
-      inline_depth() > MaxRecursiveInlineLevel )  return "recursively inlining too deep";
+      inline_depth() > MaxRecursiveInlineLevel ) {
+    return "recursively inlining too deep";
+  }
 
   int size = callee_method->code_size();
 
@@ -336,7 +389,7 @@
 
   // Check if inlining policy says no.
   WarmCallInfo wci = *(initial_wci);
-  failure_msg = try_to_inline(callee_method, caller_bci, profile, &wci);
+  failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci);
   if (failure_msg != NULL && C->log() != NULL) {
     C->log()->begin_elem("inline_fail reason='");
     C->log()->text("%s", failure_msg);
--- a/src/share/vm/opto/c2_globals.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/c2_globals.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -367,6 +367,12 @@
   notproduct(bool, PrintEliminateLocks, false,                              \
           "Print out when locks are eliminated")                            \
                                                                             \
+  diagnostic(bool, EliminateAutoBox, false,                                 \
+          "Private flag to control optimizations for autobox elimination")  \
+                                                                            \
+  product(intx, AutoBoxCacheMax, 128,                                       \
+          "Sets max value cached by the java.lang.Integer autobox cache")   \
+                                                                            \
   product(bool, DoEscapeAnalysis, false,                                    \
           "Perform escape analysis")                                        \
                                                                             \
--- a/src/share/vm/opto/c2compiler.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/c2compiler.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -35,6 +35,9 @@
 const char* C2Compiler::retry_no_subsuming_loads() {
   return "retry without subsuming loads";
 }
+const char* C2Compiler::retry_no_escape_analysis() {
+  return "retry without escape analysis";
+}
 void C2Compiler::initialize_runtime() {
 
   // Check assumptions used while running ADLC
@@ -101,17 +104,23 @@
     initialize();
   }
   bool subsume_loads = true;
+  bool do_escape_analysis = DoEscapeAnalysis;
   while (!env->failing()) {
     // Attempt to compile while subsuming loads into machine instructions.
-    Compile C(env, this, target, entry_bci, subsume_loads);
+    Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis);
 
     // Check result and retry if appropriate.
     if (C.failure_reason() != NULL) {
-        if (C.failure_reason_is(retry_no_subsuming_loads())) {
+      if (C.failure_reason_is(retry_no_subsuming_loads())) {
         assert(subsume_loads, "must make progress");
         subsume_loads = false;
         continue;  // retry
       }
+      if (C.failure_reason_is(retry_no_escape_analysis())) {
+        assert(do_escape_analysis, "must make progress");
+        do_escape_analysis = false;
+        continue;  // retry
+      }
       // Pass any other failure reason up to the ciEnv.
       // Note that serious, irreversible failures are already logged
       // on the ciEnv via env->record_method_not_compilable().
--- a/src/share/vm/opto/c2compiler.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/c2compiler.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -50,6 +50,7 @@
 
   // sentinel value used to trigger backtracking in compile_method().
   static const char* retry_no_subsuming_loads();
+  static const char* retry_no_escape_analysis();
 
   // Print compilation timers and statistics
   void print_timers();
--- a/src/share/vm/opto/callnode.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/callnode.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -832,6 +832,7 @@
 {
   init_class_id(Class_Allocate);
   init_flags(Flag_is_macro);
+  _is_scalar_replaceable = false;
   Node *topnode = C->top();
 
   init_req( TypeFunc::Control  , ctrl );
--- a/src/share/vm/opto/callnode.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/callnode.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -38,7 +38,7 @@
 class       CallLeafNode;
 class         CallLeafNoFPNode;
 class     AllocateNode;
-class     AllocateArrayNode;
+class       AllocateArrayNode;
 class     LockNode;
 class     UnlockNode;
 class JVMState;
@@ -91,7 +91,9 @@
 class ParmNode : public ProjNode {
   static const char * const names[TypeFunc::Parms+1];
 public:
-  ParmNode( StartNode *src, uint con ) : ProjNode(src,con) {}
+  ParmNode( StartNode *src, uint con ) : ProjNode(src,con) {
+    init_class_id(Class_Parm);
+  }
   virtual int Opcode() const;
   virtual bool  is_CFG() const { return (_con == TypeFunc::Control); }
   virtual uint ideal_reg() const;
@@ -624,6 +626,8 @@
     return TypeFunc::make(domain, range);
   }
 
+  bool _is_scalar_replaceable;  // Result of Escape Analysis
+
   virtual uint size_of() const; // Size is bigger
   AllocateNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio,
                Node *size, Node *klass_node, Node *initial_test);
--- a/src/share/vm/opto/cfgnode.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/cfgnode.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -310,8 +310,14 @@
   virtual const RegMask &out_RegMask() const;
   void dominated_by(Node* prev_dom, PhaseIterGVN* igvn);
   int is_range_check(Node* &range, Node* &index, jint &offset);
+  Node* fold_compares(PhaseGVN* phase);
   static Node* up_one_dom(Node* curr, bool linear_only = false);
 
+  // Takes the type of val and filters it through the test represented
+  // by if_proj and returns a more refined type if one is produced.
+  // Returns NULL is it couldn't improve the type.
+  static const TypeInt* filtered_int_type(PhaseGVN* phase, Node* val, Node* if_proj);
+
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
 #endif
--- a/src/share/vm/opto/compile.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/compile.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -333,6 +333,12 @@
     tty->print_cr("** Bailout: Recompile without subsuming loads          **");
     tty->print_cr("*********************************************************");
   }
+  if (_do_escape_analysis != DoEscapeAnalysis && PrintOpto) {
+    // Recompiling without escape analysis
+    tty->print_cr("*********************************************************");
+    tty->print_cr("** Bailout: Recompile without escape analysis          **");
+    tty->print_cr("*********************************************************");
+  }
   if (env()->break_at_compile()) {
     // Open the debugger when compiing this method.
     tty->print("### Breaking when compiling: ");
@@ -415,7 +421,7 @@
 // the continuation bci for on stack replacement.
 
 
-Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci, bool subsume_loads )
+Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci, bool subsume_loads, bool do_escape_analysis )
                 : Phase(Compiler),
                   _env(ci_env),
                   _log(ci_env->log()),
@@ -430,6 +436,7 @@
                   _for_igvn(NULL),
                   _warm_calls(NULL),
                   _subsume_loads(subsume_loads),
+                  _do_escape_analysis(do_escape_analysis),
                   _failure_reason(NULL),
                   _code_buffer("Compile::Fill_buffer"),
                   _orig_pc_slot(0),
@@ -487,7 +494,7 @@
   PhaseGVN gvn(node_arena(), estimated_size);
   set_initial_gvn(&gvn);
 
-  if (DoEscapeAnalysis)
+  if (_do_escape_analysis)
     _congraph = new ConnectionGraph(this);
 
   { // Scope for timing the parser
@@ -577,6 +584,8 @@
   if (_congraph != NULL) {
     NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); )
     _congraph->compute_escape();
+    if (failing())  return;
+
 #ifndef PRODUCT
     if (PrintEscapeAnalysis) {
       _congraph->dump();
@@ -675,6 +684,7 @@
     _orig_pc_slot(0),
     _orig_pc_slot_offset_in_bytes(0),
     _subsume_loads(true),
+    _do_escape_analysis(false),
     _failure_reason(NULL),
     _code_buffer("Compile::Fill_buffer"),
     _node_bundling_limit(0),
@@ -822,7 +832,7 @@
   //   Type::update_loaded_types(_method, _method->constants());
 
   // Init alias_type map.
-  if (!DoEscapeAnalysis && aliaslevel == 3)
+  if (!_do_escape_analysis && aliaslevel == 3)
     aliaslevel = 2;  // No unique types without escape analysis
   _AliasLevel = aliaslevel;
   const int grow_ats = 16;
--- a/src/share/vm/opto/compile.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/compile.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -31,6 +31,7 @@
 class Int_Array;
 class Matcher;
 class MachNode;
+class MachSafePointNode;
 class Node;
 class Node_Array;
 class Node_Notes;
@@ -52,9 +53,6 @@
 class Unique_Node_List;
 class nmethod;
 class WarmCallInfo;
-#ifdef ENABLE_ZAP_DEAD_LOCALS
-class MachSafePointNode;
-#endif
 
 //------------------------------Compile----------------------------------------
 // This class defines a top-level Compiler invocation.
@@ -127,6 +125,7 @@
   const int             _compile_id;
   const bool            _save_argument_registers; // save/restore arg regs for trampolines
   const bool            _subsume_loads;         // Load can be matched as part of a larger op.
+  const bool            _do_escape_analysis;    // Do escape analysis.
   ciMethod*             _method;                // The method being compiled.
   int                   _entry_bci;             // entry bci for osr methods.
   const TypeFunc*       _tf;                    // My kind of signature
@@ -260,6 +259,8 @@
   // instructions that subsume a load may result in an unschedulable
   // instruction sequence.
   bool              subsume_loads() const       { return _subsume_loads; }
+  // Do escape analysis.
+  bool              do_escape_analysis() const  { return _do_escape_analysis; }
   bool              save_argument_registers() const { return _save_argument_registers; }
 
 
@@ -560,7 +561,7 @@
   // replacement, entry_bci indicates the bytecode for which to compile a
   // continuation.
   Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target,
-          int entry_bci, bool subsume_loads);
+          int entry_bci, bool subsume_loads, bool do_escape_analysis);
 
   // Second major entry point.  From the TypeFunc signature, generate code
   // to pass arguments from the Java calling convention to the C calling
--- a/src/share/vm/opto/connode.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/connode.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -982,34 +982,9 @@
     return new (phase->C, 3) AddINode(add1,add2);
   }
 
-  // Fold up with a prior LoadL: LoadL->ConvL2I ==> LoadI
-  // Requires we understand the 'endianess' of Longs.
-  if( andl_op == Op_LoadL ) {
-    Node *adr = andl->in(MemNode::Address);
-    // VM_LITTLE_ENDIAN is #defined appropriately in the Makefiles
-#ifndef VM_LITTLE_ENDIAN
-    // The transformation can cause problems on BIG_ENDIAN architectures
-    // where the jint is not the same address as the jlong. Specifically, we
-    // will fail to insert an anti-dependence in GCM between the LoadI and a
-    // subsequent StoreL because different memory offsets provoke
-    // flatten_alias_type() into indicating two different types.  See bug
-    // 4755222.
-
-    // Node *base = adr->is_AddP() ? adr->in(AddPNode::Base) : adr;
-    // adr = phase->transform( new (phase->C, 4) AddPNode(base,adr,phase->MakeConX(sizeof(jint))));
-    return NULL;
-#else
-    if (phase->C->alias_type(andl->adr_type())->is_volatile()) {
-      // Picking up the low half by itself bypasses the atomic load and we could
-      // end up with more than one non-atomic load.  See bugs 4432655 and 4526490.
-      // We could go to the trouble of iterating over andl's output edges and
-      // punting only if there's more than one real use, but we don't bother.
-      return NULL;
-    }
-    return new (phase->C, 3) LoadINode(andl->in(MemNode::Control),andl->in(MemNode::Memory),adr,((LoadLNode*)andl)->raw_adr_type());
-#endif
-  }
-
+  // Disable optimization: LoadL->ConvL2I ==> LoadI.
+  // It causes problems (sizes of Load and Store nodes do not match)
+  // in objects initialization code and Escape Analysis.
   return NULL;
 }
 
--- a/src/share/vm/opto/escape.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/escape.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -395,6 +395,15 @@
   if (result != NULL && C->get_alias_index(result->adr_type()) == alias_idx) {
     return result;
   }
+  if ((int)C->unique() + 2*NodeLimitFudgeFactor > MaxNodeLimit) {
+    if (C->do_escape_analysis() == true && !C->failing()) {
+      // Retry compilation without escape analysis.
+      // If this is the first failure, the sentinel string will "stick"
+      // to the Compile object, and the C2Compiler will see it and retry.
+      C->record_failure(C2Compiler::retry_no_escape_analysis());
+    }
+    return NULL;
+  }
 
   orig_phi_worklist.append_if_missing(orig_phi);
   result = PhiNode::make(orig_phi->in(0), NULL, Type::MEMORY, atype);
@@ -443,6 +452,9 @@
           mem = nphi;
         }
       }
+      if (C->failing()) {
+        return NULL;
+      }
       result->set_req(idx++, mem);
     }
 #ifdef ASSERT
@@ -589,6 +601,11 @@
       if (es != PointsToNode::NoEscape || !ptn._unique_type) {
         continue; //  can't make a unique type
       }
+      if (alloc->is_Allocate()) {
+        // Set the scalar_replaceable flag before the next check.
+        alloc->as_Allocate()->_is_scalar_replaceable = true;
+      }
+
       set_map(alloc->_idx, n);
       set_map(n->_idx, alloc);
       const TypeInstPtr *t = igvn->type(n)->isa_instptr();
@@ -672,6 +689,9 @@
       if (mem->is_Phi()) {
         mem = split_memory_phi(mem->as_Phi(), alias_idx, orig_phis, igvn);
       }
+      if (_compile->failing()) {
+        return;
+      }
       if (mem != n->in(MemNode::Memory))
         set_map(n->_idx, mem);
       if (n->is_Load()) {
@@ -742,7 +762,11 @@
           if((uint)_compile->get_general_index(ni) == i) {
             Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni);
             if (nmm->is_empty_memory(m)) {
-              nmm->set_memory_at(ni, split_memory_phi(mem->as_Phi(), ni, orig_phis, igvn));
+              m = split_memory_phi(mem->as_Phi(), ni, orig_phis, igvn);
+              if (_compile->failing()) {
+                return;
+              }
+              nmm->set_memory_at(ni, m);
             }
           }
         }
@@ -881,6 +905,11 @@
   // Now use the escape information to create unique types for
   // unescaped objects
   split_unique_types(alloc_worklist);
+  if (_compile->failing())  return;
+
+  // Clean up after split unique types.
+  ResourceMark rm;
+  PhaseRemoveUseless pru(_compile->initial_gvn(), _compile->for_igvn());
 }
 
 Node * ConnectionGraph::skip_casts(Node *n) {
--- a/src/share/vm/opto/gcm.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/gcm.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -448,9 +448,9 @@
   ResourceArea *area = Thread::current()->resource_area();
   Node_List worklist_mem(area);     // prior memory state to store
   Node_List worklist_store(area);   // possible-def to explore
+  Node_List worklist_visited(area); // visited mergemem nodes
   Node_List non_early_stores(area); // all relevant stores outside of early
   bool must_raise_LCA = false;
-  DEBUG_ONLY(VectorSet should_not_repeat(area));
 
 #ifdef TRACK_PHI_INPUTS
   // %%% This extra checking fails because MergeMem nodes are not GVNed.
@@ -479,8 +479,8 @@
 
   Node* initial_mem = load->in(MemNode::Memory);
   worklist_store.push(initial_mem);
+  worklist_visited.push(initial_mem);
   worklist_mem.push(NULL);
-  DEBUG_ONLY(should_not_repeat.test_set(initial_mem->_idx));
   while (worklist_store.size() > 0) {
     // Examine a nearby store to see if it might interfere with our load.
     Node* mem   = worklist_mem.pop();
@@ -494,18 +494,20 @@
         || op == Op_MergeMem    // internal node of tree we are searching
         ) {
       mem = store;   // It's not a possibly interfering store.
+      if (store == initial_mem)
+        initial_mem = NULL;  // only process initial memory once
+
       for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
         store = mem->fast_out(i);
         if (store->is_MergeMem()) {
           // Be sure we don't get into combinatorial problems.
           // (Allow phis to be repeated; they can merge two relevant states.)
-          uint i = worklist_store.size();
-          for (; i > 0; i--) {
-            if (worklist_store.at(i-1) == store)  break;
+          uint j = worklist_visited.size();
+          for (; j > 0; j--) {
+            if (worklist_visited.at(j-1) == store)  break;
           }
-          if (i > 0)  continue; // already on work list; do not repeat
-          DEBUG_ONLY(int repeated = should_not_repeat.test_set(store->_idx));
-          assert(!repeated, "do not walk merges twice");
+          if (j > 0)  continue; // already on work list; do not repeat
+          worklist_visited.push(store);
         }
         worklist_mem.push(mem);
         worklist_store.push(store);
--- a/src/share/vm/opto/graphKit.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/graphKit.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1447,7 +1447,7 @@
 //-------------------------array_element_address-------------------------
 Node* GraphKit::array_element_address(Node* ary, Node* idx, BasicType elembt,
                                       const TypeInt* sizetype) {
-  uint shift  = exact_log2(type2aelembytes[elembt]);
+  uint shift  = exact_log2(type2aelembytes(elembt));
   uint header = arrayOopDesc::base_offset_in_bytes(elembt);
 
   // short-circuit a common case (saves lots of confusing waste motion)
@@ -2808,7 +2808,7 @@
       ciInstanceKlass* ik = oop_type->klass()->as_instance_klass();
       for (int i = 0, len = ik->nof_nonstatic_fields(); i < len; i++) {
         ciField* field = ik->nonstatic_field_at(i);
-        if (field->offset() >= TrackedInitializationLimit)
+        if (field->offset() >= TrackedInitializationLimit * HeapWordSize)
           continue;  // do not bother to track really large numbers of fields
         // Find (or create) the alias category for this field:
         int fieldidx = C->alias_type(field)->index();
--- a/src/share/vm/opto/ifnode.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/ifnode.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -543,6 +543,159 @@
   return NULL;                  // Dead loop?  Or hit root?
 }
 
+
+//------------------------------filtered_int_type--------------------------------
+// Return a possibly more restrictive type for val based on condition control flow for an if
+const TypeInt* IfNode::filtered_int_type(PhaseGVN* gvn, Node *val, Node* if_proj) {
+  assert(if_proj &&
+         (if_proj->Opcode() == Op_IfTrue || if_proj->Opcode() == Op_IfFalse), "expecting an if projection");
+  if (if_proj->in(0) && if_proj->in(0)->is_If()) {
+    IfNode* iff = if_proj->in(0)->as_If();
+    if (iff->in(1) && iff->in(1)->is_Bool()) {
+      BoolNode* bol = iff->in(1)->as_Bool();
+      if (bol->in(1) && bol->in(1)->is_Cmp()) {
+        const CmpNode* cmp  = bol->in(1)->as_Cmp();
+        if (cmp->in(1) == val) {
+          const TypeInt* cmp2_t = gvn->type(cmp->in(2))->isa_int();
+          if (cmp2_t != NULL) {
+            jint lo = cmp2_t->_lo;
+            jint hi = cmp2_t->_hi;
+            BoolTest::mask msk = if_proj->Opcode() == Op_IfTrue ? bol->_test._test : bol->_test.negate();
+            switch (msk) {
+            case BoolTest::ne:
+              // Can't refine type
+              return NULL;
+            case BoolTest::eq:
+              return cmp2_t;
+            case BoolTest::lt:
+              lo = TypeInt::INT->_lo;
+              if (hi - 1 < hi) {
+                hi = hi - 1;
+              }
+              break;
+            case BoolTest::le:
+              lo = TypeInt::INT->_lo;
+              break;
+            case BoolTest::gt:
+              if (lo + 1 > lo) {
+                lo = lo + 1;
+              }
+              hi = TypeInt::INT->_hi;
+              break;
+            case BoolTest::ge:
+              // lo unchanged
+              hi = TypeInt::INT->_hi;
+              break;
+            }
+            const TypeInt* rtn_t = TypeInt::make(lo, hi, cmp2_t->_widen);
+            return rtn_t;
+          }
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+//------------------------------fold_compares----------------------------
+// See if a pair of CmpIs can be converted into a CmpU.  In some cases
+// the direction of this if is determined by the preciding if so it
+// can be eliminate entirely.  Given an if testing (CmpI n c) check
+// for an immediately control dependent if that is testing (CmpI n c2)
+// and has one projection leading to this if and the other projection
+// leading to a region that merges one of this ifs control
+// projections.
+//
+//                   If
+//                  / |
+//                 /  |
+//                /   |
+//              If    |
+//              /\    |
+//             /  \   |
+//            /    \  |
+//           /    Region
+//
+Node* IfNode::fold_compares(PhaseGVN* phase) {
+  if (!EliminateAutoBox || Opcode() != Op_If) return NULL;
+
+  Node* this_cmp = in(1)->in(1);
+  if (this_cmp != NULL && this_cmp->Opcode() == Op_CmpI &&
+      this_cmp->in(2)->is_Con() && this_cmp->in(2) != phase->C->top()) {
+    Node* ctrl = in(0);
+    BoolNode* this_bool = in(1)->as_Bool();
+    Node* n = this_cmp->in(1);
+    int hi = this_cmp->in(2)->get_int();
+    if (ctrl != NULL && ctrl->is_Proj() && ctrl->outcnt() == 1 &&
+        ctrl->in(0)->is_If() &&
+        ctrl->in(0)->outcnt() == 2 &&
+        ctrl->in(0)->in(1)->is_Bool() &&
+        ctrl->in(0)->in(1)->in(1)->Opcode() == Op_CmpI &&
+        ctrl->in(0)->in(1)->in(1)->in(2)->is_Con() &&
+        ctrl->in(0)->in(1)->in(1)->in(1) == n) {
+      IfNode* dom_iff = ctrl->in(0)->as_If();
+      Node* otherproj = dom_iff->proj_out(!ctrl->as_Proj()->_con);
+      if (otherproj->outcnt() == 1 && otherproj->unique_out()->is_Region() &&
+          this_bool->_test._test != BoolTest::ne && this_bool->_test._test != BoolTest::eq) {
+        // Identify which proj goes to the region and which continues on
+        RegionNode* region = otherproj->unique_out()->as_Region();
+        Node* success = NULL;
+        Node* fail = NULL;
+        for (int i = 0; i < 2; i++) {
+          Node* proj = proj_out(i);
+          if (success == NULL && proj->outcnt() == 1 && proj->unique_out() == region) {
+            success = proj;
+          } else if (fail == NULL) {
+            fail = proj;
+          } else {
+            success = fail = NULL;
+          }
+        }
+        if (success != NULL && fail != NULL && !region->has_phi()) {
+          int lo = dom_iff->in(1)->in(1)->in(2)->get_int();
+          BoolNode* dom_bool = dom_iff->in(1)->as_Bool();
+          Node* dom_cmp =  dom_bool->in(1);
+          const TypeInt* failtype  = filtered_int_type(phase, n, ctrl);
+          if (failtype != NULL) {
+            const TypeInt* type2 = filtered_int_type(phase, n, fail);
+            if (type2 != NULL) {
+              failtype = failtype->join(type2)->is_int();
+            } else {
+              failtype = NULL;
+            }
+          }
+
+          if (failtype != NULL &&
+              dom_bool->_test._test != BoolTest::ne && dom_bool->_test._test != BoolTest::eq) {
+            int bound = failtype->_hi - failtype->_lo + 1;
+            if (failtype->_hi != max_jint && failtype->_lo != min_jint && bound > 1) {
+              // Merge the two compares into a single unsigned compare by building  (CmpU (n - lo) hi)
+              BoolTest::mask cond = fail->as_Proj()->_con ? BoolTest::lt : BoolTest::ge;
+              Node* adjusted = phase->transform(new (phase->C, 3) SubINode(n, phase->intcon(failtype->_lo)));
+              Node* newcmp = phase->transform(new (phase->C, 3) CmpUNode(adjusted, phase->intcon(bound)));
+              Node* newbool = phase->transform(new (phase->C, 2) BoolNode(newcmp, cond));
+              phase->hash_delete(dom_iff);
+              dom_iff->set_req(1, phase->intcon(ctrl->as_Proj()->_con));
+              phase->is_IterGVN()->_worklist.push(dom_iff);
+              phase->hash_delete(this);
+              set_req(1, newbool);
+              return this;
+            }
+            if (failtype->_lo > failtype->_hi) {
+              // previous if determines the result of this if so
+              // replace Bool with constant
+              phase->hash_delete(this);
+              set_req(1, phase->intcon(success->as_Proj()->_con));
+              return this;
+            }
+          }
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
 //------------------------------remove_useless_bool----------------------------
 // Check for people making a useless boolean: things like
 // if( (x < y ? true : false) ) { ... }
@@ -744,6 +897,11 @@
     // Normal equivalent-test check.
     if( !dom ) return NULL;     // Dead loop?
 
+    Node* result = fold_compares(phase);
+    if (result != NULL) {
+      return result;
+    }
+
     // Search up the dominator tree for an If with an identical test
     while( dom->Opcode() != op    ||  // Not same opcode?
            dom->in(1)    != in(1) ||  // Not same input 1?
--- a/src/share/vm/opto/library_call.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/library_call.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -2097,7 +2097,7 @@
   int type_words = type2size[type];
 
   // Cannot inline wide CAS on machines that don't support it natively
-  if (type2aelembytes[type] > BytesPerInt && !VM_Version::supports_cx8())
+  if (type2aelembytes(type) > BytesPerInt && !VM_Version::supports_cx8())
     return false;
 
   C->set_has_unsafe_access(true);  // Mark eventual nmethod as "unsafe".
@@ -3975,7 +3975,7 @@
     // both indices are constants
     int s_offs = src_offset_inttype->get_con();
     int d_offs = dest_offset_inttype->get_con();
-    int element_size = type2aelembytes[t];
+    int element_size = type2aelembytes(t);
     aligned = ((arrayOopDesc::base_offset_in_bytes(t) + s_offs * element_size) % HeapWordSize == 0) &&
               ((arrayOopDesc::base_offset_in_bytes(t) + d_offs * element_size) % HeapWordSize == 0);
     if (s_offs >= d_offs)  disjoint = true;
@@ -4170,6 +4170,7 @@
       && !_gvn.eqv_uncast(src, dest)
       && ((alloc = tightly_coupled_allocation(dest, slow_region))
           != NULL)
+      && _gvn.find_int_con(alloc->in(AllocateNode::ALength), 1) > 0
       && alloc->maybe_set_complete(&_gvn)) {
     // "You break it, you buy it."
     InitializeNode* init = alloc->initialization();
@@ -4389,7 +4390,7 @@
     if (alloc != NULL && use_ReduceInitialCardMarks()) {
       // If we do not need card marks, copy using the jint or jlong stub.
       copy_type = LP64_ONLY(T_LONG) NOT_LP64(T_INT);
-      assert(type2aelembytes[basic_elem_type] == type2aelembytes[copy_type],
+      assert(type2aelembytes(basic_elem_type) == type2aelembytes(copy_type),
              "sizes agree");
     }
   }
@@ -4659,7 +4660,7 @@
   Node* mem = memory(adr_type); // memory slice to operate on
 
   // scaling and rounding of indexes:
-  int scale = exact_log2(type2aelembytes[basic_elem_type]);
+  int scale = exact_log2(type2aelembytes(basic_elem_type));
   int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type);
   int clear_low = (-1 << scale) & (BytesPerInt  - 1);
   int bump_bit  = (-1 << scale) & BytesPerInt;
@@ -4753,7 +4754,7 @@
                                          Node* dest, Node* dest_offset,
                                          Node* dest_size) {
   // See if there is an advantage from block transfer.
-  int scale = exact_log2(type2aelembytes[basic_elem_type]);
+  int scale = exact_log2(type2aelembytes(basic_elem_type));
   if (scale >= LogBytesPerLong)
     return false;               // it is already a block transfer
 
--- a/src/share/vm/opto/loopTransform.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/loopTransform.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1714,6 +1714,7 @@
   // Gate unrolling, RCE and peeling efforts.
   if( !_child &&                // If not an inner loop, do not split
       !_irreducible &&
+      _allow_optimizations &&
       !tail()->is_top() ) {     // Also ignore the occasional dead backedge
     if (!_has_call) {
       iteration_split_impl( phase, old_new );
--- a/src/share/vm/opto/loopnode.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/loopnode.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -651,7 +651,7 @@
     while (if_cnt < if_limit) {
       if ((pred->Opcode() == Op_IfTrue || pred->Opcode() == Op_IfFalse)) {
         if_cnt++;
-        const TypeInt* if_t = filtered_type_at_if(val, pred);
+        const TypeInt* if_t = IfNode::filtered_int_type(&_igvn, val, pred);
         if (if_t != NULL) {
           if (rtn_t == NULL) {
             rtn_t = if_t;
@@ -674,59 +674,6 @@
 }
 
 
-//------------------------------filtered_type_at_if--------------------------------
-// Return a possibly more restrictive type for val based on condition control flow for an if
-const TypeInt* PhaseIdealLoop::filtered_type_at_if( Node* val, Node *if_proj) {
-  assert(if_proj &&
-         (if_proj->Opcode() == Op_IfTrue || if_proj->Opcode() == Op_IfFalse), "expecting an if projection");
-  if (if_proj->in(0) && if_proj->in(0)->is_If()) {
-    IfNode* iff = if_proj->in(0)->as_If();
-    if (iff->in(1) && iff->in(1)->is_Bool()) {
-      BoolNode* bol = iff->in(1)->as_Bool();
-      if (bol->in(1) && bol->in(1)->is_Cmp()) {
-        const CmpNode* cmp  = bol->in(1)->as_Cmp();
-        if (cmp->in(1) == val) {
-          const TypeInt* cmp2_t = _igvn.type(cmp->in(2))->isa_int();
-          if (cmp2_t != NULL) {
-            jint lo = cmp2_t->_lo;
-            jint hi = cmp2_t->_hi;
-            BoolTest::mask msk = if_proj->Opcode() == Op_IfTrue ? bol->_test._test : bol->_test.negate();
-            switch (msk) {
-            case BoolTest::ne:
-              // Can't refine type
-              return NULL;
-            case BoolTest::eq:
-              return cmp2_t;
-            case BoolTest::lt:
-              lo = TypeInt::INT->_lo;
-              if (hi - 1 < hi) {
-                hi = hi - 1;
-              }
-              break;
-            case BoolTest::le:
-              lo = TypeInt::INT->_lo;
-              break;
-            case BoolTest::gt:
-              if (lo + 1 > lo) {
-                lo = lo + 1;
-              }
-              hi = TypeInt::INT->_hi;
-              break;
-            case BoolTest::ge:
-              // lo unchanged
-              hi = TypeInt::INT->_hi;
-              break;
-            }
-            const TypeInt* rtn_t = TypeInt::make(lo, hi, cmp2_t->_widen);
-            return rtn_t;
-          }
-        }
-      }
-    }
-  }
-  return NULL;
-}
-
 //------------------------------dump_spec--------------------------------------
 // Dump special per-node info
 #ifndef PRODUCT
@@ -1614,7 +1561,7 @@
       // on just their loop-phi's for this pass of loop opts
       if( SplitIfBlocks && do_split_ifs ) {
         if (lpt->policy_range_check(this)) {
-          lpt->_rce_candidate = true;
+          lpt->_rce_candidate = 1; // = true
         }
       }
     }
@@ -2198,7 +2145,7 @@
     // as well?  If so, then I found another entry into the loop.
     while( is_postvisited(l->_head) ) {
       // found irreducible
-      l->_irreducible = true;
+      l->_irreducible = 1; // = true
       l = l->_parent;
       _has_irreducible_loops = true;
       // Check for bad CFG here to prevent crash, and bailout of compile
@@ -2252,6 +2199,12 @@
               (iff->as_If()->_prob >= 0.01) )
             innermost->_has_call = 1;
         }
+      } else if( n->is_Allocate() && n->as_Allocate()->_is_scalar_replaceable ) {
+        // Disable loop optimizations if the loop has a scalar replaceable
+        // allocation. This disabling may cause a potential performance lost
+        // if the allocation is not eliminated for some reason.
+        innermost->_allow_optimizations = false;
+        innermost->_has_call = 1; // = true
       }
     }
   }
--- a/src/share/vm/opto/loopnode.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/loopnode.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -289,13 +289,15 @@
         _has_sfpt:1,            // True if has non-call safepoint
         _rce_candidate:1;       // True if candidate for range check elimination
 
-  Node_List* _required_safept;      // A inner loop cannot delete these safepts;
+  Node_List* _required_safept;  // A inner loop cannot delete these safepts;
+  bool  _allow_optimizations;   // Allow loop optimizations
 
   IdealLoopTree( PhaseIdealLoop* phase, Node *head, Node *tail )
     : _parent(0), _next(0), _child(0),
       _head(head), _tail(tail),
       _phase(phase),
       _required_safept(NULL),
+      _allow_optimizations(true),
       _nest(0), _irreducible(0), _has_call(0), _has_sfpt(0), _rce_candidate(0)
   { }
 
@@ -850,7 +852,6 @@
   const TypeInt* filtered_type( Node *n ) { return filtered_type(n, NULL); }
  // Helpers for filtered type
   const TypeInt* filtered_type_from_dominators( Node* val, Node *val_ctrl);
-  const TypeInt* filtered_type_at_if( Node* val, Node *if_proj);
 
   // Helper functions
   void register_new_node( Node *n, Node *blk );
--- a/src/share/vm/opto/loopopts.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/loopopts.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -435,9 +435,11 @@
 
   // Check profitability
   int cost = 0;
+  int phis = 0;
   for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
     Node *out = region->fast_out(i);
     if( !out->is_Phi() ) continue; // Ignore other control edges, etc
+    phis++;
     PhiNode* phi = out->as_Phi();
     switch (phi->type()->basic_type()) {
     case T_LONG:
@@ -489,6 +491,12 @@
     }
   }
   if( cost >= ConditionalMoveLimit ) return NULL; // Too much goo
+  Node* bol = iff->in(1);
+  assert( bol->Opcode() == Op_Bool, "" );
+  int cmp_op = bol->in(1)->Opcode();
+  // It is expensive to generate flags from a float compare.
+  // Avoid duplicated float compare.
+  if( phis > 1 && (cmp_op == Op_CmpF || cmp_op == Op_CmpD)) return NULL;
 
   // --------------
   // Now replace all Phis with CMOV's
--- a/src/share/vm/opto/memnode.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/memnode.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -108,19 +108,13 @@
   // Avoid independent memory operations
   Node* old_mem = mem;
 
-  if (mem->is_Proj() && mem->in(0)->is_Initialize()) {
-    InitializeNode* init = mem->in(0)->as_Initialize();
-    if (init->is_complete()) {  // i.e., after macro expansion
-      const TypePtr* tp = t_adr->is_ptr();
-      uint alias_idx = phase->C->get_alias_index(tp);
-      // Free this slice from the init.  It was hooked, temporarily,
-      // by GraphKit::set_output_for_allocation.
-      if (alias_idx > Compile::AliasIdxRaw) {
-        mem = init->memory(alias_idx);
-        // ...but not with the raw-pointer slice.
-      }
-    }
-  }
+  // The code which unhooks non-raw memories from complete (macro-expanded)
+  // initializations was removed. After macro-expansion all stores catched
+  // by Initialize node became raw stores and there is no information
+  // which memory slices they modify. So it is unsafe to move any memory
+  // operation above these stores. Also in most cases hooked non-raw memories
+  // were already unhooked by using information from detect_ptr_independence()
+  // and find_previous_store().
 
   if (mem->is_MergeMem()) {
     MergeMemNode* mmem = mem->as_MergeMem();
@@ -634,6 +628,46 @@
 Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const {
   Node* ld_adr = in(MemNode::Address);
 
+  const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr();
+  Compile::AliasType* atp = tp != NULL ? phase->C->alias_type(tp) : NULL;
+  if (EliminateAutoBox && atp != NULL && atp->index() >= Compile::AliasIdxRaw &&
+      atp->field() != NULL && !atp->field()->is_volatile()) {
+    uint alias_idx = atp->index();
+    bool final = atp->field()->is_final();
+    Node* result = NULL;
+    Node* current = st;
+    // Skip through chains of MemBarNodes checking the MergeMems for
+    // new states for the slice of this load.  Stop once any other
+    // kind of node is encountered.  Loads from final memory can skip
+    // through any kind of MemBar but normal loads shouldn't skip
+    // through MemBarAcquire since the could allow them to move out of
+    // a synchronized region.
+    while (current->is_Proj()) {
+      int opc = current->in(0)->Opcode();
+      if ((final && opc == Op_MemBarAcquire) ||
+          opc == Op_MemBarRelease || opc == Op_MemBarCPUOrder) {
+        Node* mem = current->in(0)->in(TypeFunc::Memory);
+        if (mem->is_MergeMem()) {
+          MergeMemNode* merge = mem->as_MergeMem();
+          Node* new_st = merge->memory_at(alias_idx);
+          if (new_st == merge->base_memory()) {
+            // Keep searching
+            current = merge->base_memory();
+            continue;
+          }
+          // Save the new memory state for the slice and fall through
+          // to exit.
+          result = new_st;
+        }
+      }
+      break;
+    }
+    if (result != NULL) {
+      st = result;
+    }
+  }
+
+
   // Loop around twice in the case Load -> Initialize -> Store.
   // (See PhaseIterGVN::add_users_to_worklist, which knows about this case.)
   for (int trip = 0; trip <= 1; trip++) {
@@ -723,6 +757,168 @@
   return this;
 }
 
+
+// Returns true if the AliasType refers to the field that holds the
+// cached box array.  Currently only handles the IntegerCache case.
+static bool is_autobox_cache(Compile::AliasType* atp) {
+  if (atp != NULL && atp->field() != NULL) {
+    ciField* field = atp->field();
+    ciSymbol* klass = field->holder()->name();
+    if (field->name() == ciSymbol::cache_field_name() &&
+        field->holder()->uses_default_loader() &&
+        klass == ciSymbol::java_lang_Integer_IntegerCache()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Fetch the base value in the autobox array
+static bool fetch_autobox_base(Compile::AliasType* atp, int& cache_offset) {
+  if (atp != NULL && atp->field() != NULL) {
+    ciField* field = atp->field();
+    ciSymbol* klass = field->holder()->name();
+    if (field->name() == ciSymbol::cache_field_name() &&
+        field->holder()->uses_default_loader() &&
+        klass == ciSymbol::java_lang_Integer_IntegerCache()) {
+      assert(field->is_constant(), "what?");
+      ciObjArray* array = field->constant_value().as_object()->as_obj_array();
+      // Fetch the box object at the base of the array and get its value
+      ciInstance* box = array->obj_at(0)->as_instance();
+      ciInstanceKlass* ik = box->klass()->as_instance_klass();
+      if (ik->nof_nonstatic_fields() == 1) {
+        // This should be true nonstatic_field_at requires calling
+        // nof_nonstatic_fields so check it anyway
+        ciConstant c = box->field_value(ik->nonstatic_field_at(0));
+        cache_offset = c.as_int();
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
+// Returns true if the AliasType refers to the value field of an
+// autobox object.  Currently only handles Integer.
+static bool is_autobox_object(Compile::AliasType* atp) {
+  if (atp != NULL && atp->field() != NULL) {
+    ciField* field = atp->field();
+    ciSymbol* klass = field->holder()->name();
+    if (field->name() == ciSymbol::value_name() &&
+        field->holder()->uses_default_loader() &&
+        klass == ciSymbol::java_lang_Integer()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+
+// We're loading from an object which has autobox behaviour.
+// If this object is result of a valueOf call we'll have a phi
+// merging a newly allocated object and a load from the cache.
+// We want to replace this load with the original incoming
+// argument to the valueOf call.
+Node* LoadNode::eliminate_autobox(PhaseGVN* phase) {
+  Node* base = in(Address)->in(AddPNode::Base);
+  if (base->is_Phi() && base->req() == 3) {
+    AllocateNode* allocation = NULL;
+    int allocation_index = -1;
+    int load_index = -1;
+    for (uint i = 1; i < base->req(); i++) {
+      allocation = AllocateNode::Ideal_allocation(base->in(i), phase);
+      if (allocation != NULL) {
+        allocation_index = i;
+        load_index = 3 - allocation_index;
+        break;
+      }
+    }
+    LoadNode* load = NULL;
+    if (allocation != NULL && base->in(load_index)->is_Load()) {
+      load = base->in(load_index)->as_Load();
+    }
+    if (load != NULL && in(Memory)->is_Phi() && in(Memory)->in(0) == base->in(0)) {
+      // Push the loads from the phi that comes from valueOf up
+      // through it to allow elimination of the loads and the recovery
+      // of the original value.
+      Node* mem_phi = in(Memory);
+      Node* offset = in(Address)->in(AddPNode::Offset);
+
+      Node* in1 = clone();
+      Node* in1_addr = in1->in(Address)->clone();
+      in1_addr->set_req(AddPNode::Base, base->in(allocation_index));
+      in1_addr->set_req(AddPNode::Address, base->in(allocation_index));
+      in1_addr->set_req(AddPNode::Offset, offset);
+      in1->set_req(0, base->in(allocation_index));
+      in1->set_req(Address, in1_addr);
+      in1->set_req(Memory, mem_phi->in(allocation_index));
+
+      Node* in2 = clone();
+      Node* in2_addr = in2->in(Address)->clone();
+      in2_addr->set_req(AddPNode::Base, base->in(load_index));
+      in2_addr->set_req(AddPNode::Address, base->in(load_index));
+      in2_addr->set_req(AddPNode::Offset, offset);
+      in2->set_req(0, base->in(load_index));
+      in2->set_req(Address, in2_addr);
+      in2->set_req(Memory, mem_phi->in(load_index));
+
+      in1_addr = phase->transform(in1_addr);
+      in1 =      phase->transform(in1);
+      in2_addr = phase->transform(in2_addr);
+      in2 =      phase->transform(in2);
+
+      PhiNode* result = PhiNode::make_blank(base->in(0), this);
+      result->set_req(allocation_index, in1);
+      result->set_req(load_index, in2);
+      return result;
+    }
+  } else if (base->is_Load()) {
+    // Eliminate the load of Integer.value for integers from the cache
+    // array by deriving the value from the index into the array.
+    // Capture the offset of the load and then reverse the computation.
+    Node* load_base = base->in(Address)->in(AddPNode::Base);
+    if (load_base != NULL) {
+      Compile::AliasType* atp = phase->C->alias_type(load_base->adr_type());
+      intptr_t cache_offset;
+      int shift = -1;
+      Node* cache = NULL;
+      if (is_autobox_cache(atp)) {
+        shift  = exact_log2(type2aelembytes(T_OBJECT));
+        cache = AddPNode::Ideal_base_and_offset(load_base->in(Address), phase, cache_offset);
+      }
+      if (cache != NULL && base->in(Address)->is_AddP()) {
+        Node* elements[4];
+        int count = base->in(Address)->as_AddP()->unpack_offsets(elements, ARRAY_SIZE(elements));
+        int cache_low;
+        if (count > 0 && fetch_autobox_base(atp, cache_low)) {
+          int offset = arrayOopDesc::base_offset_in_bytes(memory_type()) - (cache_low << shift);
+          // Add up all the offsets making of the address of the load
+          Node* result = elements[0];
+          for (int i = 1; i < count; i++) {
+            result = phase->transform(new (phase->C, 3) AddXNode(result, elements[i]));
+          }
+          // Remove the constant offset from the address and then
+          // remove the scaling of the offset to recover the original index.
+          result = phase->transform(new (phase->C, 3) AddXNode(result, phase->MakeConX(-offset)));
+          if (result->Opcode() == Op_LShiftX && result->in(2) == phase->intcon(shift)) {
+            // Peel the shift off directly but wrap it in a dummy node
+            // since Ideal can't return existing nodes
+            result = new (phase->C, 3) RShiftXNode(result->in(1), phase->intcon(0));
+          } else {
+            result = new (phase->C, 3) RShiftXNode(result, phase->intcon(shift));
+          }
+#ifdef _LP64
+          result = new (phase->C, 2) ConvL2INode(phase->transform(result));
+#endif
+          return result;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+
 //------------------------------Ideal------------------------------------------
 // If the load is from Field memory and the pointer is non-null, we can
 // zero out the control input.
@@ -755,6 +951,17 @@
     }
   }
 
+  if (EliminateAutoBox && can_reshape && in(Address)->is_AddP()) {
+    Node* base = in(Address)->in(AddPNode::Base);
+    if (base != NULL) {
+      Compile::AliasType* atp = phase->C->alias_type(adr_type());
+      if (is_autobox_object(atp)) {
+        Node* result = eliminate_autobox(phase);
+        if (result != NULL) return result;
+      }
+    }
+  }
+
   // Check for prior store with a different base or offset; make Load
   // independent.  Skip through any number of them.  Bail out if the stores
   // are in an endless dead cycle and report no progress.  This is a key
@@ -858,6 +1065,17 @@
           // This can happen if a interface-typed array narrows to a class type.
           jt = _type;
         }
+
+        if (EliminateAutoBox) {
+          // The pointers in the autobox arrays are always non-null
+          Node* base = in(Address)->in(AddPNode::Base);
+          if (base != NULL) {
+            Compile::AliasType* atp = phase->C->alias_type(base->adr_type());
+            if (is_autobox_cache(atp)) {
+              return jt->join(TypePtr::NOTNULL)->is_ptr();
+            }
+          }
+        }
         return jt;
       }
     }
@@ -1553,9 +1771,16 @@
 
 //------------------------------Value-----------------------------------------
 const Type *StoreCMNode::Value( PhaseTransform *phase ) const {
+  // Either input is TOP ==> the result is TOP
+  const Type *t = phase->type( in(MemNode::Memory) );
+  if( t == Type::TOP ) return Type::TOP;
+  t = phase->type( in(MemNode::Address) );
+  if( t == Type::TOP ) return Type::TOP;
+  t = phase->type( in(MemNode::ValueIn) );
+  if( t == Type::TOP ) return Type::TOP;
   // If extra input is TOP ==> the result is TOP
-  const Type *t1 = phase->type( in(MemNode::OopStore) );
-  if( t1 == Type::TOP ) return Type::TOP;
+  t = phase->type( in(MemNode::OopStore) );
+  if( t == Type::TOP ) return Type::TOP;
 
   return StoreNode::Value( phase );
 }
--- a/src/share/vm/opto/memnode.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/memnode.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -60,13 +60,13 @@
     debug_only(_adr_type=at; adr_type();)
   }
 
+public:
   // Helpers for the optimizer.  Documented in memnode.cpp.
   static bool detect_ptr_independence(Node* p1, AllocateNode* a1,
                                       Node* p2, AllocateNode* a2,
                                       PhaseTransform* phase);
   static bool adr_phi_is_loop_invariant(Node* adr_phi, Node* cast);
 
-public:
   // This one should probably be a phase-specific function:
   static bool detect_dominating_control(Node* dom, Node* sub);
 
@@ -97,7 +97,13 @@
 
   // What is the type of the value in memory?  (T_VOID mean "unspecified".)
   virtual BasicType memory_type() const = 0;
-  virtual int memory_size() const { return type2aelembytes[memory_type()]; }
+  virtual int memory_size() const {
+#ifdef ASSERT
+    return type2aelembytes(memory_type(), true);
+#else
+    return type2aelembytes(memory_type());
+#endif
+  }
 
   // Search through memory states which precede this node (load or store).
   // Look for an exact match for the address, with no intervening
@@ -141,6 +147,9 @@
   // zero out the control input.
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
 
+  // Recover original value from boxed values
+  Node *eliminate_autobox(PhaseGVN *phase);
+
   // Compute a new Type for this node.  Basically we just do the pre-check,
   // then call the virtual add() to set the type.
   virtual const Type *Value( PhaseTransform *phase ) const;
--- a/src/share/vm/opto/node.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/node.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1462,97 +1462,48 @@
 }
 
 //------------------------------dump_nodes-------------------------------------
-
-// Helper class  for dump_nodes. Wraps an old and new VectorSet.
-class OldNewVectorSet : public StackObj {
-   Arena*    _node_arena;
-   VectorSet _old_vset, _new_vset;
-   VectorSet* select(Node* n) {
-     return _node_arena->contains(n) ? &_new_vset : &_old_vset;
-   }
-  public:
-  OldNewVectorSet(Arena* node_arena, ResourceArea* area) :
-     _node_arena(node_arena),
-     _old_vset(area), _new_vset(area) {}
-
-  void set(Node* n)      { select(n)->set(n->_idx); }
-  bool test_set(Node* n) { return select(n)->test_set(n->_idx) != 0; }
-  bool test(Node* n)     { return select(n)->test(n->_idx) != 0; }
-  void del(Node* n)      { (*select(n)) >>= n->_idx; }
-};
-
-
 static void dump_nodes(const Node* start, int d, bool only_ctrl) {
   Node* s = (Node*)start; // remove const
   if (NotANode(s)) return;
 
+  uint depth = (uint)ABS(d);
+  int direction = d;
   Compile* C = Compile::current();
-  ResourceArea *area = Thread::current()->resource_area();
-  Node_Stack      stack(area, MIN2((uint)ABS(d), C->unique() >> 1));
-  OldNewVectorSet visited(C->node_arena(), area);
-  OldNewVectorSet on_stack(C->node_arena(), area);
-
-  visited.set(s);
-  on_stack.set(s);
-  stack.push(s, 0);
-  if (d < 0) s->dump();
-
-  // Do a depth first walk over edges
-  while (stack.is_nonempty()) {
-    Node* tp  = stack.node();
-    uint  idx = stack.index();
-    uint  limit = d > 0 ? tp->len() : tp->outcnt();
-    if (idx >= limit) {
-      // no more arcs to visit
-      if (d > 0) tp->dump();
-      on_stack.del(tp);
-      stack.pop();
-    } else {
-      // process the "idx"th arc
-      stack.set_index(idx + 1);
-      Node* n = d > 0 ? tp->in(idx) : tp->raw_out(idx);
-
-      if (NotANode(n))  continue;
-      // do not recurse through top or the root (would reach unrelated stuff)
-      if (n->is_Root() || n->is_top())  continue;
-      if (only_ctrl && !n->is_CFG()) continue;
+  GrowableArray <Node *> nstack(C->unique());
 
-      if (!visited.test_set(n)) {  // forward arc
-        // Limit depth
-        if (stack.size() < (uint)ABS(d)) {
-          if (d < 0) n->dump();
-          stack.push(n, 0);
-          on_stack.set(n);
-        }
-      } else {  // back or cross arc
-        if (on_stack.test(n)) {  // back arc
-          // print loop if there are no phis or regions in the mix
-          bool found_loop_breaker = false;
-          int k;
-          for (k = stack.size() - 1; k >= 0; k--) {
-            Node* m = stack.node_at(k);
-            if (m->is_Phi() || m->is_Region() || m->is_Root() || m->is_Start()) {
-              found_loop_breaker = true;
-              break;
-            }
-            if (m == n) // Found loop head
-              break;
-          }
-          assert(k >= 0, "n must be on stack");
+  nstack.append(s);
+  int begin = 0;
+  int end = 0;
+  for(uint i = 0; i < depth; i++) {
+    end = nstack.length();
+    for(int j = begin; j < end; j++) {
+      Node* tp  = nstack.at(j);
+      uint limit = direction > 0 ? tp->len() : tp->outcnt();
+      for(uint k = 0; k < limit; k++) {
+        Node* n = direction > 0 ? tp->in(k) : tp->raw_out(k);
 
-          if (!found_loop_breaker) {
-            tty->print("# %s LOOP FOUND:", only_ctrl ? "CONTROL" : "DATA");
-            for (int i = stack.size() - 1; i >= k; i--) {
-              Node* m = stack.node_at(i);
-              bool mnew = C->node_arena()->contains(m);
-              tty->print(" %s%d:%s", (mnew? "": "o"), m->_idx, m->Name());
-              if (i != 0) tty->print(d > 0? " <-": " ->");
-            }
-            tty->cr();
-          }
+        if (NotANode(n))  continue;
+        // do not recurse through top or the root (would reach unrelated stuff)
+        if (n->is_Root() || n->is_top())  continue;
+        if (only_ctrl && !n->is_CFG()) continue;
+
+        bool on_stack = nstack.contains(n);
+        if (!on_stack) {
+          nstack.append(n);
         }
       }
     }
+    begin = end;
+  }
+  end = nstack.length();
+  if (direction > 0) {
+    for(int j = end-1; j >= 0; j--) {
+      nstack.at(j)->dump();
+    }
+  } else {
+    for(int j = 0; j < end; j++) {
+      nstack.at(j)->dump();
+    }
   }
 }
 
--- a/src/share/vm/opto/node.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/node.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -91,6 +91,7 @@
 class Node_Stack;
 class NullCheckNode;
 class OopMap;
+class ParmNode;
 class PCTableNode;
 class PhaseCCP;
 class PhaseGVN;
@@ -557,6 +558,7 @@
       DEFINE_CLASS_ID(JumpProj,  Proj, 1)
       DEFINE_CLASS_ID(IfTrue,    Proj, 2)
       DEFINE_CLASS_ID(IfFalse,   Proj, 3)
+      DEFINE_CLASS_ID(Parm,      Proj, 4)
 
     DEFINE_CLASS_ID(Region, Node, 3)
       DEFINE_CLASS_ID(Loop, Region, 0)
@@ -712,6 +714,7 @@
   DEFINE_CLASS_QUERY(Mul)
   DEFINE_CLASS_QUERY(Multi)
   DEFINE_CLASS_QUERY(MultiBranch)
+  DEFINE_CLASS_QUERY(Parm)
   DEFINE_CLASS_QUERY(PCTable)
   DEFINE_CLASS_QUERY(Phi)
   DEFINE_CLASS_QUERY(Proj)
@@ -1381,7 +1384,7 @@
     _inode_top->indx = i;
   }
   uint size_max() const { return (uint)pointer_delta(_inode_max, _inodes,  sizeof(INode)); } // Max size
-  uint size() const { return (uint)pointer_delta(_inode_top, _inodes,  sizeof(INode)) + 1; } // Current size
+  uint size() const { return (uint)pointer_delta((_inode_top+1), _inodes,  sizeof(INode)); } // Current size
   bool is_nonempty() const { return (_inode_top >= _inodes); }
   bool is_empty() const { return (_inode_top < _inodes); }
   void clear() { _inode_top = _inodes - 1; } // retain storage
--- a/src/share/vm/opto/output.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/output.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -921,11 +921,8 @@
     // blown the code cache size.
     C->record_failure("excessive request to CodeCache");
   } else {
-    UseInterpreter            = true;
-    UseCompiler               = false;
-    AlwaysCompileLoopMethods  = false;
+    // Let CompilerBroker disable further compilations.
     C->record_failure("CodeCache is full");
-    warning("CodeCache is full. Compiling has been disabled");
   }
 }
 
--- a/src/share/vm/opto/parse.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/parse.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -54,9 +54,9 @@
   InlineTree *build_inline_tree_for_callee(ciMethod* callee_method,
                                            JVMState* caller_jvms,
                                            int caller_bci);
-  const char* try_to_inline(ciMethod* callee_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result);
-  const char* shouldInline(ciMethod* callee_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const;
-  const char* shouldNotInline(ciMethod* callee_method, WarmCallInfo* wci_result) const;
+  const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result);
+  const char* shouldInline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const;
+  const char* shouldNotInline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const;
   void        print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const PRODUCT_RETURN;
 
   InlineTree *caller_tree()       const { return _caller_tree;  }
--- a/src/share/vm/opto/parse1.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/parse1.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1836,7 +1836,7 @@
 
   PhiNode* phi = PhiNode::make(region, o, t);
   gvn().set_type(phi, t);
-  if (DoEscapeAnalysis) record_for_igvn(phi);
+  if (C->do_escape_analysis()) record_for_igvn(phi);
   map->set_req(idx, phi);
   return phi;
 }
--- a/src/share/vm/opto/parse2.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/parse2.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -885,6 +885,9 @@
 void Parse::do_ifnull(BoolTest::mask btest) {
   int target_bci = iter().get_dest();
 
+  Block* branch_block = successor_for_bci(target_bci);
+  Block* next_block   = successor_for_bci(iter().next_bci());
+
   float cnt;
   float prob = branch_prediction(cnt, btest, target_bci);
   if (prob == PROB_UNKNOWN) {
@@ -902,13 +905,16 @@
     uncommon_trap(Deoptimization::Reason_unreached,
                   Deoptimization::Action_reinterpret,
                   NULL, "cold");
+    if (EliminateAutoBox) {
+      // Mark the successor blocks as parsed
+      branch_block->next_path_num();
+      next_block->next_path_num();
+    }
     return;
   }
 
   // If this is a backwards branch in the bytecodes, add Safepoint
   maybe_add_safepoint(target_bci);
-  Block* branch_block = successor_for_bci(target_bci);
-  Block* next_block   = successor_for_bci(iter().next_bci());
 
   explicit_null_checks_inserted++;
   Node* a = null();
@@ -935,6 +941,10 @@
 
     if (stopped()) {            // Path is dead?
       explicit_null_checks_elided++;
+      if (EliminateAutoBox) {
+        // Mark the successor block as parsed
+        branch_block->next_path_num();
+      }
     } else {                    // Path is live.
       // Update method data
       profile_taken_branch(target_bci);
@@ -950,6 +960,10 @@
 
   if (stopped()) {              // Path is dead?
     explicit_null_checks_elided++;
+    if (EliminateAutoBox) {
+      // Mark the successor block as parsed
+      next_block->next_path_num();
+    }
   } else  {                     // Path is live.
     // Update method data
     profile_not_taken_branch();
@@ -962,6 +976,9 @@
 void Parse::do_if(BoolTest::mask btest, Node* c) {
   int target_bci = iter().get_dest();
 
+  Block* branch_block = successor_for_bci(target_bci);
+  Block* next_block   = successor_for_bci(iter().next_bci());
+
   float cnt;
   float prob = branch_prediction(cnt, btest, target_bci);
   float untaken_prob = 1.0 - prob;
@@ -980,6 +997,11 @@
     uncommon_trap(Deoptimization::Reason_unreached,
                   Deoptimization::Action_reinterpret,
                   NULL, "cold");
+    if (EliminateAutoBox) {
+      // Mark the successor blocks as parsed
+      branch_block->next_path_num();
+      next_block->next_path_num();
+    }
     return;
   }
 
@@ -1000,10 +1022,27 @@
   Node* tst = _gvn.transform(tst0);
   BoolTest::mask taken_btest   = BoolTest::illegal;
   BoolTest::mask untaken_btest = BoolTest::illegal;
-  if (btest == BoolTest::ne) {
-    // For now, these are the only cases of btest that matter.  (More later.)
-    taken_btest   = taken_if_true ?        btest : BoolTest::eq;
-    untaken_btest = taken_if_true ? BoolTest::eq :        btest;
+
+  if (tst->is_Bool()) {
+    // Refresh c from the transformed bool node, since it may be
+    // simpler than the original c.  Also re-canonicalize btest.
+    // This wins when (Bool ne (Conv2B p) 0) => (Bool ne (CmpP p NULL)).
+    // That can arise from statements like: if (x instanceof C) ...
+    if (tst != tst0) {
+      // Canonicalize one more time since transform can change it.
+      btest = tst->as_Bool()->_test._test;
+      if (!BoolTest(btest).is_canonical()) {
+        // Reverse edges one more time...
+        tst   = _gvn.transform( tst->as_Bool()->negate(&_gvn) );
+        btest = tst->as_Bool()->_test._test;
+        assert(BoolTest(btest).is_canonical(), "sanity");
+        taken_if_true = !taken_if_true;
+      }
+      c = tst->in(1);
+    }
+    BoolTest::mask neg_btest = BoolTest(btest).negate();
+    taken_btest   = taken_if_true ?     btest : neg_btest;
+    untaken_btest = taken_if_true ? neg_btest :     btest;
   }
 
   // Generate real control flow
@@ -1018,15 +1057,17 @@
     untaken_branch = tmp;
   }
 
-  Block* branch_block = successor_for_bci(target_bci);
-  Block* next_block   = successor_for_bci(iter().next_bci());
-
   // Branch is taken:
   { PreserveJVMState pjvms(this);
     taken_branch = _gvn.transform(taken_branch);
     set_control(taken_branch);
 
-    if (!stopped()) {
+    if (stopped()) {
+      if (EliminateAutoBox) {
+        // Mark the successor block as parsed
+        branch_block->next_path_num();
+      }
+    } else {
       // Update method data
       profile_taken_branch(target_bci);
       adjust_map_after_if(taken_btest, c, prob, branch_block, next_block);
@@ -1039,7 +1080,12 @@
   set_control(untaken_branch);
 
   // Branch not taken.
-  if (!stopped()) {
+  if (stopped()) {
+    if (EliminateAutoBox) {
+      // Mark the successor block as parsed
+      next_block->next_path_num();
+    }
+  } else {
     // Update method data
     profile_not_taken_branch();
     adjust_map_after_if(untaken_btest, c, untaken_prob,
--- a/src/share/vm/opto/phaseX.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/phaseX.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -648,79 +648,9 @@
 //=============================================================================
 //------------------------------transform--------------------------------------
 // Return a node which computes the same function as this node, but in a
-// faster or cheaper fashion.  The Node passed in here must have no other
-// pointers to it, as its storage will be reclaimed if the Node can be
-// optimized away.
+// faster or cheaper fashion.
 Node *PhaseGVN::transform( Node *n ) {
-  NOT_PRODUCT( set_transforms(); )
-
-  // Apply the Ideal call in a loop until it no longer applies
-  Node *k = n;
-  NOT_PRODUCT( uint loop_count = 0; )
-  while( 1 ) {
-    Node *i = k->Ideal(this, /*can_reshape=*/false);
-    if( !i ) break;
-    assert( i->_idx >= k->_idx, "Idealize should return new nodes, use Identity to return old nodes" );
-    // Can never reclaim storage for Ideal calls, because the Ideal call
-    // returns a new Node, bumping the High Water Mark and our old Node
-    // is caught behind the new one.
-    //if( k != i ) {
-    //k->destruct();            // Reclaim storage for recent node
-    k = i;
-    //}
-    assert(loop_count++ < K, "infinite loop in PhaseGVN::transform");
-  }
-  NOT_PRODUCT( if( loop_count != 0 ) { set_progress(); } )
-
-  // If brand new node, make space in type array.
-  ensure_type_or_null(k);
-
-  // Cache result of Value call since it can be expensive
-  // (abstract interpretation of node 'k' using phase->_types[ inputs ])
-  const Type *t = k->Value(this); // Get runtime Value set
-  assert(t != NULL, "value sanity");
-  if (type_or_null(k) != t) {
-#ifndef PRODUCT
-    // Do not record transformation or value construction on first visit
-    if (type_or_null(k) == NULL) {
-      inc_new_values();
-      set_progress();
-    }
-#endif
-    set_type(k, t);
-    // If k is a TypeNode, capture any more-precise type permanently into Node
-    k->raise_bottom_type(t);
-  }
-
-  if( t->singleton() && !k->is_Con() ) {
-    //k->destruct();              // Reclaim storage for recent node
-    NOT_PRODUCT( set_progress(); )
-    return makecon(t);          // Turn into a constant
-  }
-
-  // Now check for Identities
-  Node *i = k->Identity(this);  // Look for a nearby replacement
-  if( i != k ) {                // Found? Return replacement!
-    //k->destruct();              // Reclaim storage for recent node
-    NOT_PRODUCT( set_progress(); )
-    return i;
-  }
-
-  // Try Global Value Numbering
-  i = hash_find_insert(k);      // Found older value when i != NULL
-  if( i && i != k ) {           // Hit? Return the old guy
-    NOT_PRODUCT( set_progress(); )
-    return i;
-  }
-
-  // Collect points-to information for escape analysys
-  ConnectionGraph *cgr = C->congraph();
-  if (cgr != NULL) {
-    cgr->record_escape(k, this);
-  }
-
-  // Return Idealized original
-  return k;
+  return transform_no_reclaim(n);
 }
 
 //------------------------------transform--------------------------------------
@@ -784,6 +714,12 @@
     return i;
   }
 
+  // Collect points-to information for escape analysys
+  ConnectionGraph *cgr = C->congraph();
+  if (cgr != NULL) {
+    cgr->record_escape(k, this);
+  }
+
   // Return Idealized original
   return k;
 }
--- a/src/share/vm/opto/subnode.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/subnode.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -614,6 +614,13 @@
   const TypeOopPtr* p0 = r0->isa_oopptr();
   const TypeOopPtr* p1 = r1->isa_oopptr();
   if (p0 && p1) {
+    Node* in1 = in(1)->uncast();
+    Node* in2 = in(2)->uncast();
+    AllocateNode* alloc1 = AllocateNode::Ideal_allocation(in1, NULL);
+    AllocateNode* alloc2 = AllocateNode::Ideal_allocation(in2, NULL);
+    if (MemNode::detect_ptr_independence(in1, alloc1, in2, alloc2, NULL)) {
+      return TypeInt::CC_GT;  // different pointers
+    }
     ciKlass* klass0 = p0->klass();
     bool    xklass0 = p0->klass_is_exact();
     ciKlass* klass1 = p1->klass();
--- a/src/share/vm/opto/superword.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/superword.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -159,7 +159,8 @@
   Node_List memops;
   for (int i = 0; i < _block.length(); i++) {
     Node* n = _block.at(i);
-    if (n->is_Mem() && in_bb(n)) {
+    if (n->is_Mem() && in_bb(n) &&
+        is_java_primitive(n->as_Mem()->memory_type())) {
       int align = memory_alignment(n->as_Mem(), 0);
       if (align != bottom_align) {
         memops.push(n);
@@ -570,7 +571,7 @@
 int SuperWord::data_size(Node* s) {
   const Type* t = velt_type(s);
   BasicType  bt = t->array_element_basic_type();
-  int bsize = type2aelembytes[bt];
+  int bsize = type2aelembytes(bt);
   assert(bsize != 0, "valid size");
   return bsize;
 }
--- a/src/share/vm/opto/type.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/type.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1070,6 +1070,7 @@
 #define LShiftXNode  LShiftLNode
 // For object size computation:
 #define AddXNode     AddLNode
+#define RShiftXNode  RShiftLNode
 // For card marks and hashcodes
 #define URShiftXNode URShiftLNode
 // Opcodes
@@ -1108,6 +1109,7 @@
 #define LShiftXNode  LShiftINode
 // For object size computation:
 #define AddXNode     AddINode
+#define RShiftXNode  RShiftINode
 // For card marks and hashcodes
 #define URShiftXNode URShiftINode
 // Opcodes
--- a/src/share/vm/opto/vectornode.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/vectornode.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -135,7 +135,7 @@
   int mid = lo + ct/2;
   Node* n1 = ct == 2 ? in(lo)   : binaryTreePack(C, lo,  mid);
   Node* n2 = ct == 2 ? in(lo+1) : binaryTreePack(C, mid, hi );
-  int rslt_bsize = ct * type2aelembytes[elt_basic_type()];
+  int rslt_bsize = ct * type2aelembytes(elt_basic_type());
   if (bottom_type()->is_floatingpoint()) {
     switch (rslt_bsize) {
     case  8: return new (C, 3) PackFNode(n1, n2);
--- a/src/share/vm/opto/vectornode.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/opto/vectornode.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -48,7 +48,7 @@
   uint length() const { return _length; } // Vector length
 
   static uint max_vlen(BasicType bt) { // max vector length
-    return (uint)(Matcher::vector_width_in_bytes() / type2aelembytes[bt]);
+    return (uint)(Matcher::vector_width_in_bytes() / type2aelembytes(bt));
   }
 
   // Element and vector type
@@ -392,7 +392,7 @@
 
   virtual uint ideal_reg() const  { return Matcher::vector_ideal_reg(); }
   virtual BasicType memory_type() const { return T_VOID; }
-  virtual int memory_size() const { return length()*type2aelembytes[elt_basic_type()]; }
+  virtual int memory_size() const { return length()*type2aelembytes(elt_basic_type()); }
 
   // Vector opcode from scalar opcode
   static int opcode(int sopc, uint vlen);
@@ -620,7 +620,7 @@
 
   virtual uint ideal_reg() const  { return Matcher::vector_ideal_reg(); }
   virtual BasicType memory_type() const { return T_VOID; }
-  virtual int memory_size() const { return length()*type2aelembytes[elt_basic_type()]; }
+  virtual int memory_size() const { return length()*type2aelembytes(elt_basic_type()); }
 
   // Vector opcode from scalar opcode
   static int opcode(int sopc, uint vlen);
--- a/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -64,7 +64,7 @@
 //    0x01000000 |   16777216 - impl details: nmethod evolution info
 //    0x02000000 |   33554432 - impl details: annotation updates
 //    0x04000000 |   67108864 - impl details: StackMapTable updates
-//    0x08000000 |  134217728 - unused
+//    0x08000000 |  134217728 - impl details: OopMapCache updates
 //    0x10000000 |  268435456 - unused
 //    0x20000000 |  536870912 - unused
 //    0x40000000 | 1073741824 - unused
--- a/src/share/vm/runtime/arguments.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/arguments.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -924,10 +924,18 @@
 void Arguments::set_parnew_gc_flags() {
   assert(!UseSerialGC && !UseParallelGC, "control point invariant");
 
+  // Turn off AdaptiveSizePolicy by default for parnew until it is
+  // complete.
+  if (UseParNewGC &&
+      FLAG_IS_DEFAULT(UseAdaptiveSizePolicy)) {
+    FLAG_SET_DEFAULT(UseAdaptiveSizePolicy, false);
+  }
+
   if (FLAG_IS_DEFAULT(UseParNewGC) && ParallelGCThreads > 1) {
     FLAG_SET_DEFAULT(UseParNewGC, true);
   } else if (UseParNewGC && ParallelGCThreads == 0) {
-    FLAG_SET_DEFAULT(ParallelGCThreads, nof_parallel_gc_threads());
+    FLAG_SET_DEFAULT(ParallelGCThreads,
+                     Abstract_VM_Version::parallel_worker_threads());
     if (FLAG_IS_DEFAULT(ParallelGCThreads) && ParallelGCThreads == 1) {
       FLAG_SET_DEFAULT(UseParNewGC, false);
     }
@@ -956,25 +964,6 @@
   }
 }
 
-// CAUTION: this code is currently shared by UseParallelGC, UseParNewGC and
-// UseconcMarkSweepGC. Further tuning of individual collectors might
-// dictate refinement on a per-collector basis.
-int Arguments::nof_parallel_gc_threads() {
-  if (FLAG_IS_DEFAULT(ParallelGCThreads)) {
-    // For very large machines, there are diminishing returns
-    // for large numbers of worker threads.  Instead of
-    // hogging the whole system, use 5/8ths of a worker for every
-    // processor after the first 8.  For example, on a 72 cpu
-    // machine use 8 + (72 - 8) * (5/8) == 48 worker threads.
-    // This is just a start and needs further tuning and study in
-    // Tiger.
-    int ncpus = os::active_processor_count();
-    return (ncpus <= 8) ? ncpus : 3 + ((ncpus * 5) / 8);
-  } else {
-    return ParallelGCThreads;
-  }
-}
-
 // Adjust some sizes to suit CMS and/or ParNew needs; these work well on
 // sparc/solaris for certain applications, but would gain from
 // further optimization and tuning efforts, and would almost
@@ -984,26 +973,24 @@
     return;
   }
 
+  assert(UseConcMarkSweepGC, "CMS is expected to be on here");
+
   // If we are using CMS, we prefer to UseParNewGC,
   // unless explicitly forbidden.
-  if (UseConcMarkSweepGC && !UseParNewGC && FLAG_IS_DEFAULT(UseParNewGC)) {
-    FLAG_SET_DEFAULT(UseParNewGC, true);
+  if (!UseParNewGC && FLAG_IS_DEFAULT(UseParNewGC)) {
+    FLAG_SET_ERGO(bool, UseParNewGC, true);
   }
 
   // Turn off AdaptiveSizePolicy by default for cms until it is
-  // complete.  Also turn it off in general if the
-  // parnew collector has been selected.
-  if ((UseConcMarkSweepGC || UseParNewGC) &&
-      FLAG_IS_DEFAULT(UseAdaptiveSizePolicy)) {
+  // complete.
+  if (FLAG_IS_DEFAULT(UseAdaptiveSizePolicy)) {
     FLAG_SET_DEFAULT(UseAdaptiveSizePolicy, false);
   }
 
   // In either case, adjust ParallelGCThreads and/or UseParNewGC
   // as needed.
-  set_parnew_gc_flags();
-
-  if (!UseConcMarkSweepGC) {
-    return;
+  if (UseParNewGC) {
+    set_parnew_gc_flags();
   }
 
   // Now make adjustments for CMS
@@ -1013,7 +1000,7 @@
   intx tenuring_default;
   if (CMSUseOldDefaults) {  // old defaults: "old" as of 6.0
     if FLAG_IS_DEFAULT(CMSYoungGenPerWorker) {
-      FLAG_SET_DEFAULT(CMSYoungGenPerWorker, 4*M);
+      FLAG_SET_ERGO(intx, CMSYoungGenPerWorker, 4*M);
     }
     young_gen_per_worker = 4*M;
     new_ratio = (intx)15;
@@ -1038,16 +1025,20 @@
   // for "short" pauses ~ 4M*ParallelGCThreads
   if (FLAG_IS_DEFAULT(MaxNewSize)) {  // MaxNewSize not set at command-line
     if (!FLAG_IS_DEFAULT(NewSize)) {   // NewSize explicitly set at command-line
-      FLAG_SET_DEFAULT(MaxNewSize, MAX2(NewSize, preferred_max_new_size));
+      FLAG_SET_ERGO(uintx, MaxNewSize, MAX2(NewSize, preferred_max_new_size));
     } else {
-      FLAG_SET_DEFAULT(MaxNewSize, preferred_max_new_size);
+      FLAG_SET_ERGO(uintx, MaxNewSize, preferred_max_new_size);
     }
+    if(PrintGCDetails && Verbose) {
+      // Too early to use gclog_or_tty
+      tty->print_cr("Ergo set MaxNewSize: " SIZE_FORMAT, MaxNewSize);
+  }
   }
   // Unless explicitly requested otherwise, prefer a large
   // Old to Young gen size so as to shift the collection load
   // to the old generation concurrent collector
   if (FLAG_IS_DEFAULT(NewRatio)) {
-    FLAG_SET_DEFAULT(NewRatio, MAX2(NewRatio, new_ratio));
+    FLAG_SET_ERGO(intx, NewRatio, MAX2(NewRatio, new_ratio));
 
     size_t min_new  = align_size_up(ScaleForWordSize(min_new_default), os::vm_page_size());
     size_t prev_initial_size = initial_heap_size();
@@ -1065,19 +1056,34 @@
     size_t max_heap = align_size_down(MaxHeapSize,
                                       CardTableRS::ct_max_alignment_constraint());
 
+    if(PrintGCDetails && Verbose) {
+      // Too early to use gclog_or_tty
+      tty->print_cr("CMS set min_heap_size: " SIZE_FORMAT
+           " initial_heap_size:  " SIZE_FORMAT
+           " max_heap: " SIZE_FORMAT,
+           min_heap_size(), initial_heap_size(), max_heap);
+    }
     if (max_heap > min_new) {
       // Unless explicitly requested otherwise, make young gen
       // at least min_new, and at most preferred_max_new_size.
       if (FLAG_IS_DEFAULT(NewSize)) {
-        FLAG_SET_DEFAULT(NewSize, MAX2(NewSize, min_new));
-        FLAG_SET_DEFAULT(NewSize, MIN2(preferred_max_new_size, NewSize));
+        FLAG_SET_ERGO(uintx, NewSize, MAX2(NewSize, min_new));
+        FLAG_SET_ERGO(uintx, NewSize, MIN2(preferred_max_new_size, NewSize));
+        if(PrintGCDetails && Verbose) {
+          // Too early to use gclog_or_tty
+          tty->print_cr("Ergo set NewSize: " SIZE_FORMAT, NewSize);
+        }
       }
       // Unless explicitly requested otherwise, size old gen
       // so that it's at least 3X of NewSize to begin with;
       // later NewRatio will decide how it grows; see above.
       if (FLAG_IS_DEFAULT(OldSize)) {
         if (max_heap > NewSize) {
-          FLAG_SET_DEFAULT(OldSize, MIN2(3*NewSize,  max_heap - NewSize));
+          FLAG_SET_ERGO(uintx, OldSize, MIN2(3*NewSize,  max_heap - NewSize));
+          if(PrintGCDetails && Verbose) {
+            // Too early to use gclog_or_tty
+            tty->print_cr("Ergo set OldSize: " SIZE_FORMAT, OldSize);
+          }
         }
       }
     }
@@ -1086,14 +1092,14 @@
   // promote all objects surviving "tenuring_default" scavenges.
   if (FLAG_IS_DEFAULT(MaxTenuringThreshold) &&
       FLAG_IS_DEFAULT(SurvivorRatio)) {
-    FLAG_SET_DEFAULT(MaxTenuringThreshold, tenuring_default);
+    FLAG_SET_ERGO(intx, MaxTenuringThreshold, tenuring_default);
   }
   // If we decided above (or user explicitly requested)
   // `promote all' (via MaxTenuringThreshold := 0),
   // prefer minuscule survivor spaces so as not to waste
   // space for (non-existent) survivors
   if (FLAG_IS_DEFAULT(SurvivorRatio) && MaxTenuringThreshold == 0) {
-    FLAG_SET_DEFAULT(SurvivorRatio, MAX2((intx)1024, SurvivorRatio));
+    FLAG_SET_ERGO(intx, SurvivorRatio, MAX2((intx)1024, SurvivorRatio));
   }
   // If OldPLABSize is set and CMSParPromoteBlocksToClaim is not,
   // set CMSParPromoteBlocksToClaim equal to OldPLABSize.
@@ -1102,7 +1108,11 @@
   // See CR 6362902.
   if (!FLAG_IS_DEFAULT(OldPLABSize)) {
     if (FLAG_IS_DEFAULT(CMSParPromoteBlocksToClaim)) {
-      FLAG_SET_CMDLINE(uintx, CMSParPromoteBlocksToClaim, OldPLABSize);
+      // OldPLABSize is not the default value but CMSParPromoteBlocksToClaim
+      // is.  In this situtation let CMSParPromoteBlocksToClaim follow
+      // the value (either from the command line or ergonomics) of
+      // OldPLABSize.  Following OldPLABSize is an ergonomics decision.
+      FLAG_SET_ERGO(uintx, CMSParPromoteBlocksToClaim, OldPLABSize);
     }
     else {
       // OldPLABSize and CMSParPromoteBlocksToClaim are both set.
@@ -1147,17 +1157,11 @@
         FLAG_IS_DEFAULT(UseParallelGC)) {
       if (should_auto_select_low_pause_collector()) {
         FLAG_SET_ERGO(bool, UseConcMarkSweepGC, true);
-        set_cms_and_parnew_gc_flags();
       } else {
         FLAG_SET_ERGO(bool, UseParallelGC, true);
       }
       no_shared_spaces();
     }
-
-    // This is here because the parallel collector could
-    // have been selected so this initialization should
-    // still be done.
-    set_parallel_gc_flags();
   }
 }
 
@@ -1170,6 +1174,9 @@
   // If no heap maximum was requested explicitly, use some reasonable fraction
   // of the physical memory, up to a maximum of 1GB.
   if (UseParallelGC) {
+    FLAG_SET_ERGO(uintx, ParallelGCThreads,
+                  Abstract_VM_Version::parallel_worker_threads());
+
     if (FLAG_IS_DEFAULT(MaxHeapSize)) {
       const uint64_t reasonable_fraction =
         os::physical_memory() / DefaultMaxRAMFraction;
@@ -1227,12 +1234,13 @@
 
     if (UseParallelOldGC) {
       // Par compact uses lower default values since they are treated as
-      // minimums.
+      // minimums.  These are different defaults because of the different
+      // interpretation and are not ergonomically set.
       if (FLAG_IS_DEFAULT(MarkSweepDeadRatio)) {
-        MarkSweepDeadRatio = 1;
+        FLAG_SET_DEFAULT(MarkSweepDeadRatio, 1);
       }
       if (FLAG_IS_DEFAULT(PermMarkSweepDeadRatio)) {
-        PermMarkSweepDeadRatio = 5;
+        FLAG_SET_DEFAULT(PermMarkSweepDeadRatio, 5);
       }
     }
   }
@@ -1254,6 +1262,22 @@
 
 // Aggressive optimization flags  -XX:+AggressiveOpts
 void Arguments::set_aggressive_opts_flags() {
+#ifdef COMPILER2
+  if (AggressiveOpts || !FLAG_IS_DEFAULT(AutoBoxCacheMax)) {
+    if (FLAG_IS_DEFAULT(EliminateAutoBox)) {
+      FLAG_SET_DEFAULT(EliminateAutoBox, true);
+    }
+    if (FLAG_IS_DEFAULT(AutoBoxCacheMax)) {
+      FLAG_SET_DEFAULT(AutoBoxCacheMax, 20000);
+    }
+
+    // Feed the cache size setting into the JDK
+    char buffer[1024];
+    sprintf(buffer, "java.lang.Integer.IntegerCache.high=%d", AutoBoxCacheMax);
+    add_property(buffer);
+  }
+#endif
+
   if (AggressiveOpts) {
 // Sample flag setting code
 //    if (FLAG_IS_DEFAULT(EliminateZeroing)) {
@@ -1310,6 +1334,31 @@
           UseParallelOldGC));
 }
 
+// Check consistency of GC selection
+bool Arguments::check_gc_consistency() {
+  bool status = true;
+  // Ensure that the user has not selected conflicting sets
+  // of collectors. [Note: this check is merely a user convenience;
+  // collectors over-ride each other so that only a non-conflicting
+  // set is selected; however what the user gets is not what they
+  // may have expected from the combination they asked for. It's
+  // better to reduce user confusion by not allowing them to
+  // select conflicting combinations.
+  uint i = 0;
+  if (UseSerialGC)                       i++;
+  if (UseConcMarkSweepGC || UseParNewGC) i++;
+  if (UseParallelGC || UseParallelOldGC) i++;
+  if (i > 1) {
+    jio_fprintf(defaultStream::error_stream(),
+                "Conflicting collector combinations in option list; "
+                "please refer to the release notes for the combinations "
+                "allowed\n");
+    status = false;
+  }
+
+  return status;
+}
+
 // Check the consistency of vm_init_args
 bool Arguments::check_vm_args_consistency() {
   // Method for adding checks for flag consistency.
@@ -1352,14 +1401,14 @@
     status = false;
   }
 
-  status &= verify_percentage(MaxLiveObjectEvacuationRatio,
+  status = status && verify_percentage(MaxLiveObjectEvacuationRatio,
                               "MaxLiveObjectEvacuationRatio");
-  status &= verify_percentage(AdaptiveSizePolicyWeight,
+  status = status && verify_percentage(AdaptiveSizePolicyWeight,
                               "AdaptiveSizePolicyWeight");
-  status &= verify_percentage(AdaptivePermSizeWeight, "AdaptivePermSizeWeight");
-  status &= verify_percentage(ThresholdTolerance, "ThresholdTolerance");
-  status &= verify_percentage(MinHeapFreeRatio, "MinHeapFreeRatio");
-  status &= verify_percentage(MaxHeapFreeRatio, "MaxHeapFreeRatio");
+  status = status && verify_percentage(AdaptivePermSizeWeight, "AdaptivePermSizeWeight");
+  status = status && verify_percentage(ThresholdTolerance, "ThresholdTolerance");
+  status = status && verify_percentage(MinHeapFreeRatio, "MinHeapFreeRatio");
+  status = status && verify_percentage(MaxHeapFreeRatio, "MaxHeapFreeRatio");
 
   if (MinHeapFreeRatio > MaxHeapFreeRatio) {
     jio_fprintf(defaultStream::error_stream(),
@@ -1375,14 +1424,14 @@
     MarkSweepAlwaysCompactCount = 1;  // Move objects every gc.
   }
 
-  status &= verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
-  status &= verify_percentage(GCTimeLimit, "GCTimeLimit");
+  status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
+  status = status && verify_percentage(GCTimeLimit, "GCTimeLimit");
   if (GCTimeLimit == 100) {
     // Turn off gc-overhead-limit-exceeded checks
     FLAG_SET_DEFAULT(UseGCOverheadLimit, false);
   }
 
-  status &= verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
+  status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
 
   // Check user specified sharing option conflict with Parallel GC
   bool cannot_share = (UseConcMarkSweepGC || UseParallelGC ||
@@ -1400,24 +1449,7 @@
     }
   }
 
-  // Ensure that the user has not selected conflicting sets
-  // of collectors. [Note: this check is merely a user convenience;
-  // collectors over-ride each other so that only a non-conflicting
-  // set is selected; however what the user gets is not what they
-  // may have expected from the combination they asked for. It's
-  // better to reduce user confusion by not allowing them to
-  // select conflicting combinations.
-  uint i = 0;
-  if (UseSerialGC)                       i++;
-  if (UseConcMarkSweepGC || UseParNewGC) i++;
-  if (UseParallelGC || UseParallelOldGC) i++;
-  if (i > 1) {
-    jio_fprintf(defaultStream::error_stream(),
-                "Conflicting collector combinations in option list; "
-                "please refer to the release notes for the combinations "
-                "allowed\n");
-    status = false;
-  }
+  status = status && check_gc_consistency();
 
   if (_has_alloc_profile) {
     if (UseParallelGC || UseParallelOldGC) {
@@ -1449,15 +1481,15 @@
                   "allocation buffers\n(-XX:+UseTLAB).\n");
       status = false;
     } else {
-      status &= verify_percentage(CMSIncrementalDutyCycle,
+      status = status && verify_percentage(CMSIncrementalDutyCycle,
                                   "CMSIncrementalDutyCycle");
-      status &= verify_percentage(CMSIncrementalDutyCycleMin,
+      status = status && verify_percentage(CMSIncrementalDutyCycleMin,
                                   "CMSIncrementalDutyCycleMin");
-      status &= verify_percentage(CMSIncrementalSafetyFactor,
+      status = status && verify_percentage(CMSIncrementalSafetyFactor,
                                   "CMSIncrementalSafetyFactor");
-      status &= verify_percentage(CMSIncrementalOffset,
+      status = status && verify_percentage(CMSIncrementalOffset,
                                   "CMSIncrementalOffset");
-      status &= verify_percentage(CMSExpAvgFactor,
+      status = status && verify_percentage(CMSExpAvgFactor,
                                   "CMSExpAvgFactor");
       // If it was not set on the command line, set
       // CMSInitiatingOccupancyFraction to 1 so icms can initiate cycles early.
@@ -2062,7 +2094,8 @@
 
       // Enable parallel GC and adaptive generation sizing
       FLAG_SET_CMDLINE(bool, UseParallelGC, true);
-      FLAG_SET_DEFAULT(ParallelGCThreads, nof_parallel_gc_threads());
+      FLAG_SET_DEFAULT(ParallelGCThreads,
+                       Abstract_VM_Version::parallel_worker_threads());
 
       // Encourage steady state memory management
       FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100);
@@ -2449,15 +2482,25 @@
   no_shared_spaces();
 #endif // KERNEL
 
-  // Set some flags for ParallelGC if needed.
-  set_parallel_gc_flags();
-
-  // Set some flags for CMS and/or ParNew collectors, as needed.
-  set_cms_and_parnew_gc_flags();
-
   // Set flags based on ergonomics.
   set_ergonomics_flags();
 
+  // Check the GC selections again.
+  if (!check_gc_consistency()) {
+    return JNI_EINVAL;
+  }
+
+  if (UseParallelGC || UseParallelOldGC) {
+    // Set some flags for ParallelGC if needed.
+    set_parallel_gc_flags();
+  } else if (UseConcMarkSweepGC) {
+    // Set some flags for CMS
+    set_cms_and_parnew_gc_flags();
+  } else if (UseParNewGC) {
+    // Set some flags for ParNew
+    set_parnew_gc_flags();
+  }
+
 #ifdef SERIALGC
   assert(verify_serial_gc_flags(), "SerialGC unset");
 #endif // SERIALGC
@@ -2477,6 +2520,12 @@
     CommandLineFlags::printSetFlags();
   }
 
+#ifdef ASSERT
+  if (PrintFlagsFinal) {
+    CommandLineFlags::printFlags();
+  }
+#endif
+
   return JNI_OK;
 }
 
--- a/src/share/vm/runtime/arguments.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/arguments.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -291,8 +291,6 @@
   static bool _CIDynamicCompilePriority;
   static intx _Tier2CompileThreshold;
 
-  // GC processing
-  static int nof_parallel_gc_threads();
   // CMS/ParNew garbage collectors
   static void set_parnew_gc_flags();
   static void set_cms_and_parnew_gc_flags();
@@ -385,6 +383,8 @@
  public:
   // Parses the arguments
   static jint parse(const JavaVMInitArgs* args);
+  // Check for consistency in the selection of the garbage collector.
+  static bool check_gc_consistency();
   // Check consistecy or otherwise of VM argument settings
   static bool check_vm_args_consistency();
   // Used by os_solaris
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/deoptimization.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -141,41 +141,45 @@
 #ifdef COMPILER2
   // Reallocate the non-escaping objects and restore their fields. Then
   // relock objects if synchronization on them was eliminated.
-  if (DoEscapeAnalysis && EliminateAllocations) {
-    GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
-    bool reallocated = false;
-    if (objects != NULL) {
-      JRT_BLOCK
-        reallocated = realloc_objects(thread, &deoptee, objects, THREAD);
-      JRT_END
-    }
-    if (reallocated) {
-      reassign_fields(&deoptee, &map, objects);
-#ifndef PRODUCT
-      if (TraceDeoptimization) {
-        ttyLocker ttyl;
-        tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread);
-        print_objects(objects);
+  if (DoEscapeAnalysis) {
+    if (EliminateAllocations) {
+      GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
+      bool reallocated = false;
+      if (objects != NULL) {
+        JRT_BLOCK
+          reallocated = realloc_objects(thread, &deoptee, objects, THREAD);
+        JRT_END
       }
-#endif
-    }
-    for (int i = 0; i < chunk->length(); i++) {
-      GrowableArray<MonitorValue*>* monitors = chunk->at(i)->scope()->monitors();
-      if (monitors != NULL) {
-        relock_objects(&deoptee, &map, monitors);
+      if (reallocated) {
+        reassign_fields(&deoptee, &map, objects);
 #ifndef PRODUCT
         if (TraceDeoptimization) {
           ttyLocker ttyl;
-          tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread);
-          for (int j = 0; i < monitors->length(); i++) {
-            MonitorValue* mv = monitors->at(i);
-            if (mv->eliminated()) {
-              StackValue* owner = StackValue::create_stack_value(&deoptee, &map, mv->owner());
-              tty->print_cr("     object <" INTPTR_FORMAT "> locked", owner->get_obj()());
+          tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread);
+          print_objects(objects);
+      }
+#endif
+      }
+    }
+    if (EliminateLocks) {
+      for (int i = 0; i < chunk->length(); i++) {
+        GrowableArray<MonitorValue*>* monitors = chunk->at(i)->scope()->monitors();
+        if (monitors != NULL) {
+          relock_objects(&deoptee, &map, monitors);
+#ifndef PRODUCT
+          if (TraceDeoptimization) {
+            ttyLocker ttyl;
+            tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread);
+            for (int j = 0; j < monitors->length(); j++) {
+              MonitorValue* mv = monitors->at(j);
+              if (mv->eliminated()) {
+                StackValue* owner = StackValue::create_stack_value(&deoptee, &map, mv->owner());
+                tty->print_cr("     object <" INTPTR_FORMAT "> locked", owner->get_obj()());
+              }
             }
           }
+#endif
         }
-#endif
       }
     }
   }
@@ -656,6 +660,7 @@
 
 
   void do_field(fieldDescriptor* fd) {
+    intptr_t val;
     StackValue* value =
       StackValue::create_stack_value(_fr, _reg_map, _sv->field_at(i()));
     int offset = fd->offset();
@@ -669,24 +674,36 @@
       assert(value->type() == T_INT, "Agreement.");
       StackValue* low =
         StackValue::create_stack_value(_fr, _reg_map, _sv->field_at(++_i));
+#ifdef _LP64
+      jlong res = (jlong)low->get_int();
+#else
+#ifdef SPARC
+      // For SPARC we have to swap high and low words.
+      jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int());
+#else
       jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
+#endif //SPARC
+#endif
       _obj->long_field_put(offset, res);
       break;
     }
-
+    // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
     case T_INT: case T_FLOAT: // 4 bytes.
       assert(value->type() == T_INT, "Agreement.");
-      _obj->int_field_put(offset, (jint)value->get_int());
+      val = value->get_int();
+      _obj->int_field_put(offset, (jint)*((jint*)&val));
       break;
 
     case T_SHORT: case T_CHAR: // 2 bytes
       assert(value->type() == T_INT, "Agreement.");
-      _obj->short_field_put(offset, (jshort)value->get_int());
+      val = value->get_int();
+      _obj->short_field_put(offset, (jshort)*((jint*)&val));
       break;
 
-    case T_BOOLEAN: // 1 byte
+    case T_BOOLEAN: case T_BYTE: // 1 byte
       assert(value->type() == T_INT, "Agreement.");
-      _obj->bool_field_put(offset, (jboolean)value->get_int());
+      val = value->get_int();
+      _obj->bool_field_put(offset, (jboolean)*((jint*)&val));
       break;
 
     default:
@@ -698,25 +715,49 @@
 
 // restore elements of an eliminated type array
 void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type) {
-  StackValue* low;
-  jlong lval;
   int index = 0;
+  intptr_t val;
 
   for (int i = 0; i < sv->field_size(); i++) {
     StackValue* value = StackValue::create_stack_value(fr, reg_map, sv->field_at(i));
     switch(type) {
-      case T_BOOLEAN: obj->bool_at_put (index, (jboolean) value->get_int()); break;
-      case T_BYTE:    obj->byte_at_put (index, (jbyte)    value->get_int()); break;
-      case T_CHAR:    obj->char_at_put (index, (jchar)    value->get_int()); break;
-      case T_SHORT:   obj->short_at_put(index, (jshort)   value->get_int()); break;
-      case T_INT:     obj->int_at_put  (index, (jint)     value->get_int()); break;
-      case T_FLOAT:   obj->float_at_put(index, (jfloat)   value->get_int()); break;
-      case T_LONG:
-      case T_DOUBLE:
-        low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++i));
-        lval = jlong_from((jint)value->get_int(), (jint)low->get_int());
-        sv->value()->long_field_put(index, lval);
-        break;
+    case T_LONG: case T_DOUBLE: {
+      assert(value->type() == T_INT, "Agreement.");
+      StackValue* low =
+        StackValue::create_stack_value(fr, reg_map, sv->field_at(++i));
+#ifdef _LP64
+      jlong res = (jlong)low->get_int();
+#else
+#ifdef SPARC
+      // For SPARC we have to swap high and low words.
+      jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int());
+#else
+      jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
+#endif //SPARC
+#endif
+      obj->long_at_put(index, res);
+      break;
+    }
+
+    // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
+    case T_INT: case T_FLOAT: // 4 bytes.
+      assert(value->type() == T_INT, "Agreement.");
+      val = value->get_int();
+      obj->int_at_put(index, (jint)*((jint*)&val));
+      break;
+
+    case T_SHORT: case T_CHAR: // 2 bytes
+      assert(value->type() == T_INT, "Agreement.");
+      val = value->get_int();
+      obj->short_at_put(index, (jshort)*((jint*)&val));
+      break;
+
+    case T_BOOLEAN: case T_BYTE: // 1 byte
+      assert(value->type() == T_INT, "Agreement.");
+      val = value->get_int();
+      obj->bool_at_put(index, (jboolean)*((jint*)&val));
+      break;
+
       default:
         ShouldNotReachHere();
     }
--- a/src/share/vm/runtime/globals.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/globals.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -205,6 +205,18 @@
   return (f->origin == DEFAULT);
 }
 
+bool CommandLineFlagsEx::is_ergo(CommandLineFlag flag) {
+  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
+  Flag* f = &Flag::flags[flag];
+  return (f->origin == ERGONOMIC);
+}
+
+bool CommandLineFlagsEx::is_cmdline(CommandLineFlag flag) {
+  assert((size_t)flag < Flag::numFlags, "bad command line flag index");
+  Flag* f = &Flag::flags[flag];
+  return (f->origin == COMMAND_LINE);
+}
+
 bool CommandLineFlags::wasSetOnCmdline(const char* name, bool* value) {
   Flag* result = Flag::find_flag((char*)name, strlen(name));
   if (result == NULL) return false;
--- a/src/share/vm/runtime/globals.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/globals.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -580,7 +580,7 @@
   develop(bool, ZapJNIHandleArea, trueInDebug,                              \
           "Zap freed JNI handle space with 0xFEFEFEFE")                     \
                                                                             \
-  develop(bool, ZapUnusedHeapArea, trueInDebug,                             \
+  develop(bool, ZapUnusedHeapArea, false,                                   \
           "Zap unused heap space with 0xBAADBABE")                          \
                                                                             \
   develop(bool, PrintVMMessages, true,                                      \
@@ -1788,6 +1788,9 @@
           "number of times a GC thread (minus the coordinator) "            \
           "will sleep while yielding before giving up and resuming GC")     \
                                                                             \
+  notproduct(bool, PrintFlagsFinal, false,                                  \
+          "Print all command line flags after argument processing")         \
+                                                                            \
   /* gc tracing */                                                          \
   manageable(bool, PrintGC, false,                                          \
           "Print message at garbage collect")                               \
--- a/src/share/vm/runtime/globals_extension.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/globals_extension.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -154,6 +154,8 @@
 } CommandLineFlagWithType;
 
 #define FLAG_IS_DEFAULT(name)         (CommandLineFlagsEx::is_default(FLAG_MEMBER(name)))
+#define FLAG_IS_ERGO(name)            (CommandLineFlagsEx::is_ergo(FLAG_MEMBER(name)))
+#define FLAG_IS_CMDLINE(name)         (CommandLineFlagsEx::is_cmdline(FLAG_MEMBER(name)))
 
 #define FLAG_SET_DEFAULT(name, value) ((name) = (value))
 
@@ -171,4 +173,6 @@
   static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, FlagValueOrigin origin);
 
   static bool is_default(CommandLineFlag flag);
+  static bool is_ergo(CommandLineFlag flag);
+  static bool is_cmdline(CommandLineFlag flag);
 };
--- a/src/share/vm/runtime/reflection.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/reflection.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1548,10 +1548,11 @@
   }
 
   instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(mirror));
-  if (!klass->methods()->is_within_bounds(slot)) {
+  methodOop m = klass->method_with_idnum(slot);
+  if (m == NULL) {
     THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke");
   }
-  methodHandle method(THREAD, methodOop(klass->methods()->obj_at(slot)));
+  methodHandle method(THREAD, m);
 
   return invoke(klass, method, receiver, override, ptypes, rtype, args, true, THREAD);
 }
@@ -1564,10 +1565,11 @@
   objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Constructor::parameter_types(constructor_mirror)));
 
   instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(mirror));
-  if (!klass->methods()->is_within_bounds(slot)) {
+  methodOop m = klass->method_with_idnum(slot);
+  if (m == NULL) {
     THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke");
   }
-  methodHandle method(THREAD, methodOop(klass->methods()->obj_at(slot)));
+  methodHandle method(THREAD, m);
   assert(method->name() == vmSymbols::object_initializer_name(), "invalid constructor");
 
   // Make sure klass gets initialize
--- a/src/share/vm/runtime/sharedRuntime.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -467,6 +467,11 @@
   throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_AbstractMethodError());
 JRT_END
 
+JRT_ENTRY(void, SharedRuntime::throw_IncompatibleClassChangeError(JavaThread* thread))
+  // These errors occur only at call sites
+  throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_IncompatibleClassChangeError(), "vtable stub");
+JRT_END
+
 JRT_ENTRY(void, SharedRuntime::throw_ArithmeticException(JavaThread* thread))
   throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArithmeticException(), "/ by zero");
 JRT_END
@@ -1832,7 +1837,25 @@
                                                                         regs);
 
     B = BufferBlob::create(AdapterHandlerEntry::name, &buffer);
-    if (B == NULL)  return -2;          // Out of CodeCache space
+    if (B == NULL) {
+      // CodeCache is full, disable compilation
+      // Ought to log this but compile log is only per compile thread
+      // and we're some non descript Java thread.
+      UseInterpreter = true;
+      if (UseCompiler || AlwaysCompileLoopMethods ) {
+#ifndef PRODUCT
+        warning("CodeCache is full. Compiler has been disabled");
+        if (CompileTheWorld || ExitOnFullCodeCache) {
+          before_exit(JavaThread::current());
+          exit_globals(); // will delete tty
+          vm_direct_exit(CompileTheWorld ? 0 : 1);
+        }
+#endif
+        UseCompiler               = false;
+        AlwaysCompileLoopMethods  = false;
+      }
+      return 0; // Out of CodeCache space (_handlers[0] == NULL)
+    }
     entry->relocate(B->instructions_begin());
 #ifndef PRODUCT
     // debugging suppport
--- a/src/share/vm/runtime/sharedRuntime.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -104,6 +104,7 @@
     STACK_OVERFLOW
   };
   static void    throw_AbstractMethodError(JavaThread* thread);
+  static void    throw_IncompatibleClassChangeError(JavaThread* thread);
   static void    throw_ArithmeticException(JavaThread* thread);
   static void    throw_NullPointerException(JavaThread* thread);
   static void    throw_NullPointerException_at_call(JavaThread* thread);
--- a/src/share/vm/runtime/stubRoutines.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/stubRoutines.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -40,6 +40,7 @@
 address StubRoutines::_catch_exception_entry                    = NULL;
 address StubRoutines::_forward_exception_entry                  = NULL;
 address StubRoutines::_throw_AbstractMethodError_entry          = NULL;
+address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL;
 address StubRoutines::_throw_ArithmeticException_entry          = NULL;
 address StubRoutines::_throw_NullPointerException_entry         = NULL;
 address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
--- a/src/share/vm/runtime/stubRoutines.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/stubRoutines.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -84,6 +84,7 @@
   static address _forward_exception_entry;
   static address _catch_exception_entry;
   static address _throw_AbstractMethodError_entry;
+  static address _throw_IncompatibleClassChangeError_entry;
   static address _throw_ArithmeticException_entry;
   static address _throw_NullPointerException_entry;
   static address _throw_NullPointerException_at_call_entry;
@@ -184,6 +185,7 @@
   static address forward_exception_entry()                 { return _forward_exception_entry; }
   // Implicit exceptions
   static address throw_AbstractMethodError_entry()         { return _throw_AbstractMethodError_entry; }
+  static address throw_IncompatibleClassChangeError_entry(){ return _throw_IncompatibleClassChangeError_entry; }
   static address throw_ArithmeticException_entry()         { return _throw_ArithmeticException_entry; }
   static address throw_NullPointerException_entry()        { return _throw_NullPointerException_entry; }
   static address throw_NullPointerException_at_call_entry(){ return _throw_NullPointerException_at_call_entry; }
--- a/src/share/vm/runtime/thread.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/thread.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -1317,10 +1317,6 @@
   ThreadSafepointState::destroy(this);
   if (_thread_profiler != NULL) delete _thread_profiler;
   if (_thread_stat != NULL) delete _thread_stat;
-
-  if (jvmti_thread_state() != NULL) {
-    JvmtiExport::cleanup_thread(this);
-  }
 }
 
 
@@ -1571,6 +1567,10 @@
     tlab().make_parsable(true);  // retire TLAB
   }
 
+  if (jvmti_thread_state() != NULL) {
+    JvmtiExport::cleanup_thread(this);
+  }
+
   // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
   Threads::remove(this);
 }
@@ -2925,6 +2925,25 @@
       warning("java.lang.String not initialized");
     }
 
+    if (AggressiveOpts) {
+      // Forcibly initialize java/util/HashMap and mutate the private
+      // static final "frontCacheEnabled" field before we start creating instances
+#ifdef ASSERT
+      klassOop tmp_k = SystemDictionary::find(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
+      assert(tmp_k == NULL, "java/util/HashMap should not be loaded yet");
+#endif
+      klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
+      KlassHandle k = KlassHandle(THREAD, k_o);
+      guarantee(k.not_null(), "Must find java/util/HashMap");
+      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::frontCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
+        k()->bool_field_put(fd.offset(), true);
+      }
+    }
+
     // Initialize java_lang.System (needed before creating the thread)
     if (InitializeJavaLangSystem) {
       initialize_class(vmSymbolHandles::java_lang_System(), CHECK_0);
--- a/src/share/vm/runtime/vm_version.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/vm_version.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -52,6 +52,8 @@
 int Abstract_VM_Version::_vm_minor_version = 0;
 int Abstract_VM_Version::_vm_build_number = 0;
 bool Abstract_VM_Version::_initialized = false;
+int Abstract_VM_Version::_parallel_worker_threads = 0;
+bool Abstract_VM_Version::_parallel_worker_threads_initialized = false;
 
 void Abstract_VM_Version::initialize() {
   if (_initialized) {
@@ -210,3 +212,43 @@
   }
 #endif
 }
+
+unsigned int Abstract_VM_Version::nof_parallel_worker_threads(
+                                                      unsigned int num,
+                                                      unsigned int den,
+                                                      unsigned int switch_pt) {
+  if (FLAG_IS_DEFAULT(ParallelGCThreads)) {
+    assert(ParallelGCThreads == 0, "Default ParallelGCThreads is not 0");
+    // For very large machines, there are diminishing returns
+    // for large numbers of worker threads.  Instead of
+    // hogging the whole system, use a fraction of the workers for every
+    // processor after the first 8.  For example, on a 72 cpu machine
+    // and a chosen fraction of 5/8
+    // use 8 + (72 - 8) * (5/8) == 48 worker threads.
+    unsigned int ncpus = (unsigned int) os::active_processor_count();
+    return (ncpus <= switch_pt) ?
+           ncpus :
+          (switch_pt + ((ncpus - switch_pt) * num) / den);
+  } else {
+    return ParallelGCThreads;
+  }
+}
+
+unsigned int Abstract_VM_Version::calc_parallel_worker_threads() {
+  return nof_parallel_worker_threads(5, 8, 8);
+}
+
+
+// Does not set the _initialized flag since it is
+// a global flag.
+unsigned int Abstract_VM_Version::parallel_worker_threads() {
+  if (!_parallel_worker_threads_initialized) {
+    if (FLAG_IS_DEFAULT(ParallelGCThreads)) {
+      _parallel_worker_threads = VM_Version::calc_parallel_worker_threads();
+    } else {
+      _parallel_worker_threads = ParallelGCThreads;
+    }
+    _parallel_worker_threads_initialized = true;
+  }
+  return _parallel_worker_threads;
+}
--- a/src/share/vm/runtime/vm_version.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/runtime/vm_version.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -36,6 +36,12 @@
   static int          _vm_minor_version;
   static int          _vm_build_number;
   static bool         _initialized;
+  static int          _parallel_worker_threads;
+  static bool         _parallel_worker_threads_initialized;
+
+  static unsigned int nof_parallel_worker_threads(unsigned int num,
+                                                  unsigned int dem,
+                                                  unsigned int switch_pt);
  public:
   static void initialize();
 
@@ -69,4 +75,13 @@
   // subclasses should define new versions to hide this one as needed.  Note
   // that the O/S may support more sizes, but at most this many are used.
   static uint page_size_count() { return 2; }
+
+  // Returns the number of parallel threads to be used for VM
+  // work.  If that number has not been calculated, do so and
+  // save it.  Returns ParallelGCThreads if it is set on the
+  // command line.
+  static unsigned int parallel_worker_threads();
+  // Calculates and returns the number of parallel threads.  May
+  // be VM version specific.
+  static unsigned int calc_parallel_worker_threads();
 };
--- a/src/share/vm/services/heapDumper.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/services/heapDumper.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -997,7 +997,7 @@
   }
 
   // If the byte ordering is big endian then we can copy most types directly
-  int length_in_bytes = array->length() * type2aelembytes[type];
+  int length_in_bytes = array->length() * type2aelembytes(type);
   assert(length_in_bytes > 0, "nothing to copy");
 
   switch (type) {
--- a/src/share/vm/utilities/globalDefinitions.cpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/utilities/globalDefinitions.cpp	Thu Mar 20 09:17:30 2008 -0500
@@ -214,7 +214,7 @@
 };
 
 
-int type2aelembytes[T_CONFLICT+1] = {
+int _type2aelembytes[T_CONFLICT+1] = {
   0,                      // 0
   0,                      // 1
   0,                      // 2
@@ -230,10 +230,16 @@
   T_OBJECT_aelem_bytes,   // T_OBJECT   = 12,
   T_ARRAY_aelem_bytes,    // T_ARRAY    = 13,
   0,                      // T_VOID     = 14,
-  T_INT_aelem_bytes,      // T_ADDRESS  = 15,
+  T_OBJECT_aelem_bytes,   // T_ADDRESS  = 15,
   0                       // T_CONFLICT = 16,
 };
 
+#ifdef ASSERT
+int type2aelembytes(BasicType t, bool allow_address) {
+  assert(allow_address || t != T_ADDRESS, " ");
+  return _type2aelembytes[t];
+}
+#endif
 
 // Support for 64-bit integer arithmetic
 
--- a/src/share/vm/utilities/globalDefinitions.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -392,6 +392,10 @@
   T_ILLEGAL  = 99
 };
 
+inline bool is_java_primitive(BasicType t) {
+  return T_BOOLEAN <= t && t <= T_LONG;
+}
+
 // Convert a char from a classfile signature to a BasicType
 inline BasicType char2type(char c) {
   switch( c ) {
@@ -464,7 +468,12 @@
   T_VOID_aelem_bytes    = 0
 };
 
-extern int type2aelembytes[T_CONFLICT+1]; // maps a BasicType to nof bytes used by its array element
+extern int _type2aelembytes[T_CONFLICT+1]; // maps a BasicType to nof bytes used by its array element
+#ifdef ASSERT
+extern int type2aelembytes(BasicType t, bool allow_address = false); // asserts
+#else
+inline int type2aelembytes(BasicType t) { return _type2aelembytes[t]; }
+#endif
 
 
 // JavaValue serves as a container for arbitrary Java values.
--- a/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp	Wed Mar 19 09:58:01 2008 -0400
+++ b/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp	Thu Mar 20 09:17:30 2008 -0500
@@ -37,23 +37,45 @@
 # include <stdlib.h>
 # include <wchar.h>
 # include <stdarg.h>
+#ifdef SOLARIS
 # include <ieeefp.h>
+#endif
 # include <math.h>
+#ifdef LINUX
+#ifndef FP_PZERO
+  // Linux doesn't have positive/negative zero
+  #define FP_PZERO FP_ZERO
+#endif
+#ifndef fpclass
+  #define fpclass fpclassify
+#endif
+#endif
 # include <time.h>
 # include <fcntl.h>
 # include <dlfcn.h>
 # include <pthread.h>
+#ifdef SOLARIS
 # include <thread.h>
+#endif
 # include <limits.h>
 # include <errno.h>
+#ifdef SOLARIS
 # include <sys/trap.h>
 # include <sys/regset.h>
 # include <sys/procset.h>
 # include <ucontext.h>
 # include <setjmp.h>
+#endif
 # ifdef SOLARIS_MUTATOR_LIBTHREAD
 # include <sys/procfs.h>
 # endif
+#ifdef LINUX
+# include <inttypes.h>
+# include <signal.h>
+# include <ucontext.h>
+# include <sys/time.h>
+#endif
+
 
 // 4810578: varargs unsafe on 32-bit integer/64-bit pointer architectures
 // When __cplusplus is defined, NULL is defined as 0 (32-bit constant) in
@@ -68,6 +90,11 @@
 // pointer when it extracts the argument, then we have a problem.
 //
 // Solution: For 64-bit architectures, redefine NULL as 64-bit constant 0.
+//
+// Note: this fix doesn't work well on Linux because NULL will be overwritten
+// whenever a system header file is included. Linux handles NULL correctly
+// through a special type '__null'.
+#ifdef SOLARIS
 #ifdef _LP64
 #undef NULL
 #define NULL 0L
@@ -76,13 +103,25 @@
 #define NULL 0
 #endif
 #endif
+#endif
 
 // NULL vs NULL_WORD:
 // On Linux NULL is defined as a special type '__null'. Assigning __null to
 // integer variable will cause gcc warning. Use NULL_WORD in places where a
-// pointer is stored as integer value.
-#define NULL_WORD NULL
+// pointer is stored as integer value. On some platforms, sizeof(intptr_t) >
+// sizeof(void*), so here we want something which is integer type, but has the
+// same size as a pointer.
+#ifdef LINUX
+  #ifdef _LP64
+    #define NULL_WORD  0L
+  #else
+    #define NULL_WORD  0
+  #endif
+#else
+  #define NULL_WORD  NULL
+#endif
 
+#ifndef LINUX
 // Compiler-specific primitive types
 typedef unsigned short     uint16_t;
 #ifndef _UINT32_T
@@ -100,6 +139,7 @@
 // If this gets an error, figure out a symbol XXX that implies the
 // prior definition of intptr_t, and add "&& !defined(XXX)" above.
 #endif
+#endif
 
 // Additional Java basic types
 
@@ -128,7 +168,7 @@
 const jlong min_jlong = CONST64(0x8000000000000000);
 const jlong max_jlong = CONST64(0x7fffffffffffffff);
 
-
+#ifdef SOLARIS
 //----------------------------------------------------------------------------------------------------
 // ANSI C++ fixes
 // NOTE:In the ANSI committee's continuing attempt to make each version
@@ -162,7 +202,7 @@
    typedef int (*int_fnP_cond_tP_i_vP)(cond_t *cv, int scope, void *arg);
    typedef int (*int_fnP_cond_tP)(cond_t *cv);
 };
-
+#endif
 
 //----------------------------------------------------------------------------------------------------
 // Debugging
@@ -173,7 +213,7 @@
 #define BREAKPOINT ::breakpoint()
 
 // checking for nanness
-
+#ifdef SOLARIS
 #ifdef SPARC
 inline int g_isnan(float  f) { return isnanf(f); }
 #else
@@ -182,6 +222,12 @@
 #endif
 
 inline int g_isnan(double f) { return isnand(f); }
+#elif LINUX
+inline int g_isnan(float  f) { return isnanf(f); }
+inline int g_isnan(double f) { return isnan(f); }
+#else
+#error "missing platform-specific definition here"
+#endif
 
 // Checking for finiteness
 
@@ -195,9 +241,11 @@
 
 
 // Misc
+// NOTE: This one leads to an infinite recursion on Linux
+#ifndef LINUX
 int local_vsnprintf(char* buf, size_t count, const char* fmt, va_list argptr);
 #define vsnprintf local_vsnprintf
-
+#endif
 
 // Portability macros
 #define PRAGMA_INTERFACE