changeset 6078:80b9cc90b643

Merge
author dcubed
date Tue, 15 May 2012 11:27:24 -0700
parents b4f7c4315c36 (diff) 7d4e6dabc6bf (current diff)
children 9793f47cdebc
files make/solaris/makefiles/defs.make make/solaris/makefiles/vm.make
diffstat 320 files changed, 11176 insertions(+), 9576 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue May 15 10:52:24 2012 -0700
+++ b/.hgtags	Tue May 15 11:27:24 2012 -0700
@@ -224,3 +224,22 @@
 f92a171cf0071ca6c3fa8231d7d570377f8b2f4d hs23-b16
 f92a171cf0071ca6c3fa8231d7d570377f8b2f4d hs23-b16
 931e5f39e365a0d550d79148ff87a7f9e864d2e1 hs23-b16
+3b24e7e01d20ca590d0f86b1222bb7c3f1a2aa2d jdk8-b27
+975c4105f1e2ef1190a75b77124033f1fd4290b5 hs24-b01
+b183b0863611b85dbac16f3b08b40ba978756d19 jdk8-b28
+030b5306d60f140e822e4a6d301744cb110ff0c8 hs24-b02
+b45b5c564098c58ea69e7cff3f7d341f0254dd1d jdk8-b29
+d61761bf305031c94f7f8eca49abd978b7d3c5da jdk8-b30
+dfae0140457cfb2c381d7679735fbedbae862c62 hs24-b03
+f4767e53d6e0d5da7e3f1775904076cce54247c1 hs24-b04
+0cd147eaa673d1642b2f466f5dc257cf192db524 jdk8-b31
+27863e4586de38be7dd17da4163f542038f4d1d7 hs24-b05
+25410a347ebb0bef166c4338a90d9dea82463a20 jdk8-b32
+cd47da9383cd932cb2b659064057feafa2a91134 hs24-b06
+785bcf415ead2eaa5f6677aaf528481008140bac jdk8-b33
+7c6aba65acd2c334f1c3512b574f9038cddac24b hs24-b07
+f284b08835584517c1ca3dd67341f569e763841f jdk8-b34
+f621660a297baa48fab9dca28e99d318826e8304 jdk8-b35
+dff6e3459210f8dd0430b9b03ccc99280560da30 hs24-b08
+50b4400ca1ecb2ac2fde35f5e53ec8f04b86be7f jdk8-b36
+7d5ec8bf38d1b12e0e09ec381f10976b8beede3b hs24-b09
--- a/agent/src/os/linux/ps_core.c	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/os/linux/ps_core.c	Tue May 15 11:27:24 2012 -0700
@@ -440,7 +440,7 @@
       int j = 0;
       print_debug("---- sorted virtual address map ----\n");
       for (j = 0; j < ph->core->num_maps; j++) {
-        print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr,
+        print_debug("base = 0x%lx\tsize = %zu\n", ph->core->map_array[j]->vaddr,
                                          ph->core->map_array[j]->memsz);
       }
    }
--- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java	Tue May 15 11:27:24 2012 -0700
@@ -572,10 +572,10 @@
 
         if (cpu.equals("x86")) {
             machDesc = new MachineDescriptionIntelX86();
-        } else if (cpu.equals("amd64")) {
+        } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
             machDesc = new MachineDescriptionAMD64();
         } else {
-            throw new DebuggerException("BSD only supported on x86/amd64");
+            throw new DebuggerException("BSD only supported on x86/x86_64. Current arch: " + cpu);
         }
 
         BsdDebuggerLocal dbg = new BsdDebuggerLocal(machDesc, !isServer);
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java	Tue May 15 11:27:24 2012 -0700
@@ -762,10 +762,10 @@
 
         if (cpu.equals("x86")) {
             machDesc = new MachineDescriptionIntelX86();
-        } else if (cpu.equals("amd64")) {
+        } else if (cpu.equals("amd64") || (cpu.equals("x86_64"))) {
             machDesc = new MachineDescriptionAMD64();
         } else {
-            throw new DebuggerException("Bsd only supported on x86/amd64");
+            throw new DebuggerException("Bsd only supported on x86/x86_64. Current arch: " + cpu);
         }
 
         // Note we do not use a cache for the local debugger in server
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdCDebugger.java	Tue May 15 11:27:24 2012 -0700
@@ -90,7 +90,7 @@
        Address pc  = context.getRegisterAsAddress(X86ThreadContext.EIP);
        if (pc == null) return null;
        return new BsdX86CFrame(dbg, ebp, pc);
-    } else if (cpu.equals("amd64")) {
+    } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
        AMD64ThreadContext context = (AMD64ThreadContext) thread.getContext();
        Address rbp = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
        if (rbp == null) return null;
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThreadContextFactory.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThreadContextFactory.java	Tue May 15 11:27:24 2012 -0700
@@ -33,7 +33,7 @@
       String cpu = dbg.getCPU();
       if (cpu.equals("x86")) {
          return new BsdX86ThreadContext(dbg);
-      } else if (cpu.equals("amd64")) {
+      } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
          return new BsdAMD64ThreadContext(dbg);
       } else {
          throw new RuntimeException("cpu " + cpu + " is not yet supported");
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java	Tue May 15 11:27:24 2012 -0700
@@ -81,7 +81,7 @@
             pcRegIndex = X86ThreadContext.EIP;
             fpRegIndex = X86ThreadContext.EBP;
             unalignedAccessesOkay = true;
-        } else if (cpu.equals("amd64")) {
+        } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
             threadFactory = new ProcAMD64ThreadFactory(this);
             pcRegIndex = AMD64ThreadContext.RIP;
             fpRegIndex = AMD64ThreadContext.RBP;
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java	Tue May 15 11:27:24 2012 -0700
@@ -64,7 +64,7 @@
         cachePageSize = 4096;
         cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
         unalignedAccessesOkay = true;
-      } else if (cpu.equals("amd64")) {
+      } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
         threadFactory = new RemoteAMD64ThreadFactory(this);
         cachePageSize = 4096;
         cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
--- a/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
 public class HeapRegionSeq extends VMObject {
     // HeapRegion** _regions;
     static private AddressField regionsField;
-    // size_t _length;
+    // uint _length;
     static private CIntegerField lengthField;
 
     static {
--- a/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSetBase.java	Tue May 15 11:27:24 2012 -0700
@@ -40,9 +40,9 @@
 // Mirror class for HeapRegionSetBase. Represents a group of regions.
 
 public class HeapRegionSetBase extends VMObject {
-    // size_t _length;
+    // uint _length;
     static private CIntegerField lengthField;
-    // size_t _region_num;
+    // uint _region_num;
     static private CIntegerField regionNumField;
     // size_t _total_used_bytes;
     static private CIntegerField totalUsedBytesField;
--- a/agent/src/share/classes/sun/jvm/hotspot/jdi/ConnectorImpl.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/ConnectorImpl.java	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -217,8 +217,8 @@
     }
 
     protected void checkNativeLink(SecurityManager sm, String os) {
-        if (os.equals("SunOS") || os.equals("Linux")) {
-            // link "saproc" - SA native library on SunOS and Linux?
+        if (os.equals("SunOS") || os.equals("Linux") || os.contains("OS X")) {
+            // link "saproc" - SA native library on SunOS, Linux, and Mac OS X
             sm.checkLink("saproc");
         } else if (os.startsWith("Windows")) {
             // link "sawindbg" - SA native library on Windows.
--- a/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -889,15 +889,9 @@
         Klass kls = ((ReferenceTypeImpl)type).ref();
         if (kls instanceof InstanceKlass) {
             InstanceKlass ik = (InstanceKlass) kls;
-            if (ik.isInterface()) {
-                if (ik.nofImplementors() == 0L) {
-                    return new ArrayList(0);
-                }
-            } else {
-                // if the Klass is final or if there are no subklasses loaded yet
-                if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) {
-                    includeSubtypes = false;
-                }
+            // if the Klass is final or if there are no subklasses loaded yet
+            if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) {
+                includeSubtypes = false;
             }
         } else {
             // no subtypes for primitive array types
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayData.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayData.java	Tue May 15 11:27:24 2012 -0700
@@ -1,24 +1,24 @@
 /*
  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- *
- *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  *
  */
 
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/BranchData.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/BranchData.java	Tue May 15 11:27:24 2012 -0700
@@ -1,24 +1,24 @@
 /*
  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- *
- *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  *
  */
 
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Tue May 15 11:27:24 2012 -0700
@@ -648,7 +648,12 @@
   }
 
   public void printValueOn(PrintStream tty) {
-    tty.print("ConstantPool for " + getPoolHolder().getName().asString());
+    Oop holder = poolHolder.getValue(this);
+    if (holder instanceof Klass) {
+      tty.print("ConstantPool for " + ((Klass)holder).getName().asString());
+    } else {
+      tty.print("ConstantPool for partially loaded class");
+    }
   }
 
   public long getObjectSize() {
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/CounterData.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/CounterData.java	Tue May 15 11:27:24 2012 -0700
@@ -1,24 +1,24 @@
 /*
  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- *
- *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  *
  */
 
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/DataLayout.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/DataLayout.java	Tue May 15 11:27:24 2012 -0700
@@ -1,24 +1,24 @@
 /*
  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- *
- *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  *
  */
 
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,6 @@
   private static int HIGH_OFFSET;
   private static int GENERIC_SIGNATURE_INDEX_OFFSET;
   private static int FIELD_SLOTS;
-  public static int IMPLEMENTORS_LIMIT;
 
   // ClassState constants
   private static int CLASS_STATE_UNPARSABLE_BY_GC;
@@ -70,13 +69,6 @@
     methodOrdering       = new OopField(type.getOopField("_method_ordering"), Oop.getHeaderSize());
     localInterfaces      = new OopField(type.getOopField("_local_interfaces"), Oop.getHeaderSize());
     transitiveInterfaces = new OopField(type.getOopField("_transitive_interfaces"), Oop.getHeaderSize());
-    nofImplementors      = new CIntField(type.getCIntegerField("_nof_implementors"), Oop.getHeaderSize());
-    IMPLEMENTORS_LIMIT   = db.lookupIntConstant("instanceKlass::implementors_limit").intValue();
-    implementors         = new OopField[IMPLEMENTORS_LIMIT];
-    for (int i = 0; i < IMPLEMENTORS_LIMIT; i++) {
-      long arrayOffset = Oop.getHeaderSize() + (i * db.getAddressSize());
-      implementors[i]    = new OopField(type.getOopField("_implementors[0]"), arrayOffset);
-    }
     fields               = new OopField(type.getOopField("_fields"), Oop.getHeaderSize());
     javaFieldsCount      = new CIntField(type.getCIntegerField("_java_fields_count"), Oop.getHeaderSize());
     constants            = new OopField(type.getOopField("_constants"), Oop.getHeaderSize());
@@ -136,8 +128,6 @@
   private static OopField  methodOrdering;
   private static OopField  localInterfaces;
   private static OopField  transitiveInterfaces;
-  private static CIntField nofImplementors;
-  private static OopField[] implementors;
   private static OopField  fields;
   private static CIntField javaFieldsCount;
   private static OopField  constants;
@@ -317,9 +307,6 @@
   public TypeArray getMethodOrdering()      { return (TypeArray)    methodOrdering.getValue(this); }
   public ObjArray  getLocalInterfaces()     { return (ObjArray)     localInterfaces.getValue(this); }
   public ObjArray  getTransitiveInterfaces() { return (ObjArray)     transitiveInterfaces.getValue(this); }
-  public long      nofImplementors()        { return                nofImplementors.getValue(this); }
-  public Klass     getImplementor()         { return (Klass)        implementors[0].getValue(this); }
-  public Klass     getImplementor(int i)    { return (Klass)        implementors[i].getValue(this); }
   public TypeArray getFields()              { return (TypeArray)    fields.getValue(this); }
   public int       getJavaFieldsCount()     { return                (int) javaFieldsCount.getValue(this); }
   public int       getAllFieldsCount()      { return                (int)getFields().getLength() / FIELD_SLOTS; }
@@ -359,6 +346,12 @@
     public static final int innerClassNextOffset = 4;
   };
 
+  public static interface EnclosingMethodAttributeOffset {
+    public static final int enclosing_method_class_index_offset = 0;
+    public static final int enclosing_method_method_index_offset = 1;
+    public static final int enclosing_method_attribute_size = 2;
+  };
+
   // refer to compute_modifier_flags in VM code.
   public long computeModifierFlags() {
     long access = getAccessFlags();
@@ -367,9 +360,14 @@
     int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
     if (length > 0) {
        if (Assert.ASSERTS_ENABLED) {
-          Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
+          Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
+                      length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
+                      "just checking");
        }
        for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
+          if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
+              break;
+          }
           int ioff = innerClassList.getShortAt(i +
                          InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
           // 'ioff' can be zero.
@@ -419,9 +417,14 @@
     int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
     if (length > 0) {
        if (Assert.ASSERTS_ENABLED) {
-         Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
+         Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
+                     length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
+                     "just checking");
        }
        for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
+         if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
+             break;
+         }
          int ioff = innerClassList.getShortAt(i +
                         InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
          // 'ioff' can be zero.
@@ -511,9 +514,6 @@
       visitor.doOop(methodOrdering, true);
       visitor.doOop(localInterfaces, true);
       visitor.doOop(transitiveInterfaces, true);
-      visitor.doCInt(nofImplementors, true);
-      for (int i = 0; i < IMPLEMENTORS_LIMIT; i++)
-        visitor.doOop(implementors[i], true);
       visitor.doOop(fields, true);
       visitor.doOop(constants, true);
       visitor.doOop(classLoader, true);
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/JumpData.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/JumpData.java	Tue May 15 11:27:24 2012 -0700
@@ -1,24 +1,24 @@
 /*
  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- *
- *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  *
  */
 
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/MultiBranchData.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/MultiBranchData.java	Tue May 15 11:27:24 2012 -0700
@@ -1,24 +1,24 @@
 /*
  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- *
- *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  *
  */
 
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ReceiverTypeData.java	Tue May 15 11:27:24 2012 -0700
@@ -1,24 +1,24 @@
 /*
  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- *
- *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  *
  */
 
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/VirtualCallData.java	Tue May 15 11:27:24 2012 -0700
@@ -1,24 +1,24 @@
 /*
  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
- *
- *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  *
  */
 
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java	Tue May 15 11:27:24 2012 -0700
@@ -95,7 +95,7 @@
         } else if (os.equals("bsd")) {
             if (cpu.equals("x86")) {
                 access = new BsdX86JavaThreadPDAccess();
-            } else if (cpu.equals("amd64")) {
+            } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
                 access = new BsdAMD64JavaThreadPDAccess();
             }
         }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Tue May 15 11:27:24 2012 -0700
@@ -199,7 +199,7 @@
          cpuHelper = new SPARCHelper();
       } else if (cpu.equals("x86")) {
          cpuHelper = new X86Helper();
-      } else if (cpu.equals("amd64")) {
+      } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
          cpuHelper = new AMD64Helper();
       } else if (cpu.equals("ia64")) {
          cpuHelper = new IA64Helper();
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
       return "bsd";
     } else if (os.equals("OpenBSD")) {
       return "bsd";
-    } else if (os.equals("Darwin") || os.startsWith("Mac OS X")) {
+    } else if (os.equals("Darwin") || os.contains("OS X")) {
       return "bsd";
     } else if (os.startsWith("Windows")) {
       return "win32";
@@ -52,17 +52,17 @@
     }
   }
 
-  /* Returns "sparc" if on SPARC, "x86" if on x86. */
+  /* Returns "sparc" for SPARC based platforms and "x86" for x86 based
+     platforms. Otherwise returns the value of os.arch.  If the value
+     is not recognized as supported, an exception is thrown instead. */
   public static String getCPU() throws UnsupportedPlatformException {
     String cpu = System.getProperty("os.arch");
-    if (cpu.equals("i386")) {
+    if (cpu.equals("i386") || cpu.equals("x86")) {
       return "x86";
-    } else if (cpu.equals("sparc") || cpu.equals("x86") || cpu.equals("ia64")) {
+    } else if (cpu.equals("sparc") || cpu.equals("sparcv9")) {
+      return "sparc";
+    } else if (cpu.equals("ia64") || cpu.equals("amd64") || cpu.equals("x86_64")) {
       return cpu;
-    } else if (cpu.equals("sparcv9")) {
-      return "sparc";
-    } else if (cpu.equals("x86_64") || cpu.equals("amd64")) {
-      return "amd64";
     } else {
       throw new UnsupportedPlatformException("CPU type " + cpu + " not yet supported");
     }
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaFrame.java	Tue May 15 10:52:24 2012 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaFrame.java	Tue May 15 11:27:24 2012 -0700
@@ -153,7 +153,8 @@
             List visibleVars = new ArrayList(0);
             for (int i = 0; i < localVars.length; i++) {
                 LocalVariableTableElement cur = localVars[i];
-                if (cur.getStartBCI() >= bci && cur.getLength() > 0) {
+                int startBCI = cur.getStartBCI();
+                if (startBCI <= bci && bci < startBCI + cur.getLength()) {
                     visibleVars.add(cur);
                 }
             }
--- a/make/Makefile	Tue May 15 10:52:24 2012 -0700
+++ b/make/Makefile	Tue May 15 11:27:24 2012 -0700
@@ -288,23 +288,25 @@
 ZERO_DIR=$(ZERO_BASE_DIR)/$(VM_SUBDIR)
 SHARK_DIR=$(SHARK_BASE_DIR)/$(VM_SUBDIR)
 
-# Misc files and generated files need to come from C1 or C2 area
-ifeq ($(ZERO_BUILD), true)
-ifeq ($(SHARK_BUILD), true)
-  MISC_DIR=$(SHARK_DIR)
-  GEN_DIR=$(SHARK_BASE_DIR)/generated
-else
-  MISC_DIR=$(ZERO_DIR)
-  GEN_DIR=$(ZERO_BASE_DIR)/generated
+ifeq ($(JVM_VARIANT_SERVER), true)
+    MISC_DIR=$(C2_DIR)
+    GEN_DIR=$(C2_BASE_DIR)/generated
+endif
+ifeq ($(JVM_VARIANT_CLIENT), true)
+    MISC_DIR=$(C1_DIR)
+    GEN_DIR=$(C1_BASE_DIR)/generated
 endif
-else
-ifeq ($(ARCH_DATA_MODEL), 32)
-  MISC_DIR=$(C1_DIR)
-  GEN_DIR=$(C1_BASE_DIR)/generated
-else
-  MISC_DIR=$(C2_DIR)
-  GEN_DIR=$(C2_BASE_DIR)/generated
+ifeq ($(JVM_VARIANT_KERNEL), true)
+    MISC_DIR=$(C2_DIR)
+    GEN_DIR=$(C2_BASE_DIR)/generated
 endif
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+    MISC_DIR=$(SHARK_DIR)
+    GEN_DIR=$(SHARK_BASE_DIR)/generated
+endif
+ifeq ($(JVM_VARIANT_ZERO), true)
+    MISC_DIR=$(ZERO_DIR)
+    GEN_DIR=$(ZERO_BASE_DIR)/generated
 endif
 
 # Bin files (windows)
@@ -357,66 +359,67 @@
 
 # Shared Library
 ifneq ($(OSNAME),windows)
-  ifeq ($(ZERO_BUILD), true)
-    ifeq ($(SHARK_BUILD), true)
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
-$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
-    else
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
-$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
+    ifeq ($(JVM_VARIANT_SERVER), true)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(C2_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX):    $(C2_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: 		$(C2_DIR)/%.debuginfo
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/%.debuginfo:       		$(C2_DIR)/%.debuginfo
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/64/%.debuginfo:    		$(C2_DIR)/%.debuginfo
+		$(install-file)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: 			$(C2_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/%.diz:       			$(C2_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/64/%.diz:    			$(C2_DIR)/%.diz
+		$(install-file)
     endif
-  else
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
-$(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX):       $(C1_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
-$(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX):    $(C1_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
-$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(C2_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
-$(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX):    $(C2_DIR)/%.$(LIBRARY_SUFFIX)
-	$(install-file)
-
-# Debug info for shared library
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo
-	$(install-file)
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo
-	$(install-file)
-$(EXPORT_CLIENT_DIR)/%.debuginfo:       $(C1_DIR)/%.debuginfo
-	$(install-file)
-$(EXPORT_CLIENT_DIR)/64/%.debuginfo:    $(C1_DIR)/%.debuginfo
-	$(install-file)
-$(EXPORT_SERVER_DIR)/%.debuginfo:       $(C2_DIR)/%.debuginfo
-	$(install-file)
-$(EXPORT_SERVER_DIR)/64/%.debuginfo:    $(C2_DIR)/%.debuginfo
-	$(install-file)
-
-# ZIP'ed debug info for shared library
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C1_DIR)/%.diz
-	$(install-file)
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C2_DIR)/%.diz
-	$(install-file)
-$(EXPORT_CLIENT_DIR)/%.diz:       $(C1_DIR)/%.diz
-	$(install-file)
-$(EXPORT_CLIENT_DIR)/64/%.diz:    $(C1_DIR)/%.diz
-	$(install-file)
-$(EXPORT_SERVER_DIR)/%.diz:       $(C2_DIR)/%.diz
-	$(install-file)
-$(EXPORT_SERVER_DIR)/64/%.diz:    $(C2_DIR)/%.diz
-	$(install-file)
-  endif
+    ifeq ($(JVM_VARIANT_CLIENT), true)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX):       $(C1_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX):    $(C1_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: 		$(C1_DIR)/%.debuginfo
+		$(install-file)
+        $(EXPORT_CLIENT_DIR)/%.debuginfo:       		$(C1_DIR)/%.debuginfo
+		$(install-file)
+        $(EXPORT_CLIENT_DIR)/64/%.debuginfo:    		$(C1_DIR)/%.debuginfo
+		$(install-file)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: 			$(C1_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_CLIENT_DIR)/%.diz:       			$(C1_DIR)/%.diz
+		$(install-file)
+        $(EXPORT_CLIENT_DIR)/64/%.diz:    			$(C1_DIR)/%.diz
+		$(install-file)
+    endif
+    ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+    endif
+    ifeq ($(JVM_VARIANT_ZERO), true)
+        $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+        $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
+		$(install-file)
+    endif
 endif
 
 # Jar file (sa-jdi.jar)
 $(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar
 	$(install-file)
 
+$(EXPORT_JRE_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar
+	$(install-file)
+
 # Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h)
 $(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/%
 	$(install-file)
@@ -486,18 +489,19 @@
 	 ($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xf -)
 
 test_jdk:
-    ifeq ($(ARCH_DATA_MODEL), 32)
-      ifneq ($(ZERO_BUILD), true)
-	$(JDK_IMAGE_DIR)/bin/java -d32 -client -Xinternalversion
-	$(JDK_IMAGE_DIR)/bin/java -d32 -client -version
-      endif
-	$(JDK_IMAGE_DIR)/bin/java -d32 -server -Xinternalversion
-	$(JDK_IMAGE_DIR)/bin/java -d32 -server -version
-    endif
-    ifeq ($(ARCH_DATA_MODEL), 64)
-	$(JDK_IMAGE_DIR)/bin/java -d64 -server -Xinternalversion
-	$(JDK_IMAGE_DIR)/bin/java -d64 -server -version
-    endif
+  ifeq ($(JVM_VARIANT_CLIENT), true)
+	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -client -Xinternalversion
+	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -client -version
+  endif
+  ifeq ($(findstring true, $(JVM_VARIANT_SERVER)\
+		$(JVM_VARIANT_ZERO)$(JVM_VARIANT_ZEROSHARK)), true)
+	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -Xinternalversion
+	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -version
+  endif
+  ifeq ($(JVM_VARIANT_KERNEL), true)
+	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -Xinternalversion
+	$(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -version
+  endif
 
 copy_product_jdk::
 	$(RM) -r $(JDK_IMAGE_DIR)
--- a/make/bsd/Makefile	Tue May 15 10:52:24 2012 -0700
+++ b/make/bsd/Makefile	Tue May 15 11:27:24 2012 -0700
@@ -188,7 +188,7 @@
 # in the build.sh script:
 TARGETS           = debug jvmg fastdebug optimized profiled product
 
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   SUBDIR_DOCS     = $(OSNAME)_$(VARIANTARCH)_docs
 else
   SUBDIR_DOCS     = $(OSNAME)_$(BUILDARCH)_docs
--- a/make/bsd/makefiles/buildtree.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/bsd/makefiles/buildtree.make	Tue May 15 11:27:24 2012 -0700
@@ -58,6 +58,7 @@
 # needs to be set here since this Makefile doesn't include defs.make
 OS_VENDOR:=$(shell uname -s)
 
+-include $(SPEC)
 include $(GAMMADIR)/make/scm.make
 include $(GAMMADIR)/make/altsrc.make
 
@@ -68,7 +69,7 @@
 # For now, until the compiler is less wobbly:
 TESTFLAGS	= -Xbatch -showversion
 
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   PLATFORM_FILE = $(shell dirname $(shell dirname $(shell pwd)))/platform_zero
 else
   ifdef USE_SUNCC
@@ -247,6 +248,8 @@
 	    echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
 	    echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \
 	echo; \
+	[ -n "$(SPEC)" ] && \
+	    echo "include $(SPEC)"; \
 	echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \
 	echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \
 	) > $@
--- a/make/bsd/makefiles/defs.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/bsd/makefiles/defs.make	Tue May 15 11:27:24 2012 -0700
@@ -38,7 +38,7 @@
 endif
 
 # zero
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   ifeq ($(ARCH_DATA_MODEL), 64)
     MAKE_ARGS      += LP64=1
   endif
@@ -124,6 +124,18 @@
   HS_ARCH          = ppc
 endif
 
+# On 32 bit bsd we build server and client, on 64 bit just server.
+ifeq ($(JVM_VARIANTS),)
+  ifeq ($(ARCH_DATA_MODEL), 32)
+    JVM_VARIANTS:=client,server
+    JVM_VARIANT_CLIENT:=true
+    JVM_VARIANT_SERVER:=true
+  else
+    JVM_VARIANTS:=server
+    JVM_VARIANT_SERVER:=true
+  endif
+endif
+
 JDK_INCLUDE_SUBDIR=bsd
 
 # Library suffix
@@ -144,16 +156,16 @@
 EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
 EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
 
-ifndef BUILD_CLIENT_ONLY
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
+EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
+
+ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
 endif
 
-ifneq ($(ZERO_BUILD), true)
-  ifeq ($(ARCH_DATA_MODEL), 32)
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
-  endif
+ifeq ($(JVM_VARIANT_CLIENT),true)
+  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
+  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
 endif
 
 # Serviceability Binaries
--- a/make/bsd/makefiles/gcc.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/bsd/makefiles/gcc.make	Tue May 15 11:27:24 2012 -0700
@@ -27,53 +27,57 @@
 #------------------------------------------------------------------------
 # CC, CXX & AS
 
-# When cross-compiling the ALT_COMPILER_PATH points
-# to the cross-compilation toolset
-ifdef CROSS_COMPILE_ARCH
- CXX = $(ALT_COMPILER_PATH)/g++
- CC  = $(ALT_COMPILER_PATH)/gcc
- HOSTCXX = g++
- HOSTCC  = gcc
-else ifneq ($(OS_VENDOR), Darwin)
- CXX = g++
- CC  = gcc
- HOSTCXX = $(CXX)
- HOSTCC  = $(CC)
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+  # When cross-compiling the ALT_COMPILER_PATH points
+  # to the cross-compilation toolset
+  ifdef CROSS_COMPILE_ARCH
+    CXX = $(ALT_COMPILER_PATH)/g++
+    CC  = $(ALT_COMPILER_PATH)/gcc
+    HOSTCXX = g++
+    HOSTCC  = gcc
+  else ifneq ($(OS_VENDOR), Darwin)
+    CXX = g++
+    CC  = gcc
+    HOSTCXX = $(CXX)
+    HOSTCC  = $(CC)
+  endif
+
+  # i486 hotspot requires -mstackrealign on Darwin.
+  # llvm-gcc supports this in Xcode 3.2.6 and 4.0.
+  # gcc-4.0 supports this on earlier versions.
+  # Prefer llvm-gcc where available.
+  ifeq ($(OS_VENDOR), Darwin)
+    ifeq ($(origin CXX), default)
+      CXX = llvm-g++
+    endif
+    ifeq ($(origin CC), default)
+      CC  = llvm-gcc
+    endif
+
+    ifeq ($(ARCH), i486)
+      LLVM_SUPPORTS_STACKREALIGN := $(shell \
+       [ "0"`llvm-gcc -v 2>&1 | grep LLVM | sed -E "s/.*LLVM build ([0-9]+).*/\1/"` -gt "2333" ] \
+       && echo true || echo false)
+
+      ifeq ($(LLVM_SUPPORTS_STACKREALIGN), true)
+        CXX32 ?= llvm-g++
+        CC32  ?= llvm-gcc
+      else
+        CXX32 ?= g++-4.0
+        CC32  ?= gcc-4.0
+      endif
+      CXX = $(CXX32)
+      CC  = $(CC32)
+    endif
+
+    HOSTCXX = $(CXX)
+    HOSTCC  = $(CC)
+  endif
+
+  AS   = $(CC) -c -x assembler-with-cpp
 endif
 
-# i486 hotspot requires -mstackrealign on Darwin.
-# llvm-gcc supports this in Xcode 3.2.6 and 4.0.
-# gcc-4.0 supports this on earlier versions.
-# Prefer llvm-gcc where available.
-ifeq ($(OS_VENDOR), Darwin)
-  ifeq ($(origin CXX), default)
-   CXX = llvm-g++
-  endif
-  ifeq ($(origin CC), default)
-   CC  = llvm-gcc
-  endif
-
-  ifeq ($(ARCH), i486)
-  LLVM_SUPPORTS_STACKREALIGN := $(shell \
-   [ "0"`llvm-gcc -v 2>&1 | grep LLVM | sed -E "s/.*LLVM build ([0-9]+).*/\1/"` -gt "2333" ] \
-   && echo true || echo false)
-
-  ifeq ($(LLVM_SUPPORTS_STACKREALIGN), true)
-    CXX32 ?= llvm-g++
-    CC32  ?= llvm-gcc
-  else
-    CXX32 ?= g++-4.0
-    CC32  ?= gcc-4.0
-  endif
-  CXX = $(CXX32)
-  CC  = $(CC32)
-  endif
-
-  HOSTCXX = $(CXX)
-  HOSTCC  = $(CC)
-endif
-
-AS   = $(CC) -c -x assembler-with-cpp
 
 # -dumpversion in gcc-2.91 shows "egcs-2.91.66". In later version, it only
 # prints the numbers (e.g. "2.95", "3.2.1")
@@ -101,11 +105,12 @@
 VM_PICFLAG/AOUT   =
 VM_PICFLAG        = $(VM_PICFLAG/$(LINK_INTO))
 
-ifeq ($(ZERO_BUILD), true)
-CFLAGS += $(LIBFFI_CFLAGS)
+ifeq ($(JVM_VARIANT_ZERO), true)
+  CFLAGS += $(LIBFFI_CFLAGS)
 endif
-ifeq ($(SHARK_BUILD), true)
-CFLAGS += $(LLVM_CFLAGS)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+  CFLAGS += $(LIBFFI_CFLAGS)
+  CFLAGS += $(LLVM_CFLAGS)
 endif
 CFLAGS += $(VM_PICFLAG)
 CFLAGS += -fno-rtti
--- a/make/bsd/makefiles/sparcWorks.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/bsd/makefiles/sparcWorks.make	Tue May 15 11:27:24 2012 -0700
@@ -25,12 +25,15 @@
 #------------------------------------------------------------------------
 # CC, CXX & AS
 
-CXX = CC
-CC  = cc
-AS  = $(CC) -c
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+  CXX = CC
+  CC  = cc
+  AS  = $(CC) -c
 
-HOSTCXX = $(CXX)
-HOSTCC  = $(CC)
+  HOSTCXX = $(CXX)
+  HOSTCC  = $(CC)
+endif
 
 ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
 ARCHFLAG/i486    = -m32
--- a/make/bsd/makefiles/vm.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/bsd/makefiles/vm.make	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
 -include $(DEP_DIR)/*.d
 
 # read machine-specific adjustments (%%% should do this via buildtree.make?)
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   include $(MAKEFILES_DIR)/zeroshark.make
 else
   include $(MAKEFILES_DIR)/$(BUILDARCH).make
@@ -271,12 +271,12 @@
 
   LIBS_VM                  += $(LIBS)
 endif
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(JVM_VARIANT_ZERO), true)
   LIBS_VM += $(LIBFFI_LIBS)
 endif
-ifeq ($(SHARK_BUILD), true)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+  LIBS_VM   += $(LIBFFI_LIBS) $(LLVM_LIBS)
   LFLAGS_VM += $(LLVM_LDFLAGS)
-  LIBS_VM   += $(LLVM_LIBS)
 endif
 
 
@@ -335,6 +335,9 @@
 # Serviceability agent
 include $(MAKEFILES_DIR)/saproc.make
 
+# Whitebox testing API
+include $(MAKEFILES_DIR)/wb.make
+
 #----------------------------------------------------------------------
 
 ifeq ($(OS_VENDOR), Darwin)
@@ -342,10 +345,10 @@
 	dsymutil $(LIBJVM)
 
 # no libjvm_db for macosx
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM $(WB_JAR)
 	echo "Doing vm.make build:"
 else
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC)
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) $(WB_JAR)
 endif
 
 install: install_jvm install_jsig install_saproc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/bsd/makefiles/wb.make	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#  
+#
+
+# Rules to build whitebox testing library, used by vm.make
+WB = wb
+
+WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox
+
+WB_JAR = $(GENERATED)/$(WB).jar
+
+WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java')
+WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes
+
+WB_JAVA_CLASSES  = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
+	$(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
+
+$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
+	$(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
+
+$(WB_JAR): $(WB_JAVA_CLASSES)
+	$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
+
+$(WB_JAVA_CLASSDIR):
+	$(QUIETLY) mkdir -p $@
+
--- a/make/defs.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/defs.make	Tue May 15 11:27:24 2012 -0700
@@ -24,6 +24,11 @@
 
 # The common definitions for hotspot builds.
 
+# Optionally include SPEC file generated by configure.
+ifneq ($(SPEC),)
+  include $(SPEC)
+endif
+
 # Default to verbose build logs (show all compile lines):
 MAKE_VERBOSE=y
 
@@ -50,6 +55,27 @@
 @$(RM) $@
 endef
 
+# Default values for JVM_VARIANT* variables if configure hasn't set
+# it already.
+ifeq ($(JVM_VARIANTS),)
+  ifeq ($(ZERO_BUILD), true)
+    ifeq ($(SHARK_BUILD), true)
+      JVM_VARIANTS:=zeroshark
+      JVM_VARIANT_ZEROSHARK:=true
+    else
+      JVM_VARIANTS:=zero
+      JVM_VARIANT_ZERO:=true
+    endif
+  else
+    # A default is needed
+    ifeq ($(BUILD_CLIENT_ONLY), true)
+      JVM_VARIANTS:=client
+      JVM_VARIANT_CLIENT:=true
+    endif
+    # Further defaults are platform and arch specific
+  endif
+endif
+
 # Directory paths and user name
 # Unless GAMMADIR is set on the command line, search upward from
 # the current directory for a parent directory containing "src/share/vm".
--- a/make/hotspot_version	Tue May 15 10:52:24 2012 -0700
+++ b/make/hotspot_version	Tue May 15 11:27:24 2012 -0700
@@ -33,9 +33,9 @@
 # Don't put quotes (fail windows build).
 HOTSPOT_VM_COPYRIGHT=Copyright 2011
 
-HS_MAJOR_VER=23
+HS_MAJOR_VER=24
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=16
+HS_BUILD_NUMBER=10
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/make/jprt.properties	Tue May 15 10:52:24 2012 -0700
+++ b/make/jprt.properties	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -54,58 +54,72 @@
 # Define the Solaris platforms we want for the various releases
 jprt.my.solaris.sparc.jdk8=solaris_sparc_5.10
 jprt.my.solaris.sparc.jdk7=solaris_sparc_5.10
+jprt.my.solaris.sparc.jdk7u4=${jprt.my.solaris.sparc.jdk7}
 jprt.my.solaris.sparc=${jprt.my.solaris.sparc.${jprt.tools.default.release}}
 
 jprt.my.solaris.sparcv9.jdk8=solaris_sparcv9_5.10
 jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10
+jprt.my.solaris.sparcv9.jdk7u4=${jprt.my.solaris.sparcv9.jdk7}
 jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}}
 
 jprt.my.solaris.i586.jdk8=solaris_i586_5.10
 jprt.my.solaris.i586.jdk7=solaris_i586_5.10
+jprt.my.solaris.i586.jdk7u4=${jprt.my.solaris.i586.jdk7}
 jprt.my.solaris.i586=${jprt.my.solaris.i586.${jprt.tools.default.release}}
 
 jprt.my.solaris.x64.jdk8=solaris_x64_5.10
 jprt.my.solaris.x64.jdk7=solaris_x64_5.10
+jprt.my.solaris.x64.jdk7u4=${jprt.my.solaris.x64.jdk7}
 jprt.my.solaris.x64=${jprt.my.solaris.x64.${jprt.tools.default.release}}
 
 jprt.my.linux.i586.jdk8=linux_i586_2.6
 jprt.my.linux.i586.jdk7=linux_i586_2.6
+jprt.my.linux.i586.jdk7u4=${jprt.my.linux.i586.jdk7}
 jprt.my.linux.i586=${jprt.my.linux.i586.${jprt.tools.default.release}}
 
 jprt.my.linux.x64.jdk8=linux_x64_2.6
 jprt.my.linux.x64.jdk7=linux_x64_2.6
+jprt.my.linux.x64.jdk7u4=${jprt.my.linux.x64.jdk7}
 jprt.my.linux.x64=${jprt.my.linux.x64.${jprt.tools.default.release}}
 
 jprt.my.linux.ppc.jdk8=linux_ppc_2.6
 jprt.my.linux.ppc.jdk7=linux_ppc_2.6
+jprt.my.linux.ppc.jdk7u4=${jprt.my.linux.ppc.jdk7}
 jprt.my.linux.ppc=${jprt.my.linux.ppc.${jprt.tools.default.release}}
 
 jprt.my.linux.ppcv2.jdk8=linux_ppcv2_2.6
 jprt.my.linux.ppcv2.jdk7=linux_ppcv2_2.6
+jprt.my.linux.ppcv2.jdk7u4=${jprt.my.linux.ppcv2.jdk7}
 jprt.my.linux.ppcv2=${jprt.my.linux.ppcv2.${jprt.tools.default.release}}
 
 jprt.my.linux.ppcsflt.jdk8=linux_ppcsflt_2.6
 jprt.my.linux.ppcsflt.jdk7=linux_ppcsflt_2.6
+jprt.my.linux.ppcsflt.jdk7u4=${jprt.my.linux.ppcsflt.jdk7}
 jprt.my.linux.ppcsflt=${jprt.my.linux.ppcsflt.${jprt.tools.default.release}}
 
 jprt.my.linux.armvfp.jdk8=linux_armvfp_2.6
 jprt.my.linux.armvfp.jdk7=linux_armvfp_2.6
+jprt.my.linux.armvfp.jdk7u4=${jprt.my.linux.armvfp.jdk7}
 jprt.my.linux.armvfp=${jprt.my.linux.armvfp.${jprt.tools.default.release}}
 
 jprt.my.linux.armsflt.jdk8=linux_armsflt_2.6
 jprt.my.linux.armsflt.jdk7=linux_armsflt_2.6
+jprt.my.linux.armsflt.jdk7u4=${jprt.my.linux.armsflt.jdk7}
 jprt.my.linux.armsflt=${jprt.my.linux.armsflt.${jprt.tools.default.release}}
 
 jprt.my.macosx.x64.jdk8=macosx_x64_10.7
 jprt.my.macosx.x64.jdk7=macosx_x64_10.7
+jprt.my.macosx.x64.jdk7u4=${jprt.my.macosx.x64.jdk7}
 jprt.my.macosx.x64=${jprt.my.macosx.x64.${jprt.tools.default.release}}
 
 jprt.my.windows.i586.jdk8=windows_i586_5.1
 jprt.my.windows.i586.jdk7=windows_i586_5.1
+jprt.my.windows.i586.jdk7u4=${jprt.my.windows.i586.jdk7}
 jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}}
 
 jprt.my.windows.x64.jdk8=windows_x64_5.2
 jprt.my.windows.x64.jdk7=windows_x64_5.2
+jprt.my.windows.x64.jdk7u4=${jprt.my.windows.x64.jdk7}
 jprt.my.windows.x64=${jprt.my.windows.x64.${jprt.tools.default.release}}
 
 # Standard list of jprt build targets for this source tree
@@ -139,16 +153,7 @@
 
 jprt.build.targets.jdk8=${jprt.build.targets.all}
 jprt.build.targets.jdk7=${jprt.build.targets.all}
-jprt.build.targets.jdk7temp=${jprt.build.targets.all}
-jprt.build.targets.jdk7b107=${jprt.build.targets.all}
-jprt.build.targets.jdk6=${jprt.build.targets.standard}
-jprt.build.targets.jdk6perf=${jprt.build.targets.standard}
-jprt.build.targets.jdk6u10=${jprt.build.targets.standard}
-jprt.build.targets.jdk6u14=${jprt.build.targets.standard}
-jprt.build.targets.jdk6u18=${jprt.build.targets.standard}
-jprt.build.targets.jdk6u20=${jprt.build.targets.standard}
-jprt.build.targets.ejdk6=${jprt.build.targets.all}
-jprt.build.targets.ejdk7=${jprt.build.targets.all}
+jprt.build.targets.jdk7u4=${jprt.build.targets.all}
 jprt.build.targets=${jprt.build.targets.${jprt.tools.default.release}}
 
 # Subset lists of test targets for this source tree
@@ -441,6 +446,7 @@
 
 jprt.test.targets.jdk8=${jprt.test.targets.standard}
 jprt.test.targets.jdk7=${jprt.test.targets.standard}
+jprt.test.targets.jdk7u4=${jprt.test.targets.jdk7}
 jprt.test.targets=${jprt.test.targets.${jprt.tools.default.release}}
 
 # The default test/Makefile targets that should be run
@@ -474,16 +480,32 @@
   ${jprt.my.macosx.x64}-fastdebug-c2-internalvmtests, \
   ${jprt.my.windows.i586}-fastdebug-c2-internalvmtests, \
   ${jprt.my.windows.x64}-fastdebug-c2-internalvmtests
-  
+
+jprt.make.rule.test.targets.standard.wbapi = \
+  ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-wbapitest, \
+  ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-wbapitest, \
+  ${jprt.my.solaris.i586}-{product|fastdebug}-c2-wbapitest, \
+  ${jprt.my.solaris.x64}-{product|fastdebug}-c2-wbapitest, \
+  ${jprt.my.linux.i586}-{product|fastdebug}-c2-wbapitest, \
+  ${jprt.my.linux.x64}-{product|fastdebug}-c2-wbapitest, \
+  ${jprt.my.windows.i586}-{product|fastdebug}-c2-wbapitest, \
+  ${jprt.my.windows.x64}-{product|fastdebug}-c2-wbapitest, \
+  ${jprt.my.solaris.sparc}-{product|fastdebug}-c1-wbapitest, \
+  ${jprt.my.solaris.i586}-{product|fastdebug}-c1-wbapitest, \
+  ${jprt.my.linux.i586}-{product|fastdebug}-c1-wbapitest, \
+  ${jprt.my.windows.i586}-{product|fastdebug}-c1-wbapitest
+
 jprt.make.rule.test.targets.standard = \
   ${jprt.make.rule.test.targets.standard.client}, \
   ${jprt.make.rule.test.targets.standard.server}, \
-  ${jprt.make.rule.test.targets.standard.internalvmtests}
+  ${jprt.make.rule.test.targets.standard.internalvmtests}, \
+  ${jprt.make.rule.test.targets.standard.wbapi}
 
 jprt.make.rule.test.targets.embedded = \
   ${jprt.make.rule.test.targets.standard.client}
 
 jprt.make.rule.test.targets.jdk8=${jprt.make.rule.test.targets.standard}
 jprt.make.rule.test.targets.jdk7=${jprt.make.rule.test.targets.standard}
+jprt.make.rule.test.targets.jdk7u4=${jprt.make.rule.test.targets.jdk7}
 jprt.make.rule.test.targets=${jprt.make.rule.test.targets.${jprt.tools.default.release}}
 
--- a/make/linux/Makefile	Tue May 15 10:52:24 2012 -0700
+++ b/make/linux/Makefile	Tue May 15 11:27:24 2012 -0700
@@ -188,7 +188,7 @@
 # in the build.sh script:
 TARGETS           = debug jvmg fastdebug optimized profiled product
 
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   SUBDIR_DOCS     = $(OSNAME)_$(VARIANTARCH)_docs
 else
   SUBDIR_DOCS     = $(OSNAME)_$(BUILDARCH)_docs
--- a/make/linux/makefiles/buildtree.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/linux/makefiles/buildtree.make	Tue May 15 11:27:24 2012 -0700
@@ -55,6 +55,7 @@
 # The makefiles are split this way so that "make foo" will run faster by not
 # having to read the dependency files for the vm.
 
+-include $(SPEC)
 include $(GAMMADIR)/make/scm.make
 include $(GAMMADIR)/make/altsrc.make
 
@@ -65,7 +66,7 @@
 # For now, until the compiler is less wobbly:
 TESTFLAGS	= -Xbatch -showversion
 
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   PLATFORM_FILE = $(shell dirname $(shell dirname $(shell pwd)))/platform_zero
 else
   ifdef USE_SUNCC
@@ -250,6 +251,8 @@
 	    echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
 	    echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \
 	echo; \
+	[ -n "$(SPEC)" ] && \
+	    echo "include $(SPEC)"; \
 	echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \
 	echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \
 	) > $@
--- a/make/linux/makefiles/defs.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/linux/makefiles/defs.make	Tue May 15 11:27:24 2012 -0700
@@ -38,7 +38,7 @@
 endif
 
 # zero
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   ifeq ($(ARCH_DATA_MODEL), 64)
     MAKE_ARGS      += LP64=1
   endif
@@ -114,6 +114,18 @@
   HS_ARCH          = ppc
 endif
 
+# On 32 bit linux we build server and client, on 64 bit just server.
+ifeq ($(JVM_VARIANTS),)
+  ifeq ($(ARCH_DATA_MODEL), 32)
+    JVM_VARIANTS:=client,server
+    JVM_VARIANT_CLIENT:=true
+    JVM_VARIANT_SERVER:=true
+  else
+    JVM_VARIANTS:=server
+    JVM_VARIANT_SERVER:=true
+  endif
+endif
+
 # determine if HotSpot is being built in JDK6 or earlier version
 JDK6_OR_EARLIER=0
 ifeq "$(shell expr \( '$(JDK_MAJOR_VERSION)' != '' \& '$(JDK_MINOR_VERSION)' != '' \& '$(JDK_MICRO_VERSION)' != '' \))" "1"
@@ -237,9 +249,11 @@
 EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
 EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
 
-ifndef BUILD_CLIENT_ONLY
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
+EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
+
+ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
     ifeq ($(ZIP_DEBUGINFO_FILES),1)
       EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.diz
@@ -249,18 +263,16 @@
   endif
 endif
 
-ifneq ($(ZERO_BUILD), true)
-  ifeq ($(ARCH_DATA_MODEL), 32)
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
-    ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
-      ifeq ($(ZIP_DEBUGINFO_FILES),1)
-        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.diz
-      else
-        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
-      endif
+ifeq ($(JVM_VARIANT_CLIENT),true)
+  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
+  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.diz
+    else
+      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
     endif
-  endif
+  endif 
 endif
 
 # Serviceability Binaries
--- a/make/linux/makefiles/gcc.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/linux/makefiles/gcc.make	Tue May 15 11:27:24 2012 -0700
@@ -25,21 +25,26 @@
 #------------------------------------------------------------------------
 # CC, CXX & AS
 
-# When cross-compiling the ALT_COMPILER_PATH points
-# to the cross-compilation toolset
-ifdef CROSS_COMPILE_ARCH
-CXX = $(ALT_COMPILER_PATH)/g++
-CC  = $(ALT_COMPILER_PATH)/gcc
-HOSTCXX = g++
-HOSTCC  = gcc
-else
-CXX = g++
-CC  = gcc
-HOSTCXX = $(CXX)
-HOSTCC  = $(CC)
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+  # When cross-compiling the ALT_COMPILER_PATH points
+  # to the cross-compilation toolset
+  ifdef CROSS_COMPILE_ARCH
+    CXX = $(ALT_COMPILER_PATH)/g++
+    CC  = $(ALT_COMPILER_PATH)/gcc
+    HOSTCXX = g++
+    HOSTCC  = gcc
+    STRIP = $(ALT_COMPILER_PATH)/strip
+  else
+    CXX = g++
+    CC  = gcc
+    HOSTCXX = $(CXX)
+    HOSTCC  = $(CC)
+    STRIP = strip
+  endif
+  AS  = $(CC) -c
 endif
 
-AS  = $(CC) -c
 
 # -dumpversion in gcc-2.91 shows "egcs-2.91.66". In later version, it only
 # prints the numbers (e.g. "2.95", "3.2.1")
@@ -67,10 +72,11 @@
 VM_PICFLAG/AOUT   =
 VM_PICFLAG        = $(VM_PICFLAG/$(LINK_INTO))
 
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(JVM_VARIANT_ZERO), true)
 CFLAGS += $(LIBFFI_CFLAGS)
 endif
-ifeq ($(SHARK_BUILD), true)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+CFLAGS += $(LIBFFI_CFLAGS)
 CFLAGS += $(LLVM_CFLAGS)
 endif
 CFLAGS += $(VM_PICFLAG)
@@ -261,9 +267,3 @@
 ifdef MINIMIZE_RAM_USAGE
 CFLAGS += -DMINIMIZE_RAM_USAGE
 endif
-
-ifdef CROSS_COMPILE_ARCH
-  STRIP = $(ALT_COMPILER_PATH)/strip
-else
-  STRIP = strip
-endif
--- a/make/linux/makefiles/ppc.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/linux/makefiles/ppc.make	Tue May 15 11:27:24 2012 -0700
@@ -28,3 +28,6 @@
 # Must also specify if CPU is big endian
 CFLAGS += -DVM_BIG_ENDIAN
 
+ifdef E500V2
+ASFLAGS += -Wa,-mspe -Wa,--defsym -Wa,E500V2=1 
+endif
--- a/make/linux/makefiles/sparcWorks.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/linux/makefiles/sparcWorks.make	Tue May 15 11:27:24 2012 -0700
@@ -25,12 +25,15 @@
 #------------------------------------------------------------------------
 # CC, CXX & AS
 
-CXX = CC
-CC  = cc
-AS  = $(CC) -c
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+  CXX = CC
+  CC  = cc
+  AS  = $(CC) -c
 
-HOSTCXX = $(CXX)
-HOSTCC  = $(CC)
+  HOSTCXX = $(CXX)
+  HOSTCC  = $(CC)
+endif
 
 ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
 ARCHFLAG/i486    = -m32
--- a/make/linux/makefiles/vm.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/linux/makefiles/vm.make	Tue May 15 11:27:24 2012 -0700
@@ -42,7 +42,7 @@
 -include $(DEP_DIR)/*.d
 
 # read machine-specific adjustments (%%% should do this via buildtree.make?)
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   include $(MAKEFILES_DIR)/zeroshark.make
 else
   include $(MAKEFILES_DIR)/$(BUILDARCH).make
@@ -238,7 +238,7 @@
 vm.def: $(Res_Files) $(Obj_Files)
 	sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@
 
-ifeq ($(SHARK_BUILD), true)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
   STATIC_CXX = false
 else
   ifeq ($(ZERO_LIBARCH), ppc64)
@@ -270,12 +270,12 @@
 
   LIBS_VM                  += $(LIBS)
 endif
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(JVM_VARIANT_ZERO), true)
   LIBS_VM += $(LIBFFI_LIBS)
 endif
-ifeq ($(SHARK_BUILD), true)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+  LIBS_VM   += $(LIBFFI_LIBS) $(LLVM_LIBS)
   LFLAGS_VM += $(LLVM_LDFLAGS)
-  LIBS_VM   += $(LLVM_LIBS)
 endif
 
 LINK_VM = $(LINK_LIB.CC)
@@ -378,9 +378,12 @@
 # Serviceability agent
 include $(MAKEFILES_DIR)/saproc.make
 
+# Whitebox testing API
+include $(MAKEFILES_DIR)/wb.make
+
 #----------------------------------------------------------------------
 
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC)
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) $(WB_JAR)
 
 install: install_jvm install_jsig install_saproc
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/linux/makefiles/wb.make	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#  
+#
+
+# Rules to build whitebox testing library, used by vm.make
+WB = wb
+
+WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox
+
+WB_JAR = $(GENERATED)/$(WB).jar
+
+WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java')
+WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes
+
+WB_JAVA_CLASSES  = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
+	$(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
+
+$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
+	$(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
+
+$(WB_JAR): $(WB_JAVA_CLASSES)
+	$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
+
+$(WB_JAVA_CLASSDIR):
+	$(QUIETLY) mkdir -p $@
+
--- a/make/solaris/makefiles/buildtree.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/solaris/makefiles/buildtree.make	Tue May 15 11:27:24 2012 -0700
@@ -55,6 +55,7 @@
 # The makefiles are split this way so that "make foo" will run faster by not
 # having to read the dependency files for the vm.
 
+-include $(SPEC)
 include $(GAMMADIR)/make/scm.make
 include $(GAMMADIR)/make/altsrc.make
 
@@ -243,6 +244,8 @@
 	    echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
 	    echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \
 	echo; \
+	[ -n "$(SPEC)" ] && \
+	    echo "include $(SPEC)"; \
 	echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \
 	echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \
 	) > $@
--- a/make/solaris/makefiles/defs.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/solaris/makefiles/defs.make	Tue May 15 11:27:24 2012 -0700
@@ -59,6 +59,18 @@
   endif
 endif
 
+# On 32 bit solaris we build server and client, on 64 bit just server.
+ifeq ($(JVM_VARIANTS),)
+  ifeq ($(ARCH_DATA_MODEL), 32)
+    JVM_VARIANTS:=client,server
+    JVM_VARIANT_CLIENT:=true
+    JVM_VARIANT_SERVER:=true
+  else
+    JVM_VARIANTS:=server
+    JVM_VARIANT_SERVER:=true
+  endif
+endif
+
 # determine if HotSpot is being built in JDK6 or earlier version
 JDK6_OR_EARLIER=0
 ifeq "$(shell expr \( '$(JDK_MAJOR_VERSION)' != '' \& '$(JDK_MINOR_VERSION)' != '' \& '$(JDK_MICRO_VERSION)' != '' \))" "1"
@@ -187,14 +199,20 @@
   endif
 endif
 
+EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
+
 EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
 EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
 
-ifneq ($(BUILD_CLIENT_ONLY),true)
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.$(LIBRARY_SUFFIX)
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX)
+ifeq ($(JVM_VARIANT_SERVER),true)
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.$(LIBRARY_SUFFIX)
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX)
+  ifeq ($(ARCH_DATA_MODEL),32)
+    EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
+    EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
+  endif
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
     ifeq ($(ZIP_DEBUGINFO_FILES),1)
       EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.diz
@@ -207,38 +225,31 @@
     endif
   endif
 endif
-ifeq ($(ARCH_DATA_MODEL), 32)
+ifeq ($(JVM_VARIANT_CLIENT),true)
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX) 
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.$(LIBRARY_SUFFIX) 
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX)
-  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
-  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
+  ifeq ($(ARCH_DATA_MODEL),32)
+    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
+    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
+  endif
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
     ifeq ($(ZIP_DEBUGINFO_FILES),1)
       EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.diz
       EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.diz
       EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.diz
-      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.diz
-      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.diz
+      ifeq ($(ARCH_DATA_MODEL),32)
+        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.diz
+        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.diz
+      endif
     else
       EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
       EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.debuginfo
       EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.debuginfo
-      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.debuginfo
-      EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.debuginfo
-    endif
-  endif
-  ifneq ($(BUILD_CLIENT_ONLY), true)
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
-    ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
-      ifeq ($(ZIP_DEBUGINFO_FILES),1)
-        EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.diz
-        EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.diz
-      else
-        EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.debuginfo
-        EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.debuginfo
+      ifeq ($(ARCH_DATA_MODEL),32)
+        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.debuginfo
+        EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.debuginfo
       endif
     endif
   endif
--- a/make/solaris/makefiles/gcc.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/solaris/makefiles/gcc.make	Tue May 15 11:27:24 2012 -0700
@@ -25,9 +25,13 @@
 #------------------------------------------------------------------------
 # CC, CXX & AS
 
-CXX = g++
-CC  = gcc
-AS  = $(CC) -c
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+  CXX = g++
+  CC  = gcc
+  AS  = $(CC) -c
+  MCS = /usr/ccs/bin/mcs
+endif
 
 Compiler = gcc
 
@@ -193,5 +197,3 @@
 ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),) 
 DEBUG_CFLAGS += -gstabs 
 endif 
-
-MCS = /usr/ccs/bin/mcs
--- a/make/solaris/makefiles/sparcWorks.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/solaris/makefiles/sparcWorks.make	Tue May 15 11:27:24 2012 -0700
@@ -22,18 +22,22 @@
 #  
 #
 
-# Compiler-specific flags for sparcworks.
-
-# tell make which C and C++ compilers to use
-CC	= cc
-CXX	= CC
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+  # Compiler-specific flags for sparcworks.
+  CC	= cc
+  CXX	= CC
 
-# Note that this 'as' is an older version of the Sun Studio 'fbe', and will
-#   use the older style options. The 'fbe' options will match 'cc' and 'CC'.
-AS	= /usr/ccs/bin/as
+  # Note that this 'as' is an older version of the Sun Studio 'fbe', and will
+  #   use the older style options. The 'fbe' options will match 'cc' and 'CC'.
+  AS	= /usr/ccs/bin/as
 
-NM	= /usr/ccs/bin/nm
-NAWK    = /bin/nawk
+  NM    = /usr/ccs/bin/nm
+  NAWK  = /bin/nawk
+
+  MCS	= /usr/ccs/bin/mcs
+  STRIP	= /usr/ccs/bin/strip
+endif
 
 REORDER_FLAG = -xF
 
@@ -557,9 +561,6 @@
 #LINK_INTO = LIBJVM
 endif
 
-MCS	= /usr/ccs/bin/mcs
-STRIP	= /usr/ccs/bin/strip
-
 # Solaris platforms collect lots of redundant file-ident lines,
 # to the point of wasting a significant percentage of file space.
 # (The text is stored in ELF .comment sections, contributed by
--- a/make/solaris/makefiles/vm.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/solaris/makefiles/vm.make	Tue May 15 11:27:24 2012 -0700
@@ -339,9 +339,12 @@
 # Serviceability agent
 include $(MAKEFILES_DIR)/saproc.make
 
+# Whitebox testing API
+include $(MAKEFILES_DIR)/wb.make
+
 #----------------------------------------------------------------------
 
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck $(WB_JAR)
 
 install: install_jvm install_jsig install_saproc
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/solaris/makefiles/wb.make	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# Rules to build whitebox testing library, used by vm.make
+
+WB = wb
+
+WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox
+
+WB_JAR = $(GENERATED)/$(WB).jar
+
+WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java')
+WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes
+
+WB_JAVA_CLASSES  = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
+	$(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
+
+$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
+	$(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
+
+$(WB_JAR): $(WB_JAVA_CLASSES)
+	$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
+
+$(WB_JAVA_CLASSDIR):
+	$(QUIETLY) mkdir -p $@
+
--- a/make/windows/build.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/windows/build.make	Tue May 15 11:27:24 2012 -0700
@@ -297,6 +297,10 @@
 	@ echo BUILDARCH=$(BUILDARCH)         			>> $@
 	@ echo Platform_arch=$(Platform_arch)        		>> $@
 	@ echo Platform_arch_model=$(Platform_arch_model)	>> $@
+	@ echo CXX=$(CXX)					>> $@
+	@ echo LD=$(LD)						>> $@
+	@ echo MT=$(MT)						>> $@
+	@ echo RC=$(RC)						>> $@
 	@ sh $(WorkSpace)/make/windows/get_msc_ver.sh		>> $@
 	@ if "$(ENABLE_FULL_DEBUG_SYMBOLS)" NEQ "" echo ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS) >> $@
 	@ if "$(ZIP_DEBUGINFO_FILES)" NEQ "" echo ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES) >> $@
--- a/make/windows/create_obj_files.sh	Tue May 15 10:52:24 2012 -0700
+++ b/make/windows/create_obj_files.sh	Tue May 15 11:27:24 2012 -0700
@@ -80,6 +80,8 @@
   BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr"
 fi
 
+BASE_PATHS="${BASE_PATHS} ${COMMONSRC}/share/vm/prims/wbtestmethods"
+
 CORE_PATHS="${BASE_PATHS}"
 # shared is already in BASE_PATHS. Should add vm/memory but that one is also in BASE_PATHS.
 if [ -d "${ALTSRC}/share/vm/gc_implementation" ]; then
--- a/make/windows/makefiles/compile.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/windows/makefiles/compile.make	Tue May 15 11:27:24 2012 -0700
@@ -23,7 +23,9 @@
 #
 
 # Generic compiler settings
+!if "x$(CXX)" == "x"
 CXX=cl.exe
+!endif
 
 # CXX Flags: (these vary slightly from VC6->VS2003->VS2005 compilers)
 #   /nologo   Supress copyright message at every cl.exe startup
@@ -185,8 +187,10 @@
 LD_FLAGS = /manifest $(LD_FLAGS) $(BUFFEROVERFLOWLIB)
 # Manifest Tool - used in VS2005 and later to adjust manifests stored
 # as resources inside build artifacts.
+!if "x$(MT)" == "x"
 MT=mt.exe
 !endif
+!endif
 
 !if "$(COMPILER_NAME)" == "VS2008"
 PRODUCT_OPT_OPTION   = /O2 /Oy-
@@ -196,8 +200,10 @@
 LD_FLAGS = /manifest $(LD_FLAGS)
 # Manifest Tool - used in VS2005 and later to adjust manifests stored
 # as resources inside build artifacts.
+!if "x$(MT)" == "x"
 MT=mt.exe
 !endif
+!endif
 
 !if "$(COMPILER_NAME)" == "VS2010"
 PRODUCT_OPT_OPTION   = /O2 /Oy-
@@ -207,7 +213,9 @@
 LD_FLAGS = /manifest $(LD_FLAGS)
 # Manifest Tool - used in VS2005 and later to adjust manifests stored
 # as resources inside build artifacts.
+!if "x$(MT)" == "x"
 MT=mt.exe
+!endif
 !if "$(BUILDARCH)" == "i486"
 LD_FLAGS = /SAFESEH $(LD_FLAGS)
 !endif
@@ -227,7 +235,9 @@
 !endif
 
 # Generic linker settings
+!if "x$(LD)" == "x"
 LD=link.exe
+!endif
 LD_FLAGS= $(LD_FLAGS) kernel32.lib user32.lib gdi32.lib winspool.lib \
  comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
  uuid.lib Wsock32.lib winmm.lib /nologo /machine:$(MACHINE) /opt:REF \
@@ -242,7 +252,9 @@
 !endif
 
 # Resource compiler settings
+!if "x$(RC)" == "x"
 RC=rc.exe
+!endif
 RC_FLAGS=/D "HS_VER=$(HS_VER)" \
 	 /D "HS_DOTVER=$(HS_DOTVER)" \
 	 /D "HS_BUILD_ID=$(HS_BUILD_ID)" \
--- a/make/windows/makefiles/debug.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/windows/makefiles/debug.make	Tue May 15 11:27:24 2012 -0700
@@ -33,7 +33,7 @@
 BUILD_PCH_FILE=_build_pch_file.obj
 !endif
 
-default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
+default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb
 
 !include ../local.make
 !include compile.make
@@ -71,3 +71,4 @@
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
 !include $(WorkSpace)/make/windows/makefiles/launcher.make
+!include $(WorkSpace)/make/windows/makefiles/wb.make
--- a/make/windows/makefiles/defs.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/windows/makefiles/defs.make	Tue May 15 11:27:24 2012 -0700
@@ -143,7 +143,9 @@
 MAKE_ARGS += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)
 
 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
-  ZIP_DEBUGINFO_FILES ?= 1
+  # Disable ZIP_DEBUGINFO_FILES by default because various tests are
+  # failing in nightly when the debug info files are ZIP'ed.
+  ZIP_DEBUGINFO_FILES ?= 0
 else
   ZIP_DEBUGINFO_FILES=0
 endif
@@ -151,6 +153,19 @@
 MAKE_ARGS += RM="$(RM)"
 MAKE_ARGS += ZIPEXE=$(ZIPEXE)
 
+# On 32 bit windows we build server, client and kernel, on 64 bit just server.
+ifeq ($(JVM_VARIANTS),)
+  ifeq ($(ARCH_DATA_MODEL), 32)
+    JVM_VARIANTS:=client,server,kernel
+    JVM_VARIANT_CLIENT:=true
+    JVM_VARIANT_SERVER:=true
+    JVM_VARIANT_KERNEL:=true
+  else
+    JVM_VARIANTS:=server
+    JVM_VARIANT_SERVER:=true
+  endif
+endif
+
 JDK_INCLUDE_SUBDIR=win32
 
 # Library suffix
@@ -221,18 +236,20 @@
 EXPORT_CLIENT_DIR = $(EXPORT_JRE_BIN_DIR)/client
 EXPORT_KERNEL_DIR = $(EXPORT_JRE_BIN_DIR)/kernel
 
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.$(LIBRARY_SUFFIX)
-ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
-  ifeq ($(ZIP_DEBUGINFO_FILES),1)
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.diz
-  else
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.pdb
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map
+ifeq ($(JVM_VARIANT_SERVER),true)
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.$(LIBRARY_SUFFIX)
+  ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+    ifeq ($(ZIP_DEBUGINFO_FILES),1)
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.diz
+    else
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.pdb
+      EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map
+    endif
   endif
+  EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
 endif
-EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
-ifeq ($(ARCH_DATA_MODEL), 32)
+ifeq ($(JVM_VARIANT_CLIENT),true)
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.$(LIBRARY_SUFFIX)
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
@@ -243,7 +260,8 @@
       EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.map
     endif
   endif
-  # kernel vm
+endif
+ifeq ($(JVM_VARIANT_KERNEL),true)
   EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX)
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
@@ -256,6 +274,8 @@
   endif
 endif
 
+EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
+
 ifeq ($(BUILD_WIN_SA), 1)
   EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX)
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
@@ -270,3 +290,19 @@
   # Must pass this down to nmake.
   MAKE_ARGS += BUILD_WIN_SA=1
 endif
+
+# Propagate compiler and tools paths from configure to nmake. 
+# Need to make sure they contain \\ and not /.
+ifneq ($(SPEC),)
+  ifeq ($(USING_CYGWIN), true)
+    MAKE_ARGS += CXX="$(subst /,\\,$(shell /bin/cygpath -s -m -a $(CXX)))"
+    MAKE_ARGS += LD="$(subst /,\\,$(shell /bin/cygpath -s -m -a $(LD)))"
+    MAKE_ARGS += RC="$(subst /,\\,$(shell /bin/cygpath -s -m -a $(RC)))"
+    MAKE_ARGS += MT="$(subst /,\\,$(shell /bin/cygpath -s -m -a $(MT)))"
+  else
+    MAKE_ARGS += CXX="$(subst /,\\,$(CXX))"
+    MAKE_ARGS += LD="$(subst /,\\,$(LD))"
+    MAKE_ARGS += RC="$(subst /,\\,$(RC))"
+    MAKE_ARGS += MT="$(subst /,\\,$(MT))"
+  endif
+endif
--- a/make/windows/makefiles/fastdebug.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/windows/makefiles/fastdebug.make	Tue May 15 11:27:24 2012 -0700
@@ -33,7 +33,7 @@
 BUILD_PCH_FILE=_build_pch_file.obj
 !endif
 
-default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
+default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb
 
 !include ../local.make
 !include compile.make
@@ -71,3 +71,4 @@
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
 !include $(WorkSpace)/make/windows/makefiles/launcher.make
+!include $(WorkSpace)/make/windows/makefiles/wb.make
--- a/make/windows/makefiles/product.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/windows/makefiles/product.make	Tue May 15 11:27:24 2012 -0700
@@ -32,7 +32,7 @@
 BUILD_PCH_FILE=_build_pch_file.obj
 !endif
 
-default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
+default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb
 
 !include ../local.make
 !include compile.make
@@ -82,3 +82,4 @@
 !include $(WorkSpace)/make/windows/makefiles/shared.make
 !include $(WorkSpace)/make/windows/makefiles/sa.make
 !include $(WorkSpace)/make/windows/makefiles/launcher.make
+!include $(WorkSpace)/make/windows/makefiles/wb.make
--- a/make/windows/makefiles/projectcreator.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/windows/makefiles/projectcreator.make	Tue May 15 11:27:24 2012 -0700
@@ -51,6 +51,7 @@
         -relativeInclude src\closed\cpu\$(Platform_arch)\vm \
         -relativeInclude src\share\vm \
         -relativeInclude src\share\vm\precompiled \
+        -relativeInclude src\share\vm\prims\wbtestmethods \
         -relativeInclude src\share\vm\prims \
         -relativeInclude src\os\windows\vm \
         -relativeInclude src\os_cpu\windows_$(Platform_arch)\vm \
--- a/make/windows/makefiles/vm.make	Tue May 15 10:52:24 2012 -0700
+++ b/make/windows/makefiles/vm.make	Tue May 15 11:27:24 2012 -0700
@@ -172,6 +172,7 @@
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/memory
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/oops
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims
+VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims/wbtestmethods
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/runtime
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/services
 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/trace
@@ -269,6 +270,9 @@
 {$(COMMONSRC)\share\vm\prims}.cpp.obj::
         $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
 
+{$(COMMONSRC)\share\vm\prims\wbtestmethods}.cpp.obj::
+        $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+
 {$(COMMONSRC)\share\vm\runtime}.cpp.obj::
         $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
 
@@ -349,6 +353,9 @@
 {$(ALTSRC)\share\vm\prims}.cpp.obj::
         $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
 
+{$(ALTSRC)\share\vm\prims\wbtestmethods}.cpp.obj::
+        $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+
 {$(ALTSRC)\share\vm\runtime}.cpp.obj::
         $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/windows/makefiles/wb.make	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#  
+#
+
+# This makefile is used to build the whitebox testing lib
+# and compile the tests which use it
+
+!include $(WorkSpace)/make/windows/makefiles/rules.make
+
+WBSRCDIR = $(WorkSpace)/src/share/tools/whitebox
+
+# turn GENERATED into a windows path to get sane dependencies
+WB_CLASSES=$(GENERATED:/=\)\wb\classes
+WB_JAR=$(GENERATED:/=\)\wb.jar
+
+# call recursive make to do wildcard expansion
+.SUFFIXES : .java .class
+wb_java_srcs: $(WorkSpace)\src\share\tools\whitebox\sun\hotspot\*.java $(WB_CLASSES)
+	$(MAKE) -f $(WorkSpace)\make\windows\makefiles\$(BUILD_FLAVOR).make $(**:.java=.class)
+
+
+{$(WorkSpace)\src\share\tools\whitebox\sun\hotspot}.java.class::
+	$(COMPILE_JAVAC) -sourcepath $(WBSRCDIR) -d $(WB_CLASSES) $<
+
+$(WB_JAR): wb_java_srcs
+	$(RUN_JAR) cf $@ -C $(WB_CLASSES) .
+
+# turn $@ to a unix path because mkdir in PATH is cygwin/mks mkdir
+$(WB_CLASSES):
+	mkdir -p $(@:\=/)
+
+# main target to build wb
+wb: $(WB_JAR)
+
--- a/src/cpu/sparc/vm/assembler_sparc.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp	Tue May 15 11:27:24 2012 -0700
@@ -2221,7 +2221,7 @@
   // traps as per trap.h (SPARC ABI?)
 
   void breakpoint_trap();
-  void breakpoint_trap(Condition c, CC cc = icc);
+  void breakpoint_trap(Condition c, CC cc);
   void flush_windows_trap();
   void clean_windows_trap();
   void get_psr_trap();
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Tue May 15 11:27:24 2012 -0700
@@ -3231,6 +3231,26 @@
   // no-op on TSO
 }
 
+void LIR_Assembler::membar_loadload() {
+  // no-op
+  //__ membar(Assembler::Membar_mask_bits(Assembler::loadload));
+}
+
+void LIR_Assembler::membar_storestore() {
+  // no-op
+  //__ membar(Assembler::Membar_mask_bits(Assembler::storestore));
+}
+
+void LIR_Assembler::membar_loadstore() {
+  // no-op
+  //__ membar(Assembler::Membar_mask_bits(Assembler::loadstore));
+}
+
+void LIR_Assembler::membar_storeload() {
+  __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
+}
+
+
 // Pack two sequential registers containing 32 bit values
 // into a single 64 bit register.
 // src and src->successor() are packed into dst
--- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1187,7 +1187,7 @@
 
   #ifdef ASSERT
     __ tst(O1);
-    __ breakpoint_trap(Assembler::zero);
+    __ breakpoint_trap(Assembler::zero, Assembler::ptr_cc);
   #endif // ASSERT
 
     const int entry_size            = frame::interpreter_frame_monitor_size() * wordSize;
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue May 15 11:27:24 2012 -0700
@@ -3325,7 +3325,7 @@
   // make sure that the frames are aligned properly
 #ifndef _LP64
   __ btst(wordSize*2-1, SP);
-  __ breakpoint_trap(Assembler::notZero);
+  __ breakpoint_trap(Assembler::notZero, Assembler::ptr_cc);
 #endif
   #endif
 
@@ -3407,7 +3407,7 @@
 #ifdef ASSERT
   // make sure that there is at least one entry in the array
   __ tst(O4array_size);
-  __ breakpoint_trap(Assembler::zero);
+  __ breakpoint_trap(Assembler::zero, Assembler::icc);
 #endif
 
   // Now push the new interpreter frames
--- a/src/cpu/sparc/vm/sparc.ad	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/sparc/vm/sparc.ad	Tue May 15 11:27:24 2012 -0700
@@ -1832,6 +1832,8 @@
   case Op_CountLeadingZerosL:
   case Op_CountTrailingZerosI:
   case Op_CountTrailingZerosL:
+  case Op_PopCountI:
+  case Op_PopCountL:
     if (!UsePopCountInstruction)
       return false;
     break;
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Tue May 15 11:27:24 2012 -0700
@@ -379,7 +379,7 @@
 
 #ifdef ASSERT
     __ tst(O0);
-    __ breakpoint_trap(Assembler::zero);
+    __ breakpoint_trap(Assembler::zero, Assembler::ptr_cc);
 #endif // ASSERT
 
     __ bind(done);
@@ -2050,7 +2050,7 @@
   AddressLiteral stop_at(&StopInterpreterAt);
   __ load_ptr_contents(stop_at, G4_scratch);
   __ cmp(G3_scratch, G4_scratch);
-  __ breakpoint_trap(Assembler::equal);
+  __ breakpoint_trap(Assembler::equal, Assembler::icc);
 }
 #endif // not PRODUCT
 #endif // !CC_INTERP
--- a/src/cpu/x86/vm/assembler_x86.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Tue May 15 11:27:24 2012 -0700
@@ -528,10 +528,12 @@
     if (which == end_pc_operand)  return ip + (is_64bit ? 8 : 4);
     // these asserts are somewhat nonsensical
 #ifndef _LP64
-    assert(which == imm_operand || which == disp32_operand, "");
+    assert(which == imm_operand || which == disp32_operand,
+           err_msg("which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, ip));
 #else
     assert((which == call32_operand || which == imm_operand) && is_64bit ||
-           which == narrow_oop_operand && !is_64bit, "");
+           which == narrow_oop_operand && !is_64bit,
+           err_msg("which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, ip));
 #endif // _LP64
     return ip;
 
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1462,7 +1462,11 @@
       break;
 
     case Bytecodes::_l2i:
+#ifdef _LP64
+      __ movl(dest->as_register(), src->as_register_lo());
+#else
       move_regs(src->as_register_lo(), dest->as_register());
+#endif
       break;
 
     case Bytecodes::_i2b:
@@ -3713,6 +3717,25 @@
   // __ store_fence();
 }
 
+void LIR_Assembler::membar_loadload() {
+  // no-op
+  //__ membar(Assembler::Membar_mask_bits(Assembler::loadload));
+}
+
+void LIR_Assembler::membar_storestore() {
+  // no-op
+  //__ membar(Assembler::Membar_mask_bits(Assembler::storestore));
+}
+
+void LIR_Assembler::membar_loadstore() {
+  // no-op
+  //__ membar(Assembler::Membar_mask_bits(Assembler::loadstore));
+}
+
+void LIR_Assembler::membar_storeload() {
+  __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
+}
+
 void LIR_Assembler::get_thread(LIR_Opr result_reg) {
   assert(result_reg->is_register(), "check");
 #ifdef _LP64
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Tue May 15 11:27:24 2012 -0700
@@ -47,6 +47,12 @@
   assert(!(oop_result1->is_valid() || oop_result2->is_valid()) || oop_result1 != oop_result2, "registers must be different");
   assert(oop_result1 != thread && oop_result2 != thread, "registers must be different");
   assert(args_size >= 0, "illegal args_size");
+  bool align_stack = false;
+#ifdef _LP64
+  // At a method handle call, the stack may not be properly aligned
+  // when returning with an exception.
+  align_stack = (stub_id() == Runtime1::handle_exception_from_callee_id);
+#endif
 
 #ifdef _LP64
   mov(c_rarg0, thread);
@@ -59,11 +65,21 @@
   push(thread);
 #endif // _LP64
 
-  set_last_Java_frame(thread, noreg, rbp, NULL);
+  int call_offset;
+  if (!align_stack) {
+    set_last_Java_frame(thread, noreg, rbp, NULL);
+  } else {
+    address the_pc = pc();
+    call_offset = offset();
+    set_last_Java_frame(thread, noreg, rbp, the_pc);
+    andptr(rsp, -(StackAlignmentInBytes));    // Align stack
+  }
 
   // do the call
   call(RuntimeAddress(entry));
-  int call_offset = offset();
+  if (!align_stack) {
+    call_offset = offset();
+  }
   // verify callee-saved register
 #ifdef ASSERT
   guarantee(thread != rax, "change this code");
@@ -78,7 +94,7 @@
   }
   pop(rax);
 #endif
-  reset_last_Java_frame(thread, true, false);
+  reset_last_Java_frame(thread, true, align_stack);
 
   // discard thread and arguments
   NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord));
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1181,14 +1181,13 @@
                                       BasicType* in_sig_bt) {
   // if map is non-NULL then the code should store the values,
   // otherwise it should load them.
-  int handle_index = 0;
+  int slot = arg_save_area;
   // Save down double word first
   for ( int i = 0; i < total_in_args; i++) {
     if (in_regs[i].first()->is_XMMRegister() && in_sig_bt[i] == T_DOUBLE) {
-      int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area;
       int offset = slot * VMRegImpl::stack_slot_size;
-      handle_index += 2;
-      assert(handle_index <= stack_slots, "overflow");
+      slot += VMRegImpl::slots_per_word;
+      assert(slot <= stack_slots, "overflow");
       if (map != NULL) {
         __ movdbl(Address(rsp, offset), in_regs[i].first()->as_XMMRegister());
       } else {
@@ -1197,10 +1196,7 @@
     }
     if (in_regs[i].first()->is_Register() &&
         (in_sig_bt[i] == T_LONG || in_sig_bt[i] == T_ARRAY)) {
-      int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area;
       int offset = slot * VMRegImpl::stack_slot_size;
-      handle_index += 2;
-      assert(handle_index <= stack_slots, "overflow");
       if (map != NULL) {
         __ movq(Address(rsp, offset), in_regs[i].first()->as_Register());
         if (in_sig_bt[i] == T_ARRAY) {
@@ -1209,14 +1205,15 @@
       } else {
         __ movq(in_regs[i].first()->as_Register(), Address(rsp, offset));
       }
+      slot += VMRegImpl::slots_per_word;
     }
   }
   // Save or restore single word registers
   for ( int i = 0; i < total_in_args; i++) {
     if (in_regs[i].first()->is_Register()) {
-      int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area;
       int offset = slot * VMRegImpl::stack_slot_size;
-      assert(handle_index <= stack_slots, "overflow");
+      slot++;
+      assert(slot <= stack_slots, "overflow");
 
       // Value is in an input register pass we must flush it to the stack
       const Register reg = in_regs[i].first()->as_Register();
@@ -1241,9 +1238,9 @@
       }
     } else if (in_regs[i].first()->is_XMMRegister()) {
       if (in_sig_bt[i] == T_FLOAT) {
-        int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area;
         int offset = slot * VMRegImpl::stack_slot_size;
-        assert(handle_index <= stack_slots, "overflow");
+        slot++;
+        assert(slot <= stack_slots, "overflow");
         if (map != NULL) {
           __ movflt(Address(rsp, offset), in_regs[i].first()->as_XMMRegister());
         } else {
@@ -1368,6 +1365,174 @@
   __ bind(done);
 }
 
+
+class ComputeMoveOrder: public StackObj {
+  class MoveOperation: public ResourceObj {
+    friend class ComputeMoveOrder;
+   private:
+    VMRegPair        _src;
+    VMRegPair        _dst;
+    int              _src_index;
+    int              _dst_index;
+    bool             _processed;
+    MoveOperation*  _next;
+    MoveOperation*  _prev;
+
+    static int get_id(VMRegPair r) {
+      return r.first()->value();
+    }
+
+   public:
+    MoveOperation(int src_index, VMRegPair src, int dst_index, VMRegPair dst):
+      _src(src)
+    , _src_index(src_index)
+    , _dst(dst)
+    , _dst_index(dst_index)
+    , _next(NULL)
+    , _prev(NULL)
+    , _processed(false) {
+    }
+
+    VMRegPair src() const              { return _src; }
+    int src_id() const                 { return get_id(src()); }
+    int src_index() const              { return _src_index; }
+    VMRegPair dst() const              { return _dst; }
+    void set_dst(int i, VMRegPair dst) { _dst_index = i, _dst = dst; }
+    int dst_index() const              { return _dst_index; }
+    int dst_id() const                 { return get_id(dst()); }
+    MoveOperation* next() const       { return _next; }
+    MoveOperation* prev() const       { return _prev; }
+    void set_processed()               { _processed = true; }
+    bool is_processed() const          { return _processed; }
+
+    // insert
+    void break_cycle(VMRegPair temp_register) {
+      // create a new store following the last store
+      // to move from the temp_register to the original
+      MoveOperation* new_store = new MoveOperation(-1, temp_register, dst_index(), dst());
+
+      // break the cycle of links and insert new_store at the end
+      // break the reverse link.
+      MoveOperation* p = prev();
+      assert(p->next() == this, "must be");
+      _prev = NULL;
+      p->_next = new_store;
+      new_store->_prev = p;
+
+      // change the original store to save it's value in the temp.
+      set_dst(-1, temp_register);
+    }
+
+    void link(GrowableArray<MoveOperation*>& killer) {
+      // link this store in front the store that it depends on
+      MoveOperation* n = killer.at_grow(src_id(), NULL);
+      if (n != NULL) {
+        assert(_next == NULL && n->_prev == NULL, "shouldn't have been set yet");
+        _next = n;
+        n->_prev = this;
+      }
+    }
+  };
+
+ private:
+  GrowableArray<MoveOperation*> edges;
+
+ public:
+  ComputeMoveOrder(int total_in_args, VMRegPair* in_regs, int total_c_args, VMRegPair* out_regs,
+                    BasicType* in_sig_bt, GrowableArray<int>& arg_order, VMRegPair tmp_vmreg) {
+    // Move operations where the dest is the stack can all be
+    // scheduled first since they can't interfere with the other moves.
+    for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) {
+      if (in_sig_bt[i] == T_ARRAY) {
+        c_arg--;
+        if (out_regs[c_arg].first()->is_stack() &&
+            out_regs[c_arg + 1].first()->is_stack()) {
+          arg_order.push(i);
+          arg_order.push(c_arg);
+        } else {
+          if (out_regs[c_arg].first()->is_stack() ||
+              in_regs[i].first() == out_regs[c_arg].first()) {
+            add_edge(i, in_regs[i].first(), c_arg, out_regs[c_arg + 1]);
+          } else {
+            add_edge(i, in_regs[i].first(), c_arg, out_regs[c_arg]);
+          }
+        }
+      } else if (in_sig_bt[i] == T_VOID) {
+        arg_order.push(i);
+        arg_order.push(c_arg);
+      } else {
+        if (out_regs[c_arg].first()->is_stack() ||
+            in_regs[i].first() == out_regs[c_arg].first()) {
+          arg_order.push(i);
+          arg_order.push(c_arg);
+        } else {
+          add_edge(i, in_regs[i].first(), c_arg, out_regs[c_arg]);
+        }
+      }
+    }
+    // Break any cycles in the register moves and emit the in the
+    // proper order.
+    GrowableArray<MoveOperation*>* stores = get_store_order(tmp_vmreg);
+    for (int i = 0; i < stores->length(); i++) {
+      arg_order.push(stores->at(i)->src_index());
+      arg_order.push(stores->at(i)->dst_index());
+    }
+ }
+
+  // Collected all the move operations
+  void add_edge(int src_index, VMRegPair src, int dst_index, VMRegPair dst) {
+    if (src.first() == dst.first()) return;
+    edges.append(new MoveOperation(src_index, src, dst_index, dst));
+  }
+
+  // Walk the edges breaking cycles between moves.  The result list
+  // can be walked in order to produce the proper set of loads
+  GrowableArray<MoveOperation*>* get_store_order(VMRegPair temp_register) {
+    // Record which moves kill which values
+    GrowableArray<MoveOperation*> killer;
+    for (int i = 0; i < edges.length(); i++) {
+      MoveOperation* s = edges.at(i);
+      assert(killer.at_grow(s->dst_id(), NULL) == NULL, "only one killer");
+      killer.at_put_grow(s->dst_id(), s, NULL);
+    }
+    assert(killer.at_grow(MoveOperation::get_id(temp_register), NULL) == NULL,
+           "make sure temp isn't in the registers that are killed");
+
+    // create links between loads and stores
+    for (int i = 0; i < edges.length(); i++) {
+      edges.at(i)->link(killer);
+    }
+
+    // at this point, all the move operations are chained together
+    // in a doubly linked list.  Processing it backwards finds
+    // the beginning of the chain, forwards finds the end.  If there's
+    // a cycle it can be broken at any point,  so pick an edge and walk
+    // backward until the list ends or we end where we started.
+    GrowableArray<MoveOperation*>* stores = new GrowableArray<MoveOperation*>();
+    for (int e = 0; e < edges.length(); e++) {
+      MoveOperation* s = edges.at(e);
+      if (!s->is_processed()) {
+        MoveOperation* start = s;
+        // search for the beginning of the chain or cycle
+        while (start->prev() != NULL && start->prev() != s) {
+          start = start->prev();
+        }
+        if (start->prev() == s) {
+          start->break_cycle(temp_register);
+        }
+        // walk the chain forward inserting to store list
+        while (start != NULL) {
+          stores->append(start);
+          start->set_processed();
+          start = start->next();
+        }
+      }
+    }
+    return stores;
+  }
+};
+
+
 // ---------------------------------------------------------------------------
 // Generate a native wrapper for a given method.  The method takes arguments
 // in the Java compiled code convention, marshals them to the native
@@ -1488,12 +1653,12 @@
       if (in_regs[i].first()->is_Register()) {
         const Register reg = in_regs[i].first()->as_Register();
         switch (in_sig_bt[i]) {
-          case T_ARRAY:
           case T_BOOLEAN:
           case T_BYTE:
           case T_SHORT:
           case T_CHAR:
           case T_INT:  single_slots++; break;
+          case T_ARRAY:
           case T_LONG: double_slots++; break;
           default:  ShouldNotReachHere();
         }
@@ -1690,36 +1855,43 @@
 
 #endif /* ASSERT */
 
-  if (is_critical_native) {
-    // The mapping of Java and C arguments passed in registers are
-    // rotated by one, which helps when passing arguments to regular
-    // Java method but for critical natives that creates a cycle which
-    // can cause arguments to be killed before they are used.  Break
-    // the cycle by moving the first argument into a temporary
-    // register.
-    for (int i = 0; i < total_c_args; i++) {
-      if (in_regs[i].first()->is_Register() &&
-          in_regs[i].first()->as_Register() == rdi) {
-        __ mov(rbx, rdi);
-        in_regs[i].set1(rbx->as_VMReg());
-      }
-    }
-  }
-
   // This may iterate in two different directions depending on the
   // kind of native it is.  The reason is that for regular JNI natives
   // the incoming and outgoing registers are offset upwards and for
   // critical natives they are offset down.
-  int c_arg = total_c_args - 1;
-  int stride = -1;
-  int init = total_in_args - 1;
-  if (is_critical_native) {
-    // stride forwards
-    c_arg = 0;
-    stride = 1;
-    init = 0;
+  GrowableArray<int> arg_order(2 * total_in_args);
+  VMRegPair tmp_vmreg;
+  tmp_vmreg.set1(rbx->as_VMReg());
+
+  if (!is_critical_native) {
+    for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) {
+      arg_order.push(i);
+      arg_order.push(c_arg);
+    }
+  } else {
+    // Compute a valid move order, using tmp_vmreg to break any cycles
+    ComputeMoveOrder cmo(total_in_args, in_regs, total_c_args, out_regs, in_sig_bt, arg_order, tmp_vmreg);
   }
-  for (int i = init, count = 0; count < total_in_args; i += stride, c_arg += stride, count++ ) {
+
+  int temploc = -1;
+  for (int ai = 0; ai < arg_order.length(); ai += 2) {
+    int i = arg_order.at(ai);
+    int c_arg = arg_order.at(ai + 1);
+    __ block_comment(err_msg("move %d -> %d", i, c_arg));
+    if (c_arg == -1) {
+      assert(is_critical_native, "should only be required for critical natives");
+      // This arg needs to be moved to a temporary
+      __ mov(tmp_vmreg.first()->as_Register(), in_regs[i].first()->as_Register());
+      in_regs[i] = tmp_vmreg;
+      temploc = i;
+      continue;
+    } else if (i == -1) {
+      assert(is_critical_native, "should only be required for critical natives");
+      // Read from the temporary location
+      assert(temploc != -1, "must be valid");
+      i = temploc;
+      temploc = -1;
+    }
 #ifdef ASSERT
     if (in_regs[i].first()->is_Register()) {
       assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "destroyed reg!");
@@ -1779,7 +1951,7 @@
 
   // point c_arg at the first arg that is already loaded in case we
   // need to spill before we call out
-  c_arg++;
+  int c_arg = total_c_args - total_in_args;
 
   // Pre-load a static method's oop into r14.  Used both by locking code and
   // the normal JNI call code.
@@ -3620,8 +3792,12 @@
   //
   // address OptoRuntime::handle_exception_C(JavaThread* thread)
 
-  __ set_last_Java_frame(noreg, noreg, NULL);
+  // At a method handle call, the stack may not be properly aligned
+  // when returning with an exception.
+  address the_pc = __ pc();
+  __ set_last_Java_frame(noreg, noreg, the_pc);
   __ mov(c_rarg0, r15_thread);
+  __ andptr(rsp, -(StackAlignmentInBytes));    // Align stack
   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C)));
 
   // Set an oopmap for the call site.  This oopmap will only be used if we
@@ -3632,9 +3808,9 @@
 
   OopMapSet* oop_maps = new OopMapSet();
 
-  oop_maps->add_gc_map( __ pc()-start, new OopMap(SimpleRuntimeFrame::framesize, 0));
-
-  __ reset_last_Java_frame(false, false);
+  oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0));
+
+  __ reset_last_Java_frame(false, true);
 
   // Restore callee-saved registers
 
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Tue May 15 11:27:24 2012 -0700
@@ -710,6 +710,21 @@
     return start;
   }
 
+  // Support for intptr_t get_previous_sp()
+  //
+  // This routine is used to find the previous stack pointer for the
+  // caller.
+  address generate_get_previous_sp() {
+    StubCodeMark mark(this, "StubRoutines", "get_previous_sp");
+    address start = __ pc();
+
+    __ movptr(rax, rsp);
+    __ addptr(rax, 8); // return address is at the top of the stack.
+    __ ret(0);
+
+    return start;
+  }
+
   //----------------------------------------------------------------------------------------------------
   // Support for void verify_mxcsr()
   //
@@ -3060,6 +3075,7 @@
 
     // platform dependent
     StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp();
+    StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();
 
     StubRoutines::x86::_verify_mxcsr_entry    = generate_verify_mxcsr();
 
--- a/src/cpu/x86/vm/stubRoutines_x86_64.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/stubRoutines_x86_64.cpp	Tue May 15 11:27:24 2012 -0700
@@ -43,6 +43,7 @@
 // a description of how to extend it, see the stubRoutines.hpp file.
 
 address StubRoutines::x86::_get_previous_fp_entry = NULL;
+address StubRoutines::x86::_get_previous_sp_entry = NULL;
 
 address StubRoutines::x86::_verify_mxcsr_entry = NULL;
 
--- a/src/cpu/x86/vm/stubRoutines_x86_64.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/stubRoutines_x86_64.hpp	Tue May 15 11:27:24 2012 -0700
@@ -41,6 +41,7 @@
 
  private:
   static address _get_previous_fp_entry;
+  static address _get_previous_sp_entry;
   static address _verify_mxcsr_entry;
 
   static address _f2i_fixup;
@@ -61,6 +62,11 @@
     return _get_previous_fp_entry;
   }
 
+  static address get_previous_sp_entry()
+  {
+    return _get_previous_sp_entry;
+  }
+
   static address verify_mxcsr_entry()
   {
     return _verify_mxcsr_entry;
--- a/src/cpu/x86/vm/templateTable_x86_32.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/templateTable_x86_32.cpp	Tue May 15 11:27:24 2012 -0700
@@ -2651,56 +2651,49 @@
     // Check to see if a field modification watch has been set before we take
     // the time to call into the VM.
     Label L2;
-    __ mov32(rcx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()));
-    __ testl(rcx,rcx);
-    __ jcc(Assembler::zero, L2);
-    __ pop_ptr(rbx);               // copy the object pointer from tos
-    __ verify_oop(rbx);
-    __ push_ptr(rbx);              // put the object pointer back on tos
-    __ subptr(rsp, sizeof(jvalue));  // add space for a jvalue object
-    __ mov(rcx, rsp);
-    __ push_ptr(rbx);                 // save object pointer so we can steal rbx,
-    __ xorptr(rbx, rbx);
-    const Address lo_value(rcx, rbx, Address::times_1, 0*wordSize);
-    const Address hi_value(rcx, rbx, Address::times_1, 1*wordSize);
-    switch (bytecode()) {          // load values into the jvalue object
-    case Bytecodes::_fast_bputfield: __ movb(lo_value, rax); break;
-    case Bytecodes::_fast_sputfield: __ movw(lo_value, rax); break;
-    case Bytecodes::_fast_cputfield: __ movw(lo_value, rax); break;
-    case Bytecodes::_fast_iputfield: __ movl(lo_value, rax);                         break;
-    case Bytecodes::_fast_lputfield:
-      NOT_LP64(__ movptr(hi_value, rdx));
-      __ movptr(lo_value, rax);
-      break;
-
-    // need to call fld_s() after fstp_s() to restore the value for below
-    case Bytecodes::_fast_fputfield: __ fstp_s(lo_value); __ fld_s(lo_value);        break;
-
-    // need to call fld_d() after fstp_d() to restore the value for below
-    case Bytecodes::_fast_dputfield: __ fstp_d(lo_value); __ fld_d(lo_value);        break;
-
-    // since rcx is not an object we don't call store_check() here
-    case Bytecodes::_fast_aputfield: __ movptr(lo_value, rax);                       break;
-
-    default:  ShouldNotReachHere();
-    }
-    __ pop_ptr(rbx);  // restore copy of object pointer
-
-    // Save rax, and sometimes rdx because call_VM() will clobber them,
-    // then use them for JVM/DI purposes
-    __ push(rax);
-    if (bytecode() == Bytecodes::_fast_lputfield) __ push(rdx);
-    // access constant pool cache entry
-    __ get_cache_entry_pointer_at_bcp(rax, rdx, 1);
-    __ verify_oop(rbx);
-    // rbx,: object pointer copied above
-    // rax,: cache entry pointer
-    // rcx: jvalue object on the stack
-    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx);
-    if (bytecode() == Bytecodes::_fast_lputfield) __ pop(rdx);  // restore high value
-    __ pop(rax);     // restore lower value
-    __ addptr(rsp, sizeof(jvalue));  // release jvalue object space
-    __ bind(L2);
+     __ mov32(rcx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()));
+     __ testl(rcx,rcx);
+     __ jcc(Assembler::zero, L2);
+     __ pop_ptr(rbx);               // copy the object pointer from tos
+     __ verify_oop(rbx);
+     __ push_ptr(rbx);              // put the object pointer back on tos
+
+     // Save tos values before call_VM() clobbers them. Since we have
+     // to do it for every data type, we use the saved values as the
+     // jvalue object.
+     switch (bytecode()) {          // load values into the jvalue object
+     case Bytecodes::_fast_aputfield: __ push_ptr(rax); break;
+     case Bytecodes::_fast_bputfield: // fall through
+     case Bytecodes::_fast_sputfield: // fall through
+     case Bytecodes::_fast_cputfield: // fall through
+     case Bytecodes::_fast_iputfield: __ push_i(rax); break;
+     case Bytecodes::_fast_dputfield: __ push_d(); break;
+     case Bytecodes::_fast_fputfield: __ push_f(); break;
+     case Bytecodes::_fast_lputfield: __ push_l(rax); break;
+
+     default:
+       ShouldNotReachHere();
+     }
+     __ mov(rcx, rsp);              // points to jvalue on the stack
+     // access constant pool cache entry
+     __ get_cache_entry_pointer_at_bcp(rax, rdx, 1);
+     __ verify_oop(rbx);
+     // rbx,: object pointer copied above
+     // rax,: cache entry pointer
+     // rcx: jvalue object on the stack
+     __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx);
+
+     switch (bytecode()) {             // restore tos values
+     case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break;
+     case Bytecodes::_fast_bputfield: // fall through
+     case Bytecodes::_fast_sputfield: // fall through
+     case Bytecodes::_fast_cputfield: // fall through
+     case Bytecodes::_fast_iputfield: __ pop_i(rax); break;
+     case Bytecodes::_fast_dputfield: __ pop_d(); break;
+     case Bytecodes::_fast_fputfield: __ pop_f(); break;
+     case Bytecodes::_fast_lputfield: __ pop_l(rax); break;
+     }
+     __ bind(L2);
   }
 }
 
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Tue May 15 11:27:24 2012 -0700
@@ -2685,26 +2685,23 @@
     __ pop_ptr(rbx);                  // copy the object pointer from tos
     __ verify_oop(rbx);
     __ push_ptr(rbx);                 // put the object pointer back on tos
-    __ subptr(rsp, sizeof(jvalue));  // add space for a jvalue object
-    __ mov(c_rarg3, rsp);
-    const Address field(c_rarg3, 0);
-
+    // Save tos values before call_VM() clobbers them. Since we have
+    // to do it for every data type, we use the saved values as the
+    // jvalue object.
     switch (bytecode()) {          // load values into the jvalue object
-    case Bytecodes::_fast_aputfield: __ movq(field, rax); break;
-    case Bytecodes::_fast_lputfield: __ movq(field, rax); break;
-    case Bytecodes::_fast_iputfield: __ movl(field, rax); break;
-    case Bytecodes::_fast_bputfield: __ movb(field, rax); break;
+    case Bytecodes::_fast_aputfield: __ push_ptr(rax); break;
+    case Bytecodes::_fast_bputfield: // fall through
     case Bytecodes::_fast_sputfield: // fall through
-    case Bytecodes::_fast_cputfield: __ movw(field, rax); break;
-    case Bytecodes::_fast_fputfield: __ movflt(field, xmm0); break;
-    case Bytecodes::_fast_dputfield: __ movdbl(field, xmm0); break;
+    case Bytecodes::_fast_cputfield: // fall through
+    case Bytecodes::_fast_iputfield: __ push_i(rax); break;
+    case Bytecodes::_fast_dputfield: __ push_d(); break;
+    case Bytecodes::_fast_fputfield: __ push_f(); break;
+    case Bytecodes::_fast_lputfield: __ push_l(rax); break;
+
     default:
       ShouldNotReachHere();
     }
-
-    // Save rax because call_VM() will clobber it, then use it for
-    // JVMTI purposes
-    __ push(rax);
+    __ mov(c_rarg3, rsp);             // points to jvalue on the stack
     // access constant pool cache entry
     __ get_cache_entry_pointer_at_bcp(c_rarg2, rax, 1);
     __ verify_oop(rbx);
@@ -2715,8 +2712,17 @@
                CAST_FROM_FN_PTR(address,
                                 InterpreterRuntime::post_field_modification),
                rbx, c_rarg2, c_rarg3);
-    __ pop(rax);     // restore lower value
-    __ addptr(rsp, sizeof(jvalue));  // release jvalue object space
+
+    switch (bytecode()) {             // restore tos values
+    case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break;
+    case Bytecodes::_fast_bputfield: // fall through
+    case Bytecodes::_fast_sputfield: // fall through
+    case Bytecodes::_fast_cputfield: // fall through
+    case Bytecodes::_fast_iputfield: __ pop_i(rax); break;
+    case Bytecodes::_fast_dputfield: __ pop_d(); break;
+    case Bytecodes::_fast_fputfield: __ pop_f(); break;
+    case Bytecodes::_fast_lputfield: __ pop_l(rax); break;
+    }
     __ bind(L2);
   }
 }
--- a/src/cpu/x86/vm/vm_version_x86.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/vm_version_x86.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,8 +65,8 @@
 
   address generate_getPsrInfo() {
     // Flags to test CPU type.
-    const uint32_t EFL_AC           = 0x40000;
-    const uint32_t EFL_ID           = 0x200000;
+    const uint32_t HS_EFL_AC           = 0x40000;
+    const uint32_t HS_EFL_ID           = 0x200000;
     // Values for when we don't have a CPUID instruction.
     const int      CPU_FAMILY_SHIFT = 8;
     const uint32_t CPU_FAMILY_386   = (3 << CPU_FAMILY_SHIFT);
@@ -100,7 +100,7 @@
     //
     // if we are unable to change the AC flag, we have a 386
     //
-    __ xorl(rax, EFL_AC);
+    __ xorl(rax, HS_EFL_AC);
     __ push(rax);
     __ popf();
     __ pushf();
@@ -118,7 +118,7 @@
     //
     __ bind(detect_486);
     __ mov(rax, rcx);
-    __ xorl(rax, EFL_ID);
+    __ xorl(rax, HS_EFL_ID);
     __ push(rax);
     __ popf();
     __ pushf();
--- a/src/cpu/x86/vm/x86_32.ad	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/x86_32.ad	Tue May 15 11:27:24 2012 -0700
@@ -1293,6 +1293,14 @@
   if (!has_match_rule(opcode))
     return false;
 
+  switch (opcode) {
+    case Op_PopCountI:
+    case Op_PopCountL:
+      if (!UsePopCountInstruction)
+        return false;
+    break;
+  }
+  
   return true;  // Per default match rules are supported.
 }
 
--- a/src/cpu/x86/vm/x86_64.ad	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/x86/vm/x86_64.ad	Tue May 15 11:27:24 2012 -0700
@@ -1714,6 +1714,14 @@
   if (!has_match_rule(opcode))
     return false;
 
+  switch (opcode) {
+    case Op_PopCountI:
+    case Op_PopCountL:
+      if (!UsePopCountInstruction)
+        return false;
+    break;
+  }
+
   return true;  // Per default match rules are supported.
 }
 
@@ -3361,15 +3369,6 @@
   interface(CONST_INTER);
 %}
 
-operand immP_poll() %{
-  predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page());
-  match(ConP);
-
-  // formats are generated automatically for constants and base registers
-  format %{ %}
-  interface(CONST_INTER);
-%}
-
 // Pointer Immediate
 operand immN() %{
   match(ConN);
@@ -5718,16 +5717,6 @@
   ins_pipe(ialu_reg);
 %}
 
-instruct loadConP_poll(rRegP dst, immP_poll src) %{
-  match(Set dst src);
-  format %{ "movq    $dst, $src\t!ptr" %}
-  ins_encode %{
-    AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_type);
-    __ lea($dst$$Register, polling_page);
-  %}
-  ins_pipe(ialu_reg_fat);
-%}
-
 instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr)
 %{
   match(Set dst src);
--- a/src/cpu/zero/vm/cppInterpreter_zero.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1026,6 +1026,16 @@
         java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
       oop arg = VMSLOTS_OBJECT(arg_slot);
       jvalue arg_value;
+      if (arg == NULL) {
+        // queue a nullpointer exception for the caller
+        stack->set_sp(calculate_unwind_sp(stack, method_handle));
+        CALL_VM_NOCHECK_NOFIX(
+          throw_exception(
+            thread, vmSymbols::java_lang_NullPointerException()));
+        // NB all oops trashed!
+        assert(HAS_PENDING_EXCEPTION, "should do");
+        return;
+      }
       BasicType arg_type = java_lang_boxing_object::get_value(arg, &arg_value);
       if (arg_type == T_LONG || arg_type == T_DOUBLE) {
         intptr_t *unwind_sp = calculate_unwind_sp(stack, method_handle);
@@ -1112,6 +1122,15 @@
       case T_SHORT:
         return;
       }
+      // INT results sometimes need narrowing
+    case T_BOOLEAN:
+    case T_CHAR:
+    case T_BYTE:
+    case T_SHORT:
+      switch (src_rtype) {
+      case T_INT:
+        return;
+      }
     }
 
     tty->print_cr("unhandled conversion:");
--- a/src/os/bsd/vm/attachListener_bsd.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/bsd/vm/attachListener_bsd.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -206,10 +206,15 @@
   // put in listen mode, set permissions, and rename into place
   res = ::listen(listener, 5);
   if (res == 0) {
-      RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
+    RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
+    if (res == 0) {
+      // make sure the file is owned by the effective user and effective group
+      // (this is the default on linux, but not on mac os)
+      RESTARTABLE(::chown(initial_path, geteuid(), getegid()), res);
       if (res == 0) {
-          res = ::rename(initial_path, path);
+        res = ::rename(initial_path, path);
       }
+    }
   }
   if (res == -1) {
     RESTARTABLE(::close(listener), res);
--- a/src/os/bsd/vm/osThread_bsd.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/bsd/vm/osThread_bsd.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,11 @@
 
 void OSThread::pd_initialize() {
   assert(this != NULL, "check");
+#ifdef __APPLE__
+  _thread_id        = 0;
+#else
   _thread_id        = NULL;
+#endif
   _pthread_id       = NULL;
   _siginfo = NULL;
   _ucontext = NULL;
--- a/src/os/bsd/vm/osThread_bsd.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/bsd/vm/osThread_bsd.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,17 @@
  private:
 
 #ifdef _ALLBSD_SOURCE
-  // _thread_id and _pthread_id are the same on BSD
-  // keep both to minimize code divergence in os_bsd.cpp
+
+#ifdef __APPLE__
+  thread_t  _thread_id;
+#else
   pthread_t _thread_id;
+#endif
+
+  // _pthread_id is the pthread id, which is used by library calls
+  // (e.g. pthread_kill).
   pthread_t _pthread_id;
+
 #else
   // _thread_id is kernel thread id (similar to LWP id on Solaris). Each
   // thread has a unique thread_id (BsdThreads or NPTL). It can be used
@@ -64,10 +71,19 @@
   void    set_caller_sigmask(sigset_t sigmask)  { _caller_sigmask = sigmask; }
 
 #ifdef _ALLBSD_SOURCE
+#ifdef __APPLE__
+  static size_t thread_id_size()         { return sizeof(thread_t); }
+  thread_t thread_id() const {
+    return _thread_id;
+  }
+#else
+  static size_t thread_id_size()         { return sizeof(pthread_t); }
   pthread_t thread_id() const {
     return _thread_id;
   }
+#endif
 #else
+  static size_t thread_id_size()         { return sizeof(pid_t); }
   pid_t thread_id() const {
     return _thread_id;
   }
@@ -84,9 +100,15 @@
   }
 #endif // ASSERT
 #ifdef _ALLBSD_SOURCE
+#ifdef __APPLE__
+  void set_thread_id(thread_t id) {
+    _thread_id = id;
+  }
+#else
   void set_thread_id(pthread_t id) {
     _thread_id = id;
   }
+#endif
 #else
   void set_thread_id(pid_t id) {
     _thread_id = id;
--- a/src/os/bsd/vm/os_bsd.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/bsd/vm/os_bsd.cpp	Tue May 15 11:27:24 2012 -0700
@@ -568,6 +568,25 @@
             sprintf(ld_library_path, "%s:%s", v, t);
             free(t);
         }
+
+#ifdef __APPLE__
+        // Apple's Java6 has "." at the beginning of java.library.path.
+        // OpenJDK on Windows has "." at the end of java.library.path.
+        // OpenJDK on Linux and Solaris don't have "." in java.library.path
+        // at all. To ease the transition from Apple's Java6 to OpenJDK7,
+        // "." is appended to the end of java.library.path. Yes, this
+        // could cause a change in behavior, but Apple's Java6 behavior
+        // can be achieved by putting "." at the beginning of the
+        // JAVA_LIBRARY_PATH environment variable.
+        {
+            char *t = ld_library_path;
+            // that's +3 for appending ":." and the trailing '\0'
+            ld_library_path = (char *) malloc(strlen(t) + 3);
+            sprintf(ld_library_path, "%s:%s", t, ".");
+            free(t);
+        }
+#endif
+
         Arguments::set_library_path(ld_library_path);
     }
 
@@ -979,8 +998,13 @@
   }
 
 #ifdef _ALLBSD_SOURCE
+#ifdef __APPLE__
+  // thread_id is mach thread on macos
+  osthread->set_thread_id(::mach_thread_self());
+#else
   // thread_id is pthread_id on BSD
   osthread->set_thread_id(::pthread_self());
+#endif
 #else
   // thread_id is kernel thread id (similar to Solaris LWP id)
   osthread->set_thread_id(os::Bsd::gettid());
@@ -1171,7 +1195,11 @@
 
   // Store pthread info into the OSThread
 #ifdef _ALLBSD_SOURCE
+#ifdef __APPLE__
+  osthread->set_thread_id(::mach_thread_self());
+#else
   osthread->set_thread_id(::pthread_self());
+#endif
 #else
   osthread->set_thread_id(os::Bsd::gettid());
 #endif
@@ -1788,7 +1816,13 @@
   return n;
 }
 
-intx os::current_thread_id() { return (intx)pthread_self(); }
+intx os::current_thread_id() {
+#ifdef __APPLE__
+  return (intx)::mach_thread_self();
+#else
+  return (intx)::pthread_self();
+#endif
+}
 int os::current_process_id() {
 
   // Under the old bsd thread library, bsd gives each thread
@@ -5133,9 +5167,9 @@
   struct thread_basic_info tinfo;
   mach_msg_type_number_t tcount = THREAD_INFO_MAX;
   kern_return_t kr;
-  mach_port_t mach_thread;
-
-  mach_thread = pthread_mach_thread_np(thread->osthread()->thread_id());
+  thread_t mach_thread;
+
+  mach_thread = thread->osthread()->thread_id();
   kr = thread_info(mach_thread, THREAD_BASIC_INFO, (thread_info_t)&tinfo, &tcount);
   if (kr != KERN_SUCCESS)
     return -1;
--- a/src/os/linux/vm/osThread_linux.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/linux/vm/osThread_linux.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,6 +56,8 @@
   sigset_t  caller_sigmask() const       { return _caller_sigmask; }
   void    set_caller_sigmask(sigset_t sigmask)  { _caller_sigmask = sigmask; }
 
+  static size_t thread_id_size()         { return sizeof(pid_t); }
+
   pid_t thread_id() const {
     return _thread_id;
   }
--- a/src/os/linux/vm/os_linux.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/linux/vm/os_linux.cpp	Tue May 15 11:27:24 2012 -0700
@@ -2547,7 +2547,14 @@
 }
 
 void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) {
-  commit_memory(addr, bytes, alignment_hint, false);
+  // This method works by doing an mmap over an existing mmaping and effectively discarding
+  // the existing pages. However it won't work for SHM-based large pages that cannot be
+  // uncommitted at all. We don't do anything in this case to avoid creating a segment with
+  // small pages on top of the SHM segment. This method always works for small pages, so we
+  // allow that in any case.
+  if (alignment_hint <= (size_t)os::vm_page_size() || !UseSHM) {
+    commit_memory(addr, bytes, alignment_hint, false);
+  }
 }
 
 void os::numa_make_global(char *addr, size_t bytes) {
@@ -4690,14 +4697,12 @@
                      char *addr, size_t bytes, bool read_only,
                      bool allow_exec) {
   int prot;
-  int flags;
+  int flags = MAP_PRIVATE;
 
   if (read_only) {
     prot = PROT_READ;
-    flags = MAP_SHARED;
   } else {
     prot = PROT_READ | PROT_WRITE;
-    flags = MAP_PRIVATE;
   }
 
   if (allow_exec) {
--- a/src/os/solaris/vm/attachListener_solaris.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/solaris/vm/attachListener_solaris.cpp	Tue May 15 11:27:24 2012 -0700
@@ -336,7 +336,9 @@
     // Return 0 (success) + file descriptor, or non-0 (error)
     if (res == 0) {
       door_desc_t desc;
-      desc.d_attributes = DOOR_DESCRIPTOR;
+      // DOOR_RELEASE flag makes sure fd is closed after passing it to
+      // the client.  See door_return(3DOOR) man page.
+      desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
       desc.d_data.d_desc.d_descriptor = return_fd;
       door_return((char*)&res, sizeof(res), &desc, 1);
     } else {
--- a/src/os/solaris/vm/osThread_solaris.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/solaris/vm/osThread_solaris.hpp	Tue May 15 11:27:24 2012 -0700
@@ -36,6 +36,7 @@
   bool     _vm_created_thread; // true if the VM created this thread,
                                // false if primary thread or attached thread
  public:
+  static size_t thread_id_size()   { return sizeof(thread_t); }
   thread_t thread_id() const       { return _thread_id; }
   uint     lwp_id() const          { return _lwp_id; }
   int      native_priority() const { return _native_priority; }
--- a/src/os/solaris/vm/os_solaris.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/solaris/vm/os_solaris.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1013,15 +1013,6 @@
   // use debugger to set breakpoint here
 }
 
-// Returns an estimate of the current stack pointer. Result must be guaranteed to
-// point into the calling threads stack, and be no lower than the current stack
-// pointer.
-address os::current_stack_pointer() {
-  volatile int dummy;
-  address sp = (address)&dummy + 8;     // %%%% need to confirm if this is right
-  return sp;
-}
-
 static thread_t main_thread;
 
 // Thread start routine for all new Java threads
--- a/src/os/windows/vm/jvm_windows.h	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/windows/vm/jvm_windows.h	Tue May 15 11:27:24 2012 -0700
@@ -59,7 +59,7 @@
 
 #include <Tlhelp32.h>
 
-typedef unsigned int socklen_t;
+typedef int socklen_t;
 
 // #include "jni.h"
 
--- a/src/os/windows/vm/osThread_windows.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/windows/vm/osThread_windows.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,8 @@
   HANDLE interrupt_event() const                   { return _interrupt_event; }
   void set_interrupt_event(HANDLE interrupt_event) { _interrupt_event = interrupt_event; }
 
+
+  static size_t thread_id_size()                   { return sizeof(unsigned long); }
   unsigned long thread_id() const                  { return _thread_id; }
 #ifndef PRODUCT
   // Used for debugging, return a unique integer for each thread.
--- a/src/os/windows/vm/os_windows.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os/windows/vm/os_windows.cpp	Tue May 15 11:27:24 2012 -0700
@@ -324,16 +324,6 @@
   os::breakpoint();
 }
 
-// Returns an estimate of the current stack pointer. Result must be guaranteed
-// to point into the calling threads stack, and be no lower than the current
-// stack pointer.
-
-address os::current_stack_pointer() {
-  int dummy;
-  address sp = (address)&dummy;
-  return sp;
-}
-
 // os::current_stack_base()
 //
 //   Returns the base of the stack, which is the stack's
@@ -4830,99 +4820,92 @@
   return (struct hostent*)os::WinSock2Dll::gethostbyname(name);
 }
 
-
 int os::socket_close(int fd) {
-  ShouldNotReachHere();
-  return 0;
+  return ::closesocket(fd);
 }
 
 int os::socket_available(int fd, jint *pbytes) {
-  ShouldNotReachHere();
-  return 0;
+  int ret = ::ioctlsocket(fd, FIONREAD, (u_long*)pbytes);
+  return (ret < 0) ? 0 : 1;
 }
 
 int os::socket(int domain, int type, int protocol) {
-  ShouldNotReachHere();
-  return 0;
+  return ::socket(domain, type, protocol);
 }
 
 int os::listen(int fd, int count) {
-  ShouldNotReachHere();
-  return 0;
+  return ::listen(fd, count);
 }
 
 int os::connect(int fd, struct sockaddr* him, socklen_t len) {
-  ShouldNotReachHere();
-  return 0;
+  return ::connect(fd, him, len);
 }
 
 int os::accept(int fd, struct sockaddr* him, socklen_t* len) {
-  ShouldNotReachHere();
-  return 0;
+  return ::accept(fd, him, len);
 }
 
 int os::sendto(int fd, char* buf, size_t len, uint flags,
                struct sockaddr* to, socklen_t tolen) {
-  ShouldNotReachHere();
-  return 0;
+
+  return ::sendto(fd, buf, (int)len, flags, to, tolen);
 }
 
 int os::recvfrom(int fd, char *buf, size_t nBytes, uint flags,
                  sockaddr* from, socklen_t* fromlen) {
-  ShouldNotReachHere();
-  return 0;
+
+  return ::recvfrom(fd, buf, (int)nBytes, flags, from, fromlen);
 }
 
 int os::recv(int fd, char* buf, size_t nBytes, uint flags) {
-  ShouldNotReachHere();
-  return 0;
+  return ::recv(fd, buf, (int)nBytes, flags);
 }
 
 int os::send(int fd, char* buf, size_t nBytes, uint flags) {
-  ShouldNotReachHere();
-  return 0;
+  return ::send(fd, buf, (int)nBytes, flags);
 }
 
 int os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {
-  ShouldNotReachHere();
-  return 0;
+  return ::send(fd, buf, (int)nBytes, flags);
 }
 
 int os::timeout(int fd, long timeout) {
-  ShouldNotReachHere();
-  return 0;
+  fd_set tbl;
+  struct timeval t;
+
+  t.tv_sec  = timeout / 1000;
+  t.tv_usec = (timeout % 1000) * 1000;
+
+  tbl.fd_count    = 1;
+  tbl.fd_array[0] = fd;
+
+  return ::select(1, &tbl, 0, 0, &t);
 }
 
 int os::get_host_name(char* name, int namelen) {
-  ShouldNotReachHere();
-  return 0;
+  return ::gethostname(name, namelen);
 }
 
 int os::socket_shutdown(int fd, int howto) {
-  ShouldNotReachHere();
-  return 0;
+  return ::shutdown(fd, howto);
 }
 
 int os::bind(int fd, struct sockaddr* him, socklen_t len) {
-  ShouldNotReachHere();
-  return 0;
+  return ::bind(fd, him, len);
 }
 
 int os::get_sock_name(int fd, struct sockaddr* him, socklen_t* len) {
-  ShouldNotReachHere();
-  return 0;
+  return ::getsockname(fd, him, len);
 }
 
 int os::get_sock_opt(int fd, int level, int optname,
                      char* optval, socklen_t* optlen) {
-  ShouldNotReachHere();
-  return 0;
+  return ::getsockopt(fd, level, optname, optval, optlen);
 }
 
 int os::set_sock_opt(int fd, int level, int optname,
                      const char* optval, socklen_t optlen) {
-  ShouldNotReachHere();
-  return 0;
+  return ::setsockopt(fd, level, optname, optval, optlen);
 }
 
 
--- a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1126,3 +1126,8 @@
                       : "r" (fpu_cntrl) : "memory");
 #endif // !AMD64
 }
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
--- a/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,12 +29,18 @@
 // constants required by the Serviceability Agent. This file is
 // referenced by vmStructs.cpp.
 
+#ifdef __APPLE__
+#define OS_THREAD_ID_TYPE thread_t
+#else
+#define OS_THREAD_ID_TYPE pthread_t
+#endif
+
 #define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \
                                                                                                                                      \
   /******************************/                                                                                                   \
   /* Threads (NOTE: incomplete) */                                                                                                   \
   /******************************/                                                                                                   \
-  nonstatic_field(OSThread,                      _thread_id,                                      pthread_t)                             \
+  nonstatic_field(OSThread,                      _thread_id,                                      OS_THREAD_ID_TYPE)                 \
   nonstatic_field(OSThread,                      _pthread_id,                                     pthread_t)                         \
   /* This must be the last entry, and must be present */                                                                             \
   last_entry()
@@ -46,7 +52,7 @@
   /* Posix Thread IDs   */                                                \
   /**********************/                                                \
                                                                           \
-  declare_integer_type(pid_t)                                             \
+  declare_unsigned_integer_type(thread_t)                                 \
   declare_unsigned_integer_type(pthread_t)                                \
                                                                           \
   /* This must be the last entry, and must be present */                  \
--- a/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp	Tue May 15 11:27:24 2012 -0700
@@ -562,3 +562,8 @@
   }
 };
 #endif // !_LP64
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
--- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Tue May 15 11:27:24 2012 -0700
@@ -756,3 +756,8 @@
   // guard page, only enable glibc guard page for non-Java threads.
   return (thr_type == java_thread ? 0 : page_size());
 }
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
--- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Tue May 15 11:27:24 2012 -0700
@@ -862,3 +862,11 @@
                       : "r" (fpu_cntrl) : "memory");
 #endif // !AMD64
 }
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+#ifdef AMD64
+  assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
+#endif
+}
+#endif
--- a/src/os_cpu/linux_zero/vm/os_linux_zero.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/linux_zero/vm/os_linux_zero.cpp	Tue May 15 11:27:24 2012 -0700
@@ -506,3 +506,8 @@
   }
 };
 #endif // !_LP64
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
--- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Tue May 15 11:27:24 2012 -0700
@@ -251,6 +251,15 @@
   return frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc());
 }
 
+// Returns an estimate of the current stack pointer. Result must be guaranteed to
+// point into the calling threads stack, and be no lower than the current stack
+// pointer.
+address os::current_stack_pointer() {
+  volatile int dummy;
+  address sp = (address)&dummy + 8;     // %%%% need to confirm if this is right
+  return sp;
+}
+
 frame os::current_frame() {
   intptr_t* sp = StubRoutines::Sparc::flush_callers_register_windows_func()();
   frame myframe(sp, frame::unpatchable,
@@ -815,3 +824,8 @@
    __asm__ __volatile__ ("wr %%g0, 0, %%fprs \n\t" : : :);
   }
 #endif //defined(__sparc) && defined(COMPILER2)
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
--- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Tue May 15 11:27:24 2012 -0700
@@ -237,6 +237,12 @@
   return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
 }
 
+extern "C" intptr_t *_get_current_sp();  // in .il file
+
+address os::current_stack_pointer() {
+  return (address)_get_current_sp();
+}
+
 extern "C" intptr_t *_get_current_fp();  // in .il file
 
 frame os::current_frame() {
@@ -954,3 +960,11 @@
   _solaris_raw_setup_fpu(fpu_cntrl);
 }
 #endif // AMD64
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+#ifdef AMD64
+  assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
+#endif
+}
+#endif
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/solaris_x86/vm/solaris_x86_32.il	Tue May 15 11:27:24 2012 -0700
@@ -37,6 +37,12 @@
       movl     %gs:0, %eax 
       .end
 
+  // Get current sp
+      .inline _get_current_sp,0
+      .volatile
+      movl     %esp, %eax 
+      .end
+
   // Get current fp
       .inline _get_current_fp,0
       .volatile
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_64.il	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/solaris_x86/vm/solaris_x86_64.il	Tue May 15 11:27:24 2012 -0700
@@ -30,6 +30,12 @@
       movq     %fs:0, %rax 
       .end
 
+  // Get current sp
+      .inline _get_current_sp,0
+      .volatile
+      movq     %rsp, %rax 
+      .end
+
   // Get current fp
       .inline _get_current_fp,0
       .volatile
--- a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Tue May 15 11:27:24 2012 -0700
@@ -370,6 +370,26 @@
   return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
 }
 
+#ifndef AMD64
+// Returns an estimate of the current stack pointer. Result must be guaranteed
+// to point into the calling threads stack, and be no lower than the current
+// stack pointer.
+address os::current_stack_pointer() {
+  int dummy;
+  address sp = (address)&dummy;
+  return sp;
+}
+#else
+// Returns the current stack pointer. Accurate value needed for
+// os::verify_stack_alignment().
+address os::current_stack_pointer() {
+  typedef address get_sp_func();
+  get_sp_func* func = CAST_TO_FN_PTR(get_sp_func*,
+                                     StubRoutines::x86::get_previous_sp_entry());
+  return (*func)();
+}
+#endif
+
 
 #ifndef AMD64
 intptr_t* _get_previous_fp() {
@@ -546,3 +566,11 @@
   __asm fldcw fpu_cntrl_word;
 #endif // !AMD64
 }
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+#ifdef AMD64
+  assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
+#endif
+}
+#endif
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
     private boolean osr;
     private Method method;
     private CallSite call = new CallSite();
+    private CallSite lateInlineCall = new CallSite();
     private int osrBci;
     private String icount;
     private String bcount;
@@ -80,6 +81,13 @@
             sb.append(site);
             sb.append("\n");
         }
+        if (getLateInlineCall().getCalls() != null) {
+            sb.append("late inline:\n");
+            for (CallSite site : getLateInlineCall().getCalls()) {
+                sb.append(site);
+                sb.append("\n");
+            }
+        }
         return sb.toString();
     }
 
@@ -115,6 +123,12 @@
                     site.print(stream, indent + 2);
                 }
             }
+            if (printInlining && lateInlineCall.getCalls() != null) {
+                stream.println("late inline:");
+                for (CallSite site : lateInlineCall.getCalls()) {
+                    site.print(stream, indent + 2);
+                }
+            }
         }
     }
 
@@ -215,7 +229,11 @@
     }
 
     public void setMethod(Method method) {
-        this.method = method;
+        // Don't change method if it is already set to avoid changing
+        // it by post parse inlining info.
+        if (getMethod() == null) {
+            this.method = method;
+        }
     }
 
     public CallSite getCall() {
@@ -226,6 +244,10 @@
         this.call = call;
     }
 
+    public CallSite getLateInlineCall() {
+        return lateInlineCall;
+    }
+
     public double getElapsedTime() {
         return end - start;
     }
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -146,6 +146,7 @@
     private CallSite site;
     private Stack<Phase> phaseStack = new Stack<Phase>();
     private UncommonTrapEvent currentTrap;
+    private Stack<CallSite> late_inline_scope;
 
     long parseLong(String l) {
         try {
@@ -302,6 +303,7 @@
             }
             events.add(compile);
             compiles.put(makeId(atts), compile);
+            site = compile.getCall();
         } else if (qname.equals("type")) {
             type(search(atts, "id"), search(atts, "name"));
         } else if (qname.equals("bc")) {
@@ -360,12 +362,22 @@
                 // uncommon trap inserted during parsing.
                 // ignore for now
             }
+        } else if (qname.equals("late_inline")) {
+            late_inline_scope = new Stack<CallSite>();
+            site = new CallSite(-999, method(search(atts, "method")));
+            late_inline_scope.push(site);
         } else if (qname.equals("jvms")) {
             // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
             if (currentTrap != null) {
                 currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci")));
+            } else if (late_inline_scope != null) {
+                bci = Integer.parseInt(search(atts, "bci"));
+                site = new CallSite(bci, method(search(atts, "method")));
+                late_inline_scope.push(site);
             } else {
-                // Ignore <eliminate_allocation type='667'> and <eliminate_lock lock='1'>
+                // Ignore <eliminate_allocation type='667'>,
+                //        <eliminate_lock lock='1'>,
+                //        <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
             }
         } else if (qname.equals("nmethod")) {
             String id = makeId(atts);
@@ -379,7 +391,7 @@
             Method m = method(search(atts, "method"));
             if (scopes.size() == 0) {
                 compile.setMethod(m);
-                scopes.push(compile.getCall());
+                scopes.push(site);
             } else {
                 if (site.getMethod() == m) {
                     scopes.push(site);
@@ -393,7 +405,7 @@
             }
         } else if (qname.equals("parse_done")) {
             CallSite call = scopes.pop();
-            call.setEndNodes(Integer.parseInt(search(atts, "nodes")));
+            call.setEndNodes(Integer.parseInt(search(atts, "nodes", "1")));
             call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
             scopes.push(call);
         }
@@ -408,6 +420,43 @@
             scopes.pop();
         } else if (qname.equals("uncommon_trap")) {
             currentTrap = null;
+        } else if (qname.equals("late_inline")) {
+            // Populate late inlining info.
+
+            // late_inline scopes are specified in reverse order:
+            // compiled method should be on top of stack.
+            CallSite caller = late_inline_scope.pop();
+            Method m = compile.getMethod();
+            if (m != caller.getMethod()) {
+                System.out.println(m);
+                System.out.println(caller.getMethod() + " bci: " + bci);
+                throw new InternalError("call site and late_inline info don't match");
+            }
+
+            // late_inline contains caller+bci info, convert it
+            // to bci+callee info used by LogCompilation.
+            site = compile.getLateInlineCall();
+            do {
+                bci = caller.getBci();
+                // Next inlined call.
+                caller = late_inline_scope.pop();
+                CallSite callee =  new CallSite(bci, caller.getMethod());
+                site.add(callee);
+                site = callee;
+            } while (!late_inline_scope.empty());
+
+            if (caller.getBci() != -999) {
+                System.out.println(caller.getMethod());
+                throw new InternalError("broken late_inline info");
+            }
+            if (site.getMethod() != caller.getMethod()) {
+                System.out.println(site.getMethod());
+                System.out.println(caller.getMethod());
+                throw new InternalError("call site and late_inline info don't match");
+            }
+            // late_inline is followed by parse with scopes.size() == 0,
+            // 'site' will be pushed to scopes.
+            late_inline_scope = null;
         } else if (qname.equals("task")) {
             types.clear();
             methods.clear();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/whitebox/sun/hotspot/WhiteBox.java	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.hotspot;
+import java.security.BasicPermission;
+import sun.hotspot.parser.DiagnosticCommand;
+
+public class WhiteBox {
+
+  @SuppressWarnings("serial")
+  public static class WhiteBoxPermission extends BasicPermission {
+    public WhiteBoxPermission(String s) {
+      super(s);
+    }
+  }
+
+  private WhiteBox() {}
+  private static final WhiteBox instance = new WhiteBox();
+  private static native void registerNatives();
+
+  /**
+   * Returns the singleton WhiteBox instance.
+   *
+   * The returned WhiteBox object should be carefully guarded
+   * by the caller, since it can be used to read and write data
+   * at arbitrary memory addresses. It must never be passed to
+   * untrusted code.
+   */
+  public synchronized static WhiteBox getWhiteBox() {
+    SecurityManager sm = System.getSecurityManager();
+    if (sm != null) {
+      sm.checkPermission(new WhiteBoxPermission("getInstance"));
+    }
+    return instance;
+  }
+
+  static {
+    registerNatives();
+  }
+
+  // Memory
+  public native long getObjectAddress(Object o);
+  public native int  getHeapOopSize();
+
+  // G1
+  public native boolean g1InConcurrentMark();
+  public native boolean g1IsHumongous(Object o);
+  public native long    g1NumFreeRegions();
+  public native int     g1RegionSize();
+  public native Object[]    parseCommandLine(String commandline, DiagnosticCommand[] args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,43 @@
+package sun.hotspot.parser;
+
+public class DiagnosticCommand {
+
+    public enum DiagnosticArgumentType {
+        JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE
+    }
+
+    private String name;
+    private String desc;
+    private DiagnosticArgumentType type;
+    private boolean mandatory;
+    private String defaultValue;
+
+    public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type,
+            boolean mandatory, String defaultValue) {
+        this.name = name;
+        this.desc = desc;
+        this.type = type;
+        this.mandatory = mandatory;
+        this.defaultValue = defaultValue;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public DiagnosticArgumentType getType() {
+        return type;
+    }
+
+    public boolean isMandatory() {
+        return mandatory;
+    }
+
+    public String getDefaultValue() {
+        return defaultValue;
+    }
+}
--- a/src/share/vm/c1/c1_Canonicalizer.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_Canonicalizer.cpp	Tue May 15 11:27:24 2012 -0700
@@ -908,3 +908,4 @@
 void Canonicalizer::do_ProfileCall(ProfileCall* x) {}
 void Canonicalizer::do_ProfileInvoke(ProfileInvoke* x) {}
 void Canonicalizer::do_RuntimeCall(RuntimeCall* x) {}
+void Canonicalizer::do_MemBar(MemBar* x) {}
--- a/src/share/vm/c1/c1_Canonicalizer.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_Canonicalizer.hpp	Tue May 15 11:27:24 2012 -0700
@@ -104,6 +104,7 @@
   virtual void do_ProfileCall    (ProfileCall*     x);
   virtual void do_ProfileInvoke  (ProfileInvoke*   x);
   virtual void do_RuntimeCall    (RuntimeCall*     x);
+  virtual void do_MemBar         (MemBar*          x);
 };
 
 #endif // SHARE_VM_C1_C1_CANONICALIZER_HPP
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1306,6 +1306,7 @@
       if (sw.dest_offset_at(i) < 0) has_bb = true;
     }
     // add default successor
+    if (sw.default_offset() < 0) has_bb = true;
     sux->at_put(i, block_at(bci() + sw.default_offset()));
     ValueStack* state_before = has_bb ? copy_state_before() : NULL;
     Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb));
@@ -1350,6 +1351,7 @@
       keys->at_put(i, pair.match());
     }
     // add default successor
+    if (sw.default_offset() < 0) has_bb = true;
     sux->at_put(i, block_at(bci() + sw.default_offset()));
     ValueStack* state_before = has_bb ? copy_state_before() : NULL;
     Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb));
@@ -1418,6 +1420,12 @@
     call_register_finalizer();
   }
 
+  bool need_mem_bar = false;
+  if (method()->name() == ciSymbol::object_initializer_name() &&
+      scope()->wrote_final()) {
+    need_mem_bar = true;
+  }
+
   // Check to see whether we are inlining. If so, Return
   // instructions become Gotos to the continuation point.
   if (continuation() != NULL) {
@@ -1437,6 +1445,10 @@
       monitorexit(state()->lock_at(0), SynchronizationEntryBCI);
     }
 
+    if (need_mem_bar) {
+      append(new MemBar(lir_membar_storestore));
+    }
+
     // State at end of inlined method is the state of the caller
     // without the method parameters on stack, including the
     // return value, if any, of the inlined method on operand stack.
@@ -1456,7 +1468,6 @@
     // the continuation point.
     append_with_bci(goto_callee, scope_data()->continuation()->bci());
     incr_num_returns();
-
     return;
   }
 
@@ -1472,6 +1483,10 @@
     append_split(new MonitorExit(receiver, state()->unlock()));
   }
 
+  if (need_mem_bar) {
+      append(new MemBar(lir_membar_storestore));
+  }
+
   append(new Return(x));
 }
 
@@ -1504,6 +1519,9 @@
     }
   }
 
+  if (field->is_final() && (code == Bytecodes::_putfield)) {
+    scope()->set_wrote_final();
+  }
 
   const int offset = !needs_patching ? field->offset() : -1;
   switch (code) {
@@ -1676,7 +1694,9 @@
       // they are roughly equivalent to Object.
       ciInstanceKlass* singleton = NULL;
       if (target->holder()->nof_implementors() == 1) {
-        singleton = target->holder()->implementor(0);
+        singleton = target->holder()->implementor();
+        assert(singleton != NULL && singleton != target->holder(),
+               "just checking");
 
         assert(holder->is_interface(), "invokeinterface to non interface?");
         ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder;
@@ -3112,10 +3132,23 @@
   bool cantrap = true;
   vmIntrinsics::ID id = callee->intrinsic_id();
   switch (id) {
-    case vmIntrinsics::_arraycopy     :
+    case vmIntrinsics::_arraycopy:
       if (!InlineArrayCopy) return false;
       break;
 
+#ifdef TRACE_HAVE_INTRINSICS
+    case vmIntrinsics::_classID:
+    case vmIntrinsics::_threadID:
+      preserves_state = true;
+      cantrap = true;
+      break;
+
+    case vmIntrinsics::_counterTime:
+      preserves_state = true;
+      cantrap = false;
+      break;
+#endif
+
     case vmIntrinsics::_currentTimeMillis:
     case vmIntrinsics::_nanoTime:
       preserves_state = true;
--- a/src/share/vm/c1/c1_IR.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_IR.cpp	Tue May 15 11:27:24 2012 -0700
@@ -141,6 +141,7 @@
   _xhandlers          = new XHandlers(method);
   _number_of_locks    = 0;
   _monitor_pairing_ok = method->has_balanced_monitors();
+  _wrote_final        = false;
   _start              = NULL;
 
   if (osr_bci == -1) {
--- a/src/share/vm/c1/c1_IR.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_IR.hpp	Tue May 15 11:27:24 2012 -0700
@@ -149,6 +149,7 @@
   XHandlers*    _xhandlers;                      // the exception handlers
   int           _number_of_locks;                // the number of monitor lock slots needed
   bool          _monitor_pairing_ok;             // the monitor pairing info
+  bool          _wrote_final;                    // has written final field
   BlockBegin*   _start;                          // the start block, successsors are method entries
 
   BitMap        _requires_phi_function;          // bit is set if phi functions at loop headers are necessary for a local variable
@@ -181,6 +182,8 @@
   void          set_min_number_of_locks(int n)   { if (n > _number_of_locks) _number_of_locks = n; }
   bool          monitor_pairing_ok() const       { return _monitor_pairing_ok; }
   BlockBegin*   start() const                    { return _start; }
+  void          set_wrote_final()                { _wrote_final = true; }
+  bool          wrote_final    () const          { return _wrote_final; }
 };
 
 
--- a/src/share/vm/c1/c1_Instruction.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_Instruction.hpp	Tue May 15 11:27:24 2012 -0700
@@ -107,6 +107,7 @@
 class   ProfileCall;
 class   ProfileInvoke;
 class   RuntimeCall;
+class   MemBar;
 
 // A Value is a reference to the instruction creating the value
 typedef Instruction* Value;
@@ -204,6 +205,7 @@
   virtual void do_ProfileCall    (ProfileCall*     x) = 0;
   virtual void do_ProfileInvoke  (ProfileInvoke*   x) = 0;
   virtual void do_RuntimeCall    (RuntimeCall*     x) = 0;
+  virtual void do_MemBar         (MemBar*          x) = 0;
 };
 
 
@@ -2351,6 +2353,23 @@
   virtual void state_values_do(ValueVisitor*);
 };
 
+LEAF(MemBar, Instruction)
+ private:
+  LIR_Code _code;
+
+ public:
+  MemBar(LIR_Code code)
+    : Instruction(voidType)
+    , _code(code)
+  {
+    pin();
+  }
+
+  LIR_Code code()           { return _code; }
+
+  virtual void input_values_do(ValueVisitor*)   {}
+};
+
 class BlockPair: public CompilationResourceObj {
  private:
   BlockBegin* _from;
--- a/src/share/vm/c1/c1_InstructionPrinter.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_InstructionPrinter.cpp	Tue May 15 11:27:24 2012 -0700
@@ -855,4 +855,20 @@
   output()->put(')');
 }
 
+void InstructionPrinter::do_MemBar(MemBar* x) {
+  if (os::is_MP()) {
+    LIR_Code code = x->code();
+    switch (code) {
+      case lir_membar_acquire   : output()->print("membar_acquire"); break;
+      case lir_membar_release   : output()->print("membar_release"); break;
+      case lir_membar           : output()->print("membar"); break;
+      case lir_membar_loadload  : output()->print("membar_loadload"); break;
+      case lir_membar_storestore: output()->print("membar_storestore"); break;
+      case lir_membar_loadstore : output()->print("membar_loadstore"); break;
+      case lir_membar_storeload : output()->print("membar_storeload"); break;
+      default                   : ShouldNotReachHere(); break;
+    }
+  }
+}
+
 #endif // PRODUCT
--- a/src/share/vm/c1/c1_InstructionPrinter.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_InstructionPrinter.hpp	Tue May 15 11:27:24 2012 -0700
@@ -132,6 +132,7 @@
   virtual void do_ProfileCall    (ProfileCall*     x);
   virtual void do_ProfileInvoke  (ProfileInvoke*   x);
   virtual void do_RuntimeCall    (RuntimeCall*     x);
+  virtual void do_MemBar         (MemBar*          x);
 };
 #endif // PRODUCT
 
--- a/src/share/vm/c1/c1_LIR.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_LIR.cpp	Tue May 15 11:27:24 2012 -0700
@@ -464,6 +464,10 @@
     case lir_membar:                   // result and info always invalid
     case lir_membar_acquire:           // result and info always invalid
     case lir_membar_release:           // result and info always invalid
+    case lir_membar_loadload:          // result and info always invalid
+    case lir_membar_storestore:        // result and info always invalid
+    case lir_membar_loadstore:         // result and info always invalid
+    case lir_membar_storeload:         // result and info always invalid
     {
       assert(op->as_Op0() != NULL, "must be");
       assert(op->_info == NULL, "info not used by this instruction");
@@ -1607,6 +1611,10 @@
      case lir_membar:                s = "membar";        break;
      case lir_membar_acquire:        s = "membar_acquire"; break;
      case lir_membar_release:        s = "membar_release"; break;
+     case lir_membar_loadload:       s = "membar_loadload";   break;
+     case lir_membar_storestore:     s = "membar_storestore"; break;
+     case lir_membar_loadstore:      s = "membar_loadstore";  break;
+     case lir_membar_storeload:      s = "membar_storeload";  break;
      case lir_word_align:            s = "word_align";    break;
      case lir_label:                 s = "label";         break;
      case lir_nop:                   s = "nop";           break;
--- a/src/share/vm/c1/c1_LIR.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_LIR.hpp	Tue May 15 11:27:24 2012 -0700
@@ -866,6 +866,10 @@
       , lir_membar
       , lir_membar_acquire
       , lir_membar_release
+      , lir_membar_loadload
+      , lir_membar_storestore
+      , lir_membar_loadstore
+      , lir_membar_storeload
       , lir_get_thread
   , end_op0
   , begin_op1
@@ -1918,6 +1922,10 @@
   void membar()                                  { append(new LIR_Op0(lir_membar)); }
   void membar_acquire()                          { append(new LIR_Op0(lir_membar_acquire)); }
   void membar_release()                          { append(new LIR_Op0(lir_membar_release)); }
+  void membar_loadload()                         { append(new LIR_Op0(lir_membar_loadload)); }
+  void membar_storestore()                       { append(new LIR_Op0(lir_membar_storestore)); }
+  void membar_loadstore()                        { append(new LIR_Op0(lir_membar_loadstore)); }
+  void membar_storeload()                        { append(new LIR_Op0(lir_membar_storeload)); }
 
   void nop()                                     { append(new LIR_Op0(lir_nop)); }
   void build_frame()                             { append(new LIR_Op0(lir_build_frame)); }
--- a/src/share/vm/c1/c1_LIRAssembler.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_LIRAssembler.cpp	Tue May 15 11:27:24 2012 -0700
@@ -664,6 +664,22 @@
       membar_release();
       break;
 
+    case lir_membar_loadload:
+      membar_loadload();
+      break;
+
+    case lir_membar_storestore:
+      membar_storestore();
+      break;
+
+    case lir_membar_loadstore:
+      membar_loadstore();
+      break;
+
+    case lir_membar_storeload:
+      membar_storeload();
+      break;
+
     case lir_get_thread:
       get_thread(op->result_opr());
       break;
--- a/src/share/vm/c1/c1_LIRAssembler.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_LIRAssembler.hpp	Tue May 15 11:27:24 2012 -0700
@@ -241,6 +241,10 @@
   void membar();
   void membar_acquire();
   void membar_release();
+  void membar_loadload();
+  void membar_storestore();
+  void membar_loadstore();
+  void membar_storeload();
   void get_thread(LIR_Opr result);
 
   void verify_oop_map(CodeEmitInfo* info);
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2879,6 +2879,50 @@
   __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type()));
 }
 
+void LIRGenerator::do_RuntimeCall(address routine, int expected_arguments, Intrinsic* x) {
+    assert(x->number_of_arguments() == expected_arguments, "wrong type");
+    LIR_Opr reg = result_register_for(x->type());
+    __ call_runtime_leaf(routine, getThreadTemp(),
+                         reg, new LIR_OprList());
+    LIR_Opr result = rlock_result(x);
+    __ move(reg, result);
+}
+
+#ifdef TRACE_HAVE_INTRINSICS
+void LIRGenerator::do_ThreadIDIntrinsic(Intrinsic* x) {
+    LIR_Opr thread = getThreadPointer();
+    LIR_Opr osthread = new_pointer_register();
+    __ move(new LIR_Address(thread, in_bytes(JavaThread::osthread_offset()), osthread->type()), osthread);
+    size_t thread_id_size = OSThread::thread_id_size();
+    if (thread_id_size == (size_t) BytesPerLong) {
+      LIR_Opr id = new_register(T_LONG);
+      __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_LONG), id);
+      __ convert(Bytecodes::_l2i, id, rlock_result(x));
+    } else if (thread_id_size == (size_t) BytesPerInt) {
+      __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_INT), rlock_result(x));
+    } else {
+      ShouldNotReachHere();
+    }
+}
+
+void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) {
+    CodeEmitInfo* info = state_for(x);
+    CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check
+    assert(info != NULL, "must have info");
+    LIRItem arg(x->argument_at(1), this);
+    arg.load_item();
+    LIR_Opr klass = new_register(T_OBJECT);
+    __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), T_OBJECT), klass, info);
+    LIR_Opr id = new_register(T_LONG);
+    ByteSize offset = TRACE_ID_OFFSET;
+    LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG);
+    __ move(trace_id_addr, id);
+    __ logical_or(id, LIR_OprFact::longConst(0x01l), id);
+    __ store(id, trace_id_addr);
+    __ logical_and(id, LIR_OprFact::longConst(~0x3l), id);
+    __ move(id, rlock_result(x));
+}
+#endif
 
 void LIRGenerator::do_Intrinsic(Intrinsic* x) {
   switch (x->id()) {
@@ -2890,25 +2934,21 @@
     break;
   }
 
-  case vmIntrinsics::_currentTimeMillis: {
-    assert(x->number_of_arguments() == 0, "wrong type");
-    LIR_Opr reg = result_register_for(x->type());
-    __ call_runtime_leaf(CAST_FROM_FN_PTR(address, os::javaTimeMillis), getThreadTemp(),
-                         reg, new LIR_OprList());
-    LIR_Opr result = rlock_result(x);
-    __ move(reg, result);
+#ifdef TRACE_HAVE_INTRINSICS
+  case vmIntrinsics::_threadID: do_ThreadIDIntrinsic(x); break;
+  case vmIntrinsics::_classID: do_ClassIDIntrinsic(x); break;
+  case vmIntrinsics::_counterTime:
+    do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), 0, x);
     break;
-  }
-
-  case vmIntrinsics::_nanoTime: {
-    assert(x->number_of_arguments() == 0, "wrong type");
-    LIR_Opr reg = result_register_for(x->type());
-    __ call_runtime_leaf(CAST_FROM_FN_PTR(address, os::javaTimeNanos), getThreadTemp(),
-                         reg, new LIR_OprList());
-    LIR_Opr result = rlock_result(x);
-    __ move(reg, result);
+#endif
+
+  case vmIntrinsics::_currentTimeMillis:
+    do_RuntimeCall(CAST_FROM_FN_PTR(address, os::javaTimeMillis), 0, x);
     break;
-  }
+
+  case vmIntrinsics::_nanoTime:
+    do_RuntimeCall(CAST_FROM_FN_PTR(address, os::javaTimeNanos), 0, x);
+    break;
 
   case vmIntrinsics::_Object_init:    do_RegisterFinalizer(x); break;
   case vmIntrinsics::_getClass:       do_getClass(x);      break;
@@ -3165,3 +3205,20 @@
   }
   return result;
 }
+
+void LIRGenerator::do_MemBar(MemBar* x) {
+  if (os::is_MP()) {
+    LIR_Code code = x->code();
+    switch(code) {
+      case lir_membar_acquire   : __ membar_acquire(); break;
+      case lir_membar_release   : __ membar_release(); break;
+      case lir_membar           : __ membar(); break;
+      case lir_membar_loadload  : __ membar_loadload(); break;
+      case lir_membar_storestore: __ membar_storestore(); break;
+      case lir_membar_loadstore : __ membar_loadstore(); break;
+      case lir_membar_storeload : __ membar_storeload(); break;
+      default                   : ShouldNotReachHere(); break;
+    }
+  }
+}
+
--- a/src/share/vm/c1/c1_LIRGenerator.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_LIRGenerator.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -426,6 +426,12 @@
   SwitchRangeArray* create_lookup_ranges(LookupSwitch* x);
   void do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux);
 
+  void do_RuntimeCall(address routine, int expected_arguments, Intrinsic* x);
+#ifdef TRACE_HAVE_INTRINSICS
+  void do_ThreadIDIntrinsic(Intrinsic* x);
+  void do_ClassIDIntrinsic(Intrinsic* x);
+#endif
+
  public:
   Compilation*  compilation() const              { return _compilation; }
   FrameMap*     frame_map() const                { return _compilation->frame_map(); }
@@ -525,6 +531,7 @@
   virtual void do_ProfileCall    (ProfileCall*     x);
   virtual void do_ProfileInvoke  (ProfileInvoke*   x);
   virtual void do_RuntimeCall    (RuntimeCall*     x);
+  virtual void do_MemBar         (MemBar*          x);
 };
 
 
--- a/src/share/vm/c1/c1_LinearScan.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_LinearScan.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1884,7 +1884,7 @@
 
   if (move_resolver.has_mappings()) {
     // insert moves after first instruction
-    move_resolver.set_insert_position(block->lir(), 1);
+    move_resolver.set_insert_position(block->lir(), 0);
     move_resolver.resolve_and_append_moves();
   }
 }
--- a/src/share/vm/c1/c1_Optimizer.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_Optimizer.cpp	Tue May 15 11:27:24 2012 -0700
@@ -509,6 +509,7 @@
   void do_ProfileCall    (ProfileCall*     x);
   void do_ProfileInvoke  (ProfileInvoke*   x);
   void do_RuntimeCall    (RuntimeCall*     x);
+  void do_MemBar         (MemBar*          x);
 };
 
 
@@ -678,6 +679,7 @@
 void NullCheckVisitor::do_ProfileCall    (ProfileCall*     x) { nce()->clear_last_explicit_null_check(); }
 void NullCheckVisitor::do_ProfileInvoke  (ProfileInvoke*   x) {}
 void NullCheckVisitor::do_RuntimeCall    (RuntimeCall*     x) {}
+void NullCheckVisitor::do_MemBar         (MemBar*          x) {}
 
 
 void NullCheckEliminator::visit(Value* p) {
--- a/src/share/vm/c1/c1_Runtime1.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Tue May 15 11:27:24 2012 -0700
@@ -295,6 +295,9 @@
   FUNCTION_CASE(entry, SharedRuntime::dtrace_method_entry);
   FUNCTION_CASE(entry, SharedRuntime::dtrace_method_exit);
   FUNCTION_CASE(entry, trace_block_entry);
+#ifdef TRACE_HAVE_INTRINSICS
+  FUNCTION_CASE(entry, TRACE_TIME_METHOD);
+#endif
 
 #undef FUNCTION_CASE
 
--- a/src/share/vm/c1/c1_ValueMap.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/c1/c1_ValueMap.hpp	Tue May 15 11:27:24 2012 -0700
@@ -200,6 +200,7 @@
   void do_ProfileCall    (ProfileCall*     x) { /* nothing to do */ }
   void do_ProfileInvoke  (ProfileInvoke*   x) { /* nothing to do */ };
   void do_RuntimeCall    (RuntimeCall*     x) { /* nothing to do */ };
+  void do_MemBar         (MemBar*          x) { /* nothing to do */ };
 };
 
 
--- a/src/share/vm/ci/ciInstanceKlass.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/ci/ciInstanceKlass.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,10 +59,7 @@
   _has_nonstatic_fields = ik->has_nonstatic_fields();
   _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
 
-  _nof_implementors = ik->nof_implementors();
-  for (int i = 0; i < implementors_limit; i++) {
-    _implementors[i] = NULL;  // we will fill these lazily
-  }
+  _implementor = NULL; // we will fill these lazily
 
   Thread *thread = Thread::current();
   if (ciObjectFactory::is_initialized()) {
@@ -102,7 +99,6 @@
   _nonstatic_field_size = -1;
   _has_nonstatic_fields = false;
   _nonstatic_fields = NULL;
-  _nof_implementors = -1;
   _loader = loader;
   _protection_domain = protection_domain;
   _is_shared = false;
@@ -133,17 +129,6 @@
 }
 
 // ------------------------------------------------------------------
-// ciInstanceKlass::compute_shared_nof_implementors
-int ciInstanceKlass::compute_shared_nof_implementors() {
-  // We requery this property, since it is a very old ciObject.
-  GUARDED_VM_ENTRY(
-    instanceKlass* ik = get_instanceKlass();
-    _nof_implementors = ik->nof_implementors();
-    return _nof_implementors;
-  )
-}
-
-// ------------------------------------------------------------------
 // ciInstanceKlass::loader
 oop ciInstanceKlass::loader() {
   ASSERT_IN_VM;
@@ -540,7 +525,7 @@
   if (is_shared()) {
     return is_final();  // approximately correct
   } else {
-    return !_has_subklass && (_nof_implementors == 0);
+    return !_has_subklass && (nof_implementors() == 0);
   }
 }
 
@@ -548,35 +533,31 @@
 // ciInstanceKlass::implementor
 //
 // Report an implementor of this interface.
-// Returns NULL if exact information is not available.
 // Note that there are various races here, since my copy
 // of _nof_implementors might be out of date with respect
 // to results returned by instanceKlass::implementor.
 // This is OK, since any dependencies we decide to assert
 // will be checked later under the Compile_lock.
-ciInstanceKlass* ciInstanceKlass::implementor(int n) {
-  if (n >= implementors_limit) {
-    return NULL;
-  }
-  ciInstanceKlass* impl = _implementors[n];
+ciInstanceKlass* ciInstanceKlass::implementor() {
+  ciInstanceKlass* impl = _implementor;
   if (impl == NULL) {
-    if (_nof_implementors > implementors_limit) {
-      return NULL;
-    }
     // Go into the VM to fetch the implementor.
     {
       VM_ENTRY_MARK;
-      klassOop k = get_instanceKlass()->implementor(n);
+      klassOop k = get_instanceKlass()->implementor();
       if (k != NULL) {
-        impl = CURRENT_THREAD_ENV->get_object(k)->as_instance_klass();
+        if (k == get_instanceKlass()->as_klassOop()) {
+          // More than one implementors. Use 'this' in this case.
+          impl = this;
+        } else {
+          impl = CURRENT_THREAD_ENV->get_object(k)->as_instance_klass();
+        }
       }
     }
     // Memoize this result.
     if (!is_shared()) {
-      _implementors[n] = (impl == NULL)? this: impl;
+      _implementor = impl;
     }
-  } else if (impl == this) {
-    impl = NULL;  // memoized null result from a VM query
   }
   return impl;
 }
--- a/src/share/vm/ci/ciInstanceKlass.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/ci/ciInstanceKlass.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,9 +65,11 @@
   ciConstantPoolCache*   _field_cache;  // cached map index->field
   GrowableArray<ciField*>* _nonstatic_fields;
 
-  enum { implementors_limit = instanceKlass::implementors_limit };
-  ciInstanceKlass*       _implementors[implementors_limit];
-  jint                   _nof_implementors;
+  // The possible values of the _implementor fall into following three cases:
+  //   NULL: no implementor.
+  //   A ciInstanceKlass that's not itself: one implementor.
+  //   Itsef: more than one implementors.
+  ciInstanceKlass*       _implementor;
 
   GrowableArray<ciField*>* _non_static_fields;
 
@@ -97,7 +99,6 @@
 
   void compute_shared_init_state();
   bool compute_shared_has_subklass();
-  int  compute_shared_nof_implementors();
   int  compute_nonstatic_fields();
   GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields);
 
@@ -158,10 +159,17 @@
     assert(is_loaded(), "must be loaded");
     return _nonstatic_oop_map_size; }
   ciInstanceKlass*       super();
-  jint                   nof_implementors()  {
+  jint                   nof_implementors() {
+    ciInstanceKlass* impl;
     assert(is_loaded(), "must be loaded");
-    if (_is_shared)  return compute_shared_nof_implementors();
-    return _nof_implementors;
+    impl = implementor();
+    if (impl == NULL) {
+      return 0;
+    } else if (impl != this) {
+      return 1;
+    } else {
+      return 2;
+    }
   }
 
   ciInstanceKlass* get_canonical_holder(int offset);
@@ -207,7 +215,7 @@
   // but consider adding to vmSymbols.hpp instead.
 
   bool is_leaf_type();
-  ciInstanceKlass* implementor(int n);
+  ciInstanceKlass* implementor();
 
   // Is the defining class loader of this class the default loader?
   bool uses_default_loader();
--- a/src/share/vm/classfile/classFileParser.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,7 @@
 #define JAVA_7_VERSION                    51
 
 
-void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS) {
+void ClassFileParser::parse_constant_pool_entries(Handle class_loader, constantPoolHandle cp, int length, TRAPS) {
   // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
   // this function (_current can be allocated in a register, with scalar
   // replacement of aggregates). The _current pointer is copied back to
@@ -272,7 +272,7 @@
             indices[names_count] = index;
             hashValues[names_count++] = hash;
             if (names_count == SymbolTable::symbol_alloc_batch_size) {
-              SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
+              SymbolTable::new_symbols(class_loader, cp, names_count, names, lengths, indices, hashValues, CHECK);
               names_count = 0;
             }
           } else {
@@ -289,7 +289,7 @@
 
   // Allocate the remaining symbols
   if (names_count > 0) {
-    SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
+    SymbolTable::new_symbols(class_loader, cp, names_count, names, lengths, indices, hashValues, CHECK);
   }
 
   // Copy _current pointer of local copy back to stream().
@@ -318,7 +318,7 @@
 
 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
 
-constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
+constantPoolHandle ClassFileParser::parse_constant_pool(Handle class_loader, TRAPS) {
   ClassFileStream* cfs = stream();
   constantPoolHandle nullHandle;
 
@@ -337,7 +337,7 @@
   ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up.
 
   // parsing constant pool entries
-  parse_constant_pool_entries(cp, length, CHECK_(nullHandle));
+  parse_constant_pool_entries(class_loader, cp, length, CHECK_(nullHandle));
 
   int index = 1;  // declared outside of loops for portability
 
@@ -2315,13 +2315,32 @@
 #define RECOGNIZED_INNER_CLASS_MODIFIERS (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC)
 
 // Return number of classes in the inner classes attribute table
-u2 ClassFileParser::parse_classfile_inner_classes_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
+u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
+                                                            bool parsed_enclosingmethod_attribute,
+                                                            u2 enclosing_method_class_index,
+                                                            u2 enclosing_method_method_index,
+                                                            constantPoolHandle cp,
+                                                            instanceKlassHandle k, TRAPS) {
   ClassFileStream* cfs = stream();
-  cfs->guarantee_more(2, CHECK_0);  // length
-  u2 length = cfs->get_u2_fast();
-
-  // 4-tuples of shorts [inner_class_info_index, outer_class_info_index, inner_name_index, inner_class_access_flags]
-  typeArrayOop ic = oopFactory::new_permanent_shortArray(length*4, CHECK_0);
+  u1* current_mark = cfs->current();
+  u2 length = 0;
+  if (inner_classes_attribute_start != NULL) {
+    cfs->set_current(inner_classes_attribute_start);
+    cfs->guarantee_more(2, CHECK_0);  // length
+    length = cfs->get_u2_fast();
+  }
+
+  // 4-tuples of shorts of inner classes data and 2 shorts of enclosing
+  // method data:
+  //   [inner_class_info_index,
+  //    outer_class_info_index,
+  //    inner_name_index,
+  //    inner_class_access_flags,
+  //    ...
+  //    enclosing_method_class_index,
+  //    enclosing_method_method_index]
+  int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0);
+  typeArrayOop ic = oopFactory::new_permanent_shortArray(size, CHECK_0);
   typeArrayHandle inner_classes(THREAD, ic);
   int index = 0;
   int cp_size = cp->length();
@@ -2372,8 +2391,8 @@
 
   // 4347400: make sure there's no duplicate entry in the classes array
   if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
-    for(int i = 0; i < inner_classes->length(); i += 4) {
-      for(int j = i + 4; j < inner_classes->length(); j += 4) {
+    for(int i = 0; i < length * 4; i += 4) {
+      for(int j = i + 4; j < length * 4; j += 4) {
         guarantee_property((inner_classes->ushort_at(i)   != inner_classes->ushort_at(j) ||
                             inner_classes->ushort_at(i+1) != inner_classes->ushort_at(j+1) ||
                             inner_classes->ushort_at(i+2) != inner_classes->ushort_at(j+2) ||
@@ -2384,8 +2403,19 @@
     }
   }
 
+  // Set EnclosingMethod class and method indexes.
+  if (parsed_enclosingmethod_attribute) {
+    inner_classes->short_at_put(index++, enclosing_method_class_index);
+    inner_classes->short_at_put(index++, enclosing_method_method_index);
+  }
+  assert(index == size, "wrong size");
+
   // Update instanceKlass with inner class info.
   k->set_inner_classes(inner_classes());
+
+  // Restore buffer's current position.
+  cfs->set_current(current_mark);
+
   return length;
 }
 
@@ -2490,6 +2520,10 @@
   int runtime_visible_annotations_length = 0;
   u1* runtime_invisible_annotations = NULL;
   int runtime_invisible_annotations_length = 0;
+  u1* inner_classes_attribute_start = NULL;
+  u4  inner_classes_attribute_length = 0;
+  u2  enclosing_method_class_index = 0;
+  u2  enclosing_method_method_index = 0;
   // Iterate over attributes
   while (attributes_count--) {
     cfs->guarantee_more(6, CHECK);  // attribute_name_index, attribute_length
@@ -2522,11 +2556,9 @@
       } else {
         parsed_innerclasses_attribute = true;
       }
-      u2 num_of_classes = parse_classfile_inner_classes_attribute(cp, k, CHECK);
-      if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
-        guarantee_property(attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
-                          "Wrong InnerClasses attribute length in class file %s", CHECK);
-      }
+      inner_classes_attribute_start = cfs->get_u1_buffer();
+      inner_classes_attribute_length = attribute_length;
+      cfs->skip_u1(inner_classes_attribute_length, CHECK);
     } else if (tag == vmSymbols::tag_synthetic()) {
       // Check for Synthetic tag
       // Shouldn't we check that the synthetic flags wasn't already set? - not required in spec
@@ -2568,22 +2600,21 @@
           parsed_enclosingmethod_attribute = true;
         }
         cfs->guarantee_more(4, CHECK);  // class_index, method_index
-        u2 class_index  = cfs->get_u2_fast();
-        u2 method_index = cfs->get_u2_fast();
-        if (class_index == 0) {
+        enclosing_method_class_index  = cfs->get_u2_fast();
+        enclosing_method_method_index = cfs->get_u2_fast();
+        if (enclosing_method_class_index == 0) {
           classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK);
         }
         // Validate the constant pool indices and types
-        if (!cp->is_within_bounds(class_index) ||
-            !is_klass_reference(cp, class_index)) {
+        if (!cp->is_within_bounds(enclosing_method_class_index) ||
+            !is_klass_reference(cp, enclosing_method_class_index)) {
           classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
         }
-        if (method_index != 0 &&
-            (!cp->is_within_bounds(method_index) ||
-             !cp->tag_at(method_index).is_name_and_type())) {
+        if (enclosing_method_method_index != 0 &&
+            (!cp->is_within_bounds(enclosing_method_method_index) ||
+             !cp->tag_at(enclosing_method_method_index).is_name_and_type())) {
           classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK);
         }
-        k->set_enclosing_method_indices(class_index, method_index);
       } else if (tag == vmSymbols::tag_bootstrap_methods() &&
                  _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
         if (parsed_bootstrap_methods_attribute)
@@ -2606,6 +2637,20 @@
                                                      CHECK);
   k->set_class_annotations(annotations());
 
+  if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
+    u2 num_of_classes = parse_classfile_inner_classes_attribute(
+                            inner_classes_attribute_start,
+                            parsed_innerclasses_attribute,
+                            enclosing_method_class_index,
+                            enclosing_method_method_index,
+                            cp, k, CHECK);
+    if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) {
+      guarantee_property(
+        inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
+        "Wrong InnerClasses attribute length in class file %s", CHECK);
+    }
+  }
+
   if (_max_bootstrap_specifier_index >= 0) {
     guarantee_property(parsed_bootstrap_methods_attribute,
                        "Missing BootstrapMethods attribute in class file %s", CHECK);
@@ -2758,7 +2803,7 @@
   _relax_verify = Verifier::relax_verify_for(class_loader());
 
   // Constant pool
-  constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle));
+  constantPoolHandle cp = parse_constant_pool(class_loader, CHECK_(nullHandle));
   ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up.
 
   int cp_size = cp->length();
@@ -3309,7 +3354,9 @@
     klassOop ik = oopFactory::new_instanceKlass(name, vtable_size, itable_size,
                                                 static_field_size,
                                                 total_oop_map_count,
-                                                rt, CHECK_(nullHandle));
+                                                access_flags,
+                                                rt, host_klass,
+                                                CHECK_(nullHandle));
     instanceKlassHandle this_klass (THREAD, ik);
 
     assert(this_klass->static_field_size() == static_field_size, "sanity");
@@ -3317,7 +3364,6 @@
            "sanity");
 
     // Fill in information already parsed
-    this_klass->set_access_flags(access_flags);
     this_klass->set_should_verify_class(verify);
     jint lh = Klass::instance_layout_helper(instance_size, false);
     this_klass->set_layout_helper(lh);
--- a/src/share/vm/classfile/classFileParser.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/classfile/classFileParser.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,9 +68,10 @@
   void set_stream(ClassFileStream* st)             { _stream = st; }
 
   // Constant pool parsing
-  void parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS);
+  void parse_constant_pool_entries(Handle class_loader,
+                                   constantPoolHandle cp, int length, TRAPS);
 
-  constantPoolHandle parse_constant_pool(TRAPS);
+  constantPoolHandle parse_constant_pool(Handle class_loader, TRAPS);
 
   // Interface parsing
   objArrayHandle parse_interfaces(constantPoolHandle cp,
@@ -130,7 +131,11 @@
   void parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
   void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
                                                 instanceKlassHandle k, int length, TRAPS);
-  u2   parse_classfile_inner_classes_attribute(constantPoolHandle cp,
+  u2   parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
+                                               bool parsed_enclosingmethod_attribute,
+                                               u2 enclosing_method_class_index,
+                                               u2 enclosing_method_method_index,
+                                               constantPoolHandle cp,
                                                instanceKlassHandle k, TRAPS);
   void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
   void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
--- a/src/share/vm/classfile/symbolTable.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/classfile/symbolTable.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/filemap.hpp"
 #include "memory/gcLocker.inline.hpp"
 #include "oops/oop.inline.hpp"
@@ -37,34 +38,35 @@
 // --------------------------------------------------------------------------
 
 SymbolTable* SymbolTable::_the_table = NULL;
+// Static arena for symbols that are not deallocated
+Arena* SymbolTable::_arena = NULL;
 
-Symbol* SymbolTable::allocate_symbol(const u1* name, int len, TRAPS) {
+Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) {
   // Don't allow symbols to be created which cannot fit in a Symbol*.
   if (len > Symbol::max_length()) {
     THROW_MSG_0(vmSymbols::java_lang_InternalError(),
                 "name is too long to represent");
   }
-  Symbol* sym = new (len) Symbol(name, len);
+  Symbol* sym;
+  // Allocate symbols in the C heap when dumping shared spaces in case there
+  // are temporary symbols we can remove.
+  if (c_heap || DumpSharedSpaces) {
+    // refcount starts as 1
+    sym = new (len, THREAD) Symbol(name, len, 1);
+  } else {
+    sym = new (len, arena(), THREAD) Symbol(name, len, -1);
+  }
   assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
   return sym;
 }
 
-bool SymbolTable::allocate_symbols(int names_count, const u1** names,
-                                   int* lengths, Symbol** syms, TRAPS) {
-  for (int i = 0; i< names_count; i++) {
-    if (lengths[i] > Symbol::max_length()) {
-      THROW_MSG_0(vmSymbols::java_lang_InternalError(),
-                  "name is too long to represent");
-    }
+void SymbolTable::initialize_symbols(int arena_alloc_size) {
+  // Initialize the arena for global symbols, size passed in depends on CDS.
+  if (arena_alloc_size == 0) {
+    _arena = new Arena();
+  } else {
+    _arena = new Arena(arena_alloc_size);
   }
-
-  for (int i = 0; i< names_count; i++) {
-    int len = lengths[i];
-    syms[i] = new (len) Symbol(names[i], len);
-    assert(syms[i] != NULL, "new should call vm_exit_out_of_memory if "
-                            "C_HEAP is exhausted");
-  }
-  return true;
 }
 
 // Call function for all symbols in the symbol table.
@@ -83,8 +85,7 @@
 int SymbolTable::symbols_counted = 0;
 
 // Remove unreferenced symbols from the symbol table
-// This is done late during GC.  This doesn't use the hash table unlink because
-// it assumes that the literals are oops.
+// This is done late during GC.
 void SymbolTable::unlink() {
   int removed = 0;
   int total = 0;
@@ -156,7 +157,7 @@
   if (s != NULL) return s;
 
   // Otherwise, add to symbol to table
-  return the_table()->basic_add(index, (u1*)name, len, hashValue, CHECK_NULL);
+  return the_table()->basic_add(index, (u1*)name, len, hashValue, true, CHECK_NULL);
 }
 
 Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
@@ -192,7 +193,7 @@
   // We can't include the code in No_Safepoint_Verifier because of the
   // ResourceMark.
 
-  return the_table()->basic_add(index, (u1*)buffer, len, hashValue, CHECK_NULL);
+  return the_table()->basic_add(index, (u1*)buffer, len, hashValue, true, CHECK_NULL);
 }
 
 Symbol* SymbolTable::lookup_only(const char* name, int len,
@@ -256,71 +257,81 @@
   }
 }
 
-void SymbolTable::add(constantPoolHandle cp, int names_count,
+void SymbolTable::add(Handle class_loader, constantPoolHandle cp,
+                      int names_count,
                       const char** names, int* lengths, int* cp_indices,
                       unsigned int* hashValues, TRAPS) {
   SymbolTable* table = the_table();
-  bool added = table->basic_add(cp, names_count, names, lengths,
+  bool added = table->basic_add(class_loader, cp, names_count, names, lengths,
                                 cp_indices, hashValues, CHECK);
   if (!added) {
     // do it the hard way
     for (int i=0; i<names_count; i++) {
       int index = table->hash_to_index(hashValues[i]);
-      Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i],
-                                       hashValues[i], CHECK);
+      bool c_heap = class_loader() != NULL;
+      Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK);
       cp->symbol_at_put(cp_indices[i], sym);
     }
   }
 }
 
+Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) {
+  unsigned int hash;
+  Symbol* result = SymbolTable::lookup_only((char*)name, (int)strlen(name), hash);
+  if (result != NULL) {
+    return result;
+  }
+  SymbolTable* table = the_table();
+  int index = table->hash_to_index(hash);
+  return table->basic_add(index, (u1*)name, (int)strlen(name), hash, false, THREAD);
+}
+
 Symbol* SymbolTable::basic_add(int index, u1 *name, int len,
-                                 unsigned int hashValue, TRAPS) {
+                               unsigned int hashValue, bool c_heap, TRAPS) {
   assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
          "proposed name of symbol must be stable");
 
-  // We assume that lookup() has been called already, that it failed,
-  // and symbol was not found.  We create the symbol here.
-  Symbol* sym = allocate_symbol(name, len, CHECK_NULL);
-
-  // Allocation must be done before grabbing the SymbolTable_lock lock
+  // Grab SymbolTable_lock first.
   MutexLocker ml(SymbolTable_lock, THREAD);
 
-  assert(sym->equals((char*)name, len), "symbol must be properly initialized");
-
   // Since look-up was done lock-free, we need to check if another
   // thread beat us in the race to insert the symbol.
-
   Symbol* test = lookup(index, (char*)name, len, hashValue);
   if (test != NULL) {
-    // A race occurred and another thread introduced the symbol, this one
-    // will be dropped and collected.
-    delete sym;
+    // A race occurred and another thread introduced the symbol.
     assert(test->refcount() != 0, "lookup should have incremented the count");
     return test;
   }
 
+  // Create a new symbol.
+  Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL);
+  assert(sym->equals((char*)name, len), "symbol must be properly initialized");
+
   HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym);
-  sym->increment_refcount();
   add_entry(index, entry);
   return sym;
 }
 
-bool SymbolTable::basic_add(constantPoolHandle cp, int names_count,
+// This version of basic_add adds symbols in batch from the constant pool
+// parsing.
+bool SymbolTable::basic_add(Handle class_loader, constantPoolHandle cp,
+                            int names_count,
                             const char** names, int* lengths,
                             int* cp_indices, unsigned int* hashValues,
                             TRAPS) {
-  Symbol* syms[symbol_alloc_batch_size];
-  bool allocated = allocate_symbols(names_count, (const u1**)names, lengths,
-                                    syms, CHECK_false);
-  if (!allocated) {
-    return false;
+
+  // Check symbol names are not too long.  If any are too long, don't add any.
+  for (int i = 0; i< names_count; i++) {
+    if (lengths[i] > Symbol::max_length()) {
+      THROW_MSG_0(vmSymbols::java_lang_InternalError(),
+                  "name is too long to represent");
+    }
   }
 
-  // Allocation must be done before grabbing the SymbolTable_lock lock
+  // Hold SymbolTable_lock through the symbol creation
   MutexLocker ml(SymbolTable_lock, THREAD);
 
   for (int i=0; i<names_count; i++) {
-    assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized");
     // Since look-up was done lock-free, we need to check if another
     // thread beat us in the race to insert the symbol.
     int index = hash_to_index(hashValues[i]);
@@ -330,16 +341,17 @@
       // will be dropped and collected. Use test instead.
       cp->symbol_at_put(cp_indices[i], test);
       assert(test->refcount() != 0, "lookup should have incremented the count");
-      delete syms[i];
     } else {
-      Symbol* sym = syms[i];
+      // Create a new symbol.  The null class loader is never unloaded so these
+      // are allocated specially in a permanent arena.
+      bool c_heap = class_loader() != NULL;
+      Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false));
+      assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized");  // why wouldn't it be???
       HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym);
-      sym->increment_refcount();  // increment refcount in external hashtable
       add_entry(index, entry);
       cp->symbol_at_put(cp_indices[i], sym);
     }
   }
-
   return true;
 }
 
@@ -406,6 +418,8 @@
           ((float)symbols_removed/(float)symbols_counted)* 100);
   }
   tty->print_cr("Reference counts         %5d", Symbol::_total_count);
+  tty->print_cr("Symbol arena size        %5d used %5d",
+                 arena()->size_in_bytes(), arena()->used());
   tty->print_cr("Histogram of symbol length:");
   tty->print_cr("%8s %5d", "Total  ", total);
   tty->print_cr("%8s %5d", "Maximum", max_symbols);
--- a/src/share/vm/classfile/symbolTable.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/classfile/symbolTable.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -82,24 +82,24 @@
   static int symbols_removed;
   static int symbols_counted;
 
-  Symbol* allocate_symbol(const u1* name, int len, TRAPS);   // Assumes no characters larger than 0x7F
-  bool allocate_symbols(int names_count, const u1** names, int* lengths, Symbol** syms, TRAPS);
+  Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
 
   // Adding elements
-  Symbol* basic_add(int index, u1* name, int len,
-                      unsigned int hashValue, TRAPS);
-  bool basic_add(constantPoolHandle cp, int names_count,
+  Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue,
+                    bool c_heap, TRAPS);
+
+  bool basic_add(Handle class_loader, constantPoolHandle cp, int names_count,
                  const char** names, int* lengths, int* cp_indices,
                  unsigned int* hashValues, TRAPS);
 
-  static void new_symbols(constantPoolHandle cp, int names_count,
+  static void new_symbols(Handle class_loader, constantPoolHandle cp,
+                          int names_count,
                           const char** name, int* lengths,
                           int* cp_indices, unsigned int* hashValues,
                           TRAPS) {
-    add(cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
+    add(class_loader, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
   }
 
-
   // Table size
   enum {
     symbol_table_size = 20011
@@ -114,10 +114,16 @@
     : Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>), t,
                 number_of_entries) {}
 
+  // Arena for permanent symbols (null class loader) that are never unloaded
+  static Arena*  _arena;
+  static Arena* arena() { return _arena; }  // called for statistics
 
+  static void initialize_symbols(int arena_alloc_size = 0);
 public:
   enum {
-    symbol_alloc_batch_size = 8
+    symbol_alloc_batch_size = 8,
+    // Pick initial size based on java -version size measurements
+    symbol_alloc_arena_size = 360*K
   };
 
   // The symbol table
@@ -126,6 +132,7 @@
   static void create_table() {
     assert(_the_table == NULL, "One symbol table allowed.");
     _the_table = new SymbolTable();
+    initialize_symbols(symbol_alloc_arena_size);
   }
 
   static void create_table(HashtableBucket* t, int length,
@@ -134,6 +141,9 @@
     assert(length == symbol_table_size * sizeof(HashtableBucket),
            "bad shared symbol size.");
     _the_table = new SymbolTable(t, number_of_entries);
+    // if CDS give symbol table a default arena size since most symbols
+    // are already allocated in the shared misc section.
+    initialize_symbols();
   }
 
   static Symbol* lookup(const char* name, int len, TRAPS);
@@ -151,7 +161,7 @@
   static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
   static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
 
-  static void add(constantPoolHandle cp, int names_count,
+  static void add(Handle class_loader, constantPoolHandle cp, int names_count,
                   const char** names, int* lengths, int* cp_indices,
                   unsigned int* hashValues, TRAPS);
 
@@ -174,6 +184,9 @@
     return lookup(sym, begin, end, THREAD);
   }
 
+  // Create a symbol in the arena for symbols that are not deleted
+  static Symbol* new_permanent_symbol(const char* name, TRAPS);
+
   // Symbol lookup
   static Symbol* lookup(int index, const char* name, int len, TRAPS);
 
--- a/src/share/vm/classfile/vmSymbols.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/classfile/vmSymbols.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,7 @@
   if (!UseSharedSpaces) {
     const char* string = &vm_symbol_bodies[0];
     for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
-      Symbol* sym = SymbolTable::new_symbol(string, CHECK);
+      Symbol* sym = SymbolTable::new_permanent_symbol(string, CHECK);
       _symbols[index] = sym;
       string += strlen(string); // skip string body
       string += 1;              // skip trailing null
@@ -128,7 +128,7 @@
     // Spot-check correspondence between strings, symbols, and enums:
     assert(_symbols[NO_SID] == NULL, "must be");
     const char* str = "java/lang/Object";
-    TempNewSymbol jlo = SymbolTable::new_symbol(str, CHECK);
+    TempNewSymbol jlo = SymbolTable::new_permanent_symbol(str, CHECK);
     assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, "");
     assert(jlo == java_lang_Object(), "");
     SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object);
@@ -147,7 +147,7 @@
     // The string "format" happens (at the moment) not to be a vmSymbol,
     // though it is a method name in java.lang.String.
     str = "format";
-    TempNewSymbol fmt = SymbolTable::new_symbol(str, CHECK);
+    TempNewSymbol fmt = SymbolTable::new_permanent_symbol(str, CHECK);
     sid = find_sid(fmt);
     assert(sid == NO_SID, "symbol index works (negative test)");
   }
--- a/src/share/vm/classfile/vmSymbols.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 
 #include "oops/symbol.hpp"
 #include "memory/iterator.hpp"
+#include "trace/traceMacros.hpp"
 
 // The class vmSymbols is a name space for fast lookup of
 // symbols commonly used in the VM.
@@ -424,6 +425,7 @@
   template(throwable_throwable_signature,             "(Ljava/lang/Throwable;)Ljava/lang/Throwable;")             \
   template(class_void_signature,                      "(Ljava/lang/Class;)V")                     \
   template(class_int_signature,                       "(Ljava/lang/Class;)I")                     \
+  template(class_long_signature,                      "(Ljava/lang/Class;)J")                     \
   template(class_boolean_signature,                   "(Ljava/lang/Class;)Z")                     \
   template(throwable_string_void_signature,           "(Ljava/lang/Throwable;Ljava/lang/String;)V")               \
   template(string_array_void_signature,               "([Ljava/lang/String;)V")                                   \
@@ -509,6 +511,9 @@
   template(clear_name,                                 "clear")                                                   \
   template(trigger_method_signature,                   "(ILjava/lang/management/MemoryUsage;)V")                                                 \
   template(startAgent_name,                            "startAgent")                                              \
+  template(startRemoteAgent_name,                      "startRemoteManagementAgent")                              \
+  template(startLocalAgent_name,                       "startLocalManagementAgent")                               \
+  template(stopRemoteAgent_name,                       "stopRemoteManagementAgent")                               \
   template(java_lang_management_ThreadInfo_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;)V") \
   template(java_lang_management_ThreadInfo_with_locks_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;[Ljava/lang/Object;[I[Ljava/lang/Object;)V") \
   template(long_long_long_long_void_signature,         "(JJJJ)V")                                                 \
@@ -536,10 +541,12 @@
   template(serializePropertiesToByteArray_signature,   "()[B")                                                    \
   template(serializeAgentPropertiesToByteArray_name,   "serializeAgentPropertiesToByteArray")                     \
   template(classRedefinedCount_name,                   "classRedefinedCount")                                     \
+                                                                                                                  \
+  /* trace signatures */                                                                                          \
+  TRACE_TEMPLATES(template)                                                                                       \
+                                                                                                                  \
   /*end*/
 
-
-
 // Here are all the intrinsics known to the runtime and the CI.
 // Each intrinsic consists of a public enum name (like _hashCode),
 // followed by a specification of its klass, name, and signature:
@@ -645,6 +652,8 @@
   do_intrinsic(_nanoTime,                 java_lang_System,       nanoTime_name,          void_long_signature,   F_S)   \
    do_name(     nanoTime_name,                                   "nanoTime")                                            \
                                                                                                                         \
+  TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias)                                             \
+                                                                                                                        \
   do_intrinsic(_arraycopy,                java_lang_System,       arraycopy_name, arraycopy_signature,           F_S)   \
    do_name(     arraycopy_name,                                  "arraycopy")                                           \
    do_signature(arraycopy_signature,                             "(Ljava/lang/Object;ILjava/lang/Object;II)V")          \
--- a/src/share/vm/code/dependencies.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/code/dependencies.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1033,21 +1033,25 @@
     // (Old CHA had the same limitation.)
     return context_type;
   }
-  for (int i = 0; i < nof_impls; i++) {
-    klassOop impl = instanceKlass::cast(context_type)->implementor(i);
-    if (impl == NULL) {
-      // implementors array overflowed => no exact info.
+  if (nof_impls > 0) {
+    klassOop impl = instanceKlass::cast(context_type)->implementor();
+    assert(impl != NULL, "just checking");
+    // If impl is the same as the context_type, then more than one
+    // implementor has seen. No exact info in this case.
+    if (impl == context_type) {
       return context_type;  // report an inexact witness to this sad affair
     }
     if (do_counts)
       { NOT_PRODUCT(deps_find_witness_steps++); }
     if (is_participant(impl)) {
-      if (participants_hide_witnesses)  continue;
-      // else fall through to process this guy's subclasses
+      if (!participants_hide_witnesses) {
+        ADD_SUBCLASS_CHAIN(impl);
+      }
     } else if (is_witness(impl) && !ignore_witness(impl)) {
       return impl;
+    } else {
+      ADD_SUBCLASS_CHAIN(impl);
     }
-    ADD_SUBCLASS_CHAIN(impl);
   }
 
   // Recursively process each non-trivial sibling chain.
@@ -1174,8 +1178,9 @@
   } else if (ctx->nof_implementors() != 0) {
     // if it is an interface, it must be unimplemented
     // (if it is not an interface, nof_implementors is always zero)
-    klassOop impl = ctx->implementor(0);
-    return (impl != NULL)? impl: ctxk;
+    klassOop impl = ctx->implementor();
+    assert(impl != NULL, "must be set");
+    return impl;
   } else {
     return NULL;
   }
--- a/src/share/vm/code/nmethod.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/code/nmethod.hpp	Tue May 15 11:27:24 2012 -0700
@@ -553,7 +553,7 @@
   static void oops_do_marking_prologue();
   static void oops_do_marking_epilogue();
   static bool oops_do_marking_is_active() { return _oops_do_mark_nmethods != NULL; }
-  DEBUG_ONLY(bool test_oops_do_mark() { return _oops_do_mark_link != NULL; })
+  bool test_oops_do_mark() { return _oops_do_mark_link != NULL; }
 
   // ScopeDesc for an instruction
   ScopeDesc* scope_desc_at(address pc);
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp	Tue May 15 10:52:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1257 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp"
-#include "gc_implementation/shared/allocationStats.hpp"
-#include "gc_implementation/shared/spaceDecorator.hpp"
-#include "memory/space.inline.hpp"
-#include "runtime/globals.hpp"
-#include "utilities/ostream.hpp"
-
-////////////////////////////////////////////////////////////////////////////////
-// A binary tree based search structure for free blocks.
-// This is currently used in the Concurrent Mark&Sweep implementation.
-////////////////////////////////////////////////////////////////////////////////
-
-TreeChunk* TreeChunk::as_TreeChunk(FreeChunk* fc) {
-  // Do some assertion checking here.
-  return (TreeChunk*) fc;
-}
-
-void TreeChunk::verifyTreeChunkList() const {
-  TreeChunk* nextTC = (TreeChunk*)next();
-  if (prev() != NULL) { // interior list node shouldn'r have tree fields
-    guarantee(embedded_list()->parent() == NULL && embedded_list()->left() == NULL &&
-              embedded_list()->right()  == NULL, "should be clear");
-  }
-  if (nextTC != NULL) {
-    guarantee(as_TreeChunk(nextTC->prev()) == this, "broken chain");
-    guarantee(nextTC->size() == size(), "wrong size");
-    nextTC->verifyTreeChunkList();
-  }
-}
-
-
-TreeList* TreeList::as_TreeList(TreeChunk* tc) {
-  // This first free chunk in the list will be the tree list.
-  assert(tc->size() >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk");
-  TreeList* tl = tc->embedded_list();
-  tc->set_list(tl);
-#ifdef ASSERT
-  tl->set_protecting_lock(NULL);
-#endif
-  tl->set_hint(0);
-  tl->set_size(tc->size());
-  tl->link_head(tc);
-  tl->link_tail(tc);
-  tl->set_count(1);
-  tl->init_statistics(true /* split_birth */);
-  tl->setParent(NULL);
-  tl->setLeft(NULL);
-  tl->setRight(NULL);
-  return tl;
-}
-
-TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) {
-  TreeChunk* tc = (TreeChunk*) addr;
-  assert(size >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk");
-  // The space in the heap will have been mangled initially but
-  // is not remangled when a free chunk is returned to the free list
-  // (since it is used to maintain the chunk on the free list).
-  assert((ZapUnusedHeapArea &&
-          SpaceMangler::is_mangled((HeapWord*) tc->size_addr()) &&
-          SpaceMangler::is_mangled((HeapWord*) tc->prev_addr()) &&
-          SpaceMangler::is_mangled((HeapWord*) tc->next_addr())) ||
-          (tc->size() == 0 && tc->prev() == NULL && tc->next() == NULL),
-    "Space should be clear or mangled");
-  tc->setSize(size);
-  tc->linkPrev(NULL);
-  tc->linkNext(NULL);
-  TreeList* tl = TreeList::as_TreeList(tc);
-  return tl;
-}
-
-TreeList* TreeList::removeChunkReplaceIfNeeded(TreeChunk* tc) {
-
-  TreeList* retTL = this;
-  FreeChunk* list = head();
-  assert(!list || list != list->next(), "Chunk on list twice");
-  assert(tc != NULL, "Chunk being removed is NULL");
-  assert(parent() == NULL || this == parent()->left() ||
-    this == parent()->right(), "list is inconsistent");
-  assert(tc->isFree(), "Header is not marked correctly");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  FreeChunk* prevFC = tc->prev();
-  TreeChunk* nextTC = TreeChunk::as_TreeChunk(tc->next());
-  assert(list != NULL, "should have at least the target chunk");
-
-  // Is this the first item on the list?
-  if (tc == list) {
-    // The "getChunk..." functions for a TreeList will not return the
-    // first chunk in the list unless it is the last chunk in the list
-    // because the first chunk is also acting as the tree node.
-    // When coalescing happens, however, the first chunk in the a tree
-    // list can be the start of a free range.  Free ranges are removed
-    // from the free lists so that they are not available to be
-    // allocated when the sweeper yields (giving up the free list lock)
-    // to allow mutator activity.  If this chunk is the first in the
-    // list and is not the last in the list, do the work to copy the
-    // TreeList from the first chunk to the next chunk and update all
-    // the TreeList pointers in the chunks in the list.
-    if (nextTC == NULL) {
-      assert(prevFC == NULL, "Not last chunk in the list");
-      set_tail(NULL);
-      set_head(NULL);
-    } else {
-      // copy embedded list.
-      nextTC->set_embedded_list(tc->embedded_list());
-      retTL = nextTC->embedded_list();
-      // Fix the pointer to the list in each chunk in the list.
-      // This can be slow for a long list.  Consider having
-      // an option that does not allow the first chunk on the
-      // list to be coalesced.
-      for (TreeChunk* curTC = nextTC; curTC != NULL;
-          curTC = TreeChunk::as_TreeChunk(curTC->next())) {
-        curTC->set_list(retTL);
-      }
-      // Fix the parent to point to the new TreeList.
-      if (retTL->parent() != NULL) {
-        if (this == retTL->parent()->left()) {
-          retTL->parent()->setLeft(retTL);
-        } else {
-          assert(this == retTL->parent()->right(), "Parent is incorrect");
-          retTL->parent()->setRight(retTL);
-        }
-      }
-      // Fix the children's parent pointers to point to the
-      // new list.
-      assert(right() == retTL->right(), "Should have been copied");
-      if (retTL->right() != NULL) {
-        retTL->right()->setParent(retTL);
-      }
-      assert(left() == retTL->left(), "Should have been copied");
-      if (retTL->left() != NULL) {
-        retTL->left()->setParent(retTL);
-      }
-      retTL->link_head(nextTC);
-      assert(nextTC->isFree(), "Should be a free chunk");
-    }
-  } else {
-    if (nextTC == NULL) {
-      // Removing chunk at tail of list
-      link_tail(prevFC);
-    }
-    // Chunk is interior to the list
-    prevFC->linkAfter(nextTC);
-  }
-
-  // Below this point the embeded TreeList being used for the
-  // tree node may have changed. Don't use "this"
-  // TreeList*.
-  // chunk should still be a free chunk (bit set in _prev)
-  assert(!retTL->head() || retTL->size() == retTL->head()->size(),
-    "Wrong sized chunk in list");
-  debug_only(
-    tc->linkPrev(NULL);
-    tc->linkNext(NULL);
-    tc->set_list(NULL);
-    bool prev_found = false;
-    bool next_found = false;
-    for (FreeChunk* curFC = retTL->head();
-         curFC != NULL; curFC = curFC->next()) {
-      assert(curFC != tc, "Chunk is still in list");
-      if (curFC == prevFC) {
-        prev_found = true;
-      }
-      if (curFC == nextTC) {
-        next_found = true;
-      }
-    }
-    assert(prevFC == NULL || prev_found, "Chunk was lost from list");
-    assert(nextTC == NULL || next_found, "Chunk was lost from list");
-    assert(retTL->parent() == NULL ||
-           retTL == retTL->parent()->left() ||
-           retTL == retTL->parent()->right(),
-           "list is inconsistent");
-  )
-  retTL->decrement_count();
-
-  assert(tc->isFree(), "Should still be a free chunk");
-  assert(retTL->head() == NULL || retTL->head()->prev() == NULL,
-    "list invariant");
-  assert(retTL->tail() == NULL || retTL->tail()->next() == NULL,
-    "list invariant");
-  return retTL;
-}
-void TreeList::returnChunkAtTail(TreeChunk* chunk) {
-  assert(chunk != NULL, "returning NULL chunk");
-  assert(chunk->list() == this, "list should be set for chunk");
-  assert(tail() != NULL, "The tree list is embedded in the first chunk");
-  // which means that the list can never be empty.
-  assert(!verifyChunkInFreeLists(chunk), "Double entry");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  FreeChunk* fc = tail();
-  fc->linkAfter(chunk);
-  link_tail(chunk);
-
-  assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
-  increment_count();
-  debug_only(increment_returnedBytes_by(chunk->size()*sizeof(HeapWord));)
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-}
-
-// Add this chunk at the head of the list.  "At the head of the list"
-// is defined to be after the chunk pointer to by head().  This is
-// because the TreeList is embedded in the first TreeChunk in the
-// list.  See the definition of TreeChunk.
-void TreeList::returnChunkAtHead(TreeChunk* chunk) {
-  assert(chunk->list() == this, "list should be set for chunk");
-  assert(head() != NULL, "The tree list is embedded in the first chunk");
-  assert(chunk != NULL, "returning NULL chunk");
-  assert(!verifyChunkInFreeLists(chunk), "Double entry");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  FreeChunk* fc = head()->next();
-  if (fc != NULL) {
-    chunk->linkAfter(fc);
-  } else {
-    assert(tail() == NULL, "List is inconsistent");
-    link_tail(chunk);
-  }
-  head()->linkAfter(chunk);
-  assert(!head() || size() == head()->size(), "Wrong sized chunk in list");
-  increment_count();
-  debug_only(increment_returnedBytes_by(chunk->size()*sizeof(HeapWord));)
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-}
-
-TreeChunk* TreeList::head_as_TreeChunk() {
-  assert(head() == NULL || TreeChunk::as_TreeChunk(head())->list() == this,
-    "Wrong type of chunk?");
-  return TreeChunk::as_TreeChunk(head());
-}
-
-TreeChunk* TreeList::first_available() {
-  assert(head() != NULL, "The head of the list cannot be NULL");
-  FreeChunk* fc = head()->next();
-  TreeChunk* retTC;
-  if (fc == NULL) {
-    retTC = head_as_TreeChunk();
-  } else {
-    retTC = TreeChunk::as_TreeChunk(fc);
-  }
-  assert(retTC->list() == this, "Wrong type of chunk.");
-  return retTC;
-}
-
-// Returns the block with the largest heap address amongst
-// those in the list for this size; potentially slow and expensive,
-// use with caution!
-TreeChunk* TreeList::largest_address() {
-  assert(head() != NULL, "The head of the list cannot be NULL");
-  FreeChunk* fc = head()->next();
-  TreeChunk* retTC;
-  if (fc == NULL) {
-    retTC = head_as_TreeChunk();
-  } else {
-    // walk down the list and return the one with the highest
-    // heap address among chunks of this size.
-    FreeChunk* last = fc;
-    while (fc->next() != NULL) {
-      if ((HeapWord*)last < (HeapWord*)fc) {
-        last = fc;
-      }
-      fc = fc->next();
-    }
-    retTC = TreeChunk::as_TreeChunk(last);
-  }
-  assert(retTC->list() == this, "Wrong type of chunk.");
-  return retTC;
-}
-
-BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr, bool splay):
-  _splay(splay)
-{
-  assert(mr.byte_size() > MIN_TREE_CHUNK_SIZE, "minimum chunk size");
-
-  reset(mr);
-  assert(root()->left() == NULL, "reset check failed");
-  assert(root()->right() == NULL, "reset check failed");
-  assert(root()->head()->next() == NULL, "reset check failed");
-  assert(root()->head()->prev() == NULL, "reset check failed");
-  assert(totalSize() == root()->size(), "reset check failed");
-  assert(totalFreeBlocks() == 1, "reset check failed");
-}
-
-void BinaryTreeDictionary::inc_totalSize(size_t inc) {
-  _totalSize = _totalSize + inc;
-}
-
-void BinaryTreeDictionary::dec_totalSize(size_t dec) {
-  _totalSize = _totalSize - dec;
-}
-
-void BinaryTreeDictionary::reset(MemRegion mr) {
-  assert(mr.byte_size() > MIN_TREE_CHUNK_SIZE, "minimum chunk size");
-  set_root(TreeList::as_TreeList(mr.start(), mr.word_size()));
-  set_totalSize(mr.word_size());
-  set_totalFreeBlocks(1);
-}
-
-void BinaryTreeDictionary::reset(HeapWord* addr, size_t byte_size) {
-  MemRegion mr(addr, heap_word_size(byte_size));
-  reset(mr);
-}
-
-void BinaryTreeDictionary::reset() {
-  set_root(NULL);
-  set_totalSize(0);
-  set_totalFreeBlocks(0);
-}
-
-// Get a free block of size at least size from tree, or NULL.
-// If a splay step is requested, the removal algorithm (only) incorporates
-// a splay step as follows:
-// . the search proceeds down the tree looking for a possible
-//   match. At the (closest) matching location, an appropriate splay step is applied
-//   (zig, zig-zig or zig-zag). A chunk of the appropriate size is then returned
-//   if available, and if it's the last chunk, the node is deleted. A deteleted
-//   node is replaced in place by its tree successor.
-TreeChunk*
-BinaryTreeDictionary::getChunkFromTree(size_t size, Dither dither, bool splay)
-{
-  TreeList *curTL, *prevTL;
-  TreeChunk* retTC = NULL;
-  assert(size >= MIN_TREE_CHUNK_SIZE, "minimum chunk size");
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-  // starting at the root, work downwards trying to find match.
-  // Remember the last node of size too great or too small.
-  for (prevTL = curTL = root(); curTL != NULL;) {
-    if (curTL->size() == size) {        // exact match
-      break;
-    }
-    prevTL = curTL;
-    if (curTL->size() < size) {        // proceed to right sub-tree
-      curTL = curTL->right();
-    } else {                           // proceed to left sub-tree
-      assert(curTL->size() > size, "size inconsistency");
-      curTL = curTL->left();
-    }
-  }
-  if (curTL == NULL) { // couldn't find exact match
-    // try and find the next larger size by walking back up the search path
-    for (curTL = prevTL; curTL != NULL;) {
-      if (curTL->size() >= size) break;
-      else curTL = curTL->parent();
-    }
-    assert(curTL == NULL || curTL->count() > 0,
-      "An empty list should not be in the tree");
-  }
-  if (curTL != NULL) {
-    assert(curTL->size() >= size, "size inconsistency");
-    if (UseCMSAdaptiveFreeLists) {
-
-      // A candidate chunk has been found.  If it is already under
-      // populated, get a chunk associated with the hint for this
-      // chunk.
-      if (curTL->surplus() <= 0) {
-        /* Use the hint to find a size with a surplus, and reset the hint. */
-        TreeList* hintTL = curTL;
-        while (hintTL->hint() != 0) {
-          assert(hintTL->hint() == 0 || hintTL->hint() > hintTL->size(),
-            "hint points in the wrong direction");
-          hintTL = findList(hintTL->hint());
-          assert(curTL != hintTL, "Infinite loop");
-          if (hintTL == NULL ||
-              hintTL == curTL /* Should not happen but protect against it */ ) {
-            // No useful hint.  Set the hint to NULL and go on.
-            curTL->set_hint(0);
-            break;
-          }
-          assert(hintTL->size() > size, "hint is inconsistent");
-          if (hintTL->surplus() > 0) {
-            // The hint led to a list that has a surplus.  Use it.
-            // Set the hint for the candidate to an overpopulated
-            // size.
-            curTL->set_hint(hintTL->size());
-            // Change the candidate.
-            curTL = hintTL;
-            break;
-          }
-          // The evm code reset the hint of the candidate as
-          // at an interim point.  Why?  Seems like this leaves
-          // the hint pointing to a list that didn't work.
-          // curTL->set_hint(hintTL->size());
-        }
-      }
-    }
-    // don't waste time splaying if chunk's singleton
-    if (splay && curTL->head()->next() != NULL) {
-      semiSplayStep(curTL);
-    }
-    retTC = curTL->first_available();
-    assert((retTC != NULL) && (curTL->count() > 0),
-      "A list in the binary tree should not be NULL");
-    assert(retTC->size() >= size,
-      "A chunk of the wrong size was found");
-    removeChunkFromTree(retTC);
-    assert(retTC->isFree(), "Header is not marked correctly");
-  }
-
-  if (FLSVerifyDictionary) {
-    verify();
-  }
-  return retTC;
-}
-
-TreeList* BinaryTreeDictionary::findList(size_t size) const {
-  TreeList* curTL;
-  for (curTL = root(); curTL != NULL;) {
-    if (curTL->size() == size) {        // exact match
-      break;
-    }
-
-    if (curTL->size() < size) {        // proceed to right sub-tree
-      curTL = curTL->right();
-    } else {                           // proceed to left sub-tree
-      assert(curTL->size() > size, "size inconsistency");
-      curTL = curTL->left();
-    }
-  }
-  return curTL;
-}
-
-
-bool BinaryTreeDictionary::verifyChunkInFreeLists(FreeChunk* tc) const {
-  size_t size = tc->size();
-  TreeList* tl = findList(size);
-  if (tl == NULL) {
-    return false;
-  } else {
-    return tl->verifyChunkInFreeLists(tc);
-  }
-}
-
-FreeChunk* BinaryTreeDictionary::findLargestDict() const {
-  TreeList *curTL = root();
-  if (curTL != NULL) {
-    while(curTL->right() != NULL) curTL = curTL->right();
-    return curTL->largest_address();
-  } else {
-    return NULL;
-  }
-}
-
-// Remove the current chunk from the tree.  If it is not the last
-// chunk in a list on a tree node, just unlink it.
-// If it is the last chunk in the list (the next link is NULL),
-// remove the node and repair the tree.
-TreeChunk*
-BinaryTreeDictionary::removeChunkFromTree(TreeChunk* tc) {
-  assert(tc != NULL, "Should not call with a NULL chunk");
-  assert(tc->isFree(), "Header is not marked correctly");
-
-  TreeList *newTL, *parentTL;
-  TreeChunk* retTC;
-  TreeList* tl = tc->list();
-  debug_only(
-    bool removing_only_chunk = false;
-    if (tl == _root) {
-      if ((_root->left() == NULL) && (_root->right() == NULL)) {
-        if (_root->count() == 1) {
-          assert(_root->head() == tc, "Should only be this one chunk");
-          removing_only_chunk = true;
-        }
-      }
-    }
-  )
-  assert(tl != NULL, "List should be set");
-  assert(tl->parent() == NULL || tl == tl->parent()->left() ||
-         tl == tl->parent()->right(), "list is inconsistent");
-
-  bool complicatedSplice = false;
-
-  retTC = tc;
-  // Removing this chunk can have the side effect of changing the node
-  // (TreeList*) in the tree.  If the node is the root, update it.
-  TreeList* replacementTL = tl->removeChunkReplaceIfNeeded(tc);
-  assert(tc->isFree(), "Chunk should still be free");
-  assert(replacementTL->parent() == NULL ||
-         replacementTL == replacementTL->parent()->left() ||
-         replacementTL == replacementTL->parent()->right(),
-         "list is inconsistent");
-  if (tl == root()) {
-    assert(replacementTL->parent() == NULL, "Incorrectly replacing root");
-    set_root(replacementTL);
-  }
-  debug_only(
-    if (tl != replacementTL) {
-      assert(replacementTL->head() != NULL,
-        "If the tree list was replaced, it should not be a NULL list");
-      TreeList* rhl = replacementTL->head_as_TreeChunk()->list();
-      TreeList* rtl = TreeChunk::as_TreeChunk(replacementTL->tail())->list();
-      assert(rhl == replacementTL, "Broken head");
-      assert(rtl == replacementTL, "Broken tail");
-      assert(replacementTL->size() == tc->size(),  "Broken size");
-    }
-  )
-
-  // Does the tree need to be repaired?
-  if (replacementTL->count() == 0) {
-    assert(replacementTL->head() == NULL &&
-           replacementTL->tail() == NULL, "list count is incorrect");
-    // Find the replacement node for the (soon to be empty) node being removed.
-    // if we have a single (or no) child, splice child in our stead
-    if (replacementTL->left() == NULL) {
-      // left is NULL so pick right.  right may also be NULL.
-      newTL = replacementTL->right();
-      debug_only(replacementTL->clearRight();)
-    } else if (replacementTL->right() == NULL) {
-      // right is NULL
-      newTL = replacementTL->left();
-      debug_only(replacementTL->clearLeft();)
-    } else {  // we have both children, so, by patriarchal convention,
-              // my replacement is least node in right sub-tree
-      complicatedSplice = true;
-      newTL = removeTreeMinimum(replacementTL->right());
-      assert(newTL != NULL && newTL->left() == NULL &&
-             newTL->right() == NULL, "sub-tree minimum exists");
-    }
-    // newTL is the replacement for the (soon to be empty) node.
-    // newTL may be NULL.
-    // should verify; we just cleanly excised our replacement
-    if (FLSVerifyDictionary) {
-      verifyTree();
-    }
-    // first make newTL my parent's child
-    if ((parentTL = replacementTL->parent()) == NULL) {
-      // newTL should be root
-      assert(tl == root(), "Incorrectly replacing root");
-      set_root(newTL);
-      if (newTL != NULL) {
-        newTL->clearParent();
-      }
-    } else if (parentTL->right() == replacementTL) {
-      // replacementTL is a right child
-      parentTL->setRight(newTL);
-    } else {                                // replacementTL is a left child
-      assert(parentTL->left() == replacementTL, "should be left child");
-      parentTL->setLeft(newTL);
-    }
-    debug_only(replacementTL->clearParent();)
-    if (complicatedSplice) {  // we need newTL to get replacementTL's
-                              // two children
-      assert(newTL != NULL &&
-             newTL->left() == NULL && newTL->right() == NULL,
-            "newTL should not have encumbrances from the past");
-      // we'd like to assert as below:
-      // assert(replacementTL->left() != NULL && replacementTL->right() != NULL,
-      //       "else !complicatedSplice");
-      // ... however, the above assertion is too strong because we aren't
-      // guaranteed that replacementTL->right() is still NULL.
-      // Recall that we removed
-      // the right sub-tree minimum from replacementTL.
-      // That may well have been its right
-      // child! So we'll just assert half of the above:
-      assert(replacementTL->left() != NULL, "else !complicatedSplice");
-      newTL->setLeft(replacementTL->left());
-      newTL->setRight(replacementTL->right());
-      debug_only(
-        replacementTL->clearRight();
-        replacementTL->clearLeft();
-      )
-    }
-    assert(replacementTL->right() == NULL &&
-           replacementTL->left() == NULL &&
-           replacementTL->parent() == NULL,
-        "delete without encumbrances");
-  }
-
-  assert(totalSize() >= retTC->size(), "Incorrect total size");
-  dec_totalSize(retTC->size());     // size book-keeping
-  assert(totalFreeBlocks() > 0, "Incorrect total count");
-  set_totalFreeBlocks(totalFreeBlocks() - 1);
-
-  assert(retTC != NULL, "null chunk?");
-  assert(retTC->prev() == NULL && retTC->next() == NULL,
-         "should return without encumbrances");
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-  assert(!removing_only_chunk || _root == NULL, "root should be NULL");
-  return TreeChunk::as_TreeChunk(retTC);
-}
-
-// Remove the leftmost node (lm) in the tree and return it.
-// If lm has a right child, link it to the left node of
-// the parent of lm.
-TreeList* BinaryTreeDictionary::removeTreeMinimum(TreeList* tl) {
-  assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
-  // locate the subtree minimum by walking down left branches
-  TreeList* curTL = tl;
-  for (; curTL->left() != NULL; curTL = curTL->left());
-  // obviously curTL now has at most one child, a right child
-  if (curTL != root()) {  // Should this test just be removed?
-    TreeList* parentTL = curTL->parent();
-    if (parentTL->left() == curTL) { // curTL is a left child
-      parentTL->setLeft(curTL->right());
-    } else {
-      // If the list tl has no left child, then curTL may be
-      // the right child of parentTL.
-      assert(parentTL->right() == curTL, "should be a right child");
-      parentTL->setRight(curTL->right());
-    }
-  } else {
-    // The only use of this method would not pass the root of the
-    // tree (as indicated by the assertion above that the tree list
-    // has a parent) but the specification does not explicitly exclude the
-    // passing of the root so accomodate it.
-    set_root(NULL);
-  }
-  debug_only(
-    curTL->clearParent();  // Test if this needs to be cleared
-    curTL->clearRight();    // recall, above, left child is already null
-  )
-  // we just excised a (non-root) node, we should still verify all tree invariants
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-  return curTL;
-}
-
-// Based on a simplification of the algorithm by Sleator and Tarjan (JACM 1985).
-// The simplifications are the following:
-// . we splay only when we delete (not when we insert)
-// . we apply a single spay step per deletion/access
-// By doing such partial splaying, we reduce the amount of restructuring,
-// while getting a reasonably efficient search tree (we think).
-// [Measurements will be needed to (in)validate this expectation.]
-
-void BinaryTreeDictionary::semiSplayStep(TreeList* tc) {
-  // apply a semi-splay step at the given node:
-  // . if root, norting needs to be done
-  // . if child of root, splay once
-  // . else zig-zig or sig-zag depending on path from grandparent
-  if (root() == tc) return;
-  warning("*** Splaying not yet implemented; "
-          "tree operations may be inefficient ***");
-}
-
-void BinaryTreeDictionary::insertChunkInTree(FreeChunk* fc) {
-  TreeList *curTL, *prevTL;
-  size_t size = fc->size();
-
-  assert(size >= MIN_TREE_CHUNK_SIZE, "too small to be a TreeList");
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-  // XXX: do i need to clear the FreeChunk fields, let me do it just in case
-  // Revisit this later
-
-  fc->clearNext();
-  fc->linkPrev(NULL);
-
-  // work down from the _root, looking for insertion point
-  for (prevTL = curTL = root(); curTL != NULL;) {
-    if (curTL->size() == size)  // exact match
-      break;
-    prevTL = curTL;
-    if (curTL->size() > size) { // follow left branch
-      curTL = curTL->left();
-    } else {                    // follow right branch
-      assert(curTL->size() < size, "size inconsistency");
-      curTL = curTL->right();
-    }
-  }
-  TreeChunk* tc = TreeChunk::as_TreeChunk(fc);
-  // This chunk is being returned to the binary tree.  Its embedded
-  // TreeList should be unused at this point.
-  tc->initialize();
-  if (curTL != NULL) {          // exact match
-    tc->set_list(curTL);
-    curTL->returnChunkAtTail(tc);
-  } else {                     // need a new node in tree
-    tc->clearNext();
-    tc->linkPrev(NULL);
-    TreeList* newTL = TreeList::as_TreeList(tc);
-    assert(((TreeChunk*)tc)->list() == newTL,
-      "List was not initialized correctly");
-    if (prevTL == NULL) {      // we are the only tree node
-      assert(root() == NULL, "control point invariant");
-      set_root(newTL);
-    } else {                   // insert under prevTL ...
-      if (prevTL->size() < size) {   // am right child
-        assert(prevTL->right() == NULL, "control point invariant");
-        prevTL->setRight(newTL);
-      } else {                       // am left child
-        assert(prevTL->size() > size && prevTL->left() == NULL, "cpt pt inv");
-        prevTL->setLeft(newTL);
-      }
-    }
-  }
-  assert(tc->list() != NULL, "Tree list should be set");
-
-  inc_totalSize(size);
-  // Method 'totalSizeInTree' walks through the every block in the
-  // tree, so it can cause significant performance loss if there are
-  // many blocks in the tree
-  assert(!FLSVerifyDictionary || totalSizeInTree(root()) == totalSize(), "_totalSize inconsistency");
-  set_totalFreeBlocks(totalFreeBlocks() + 1);
-  if (FLSVerifyDictionary) {
-    verifyTree();
-  }
-}
-
-size_t BinaryTreeDictionary::maxChunkSize() const {
-  verify_par_locked();
-  TreeList* tc = root();
-  if (tc == NULL) return 0;
-  for (; tc->right() != NULL; tc = tc->right());
-  return tc->size();
-}
-
-size_t BinaryTreeDictionary::totalListLength(TreeList* tl) const {
-  size_t res;
-  res = tl->count();
-#ifdef ASSERT
-  size_t cnt;
-  FreeChunk* tc = tl->head();
-  for (cnt = 0; tc != NULL; tc = tc->next(), cnt++);
-  assert(res == cnt, "The count is not being maintained correctly");
-#endif
-  return res;
-}
-
-size_t BinaryTreeDictionary::totalSizeInTree(TreeList* tl) const {
-  if (tl == NULL)
-    return 0;
-  return (tl->size() * totalListLength(tl)) +
-         totalSizeInTree(tl->left())    +
-         totalSizeInTree(tl->right());
-}
-
-double BinaryTreeDictionary::sum_of_squared_block_sizes(TreeList* const tl) const {
-  if (tl == NULL) {
-    return 0.0;
-  }
-  double size = (double)(tl->size());
-  double curr = size * size * totalListLength(tl);
-  curr += sum_of_squared_block_sizes(tl->left());
-  curr += sum_of_squared_block_sizes(tl->right());
-  return curr;
-}
-
-size_t BinaryTreeDictionary::totalFreeBlocksInTree(TreeList* tl) const {
-  if (tl == NULL)
-    return 0;
-  return totalListLength(tl) +
-         totalFreeBlocksInTree(tl->left()) +
-         totalFreeBlocksInTree(tl->right());
-}
-
-size_t BinaryTreeDictionary::numFreeBlocks() const {
-  assert(totalFreeBlocksInTree(root()) == totalFreeBlocks(),
-         "_totalFreeBlocks inconsistency");
-  return totalFreeBlocks();
-}
-
-size_t BinaryTreeDictionary::treeHeightHelper(TreeList* tl) const {
-  if (tl == NULL)
-    return 0;
-  return 1 + MAX2(treeHeightHelper(tl->left()),
-                  treeHeightHelper(tl->right()));
-}
-
-size_t BinaryTreeDictionary::treeHeight() const {
-  return treeHeightHelper(root());
-}
-
-size_t BinaryTreeDictionary::totalNodesHelper(TreeList* tl) const {
-  if (tl == NULL) {
-    return 0;
-  }
-  return 1 + totalNodesHelper(tl->left()) +
-    totalNodesHelper(tl->right());
-}
-
-size_t BinaryTreeDictionary::totalNodesInTree(TreeList* tl) const {
-  return totalNodesHelper(root());
-}
-
-void BinaryTreeDictionary::dictCensusUpdate(size_t size, bool split, bool birth){
-  TreeList* nd = findList(size);
-  if (nd) {
-    if (split) {
-      if (birth) {
-        nd->increment_splitBirths();
-        nd->increment_surplus();
-      }  else {
-        nd->increment_splitDeaths();
-        nd->decrement_surplus();
-      }
-    } else {
-      if (birth) {
-        nd->increment_coalBirths();
-        nd->increment_surplus();
-      } else {
-        nd->increment_coalDeaths();
-        nd->decrement_surplus();
-      }
-    }
-  }
-  // A list for this size may not be found (nd == 0) if
-  //   This is a death where the appropriate list is now
-  //     empty and has been removed from the list.
-  //   This is a birth associated with a LinAB.  The chunk
-  //     for the LinAB is not in the dictionary.
-}
-
-bool BinaryTreeDictionary::coalDictOverPopulated(size_t size) {
-  if (FLSAlwaysCoalesceLarge) return true;
-
-  TreeList* list_of_size = findList(size);
-  // None of requested size implies overpopulated.
-  return list_of_size == NULL || list_of_size->coalDesired() <= 0 ||
-         list_of_size->count() > list_of_size->coalDesired();
-}
-
-// Closures for walking the binary tree.
-//   do_list() walks the free list in a node applying the closure
-//     to each free chunk in the list
-//   do_tree() walks the nodes in the binary tree applying do_list()
-//     to each list at each node.
-
-class TreeCensusClosure : public StackObj {
- protected:
-  virtual void do_list(FreeList* fl) = 0;
- public:
-  virtual void do_tree(TreeList* tl) = 0;
-};
-
-class AscendTreeCensusClosure : public TreeCensusClosure {
- public:
-  void do_tree(TreeList* tl) {
-    if (tl != NULL) {
-      do_tree(tl->left());
-      do_list(tl);
-      do_tree(tl->right());
-    }
-  }
-};
-
-class DescendTreeCensusClosure : public TreeCensusClosure {
- public:
-  void do_tree(TreeList* tl) {
-    if (tl != NULL) {
-      do_tree(tl->right());
-      do_list(tl);
-      do_tree(tl->left());
-    }
-  }
-};
-
-// For each list in the tree, calculate the desired, desired
-// coalesce, count before sweep, and surplus before sweep.
-class BeginSweepClosure : public AscendTreeCensusClosure {
-  double _percentage;
-  float _inter_sweep_current;
-  float _inter_sweep_estimate;
-  float _intra_sweep_estimate;
-
- public:
-  BeginSweepClosure(double p, float inter_sweep_current,
-                              float inter_sweep_estimate,
-                              float intra_sweep_estimate) :
-   _percentage(p),
-   _inter_sweep_current(inter_sweep_current),
-   _inter_sweep_estimate(inter_sweep_estimate),
-   _intra_sweep_estimate(intra_sweep_estimate) { }
-
-  void do_list(FreeList* fl) {
-    double coalSurplusPercent = _percentage;
-    fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
-    fl->set_coalDesired((ssize_t)((double)fl->desired() * coalSurplusPercent));
-    fl->set_beforeSweep(fl->count());
-    fl->set_bfrSurp(fl->surplus());
-  }
-};
-
-// Used to search the tree until a condition is met.
-// Similar to TreeCensusClosure but searches the
-// tree and returns promptly when found.
-
-class TreeSearchClosure : public StackObj {
- protected:
-  virtual bool do_list(FreeList* fl) = 0;
- public:
-  virtual bool do_tree(TreeList* tl) = 0;
-};
-
-#if 0 //  Don't need this yet but here for symmetry.
-class AscendTreeSearchClosure : public TreeSearchClosure {
- public:
-  bool do_tree(TreeList* tl) {
-    if (tl != NULL) {
-      if (do_tree(tl->left())) return true;
-      if (do_list(tl)) return true;
-      if (do_tree(tl->right())) return true;
-    }
-    return false;
-  }
-};
-#endif
-
-class DescendTreeSearchClosure : public TreeSearchClosure {
- public:
-  bool do_tree(TreeList* tl) {
-    if (tl != NULL) {
-      if (do_tree(tl->right())) return true;
-      if (do_list(tl)) return true;
-      if (do_tree(tl->left())) return true;
-    }
-    return false;
-  }
-};
-
-// Searches the tree for a chunk that ends at the
-// specified address.
-class EndTreeSearchClosure : public DescendTreeSearchClosure {
-  HeapWord* _target;
-  FreeChunk* _found;
-
- public:
-  EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {}
-  bool do_list(FreeList* fl) {
-    FreeChunk* item = fl->head();
-    while (item != NULL) {
-      if (item->end() == _target) {
-        _found = item;
-        return true;
-      }
-      item = item->next();
-    }
-    return false;
-  }
-  FreeChunk* found() { return _found; }
-};
-
-FreeChunk* BinaryTreeDictionary::find_chunk_ends_at(HeapWord* target) const {
-  EndTreeSearchClosure etsc(target);
-  bool found_target = etsc.do_tree(root());
-  assert(found_target || etsc.found() == NULL, "Consistency check");
-  assert(!found_target || etsc.found() != NULL, "Consistency check");
-  return etsc.found();
-}
-
-void BinaryTreeDictionary::beginSweepDictCensus(double coalSurplusPercent,
-  float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
-  BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current,
-                                            inter_sweep_estimate,
-                                            intra_sweep_estimate);
-  bsc.do_tree(root());
-}
-
-// Closures and methods for calculating total bytes returned to the
-// free lists in the tree.
-NOT_PRODUCT(
-  class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure {
-   public:
-    void do_list(FreeList* fl) {
-      fl->set_returnedBytes(0);
-    }
-  };
-
-  void BinaryTreeDictionary::initializeDictReturnedBytes() {
-    InitializeDictReturnedBytesClosure idrb;
-    idrb.do_tree(root());
-  }
-
-  class ReturnedBytesClosure : public AscendTreeCensusClosure {
-    size_t _dictReturnedBytes;
-   public:
-    ReturnedBytesClosure() { _dictReturnedBytes = 0; }
-    void do_list(FreeList* fl) {
-      _dictReturnedBytes += fl->returnedBytes();
-    }
-    size_t dictReturnedBytes() { return _dictReturnedBytes; }
-  };
-
-  size_t BinaryTreeDictionary::sumDictReturnedBytes() {
-    ReturnedBytesClosure rbc;
-    rbc.do_tree(root());
-
-    return rbc.dictReturnedBytes();
-  }
-
-  // Count the number of entries in the tree.
-  class treeCountClosure : public DescendTreeCensusClosure {
-   public:
-    uint count;
-    treeCountClosure(uint c) { count = c; }
-    void do_list(FreeList* fl) {
-      count++;
-    }
-  };
-
-  size_t BinaryTreeDictionary::totalCount() {
-    treeCountClosure ctc(0);
-    ctc.do_tree(root());
-    return ctc.count;
-  }
-)
-
-// Calculate surpluses for the lists in the tree.
-class setTreeSurplusClosure : public AscendTreeCensusClosure {
-  double percentage;
- public:
-  setTreeSurplusClosure(double v) { percentage = v; }
-  void do_list(FreeList* fl) {
-    double splitSurplusPercent = percentage;
-    fl->set_surplus(fl->count() -
-                   (ssize_t)((double)fl->desired() * splitSurplusPercent));
-  }
-};
-
-void BinaryTreeDictionary::setTreeSurplus(double splitSurplusPercent) {
-  setTreeSurplusClosure sts(splitSurplusPercent);
-  sts.do_tree(root());
-}
-
-// Set hints for the lists in the tree.
-class setTreeHintsClosure : public DescendTreeCensusClosure {
-  size_t hint;
- public:
-  setTreeHintsClosure(size_t v) { hint = v; }
-  void do_list(FreeList* fl) {
-    fl->set_hint(hint);
-    assert(fl->hint() == 0 || fl->hint() > fl->size(),
-      "Current hint is inconsistent");
-    if (fl->surplus() > 0) {
-      hint = fl->size();
-    }
-  }
-};
-
-void BinaryTreeDictionary::setTreeHints(void) {
-  setTreeHintsClosure sth(0);
-  sth.do_tree(root());
-}
-
-// Save count before previous sweep and splits and coalesces.
-class clearTreeCensusClosure : public AscendTreeCensusClosure {
-  void do_list(FreeList* fl) {
-    fl->set_prevSweep(fl->count());
-    fl->set_coalBirths(0);
-    fl->set_coalDeaths(0);
-    fl->set_splitBirths(0);
-    fl->set_splitDeaths(0);
-  }
-};
-
-void BinaryTreeDictionary::clearTreeCensus(void) {
-  clearTreeCensusClosure ctc;
-  ctc.do_tree(root());
-}
-
-// Do reporting and post sweep clean up.
-void BinaryTreeDictionary::endSweepDictCensus(double splitSurplusPercent) {
-  // Does walking the tree 3 times hurt?
-  setTreeSurplus(splitSurplusPercent);
-  setTreeHints();
-  if (PrintGC && Verbose) {
-    reportStatistics();
-  }
-  clearTreeCensus();
-}
-
-// Print summary statistics
-void BinaryTreeDictionary::reportStatistics() const {
-  verify_par_locked();
-  gclog_or_tty->print("Statistics for BinaryTreeDictionary:\n"
-         "------------------------------------\n");
-  size_t totalSize = totalChunkSize(debug_only(NULL));
-  size_t    freeBlocks = numFreeBlocks();
-  gclog_or_tty->print("Total Free Space: %d\n", totalSize);
-  gclog_or_tty->print("Max   Chunk Size: %d\n", maxChunkSize());
-  gclog_or_tty->print("Number of Blocks: %d\n", freeBlocks);
-  if (freeBlocks > 0) {
-    gclog_or_tty->print("Av.  Block  Size: %d\n", totalSize/freeBlocks);
-  }
-  gclog_or_tty->print("Tree      Height: %d\n", treeHeight());
-}
-
-// Print census information - counts, births, deaths, etc.
-// for each list in the tree.  Also print some summary
-// information.
-class PrintTreeCensusClosure : public AscendTreeCensusClosure {
-  int _print_line;
-  size_t _totalFree;
-  FreeList _total;
-
- public:
-  PrintTreeCensusClosure() {
-    _print_line = 0;
-    _totalFree = 0;
-  }
-  FreeList* total() { return &_total; }
-  size_t totalFree() { return _totalFree; }
-  void do_list(FreeList* fl) {
-    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");
-  FreeList::print_labels_on(gclog_or_tty, "size");
-  PrintTreeCensusClosure ptc;
-  ptc.do_tree(root());
-
-  FreeList* total = ptc.total();
-  FreeList::print_labels_on(gclog_or_tty, " ");
-  total->print_on(gclog_or_tty, "TOTAL\t");
-  gclog_or_tty->print(
-              "totalFree(words): " SIZE_FORMAT_W(16)
-              " growth: %8.5f  deficit: %8.5f\n",
-              ptc.totalFree(),
-              (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));
-}
-
-class PrintFreeListsClosure : public AscendTreeCensusClosure {
-  outputStream* _st;
-  int _print_line;
-
- public:
-  PrintFreeListsClosure(outputStream* st) {
-    _st = st;
-    _print_line = 0;
-  }
-  void do_list(FreeList* fl) {
-    if (++_print_line >= 40) {
-      FreeList::print_labels_on(_st, "size");
-      _print_line = 0;
-    }
-    fl->print_on(gclog_or_tty);
-    size_t sz = fl->size();
-    for (FreeChunk* fc = fl->head(); fc != NULL;
-         fc = fc->next()) {
-      _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ")  %s",
-                    fc, (HeapWord*)fc + sz,
-                    fc->cantCoalesce() ? "\t CC" : "");
-    }
-  }
-};
-
-void BinaryTreeDictionary::print_free_lists(outputStream* st) const {
-
-  FreeList::print_labels_on(st, "size");
-  PrintFreeListsClosure pflc(st);
-  pflc.do_tree(root());
-}
-
-// Verify the following tree invariants:
-// . _root has no parent
-// . parent and child point to each other
-// . each node's key correctly related to that of its child(ren)
-void BinaryTreeDictionary::verifyTree() const {
-  guarantee(root() == NULL || totalFreeBlocks() == 0 ||
-    totalSize() != 0, "_totalSize should't be 0?");
-  guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
-  verifyTreeHelper(root());
-}
-
-size_t BinaryTreeDictionary::verifyPrevFreePtrs(TreeList* tl) {
-  size_t ct = 0;
-  for (FreeChunk* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
-    ct++;
-    assert(curFC->prev() == NULL || curFC->prev()->isFree(),
-      "Chunk should be free");
-  }
-  return ct;
-}
-
-// Note: this helper is recursive rather than iterative, so use with
-// caution on very deep trees; and watch out for stack overflow errors;
-// In general, to be used only for debugging.
-void BinaryTreeDictionary::verifyTreeHelper(TreeList* tl) const {
-  if (tl == NULL)
-    return;
-  guarantee(tl->size() != 0, "A list must has a size");
-  guarantee(tl->left()  == NULL || tl->left()->parent()  == tl,
-         "parent<-/->left");
-  guarantee(tl->right() == NULL || tl->right()->parent() == tl,
-         "parent<-/->right");;
-  guarantee(tl->left() == NULL  || tl->left()->size()    <  tl->size(),
-         "parent !> left");
-  guarantee(tl->right() == NULL || tl->right()->size()   >  tl->size(),
-         "parent !< left");
-  guarantee(tl->head() == NULL || tl->head()->isFree(), "!Free");
-  guarantee(tl->head() == NULL || tl->head_as_TreeChunk()->list() == tl,
-    "list inconsistency");
-  guarantee(tl->count() > 0 || (tl->head() == NULL && tl->tail() == NULL),
-    "list count is inconsistent");
-  guarantee(tl->count() > 1 || tl->head() == tl->tail(),
-    "list is incorrectly constructed");
-  size_t count = verifyPrevFreePtrs(tl);
-  guarantee(count == (size_t)tl->count(), "Node count is incorrect");
-  if (tl->head() != NULL) {
-    tl->head_as_TreeChunk()->verifyTreeChunkList();
-  }
-  verifyTreeHelper(tl->left());
-  verifyTreeHelper(tl->right());
-}
-
-void BinaryTreeDictionary::verify() const {
-  verifyTree();
-  guarantee(totalSize() == totalSizeInTree(root()), "Total Size inconsistency");
-}
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp	Tue May 15 10:52:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_BINARYTREEDICTIONARY_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_BINARYTREEDICTIONARY_HPP
-
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeList.hpp"
-
-/*
- * A binary tree based search structure for free blocks.
- * This is currently used in the Concurrent Mark&Sweep implementation.
- */
-
-// A TreeList is a FreeList which can be used to maintain a
-// binary tree of free lists.
-
-class TreeChunk;
-class BinaryTreeDictionary;
-class AscendTreeCensusClosure;
-class DescendTreeCensusClosure;
-class DescendTreeSearchClosure;
-
-class TreeList: public FreeList {
-  friend class TreeChunk;
-  friend class BinaryTreeDictionary;
-  friend class AscendTreeCensusClosure;
-  friend class DescendTreeCensusClosure;
-  friend class DescendTreeSearchClosure;
-
- protected:
-  TreeList* parent() const { return _parent; }
-  TreeList* left()   const { return _left;   }
-  TreeList* right()  const { return _right;  }
-
-  // Accessors for links in tree.
-
-  void setLeft(TreeList* tl) {
-    _left   = tl;
-    if (tl != NULL)
-      tl->setParent(this);
-  }
-  void setRight(TreeList* tl) {
-    _right  = tl;
-    if (tl != NULL)
-      tl->setParent(this);
-  }
-  void setParent(TreeList* tl)  { _parent = tl;   }
-
-  void clearLeft()               { _left = NULL;   }
-  void clearRight()              { _right = NULL;  }
-  void clearParent()             { _parent = NULL; }
-  void initialize()              { clearLeft(); clearRight(), clearParent(); }
-
-  // For constructing a TreeList from a Tree chunk or
-  // address and size.
-  static TreeList* as_TreeList(TreeChunk* tc);
-  static TreeList* as_TreeList(HeapWord* addr, size_t size);
-
-  // Returns the head of the free list as a pointer to a TreeChunk.
-  TreeChunk* head_as_TreeChunk();
-
-  // Returns the first available chunk in the free list as a pointer
-  // to a TreeChunk.
-  TreeChunk* first_available();
-
-  // Returns the block with the largest heap address amongst
-  // those in the list for this size; potentially slow and expensive,
-  // use with caution!
-  TreeChunk* largest_address();
-
-  // removeChunkReplaceIfNeeded() removes the given "tc" from the TreeList.
-  // If "tc" is the first chunk in the list, it is also the
-  // TreeList that is the node in the tree.  removeChunkReplaceIfNeeded()
-  // returns the possibly replaced TreeList* for the node in
-  // the tree.  It also updates the parent of the original
-  // node to point to the new node.
-  TreeList* removeChunkReplaceIfNeeded(TreeChunk* tc);
-  // See FreeList.
-  void returnChunkAtHead(TreeChunk* tc);
-  void returnChunkAtTail(TreeChunk* tc);
-};
-
-// A TreeChunk is a subclass of a FreeChunk that additionally
-// maintains a pointer to the free list on which it is currently
-// linked.
-// A TreeChunk is also used as a node in the binary tree.  This
-// allows the binary tree to be maintained without any additional
-// storage (the free chunks are used).  In a binary tree the first
-// chunk in the free list is also the tree node.  Note that the
-// TreeChunk has an embedded TreeList for this purpose.  Because
-// the first chunk in the list is distinguished in this fashion
-// (also is the node in the tree), it is the last chunk to be found
-// on the free list for a node in the tree and is only removed if
-// it is the last chunk on the free list.
-
-class TreeChunk : public FreeChunk {
-  friend class TreeList;
-  TreeList* _list;
-  TreeList _embedded_list;  // if non-null, this chunk is on _list
- protected:
-  TreeList* embedded_list() const { return (TreeList*) &_embedded_list; }
-  void set_embedded_list(TreeList* v) { _embedded_list = *v; }
- public:
-  TreeList* list() { return _list; }
-  void set_list(TreeList* v) { _list = v; }
-  static TreeChunk* as_TreeChunk(FreeChunk* fc);
-  // Initialize fields in a TreeChunk that should be
-  // initialized when the TreeChunk is being added to
-  // a free list in the tree.
-  void initialize() { embedded_list()->initialize(); }
-
-  // debugging
-  void verifyTreeChunkList() const;
-};
-
-const size_t MIN_TREE_CHUNK_SIZE  = sizeof(TreeChunk)/HeapWordSize;
-
-class BinaryTreeDictionary: public FreeBlockDictionary {
-  friend class VMStructs;
-  bool       _splay;
-  size_t     _totalSize;
-  size_t     _totalFreeBlocks;
-  TreeList* _root;
-
-  // private accessors
-  bool splay() const { return _splay; }
-  void set_splay(bool v) { _splay = v; }
-  size_t totalSize() const { return _totalSize; }
-  void set_totalSize(size_t v) { _totalSize = v; }
-  virtual void inc_totalSize(size_t v);
-  virtual void dec_totalSize(size_t v);
-  size_t totalFreeBlocks() const { return _totalFreeBlocks; }
-  void set_totalFreeBlocks(size_t v) { _totalFreeBlocks = v; }
-  TreeList* root() const { return _root; }
-  void set_root(TreeList* v) { _root = v; }
-
-  // Remove a chunk of size "size" or larger from the tree and
-  // return it.  If the chunk
-  // is the last chunk of that size, remove the node for that size
-  // from the tree.
-  TreeChunk* getChunkFromTree(size_t size, Dither dither, bool splay);
-  // Return a list of the specified size or NULL from the tree.
-  // The list is not removed from the tree.
-  TreeList* findList (size_t size) const;
-  // Remove this chunk from the tree.  If the removal results
-  // in an empty list in the tree, remove the empty list.
-  TreeChunk* removeChunkFromTree(TreeChunk* tc);
-  // Remove the node in the trees starting at tl that has the
-  // minimum value and return it.  Repair the tree as needed.
-  TreeList* removeTreeMinimum(TreeList* tl);
-  void       semiSplayStep(TreeList* tl);
-  // Add this free chunk to the tree.
-  void       insertChunkInTree(FreeChunk* freeChunk);
- public:
-  void       verifyTree() const;
-  // verify that the given chunk is in the tree.
-  bool       verifyChunkInFreeLists(FreeChunk* tc) const;
- private:
-  void          verifyTreeHelper(TreeList* tl) const;
-  static size_t verifyPrevFreePtrs(TreeList* tl);
-
-  // Returns the total number of chunks in the list.
-  size_t     totalListLength(TreeList* tl) const;
-  // Returns the total number of words in the chunks in the tree
-  // starting at "tl".
-  size_t     totalSizeInTree(TreeList* tl) const;
-  // Returns the sum of the square of the size of each block
-  // in the tree starting at "tl".
-  double     sum_of_squared_block_sizes(TreeList* const tl) const;
-  // Returns the total number of free blocks in the tree starting
-  // at "tl".
-  size_t     totalFreeBlocksInTree(TreeList* tl) const;
-  size_t     numFreeBlocks() const;
-  size_t     treeHeight() const;
-  size_t     treeHeightHelper(TreeList* tl) const;
-  size_t     totalNodesInTree(TreeList* tl) const;
-  size_t     totalNodesHelper(TreeList* tl) const;
-
- public:
-  // Constructor
-  BinaryTreeDictionary(MemRegion mr, bool splay = false);
-
-  // Reset the dictionary to the initial conditions with
-  // a single free chunk.
-  void       reset(MemRegion mr);
-  void       reset(HeapWord* addr, size_t size);
-  // Reset the dictionary to be empty.
-  void       reset();
-
-  // Return a chunk of size "size" or greater from
-  // the tree.
-  // want a better dynamic splay strategy for the future.
-  FreeChunk* getChunk(size_t size, Dither dither) {
-    verify_par_locked();
-    FreeChunk* res = getChunkFromTree(size, dither, splay());
-    assert(res == NULL || res->isFree(),
-           "Should be returning a free chunk");
-    return res;
-  }
-
-  void returnChunk(FreeChunk* chunk) {
-    verify_par_locked();
-    insertChunkInTree(chunk);
-  }
-
-  void removeChunk(FreeChunk* chunk) {
-    verify_par_locked();
-    removeChunkFromTree((TreeChunk*)chunk);
-    assert(chunk->isFree(), "Should still be a free chunk");
-  }
-
-  size_t     maxChunkSize() const;
-  size_t     totalChunkSize(debug_only(const Mutex* lock)) const {
-    debug_only(
-      if (lock != NULL && lock->owned_by_self()) {
-        assert(totalSizeInTree(root()) == totalSize(),
-               "_totalSize inconsistency");
-      }
-    )
-    return totalSize();
-  }
-
-  size_t     minSize() const {
-    return MIN_TREE_CHUNK_SIZE;
-  }
-
-  double     sum_of_squared_block_sizes() const {
-    return sum_of_squared_block_sizes(root());
-  }
-
-  FreeChunk* find_chunk_ends_at(HeapWord* target) const;
-
-  // Find the list with size "size" in the binary tree and update
-  // the statistics in the list according to "split" (chunk was
-  // split or coalesce) and "birth" (chunk was added or removed).
-  void       dictCensusUpdate(size_t size, bool split, bool birth);
-  // Return true if the dictionary is overpopulated (more chunks of
-  // this size than desired) for size "size".
-  bool       coalDictOverPopulated(size_t size);
-  // Methods called at the beginning of a sweep to prepare the
-  // statistics for the sweep.
-  void       beginSweepDictCensus(double coalSurplusPercent,
-                                  float inter_sweep_current,
-                                  float inter_sweep_estimate,
-                                  float intra_sweep_estimate);
-  // Methods called after the end of a sweep to modify the
-  // statistics for the sweep.
-  void       endSweepDictCensus(double splitSurplusPercent);
-  // Return the largest free chunk in the tree.
-  FreeChunk* findLargestDict() const;
-  // Accessors for statistics
-  void       setTreeSurplus(double splitSurplusPercent);
-  void       setTreeHints(void);
-  // Reset statistics for all the lists in the tree.
-  void       clearTreeCensus(void);
-  // Print the statistcis for all the lists in the tree.  Also may
-  // print out summaries.
-  void       printDictCensus(void) const;
-  void       print_free_lists(outputStream* st) const;
-
-  // For debugging.  Returns the sum of the _returnedBytes for
-  // all lists in the tree.
-  size_t     sumDictReturnedBytes()     PRODUCT_RETURN0;
-  // Sets the _returnedBytes for all the lists in the tree to zero.
-  void       initializeDictReturnedBytes()      PRODUCT_RETURN;
-  // For debugging.  Return the total number of chunks in the dictionary.
-  size_t     totalCount()       PRODUCT_RETURN0;
-
-  void       reportStatistics() const;
-
-  void       verify() const;
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_BINARYTREEDICTIONARY_HPP
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.cpp	Tue May 15 11:27:24 2012 -0700
@@ -38,7 +38,7 @@
 
 CMSPermGen::CMSPermGen(ReservedSpace rs, size_t initial_byte_size,
              CardTableRS* ct,
-             FreeBlockDictionary::DictionaryChoice dictionaryChoice) {
+             FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) {
   CMSPermGenGen* g =
     new CMSPermGenGen(rs, initial_byte_size, -1, ct);
   if (g == NULL) {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.hpp	Tue May 15 11:27:24 2012 -0700
@@ -45,7 +45,7 @@
 
  public:
   CMSPermGen(ReservedSpace rs, size_t initial_byte_size,
-             CardTableRS* ct, FreeBlockDictionary::DictionaryChoice);
+             CardTableRS* ct, FreeBlockDictionary<FreeChunk>::DictionaryChoice);
 
   HeapWord* mem_allocate(size_t size);
 
@@ -65,7 +65,7 @@
     // regarding not using adaptive free lists for a perm gen.
     ConcurrentMarkSweepGeneration(rs, initial_byte_size, // MinPermHeapExapnsion
       level, ct, false /* use adaptive freelists */,
-      (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice)
+      (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice)
   {}
 
   void initialize_performance_counters();
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@
 // Constructor
 CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
   MemRegion mr, bool use_adaptive_freelists,
-  FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
+  FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
   _dictionaryChoice(dictionaryChoice),
   _adaptive_freelists(use_adaptive_freelists),
   _bt(bs, mr),
@@ -87,6 +87,8 @@
                     CMSConcMarkMultiple),
   _collector(NULL)
 {
+  assert(sizeof(FreeChunk) / BytesPerWord <= MinChunkSize,
+    "FreeChunk is larger than expected");
   _bt.set_space(this);
   initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle);
   // We have all of "mr", all of which we place in the dictionary
@@ -96,13 +98,13 @@
   // implementation, namely, the simple binary tree (splaying
   // temporarily disabled).
   switch (dictionaryChoice) {
-    case FreeBlockDictionary::dictionarySplayTree:
-    case FreeBlockDictionary::dictionarySkipList:
+    case FreeBlockDictionary<FreeChunk>::dictionarySplayTree:
+    case FreeBlockDictionary<FreeChunk>::dictionarySkipList:
     default:
       warning("dictionaryChoice: selected option not understood; using"
               " default BinaryTreeDictionary implementation instead.");
-    case FreeBlockDictionary::dictionaryBinaryTree:
-      _dictionary = new BinaryTreeDictionary(mr);
+    case FreeBlockDictionary<FreeChunk>::dictionaryBinaryTree:
+      _dictionary = new BinaryTreeDictionary<FreeChunk>(mr, use_adaptive_freelists);
       break;
   }
   assert(_dictionary != NULL, "CMS dictionary initialization");
@@ -117,7 +119,7 @@
   // moved to its new location before the klass is moved.
   // Set the _refillSize for the linear allocation blocks
   if (!use_adaptive_freelists) {
-    FreeChunk* fc = _dictionary->getChunk(mr.word_size());
+    FreeChunk* fc = _dictionary->get_chunk(mr.word_size());
     // The small linAB initially has all the space and will allocate
     // a chunk of any size.
     HeapWord* addr = (HeapWord*) fc;
@@ -273,12 +275,12 @@
     assert(mr.word_size() >= MinChunkSize, "Chunk size is too small");
     _bt.single_block(mr.start(), mr.word_size());
     FreeChunk* fc = (FreeChunk*) mr.start();
-    fc->setSize(mr.word_size());
+    fc->set_size(mr.word_size());
     if (mr.word_size() >= IndexSetSize ) {
       returnChunkToDictionary(fc);
     } else {
       _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
-      _indexedFreeList[mr.word_size()].returnChunkAtHead(fc);
+      _indexedFreeList[mr.word_size()].return_chunk_at_head(fc);
     }
   }
   _promoInfo.reset();
@@ -296,7 +298,7 @@
   } else {
     // Place as much of mr in the linAB as we can get,
     // provided it was big enough to go into the dictionary.
-    FreeChunk* fc = dictionary()->findLargestDict();
+    FreeChunk* fc = dictionary()->find_largest_dict();
     if (fc != NULL) {
       assert(fc->size() == mr.word_size(),
              "Why was the chunk broken up?");
@@ -323,14 +325,14 @@
 #ifndef PRODUCT
 void CompactibleFreeListSpace::initializeIndexedFreeListArrayReturnedBytes() {
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    _indexedFreeList[i].allocation_stats()->set_returnedBytes(0);
+    _indexedFreeList[i].allocation_stats()->set_returned_bytes(0);
   }
 }
 
 size_t CompactibleFreeListSpace::sumIndexedFreeListArrayReturnedBytes() {
   size_t sum = 0;
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    sum += _indexedFreeList[i].allocation_stats()->returnedBytes();
+    sum += _indexedFreeList[i].allocation_stats()->returned_bytes();
   }
   return sum;
 }
@@ -354,7 +356,7 @@
 
 size_t CompactibleFreeListSpace::totalCount() {
   size_t num = totalCountInIndexedFreeLists();
-  num +=  dictionary()->totalCount();
+  num +=  dictionary()->total_count();
   if (_smallLinearAllocBlock._word_size != 0) {
     num++;
   }
@@ -364,7 +366,7 @@
 
 bool CompactibleFreeListSpace::is_free_block(const HeapWord* p) const {
   FreeChunk* fc = (FreeChunk*) p;
-  return fc->isFree();
+  return fc->is_free();
 }
 
 size_t CompactibleFreeListSpace::used() const {
@@ -391,7 +393,7 @@
   // that supports jvmstat, and you are apt to see the values
   // flicker in such cases.
   assert(_dictionary != NULL, "No _dictionary?");
-  return (_dictionary->totalChunkSize(DEBUG_ONLY(freelistLock())) +
+  return (_dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())) +
           totalSizeInIndexedFreeLists() +
           _smallLinearAllocBlock._word_size) * HeapWordSize;
 }
@@ -399,7 +401,7 @@
 size_t CompactibleFreeListSpace::max_alloc_in_words() const {
   assert(_dictionary != NULL, "No _dictionary?");
   assert_locked();
-  size_t res = _dictionary->maxChunkSize();
+  size_t res = _dictionary->max_chunk_size();
   res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size,
                        (size_t) SmallForLinearAlloc - 1));
   // XXX the following could potentially be pretty slow;
@@ -448,7 +450,7 @@
   reportIndexedFreeListStatistics();
   gclog_or_tty->print_cr("Layout of Indexed Freelists");
   gclog_or_tty->print_cr("---------------------------");
-  FreeList::print_labels_on(st, "size");
+  FreeList<FreeChunk>::print_labels_on(st, "size");
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
     _indexedFreeList[i].print_on(gclog_or_tty);
     for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
@@ -467,7 +469,7 @@
 
 void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st)
 const {
-  _dictionary->reportStatistics();
+  _dictionary->report_statistics();
   st->print_cr("Layout of Freelists in Tree");
   st->print_cr("---------------------------");
   _dictionary->print_free_lists(st);
@@ -545,12 +547,12 @@
 void CompactibleFreeListSpace::reportFreeListStatistics() const {
   assert_lock_strong(&_freelistLock);
   assert(PrintFLSStatistics != 0, "Reporting error");
-  _dictionary->reportStatistics();
+  _dictionary->report_statistics();
   if (PrintFLSStatistics > 1) {
     reportIndexedFreeListStatistics();
-    size_t totalSize = totalSizeInIndexedFreeLists() +
-                       _dictionary->totalChunkSize(DEBUG_ONLY(freelistLock()));
-    gclog_or_tty->print(" free=%ld frag=%1.4f\n", totalSize, flsFrag());
+    size_t total_size = totalSizeInIndexedFreeLists() +
+                       _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock()));
+    gclog_or_tty->print(" free=%ld frag=%1.4f\n", total_size, flsFrag());
   }
 }
 
@@ -558,13 +560,13 @@
   assert_lock_strong(&_freelistLock);
   gclog_or_tty->print("Statistics for IndexedFreeLists:\n"
                       "--------------------------------\n");
-  size_t totalSize = totalSizeInIndexedFreeLists();
-  size_t   freeBlocks = numFreeBlocksInIndexedFreeLists();
-  gclog_or_tty->print("Total Free Space: %d\n", totalSize);
+  size_t total_size = totalSizeInIndexedFreeLists();
+  size_t   free_blocks = numFreeBlocksInIndexedFreeLists();
+  gclog_or_tty->print("Total Free Space: %d\n", total_size);
   gclog_or_tty->print("Max   Chunk Size: %d\n", maxChunkSizeInIndexedFreeLists());
-  gclog_or_tty->print("Number of Blocks: %d\n", freeBlocks);
-  if (freeBlocks != 0) {
-    gclog_or_tty->print("Av.  Block  Size: %d\n", totalSize/freeBlocks);
+  gclog_or_tty->print("Number of Blocks: %d\n", free_blocks);
+  if (free_blocks != 0) {
+    gclog_or_tty->print("Av.  Block  Size: %d\n", total_size/free_blocks);
   }
 }
 
@@ -911,7 +913,7 @@
   for (addr = bottom(), last  = end();
        addr < last; addr += size) {
     FreeChunk* fc = (FreeChunk*)addr;
-    if (fc->isFree()) {
+    if (fc->is_free()) {
       // Since we hold the free list lock, which protects direct
       // allocation in this generation by mutators, a free object
       // will remain free throughout this iteration code.
@@ -953,7 +955,7 @@
   for (addr = block_start_careful(mr.start()), end  = mr.end();
        addr < end; addr += size) {
     FreeChunk* fc = (FreeChunk*)addr;
-    if (fc->isFree()) {
+    if (fc->is_free()) {
       // Since we hold the free list lock, which protects direct
       // allocation in this generation by mutators, a free object
       // will remain free throughout this iteration code.
@@ -1069,7 +1071,7 @@
   NOT_PRODUCT(verify_objects_initialized());
   assert(MemRegion(bottom(), end()).contains(p), "p not in space");
   FreeChunk* fc = (FreeChunk*)p;
-  if (fc->isFree()) {
+  if (fc->is_free()) {
     return fc->size();
   } else {
     // Ignore mark word because this may be a recently promoted
@@ -1160,7 +1162,7 @@
   FreeChunk* fc = (FreeChunk*)p;
   assert(is_in_reserved(p), "Should be in space");
   assert(_bt.block_start(p) == p, "Should be a block boundary");
-  if (!fc->isFree()) {
+  if (!fc->is_free()) {
     // Ignore mark word because it may have been used to
     // chain together promoted objects (the last one
     // would have a null value).
@@ -1222,7 +1224,7 @@
 
     FreeChunk* fc = (FreeChunk*)res;
     fc->markNotFree();
-    assert(!fc->isFree(), "shouldn't be marked free");
+    assert(!fc->is_free(), "shouldn't be marked free");
     assert(oop(fc)->klass_or_null() == NULL, "should look uninitialized");
     // Verify that the block offset table shows this to
     // be a single block, but not one which is unallocated.
@@ -1331,10 +1333,10 @@
   size_t currSize = numWords + MinChunkSize;
   assert(currSize % MinObjAlignment == 0, "currSize should be aligned");
   for (i = currSize; i < IndexSetSize; i += IndexSetStride) {
-    FreeList* fl = &_indexedFreeList[i];
+    FreeList<FreeChunk>* fl = &_indexedFreeList[i];
     if (fl->head()) {
       ret = getFromListGreater(fl, numWords);
-      assert(ret == NULL || ret->isFree(), "Should be returning a free chunk");
+      assert(ret == NULL || ret->is_free(), "Should be returning a free chunk");
       return ret;
     }
   }
@@ -1345,7 +1347,7 @@
   /* Try to get a chunk that satisfies request, while avoiding
      fragmentation that can't be handled. */
   {
-    ret =  dictionary()->getChunk(currSize);
+    ret =  dictionary()->get_chunk(currSize);
     if (ret != NULL) {
       assert(ret->size() - numWords >= MinChunkSize,
              "Chunk is too small");
@@ -1353,10 +1355,10 @@
       /* Carve returned chunk. */
       (void) splitChunkAndReturnRemainder(ret, numWords);
       /* Label this as no longer a free chunk. */
-      assert(ret->isFree(), "This chunk should be free");
-      ret->linkPrev(NULL);
+      assert(ret->is_free(), "This chunk should be free");
+      ret->link_prev(NULL);
     }
-    assert(ret == NULL || ret->isFree(), "Should be returning a free chunk");
+    assert(ret == NULL || ret->is_free(), "Should be returning a free chunk");
     return ret;
   }
   ShouldNotReachHere();
@@ -1364,7 +1366,7 @@
 
 bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const {
   assert(fc->size() < IndexSetSize, "Size of chunk is too large");
-  return _indexedFreeList[fc->size()].verifyChunkInFreeLists(fc);
+  return _indexedFreeList[fc->size()].verify_chunk_in_free_list(fc);
 }
 
 bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const {
@@ -1378,13 +1380,13 @@
 // Check if the purported free chunk is present either as a linear
 // allocation block, the size-indexed table of (smaller) free blocks,
 // or the larger free blocks kept in the binary tree dictionary.
-bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const {
+bool CompactibleFreeListSpace::verify_chunk_in_free_list(FreeChunk* fc) const {
   if (verify_chunk_is_linear_alloc_block(fc)) {
     return true;
   } else if (fc->size() < IndexSetSize) {
     return verifyChunkInIndexedFreeLists(fc);
   } else {
-    return dictionary()->verifyChunkInFreeLists(fc);
+    return dictionary()->verify_chunk_in_free_list(fc);
   }
 }
 
@@ -1412,7 +1414,7 @@
   }
   if (fc != NULL) {
     fc->dontCoalesce();
-    assert(fc->isFree(), "Should be free, but not coalescable");
+    assert(fc->is_free(), "Should be free, but not coalescable");
     // Verify that the block offset table shows this to
     // be a single block, but not one which is unallocated.
     _bt.verify_single_block((HeapWord*)fc, fc->size());
@@ -1492,7 +1494,7 @@
     }
     // Return the chunk that isn't big enough, and then refill below.
     addChunkToFreeLists(blk->_ptr, sz);
-    splitBirth(sz);
+    split_birth(sz);
     // Don't keep statistics on adding back chunk from a LinAB.
   } else {
     // A refilled block would not satisfy the request.
@@ -1504,14 +1506,14 @@
   assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize,
          "block was replenished");
   if (res != NULL) {
-    splitBirth(size);
+    split_birth(size);
     repairLinearAllocBlock(blk);
   } else if (blk->_ptr != NULL) {
     res = blk->_ptr;
     size_t blk_size = blk->_word_size;
     blk->_word_size -= size;
     blk->_ptr  += size;
-    splitBirth(size);
+    split_birth(size);
     repairLinearAllocBlock(blk);
     // Update BOT last so that other (parallel) GC threads see a consistent
     // view of the BOT and free blocks.
@@ -1540,7 +1542,7 @@
     size_t blk_size = blk->_word_size;
     blk->_word_size -= size;
     blk->_ptr  += size;
-    splitBirth(size);
+    split_birth(size);
     repairLinearAllocBlock(blk);
     // Update BOT last so that other (parallel) GC threads see a consistent
     // view of the BOT and free blocks.
@@ -1557,7 +1559,7 @@
   assert_locked();
   assert(size < SmallForDictionary, "just checking");
   FreeChunk* res;
-  res = _indexedFreeList[size].getChunkAtHead();
+  res = _indexedFreeList[size].get_chunk_at_head();
   if (res == NULL) {
     res = getChunkFromIndexedFreeListHelper(size);
   }
@@ -1591,7 +1593,7 @@
         // Do not replenish from an underpopulated size.
         if (_indexedFreeList[replenish_size].surplus() > 0 &&
             _indexedFreeList[replenish_size].head() != NULL) {
-          newFc = _indexedFreeList[replenish_size].getChunkAtHead();
+          newFc = _indexedFreeList[replenish_size].get_chunk_at_head();
         } else if (bestFitFirst()) {
           newFc = bestFitSmall(replenish_size);
         }
@@ -1624,13 +1626,13 @@
                i < (num_blk - 1);
                curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size),
                i++) {
-            curFc->setSize(size);
+            curFc->set_size(size);
             // Don't record this as a return in order to try and
             // determine the "returns" from a GC.
             _bt.verify_not_unallocated((HeapWord*) fc, size);
-            _indexedFreeList[size].returnChunkAtTail(curFc, false);
+            _indexedFreeList[size].return_chunk_at_tail(curFc, false);
             _bt.mark_block((HeapWord*)curFc, size);
-            splitBirth(size);
+            split_birth(size);
             // Don't record the initial population of the indexed list
             // as a split birth.
           }
@@ -1638,9 +1640,9 @@
           // check that the arithmetic was OK above
           assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size,
             "inconsistency in carving newFc");
-          curFc->setSize(size);
+          curFc->set_size(size);
           _bt.mark_block((HeapWord*)curFc, size);
-          splitBirth(size);
+          split_birth(size);
           fc = curFc;
         } else {
           // Return entire block to caller
@@ -1653,14 +1655,14 @@
     // replenish the indexed free list.
     fc = getChunkFromDictionaryExact(size);
   }
-  // assert(fc == NULL || fc->isFree(), "Should be returning a free chunk");
+  // assert(fc == NULL || fc->is_free(), "Should be returning a free chunk");
   return fc;
 }
 
 FreeChunk*
 CompactibleFreeListSpace::getChunkFromDictionary(size_t size) {
   assert_locked();
-  FreeChunk* fc = _dictionary->getChunk(size);
+  FreeChunk* fc = _dictionary->get_chunk(size);
   if (fc == NULL) {
     return NULL;
   }
@@ -1677,7 +1679,7 @@
 FreeChunk*
 CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) {
   assert_locked();
-  FreeChunk* fc = _dictionary->getChunk(size);
+  FreeChunk* fc = _dictionary->get_chunk(size);
   if (fc == NULL) {
     return fc;
   }
@@ -1686,11 +1688,11 @@
     _bt.verify_single_block((HeapWord*)fc, size);
     return fc;
   }
-  assert(fc->size() > size, "getChunk() guarantee");
+  assert(fc->size() > size, "get_chunk() guarantee");
   if (fc->size() < size + MinChunkSize) {
     // Return the chunk to the dictionary and go get a bigger one.
     returnChunkToDictionary(fc);
-    fc = _dictionary->getChunk(size + MinChunkSize);
+    fc = _dictionary->get_chunk(size + MinChunkSize);
     if (fc == NULL) {
       return NULL;
     }
@@ -1711,10 +1713,10 @@
   _bt.verify_single_block((HeapWord*)chunk, size);
   // adjust _unallocated_block downward, as necessary
   _bt.freed((HeapWord*)chunk, size);
-  _dictionary->returnChunk(chunk);
+  _dictionary->return_chunk(chunk);
 #ifndef PRODUCT
   if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
-    TreeChunk::as_TreeChunk(chunk)->list()->verify_stats();
+    TreeChunk<FreeChunk>::as_TreeChunk(chunk)->list()->verify_stats();
   }
 #endif // PRODUCT
 }
@@ -1726,9 +1728,9 @@
   _bt.verify_single_block((HeapWord*) fc, size);
   _bt.verify_not_unallocated((HeapWord*) fc, size);
   if (_adaptive_freelists) {
-    _indexedFreeList[size].returnChunkAtTail(fc);
+    _indexedFreeList[size].return_chunk_at_tail(fc);
   } else {
-    _indexedFreeList[size].returnChunkAtHead(fc);
+    _indexedFreeList[size].return_chunk_at_head(fc);
   }
 #ifndef PRODUCT
   if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
@@ -1756,7 +1758,7 @@
   FreeChunk* ec;
   {
     MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
-    ec = dictionary()->findLargestDict();  // get largest block
+    ec = dictionary()->find_largest_dict();  // get largest block
     if (ec != NULL && ec->end() == chunk) {
       // It's a coterminal block - we can coalesce.
       size_t old_size = ec->size();
@@ -1767,7 +1769,7 @@
       ec = (FreeChunk*)chunk;
     }
   }
-  ec->setSize(size);
+  ec->set_size(size);
   debug_only(ec->mangleFreed(size));
   if (size < SmallForDictionary) {
     lock = _indexedFreeListParLocks[size];
@@ -1790,7 +1792,7 @@
   _bt.verify_single_block(chunk, size);
 
   FreeChunk* fc = (FreeChunk*) chunk;
-  fc->setSize(size);
+  fc->set_size(size);
   debug_only(fc->mangleFreed(size));
   if (size < SmallForDictionary) {
     returnChunkToFreeList(fc);
@@ -1833,7 +1835,7 @@
   assert_locked();
   assert(fc != NULL, "null chunk");
   _bt.verify_single_block((HeapWord*)fc, size);
-  _dictionary->removeChunk(fc);
+  _dictionary->remove_chunk(fc);
   // adjust _unallocated_block upward, as necessary
   _bt.allocated((HeapWord*)fc, size);
 }
@@ -1848,7 +1850,7 @@
       verifyIndexedFreeList(size);
     }
   )
-  _indexedFreeList[size].removeChunk(fc);
+  _indexedFreeList[size].remove_chunk(fc);
   NOT_PRODUCT(
     if (FLSVerifyIndexTable) {
       verifyIndexedFreeList(size);
@@ -1862,17 +1864,17 @@
      the excess is >= MIN_CHUNK. */
   size_t start = align_object_size(numWords + MinChunkSize);
   if (start < IndexSetSize) {
-    FreeList* it   = _indexedFreeList;
+    FreeList<FreeChunk>* it   = _indexedFreeList;
     size_t    hint = _indexedFreeList[start].hint();
     while (hint < IndexSetSize) {
       assert(hint % MinObjAlignment == 0, "hint should be aligned");
-      FreeList *fl = &_indexedFreeList[hint];
+      FreeList<FreeChunk> *fl = &_indexedFreeList[hint];
       if (fl->surplus() > 0 && fl->head() != NULL) {
         // Found a list with surplus, reset original hint
         // and split out a free chunk which is returned.
         _indexedFreeList[start].set_hint(hint);
         FreeChunk* res = getFromListGreater(fl, numWords);
-        assert(res == NULL || res->isFree(),
+        assert(res == NULL || res->is_free(),
           "Should be returning a free chunk");
         return res;
       }
@@ -1885,7 +1887,7 @@
 }
 
 /* Requires fl->size >= numWords + MinChunkSize */
-FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList* fl,
+FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList<FreeChunk>* fl,
   size_t numWords) {
   FreeChunk *curr = fl->head();
   size_t oldNumWords = curr->size();
@@ -1894,13 +1896,13 @@
   assert(oldNumWords >= numWords + MinChunkSize,
         "Size of chunks in the list is too small");
 
-  fl->removeChunk(curr);
+  fl->remove_chunk(curr);
   // recorded indirectly by splitChunkAndReturnRemainder -
   // smallSplit(oldNumWords, numWords);
   FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords);
   // Does anything have to be done for the remainder in terms of
   // fixing the card table?
-  assert(new_chunk == NULL || new_chunk->isFree(),
+  assert(new_chunk == NULL || new_chunk->is_free(),
     "Should be returning a free chunk");
   return new_chunk;
 }
@@ -1918,13 +1920,13 @@
   assert(rem_size >= MinChunkSize, "Free chunk smaller than minimum");
   FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size);
   assert(is_aligned(ffc), "alignment problem");
-  ffc->setSize(rem_size);
-  ffc->linkNext(NULL);
-  ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
+  ffc->set_size(rem_size);
+  ffc->link_next(NULL);
+  ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads.
   // Above must occur before BOT is updated below.
   // adjust block offset table
   OrderAccess::storestore();
-  assert(chunk->isFree() && ffc->isFree(), "Error");
+  assert(chunk->is_free() && ffc->is_free(), "Error");
   _bt.split_block((HeapWord*)chunk, chunk->size(), new_size);
   if (rem_size < SmallForDictionary) {
     bool is_par = (SharedHeap::heap()->n_par_threads() > 0);
@@ -1939,7 +1941,7 @@
     returnChunkToDictionary(ffc);
     split(size ,rem_size);
   }
-  chunk->setSize(new_size);
+  chunk->set_size(new_size);
   return chunk;
 }
 
@@ -2046,10 +2048,10 @@
     assert(blk->_word_size != 0 && blk->_word_size >= MinChunkSize,
            "Minimum block size requirement");
     FreeChunk* fc = (FreeChunk*)(blk->_ptr);
-    fc->setSize(blk->_word_size);
-    fc->linkPrev(NULL);   // mark as free
+    fc->set_size(blk->_word_size);
+    fc->link_prev(NULL);   // mark as free
     fc->dontCoalesce();
-    assert(fc->isFree(), "just marked it free");
+    assert(fc->is_free(), "just marked it free");
     assert(fc->cantCoalesce(), "just marked it uncoalescable");
   }
 }
@@ -2149,7 +2151,7 @@
   }
 
   double totFree = itabFree +
-                   _dictionary->totalChunkSize(DEBUG_ONLY(freelistLock()));
+                   _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock()));
   if (totFree > 0) {
     frag = ((frag + _dictionary->sum_of_squared_block_sizes()) /
             (totFree * totFree));
@@ -2167,16 +2169,16 @@
   assert_locked();
   size_t i;
   for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    FreeList* fl    = &_indexedFreeList[i];
+    FreeList<FreeChunk>* fl = &_indexedFreeList[i];
     if (PrintFLSStatistics > 1) {
       gclog_or_tty->print("size[%d] : ", i);
     }
     fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
-    fl->set_coalDesired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
-    fl->set_beforeSweep(fl->count());
-    fl->set_bfrSurp(fl->surplus());
+    fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
+    fl->set_before_sweep(fl->count());
+    fl->set_bfr_surp(fl->surplus());
   }
-  _dictionary->beginSweepDictCensus(CMSLargeCoalSurplusPercent,
+  _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent,
                                     inter_sweep_current,
                                     inter_sweep_estimate,
                                     intra_sweep_estimate);
@@ -2186,7 +2188,7 @@
   assert_locked();
   size_t i;
   for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    FreeList *fl = &_indexedFreeList[i];
+    FreeList<FreeChunk> *fl = &_indexedFreeList[i];
     fl->set_surplus(fl->count() -
                     (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
   }
@@ -2197,7 +2199,7 @@
   size_t i;
   size_t h = IndexSetSize;
   for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) {
-    FreeList *fl = &_indexedFreeList[i];
+    FreeList<FreeChunk> *fl = &_indexedFreeList[i];
     fl->set_hint(h);
     if (fl->surplus() > 0) {
       h = i;
@@ -2209,18 +2211,18 @@
   assert_locked();
   size_t i;
   for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    FreeList *fl = &_indexedFreeList[i];
-    fl->set_prevSweep(fl->count());
-    fl->set_coalBirths(0);
-    fl->set_coalDeaths(0);
-    fl->set_splitBirths(0);
-    fl->set_splitDeaths(0);
+    FreeList<FreeChunk> *fl = &_indexedFreeList[i];
+    fl->set_prev_sweep(fl->count());
+    fl->set_coal_births(0);
+    fl->set_coal_deaths(0);
+    fl->set_split_births(0);
+    fl->set_split_deaths(0);
   }
 }
 
 void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
   if (PrintFLSStatistics > 0) {
-    HeapWord* largestAddr = (HeapWord*) dictionary()->findLargestDict();
+    HeapWord* largestAddr = (HeapWord*) dictionary()->find_largest_dict();
     gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT,
                            largestAddr);
   }
@@ -2231,30 +2233,30 @@
   }
   clearFLCensus();
   assert_locked();
-  _dictionary->endSweepDictCensus(CMSLargeSplitSurplusPercent);
+  _dictionary->end_sweep_dict_census(CMSLargeSplitSurplusPercent);
 }
 
 bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
   if (size < SmallForDictionary) {
-    FreeList *fl = &_indexedFreeList[size];
-    return (fl->coalDesired() < 0) ||
-           ((int)fl->count() > fl->coalDesired());
+    FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+    return (fl->coal_desired() < 0) ||
+           ((int)fl->count() > fl->coal_desired());
   } else {
-    return dictionary()->coalDictOverPopulated(size);
+    return dictionary()->coal_dict_over_populated(size);
   }
 }
 
 void CompactibleFreeListSpace::smallCoalBirth(size_t size) {
   assert(size < SmallForDictionary, "Size too large for indexed list");
-  FreeList *fl = &_indexedFreeList[size];
-  fl->increment_coalBirths();
+  FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+  fl->increment_coal_births();
   fl->increment_surplus();
 }
 
 void CompactibleFreeListSpace::smallCoalDeath(size_t size) {
   assert(size < SmallForDictionary, "Size too large for indexed list");
-  FreeList *fl = &_indexedFreeList[size];
-  fl->increment_coalDeaths();
+  FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+  fl->increment_coal_deaths();
   fl->decrement_surplus();
 }
 
@@ -2262,7 +2264,7 @@
   if (size  < SmallForDictionary) {
     smallCoalBirth(size);
   } else {
-    dictionary()->dictCensusUpdate(size,
+    dictionary()->dict_census_udpate(size,
                                    false /* split */,
                                    true /* birth */);
   }
@@ -2272,7 +2274,7 @@
   if(size  < SmallForDictionary) {
     smallCoalDeath(size);
   } else {
-    dictionary()->dictCensusUpdate(size,
+    dictionary()->dict_census_udpate(size,
                                    false /* split */,
                                    false /* birth */);
   }
@@ -2280,23 +2282,23 @@
 
 void CompactibleFreeListSpace::smallSplitBirth(size_t size) {
   assert(size < SmallForDictionary, "Size too large for indexed list");
-  FreeList *fl = &_indexedFreeList[size];
-  fl->increment_splitBirths();
+  FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+  fl->increment_split_births();
   fl->increment_surplus();
 }
 
 void CompactibleFreeListSpace::smallSplitDeath(size_t size) {
   assert(size < SmallForDictionary, "Size too large for indexed list");
-  FreeList *fl = &_indexedFreeList[size];
-  fl->increment_splitDeaths();
+  FreeList<FreeChunk> *fl = &_indexedFreeList[size];
+  fl->increment_split_deaths();
   fl->decrement_surplus();
 }
 
-void CompactibleFreeListSpace::splitBirth(size_t size) {
+void CompactibleFreeListSpace::split_birth(size_t size) {
   if (size  < SmallForDictionary) {
     smallSplitBirth(size);
   } else {
-    dictionary()->dictCensusUpdate(size,
+    dictionary()->dict_census_udpate(size,
                                    true /* split */,
                                    true /* birth */);
   }
@@ -2306,7 +2308,7 @@
   if (size  < SmallForDictionary) {
     smallSplitDeath(size);
   } else {
-    dictionary()->dictCensusUpdate(size,
+    dictionary()->dict_census_udpate(size,
                                    true /* split */,
                                    false /* birth */);
   }
@@ -2315,8 +2317,8 @@
 void CompactibleFreeListSpace::split(size_t from, size_t to1) {
   size_t to2 = from - to1;
   splitDeath(from);
-  splitBirth(to1);
-  splitBirth(to2);
+  split_birth(to1);
+  split_birth(to2);
 }
 
 void CompactibleFreeListSpace::print() const {
@@ -2362,7 +2364,7 @@
       FreeChunk* fc = (FreeChunk*)addr;
       res = fc->size();
       if (FLSVerifyLists && !fc->cantCoalesce()) {
-        guarantee(_sp->verifyChunkInFreeLists(fc),
+        guarantee(_sp->verify_chunk_in_free_list(fc),
                   "Chunk should be on a free list");
       }
     }
@@ -2444,7 +2446,7 @@
   virtual void do_oop(narrowOop* p) { VerifyAllOopsClosure::do_oop_work(p); }
 };
 
-void CompactibleFreeListSpace::verify(bool ignored) const {
+void CompactibleFreeListSpace::verify() const {
   assert_lock_strong(&_freelistLock);
   verify_objects_initialized();
   MemRegion span = _collector->_span;
@@ -2518,7 +2520,7 @@
             "Slot should have been empty");
   for (; fc != NULL; fc = fc->next(), n++) {
     guarantee(fc->size() == size, "Size inconsistency");
-    guarantee(fc->isFree(), "!free?");
+    guarantee(fc->is_free(), "!free?");
     guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list");
     guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail");
   }
@@ -2527,10 +2529,10 @@
 
 #ifndef PRODUCT
 void CompactibleFreeListSpace::check_free_list_consistency() const {
-  assert(_dictionary->minSize() <= IndexSetSize,
+  assert(_dictionary->min_size() <= IndexSetSize,
     "Some sizes can't be allocated without recourse to"
     " linear allocation buffers");
-  assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk),
+  assert(BinaryTreeDictionary<FreeChunk>::min_tree_chunk_size*HeapWordSize == sizeof(TreeChunk<FreeChunk>),
     "else MIN_TREE_CHUNK_SIZE is wrong");
   assert((IndexSetStride == 2 && IndexSetStart == 4) ||                   // 32-bit
          (IndexSetStride == 1 && IndexSetStart == 3), "just checking");   // 64-bit
@@ -2543,36 +2545,36 @@
 
 void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
   assert_lock_strong(&_freelistLock);
-  FreeList total;
+  FreeList<FreeChunk> total;
   gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
-  FreeList::print_labels_on(gclog_or_tty, "size");
-  size_t totalFree = 0;
+  FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
+  size_t total_free = 0;
   for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
-    const FreeList *fl = &_indexedFreeList[i];
-    totalFree += fl->count() * fl->size();
+    const FreeList<FreeChunk> *fl = &_indexedFreeList[i];
+    total_free += fl->count() * fl->size();
     if (i % (40*IndexSetStride) == 0) {
-      FreeList::print_labels_on(gclog_or_tty, "size");
+      FreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
     }
     fl->print_on(gclog_or_tty);
-    total.set_bfrSurp(    total.bfrSurp()     + fl->bfrSurp()    );
+    total.set_bfr_surp(    total.bfr_surp()     + fl->bfr_surp()    );
     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_prev_sweep(  total.prev_sweep()   + fl->prev_sweep()  );
+    total.set_before_sweep(total.before_sweep() + fl->before_sweep());
     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());
+    total.set_coal_births( total.coal_births()  + fl->coal_births() );
+    total.set_coal_deaths( total.coal_deaths()  + fl->coal_deaths() );
+    total.set_split_births(total.split_births() + fl->split_births());
+    total.set_split_deaths(total.split_deaths() + fl->split_deaths());
   }
   total.print_on(gclog_or_tty, "TOTAL");
   gclog_or_tty->print_cr("Total free in indexed lists "
-                         SIZE_FORMAT " words", totalFree);
+                         SIZE_FORMAT " words", total_free);
   gclog_or_tty->print("growth: %8.5f  deficit: %8.5f\n",
-    (double)(total.splitBirths()+total.coalBirths()-total.splitDeaths()-total.coalDeaths())/
-            (total.prevSweep() != 0 ? (double)total.prevSweep() : 1.0),
+    (double)(total.split_births()+total.coal_births()-total.split_deaths()-total.coal_deaths())/
+            (total.prev_sweep() != 0 ? (double)total.prev_sweep() : 1.0),
     (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
-  _dictionary->printDictCensus();
+  _dictionary->print_dict_census();
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -2634,18 +2636,18 @@
     res = _cfls->getChunkFromDictionaryExact(word_sz);
     if (res == NULL) return NULL;
   } else {
-    FreeList* fl = &_indexedFreeList[word_sz];
+    FreeList<FreeChunk>* fl = &_indexedFreeList[word_sz];
     if (fl->count() == 0) {
       // Attempt to refill this local free list.
       get_from_global_pool(word_sz, fl);
       // If it didn't work, give up.
       if (fl->count() == 0) return NULL;
     }
-    res = fl->getChunkAtHead();
+    res = fl->get_chunk_at_head();
     assert(res != NULL, "Why was count non-zero?");
   }
   res->markNotFree();
-  assert(!res->isFree(), "shouldn't be marked free");
+  assert(!res->is_free(), "shouldn't be marked free");
   assert(oop(res)->klass_or_null() == NULL, "should look uninitialized");
   // mangle a just allocated object with a distinct pattern.
   debug_only(res->mangleAllocated(word_sz));
@@ -2654,7 +2656,7 @@
 
 // Get a chunk of blocks of the right size and update related
 // book-keeping stats
-void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList* fl) {
+void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList<FreeChunk>* fl) {
   // Get the #blocks we want to claim
   size_t n_blks = (size_t)_blocks_to_claim[word_sz].average();
   assert(n_blks > 0, "Error");
@@ -2736,7 +2738,7 @@
         if (num_retire > 0) {
           _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
           // Reset this list.
-          _indexedFreeList[i] = FreeList();
+          _indexedFreeList[i] = FreeList<FreeChunk>();
           _indexedFreeList[i].set_size(i);
         }
       }
@@ -2750,7 +2752,7 @@
   }
 }
 
-void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
+void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList<FreeChunk>* fl) {
   assert(fl->count() == 0, "Precondition.");
   assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
          "Precondition");
@@ -2766,12 +2768,12 @@
          (cur_sz < CompactibleFreeListSpace::IndexSetSize) &&
          (CMSSplitIndexedFreeListBlocks || k <= 1);
          k++, cur_sz = k * word_sz) {
-      FreeList fl_for_cur_sz;  // Empty.
+      FreeList<FreeChunk> fl_for_cur_sz;  // Empty.
       fl_for_cur_sz.set_size(cur_sz);
       {
         MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
                         Mutex::_no_safepoint_check_flag);
-        FreeList* gfl = &_indexedFreeList[cur_sz];
+        FreeList<FreeChunk>* gfl = &_indexedFreeList[cur_sz];
         if (gfl->count() != 0) {
           // nn is the number of chunks of size cur_sz that
           // we'd need to split k-ways each, in order to create
@@ -2784,9 +2786,9 @@
             // we increment the split death count by the number of blocks
             // we just took from the cur_sz-size blocks list and which
             // we will be splitting below.
-            ssize_t deaths = gfl->splitDeaths() +
+            ssize_t deaths = gfl->split_deaths() +
                              fl_for_cur_sz.count();
-            gfl->set_splitDeaths(deaths);
+            gfl->set_split_deaths(deaths);
           }
         }
       }
@@ -2797,21 +2799,21 @@
         } else {
           // Divide each block on fl_for_cur_sz up k ways.
           FreeChunk* fc;
-          while ((fc = fl_for_cur_sz.getChunkAtHead()) != NULL) {
+          while ((fc = fl_for_cur_sz.get_chunk_at_head()) != NULL) {
             // Must do this in reverse order, so that anybody attempting to
             // access the main chunk sees it as a single free block until we
             // change it.
             size_t fc_size = fc->size();
-            assert(fc->isFree(), "Error");
+            assert(fc->is_free(), "Error");
             for (int i = k-1; i >= 0; i--) {
               FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
               assert((i != 0) ||
-                        ((fc == ffc) && ffc->isFree() &&
+                        ((fc == ffc) && ffc->is_free() &&
                          (ffc->size() == k*word_sz) && (fc_size == word_sz)),
                         "Counting error");
-              ffc->setSize(word_sz);
-              ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
-              ffc->linkNext(NULL);
+              ffc->set_size(word_sz);
+              ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads.
+              ffc->link_next(NULL);
               // Above must occur before BOT is updated below.
               OrderAccess::storestore();
               // splitting from the right, fc_size == i * word_sz
@@ -2822,7 +2824,7 @@
               _bt.verify_single_block((HeapWord*)fc, fc_size);
               _bt.verify_single_block((HeapWord*)ffc, word_sz);
               // Push this on "fl".
-              fl->returnChunkAtHead(ffc);
+              fl->return_chunk_at_head(ffc);
             }
             // TRAP
             assert(fl->tail()->next() == NULL, "List invariant.");
@@ -2832,8 +2834,8 @@
         size_t num = fl->count();
         MutexLockerEx x(_indexedFreeListParLocks[word_sz],
                         Mutex::_no_safepoint_check_flag);
-        ssize_t births = _indexedFreeList[word_sz].splitBirths() + num;
-        _indexedFreeList[word_sz].set_splitBirths(births);
+        ssize_t births = _indexedFreeList[word_sz].split_births() + num;
+        _indexedFreeList[word_sz].set_split_births(births);
         return;
       }
     }
@@ -2846,12 +2848,12 @@
     MutexLockerEx x(parDictionaryAllocLock(),
                     Mutex::_no_safepoint_check_flag);
     while (n > 0) {
-      fc = dictionary()->getChunk(MAX2(n * word_sz,
-                                  _dictionary->minSize()),
-                                  FreeBlockDictionary::atLeast);
+      fc = dictionary()->get_chunk(MAX2(n * word_sz,
+                                  _dictionary->min_size()),
+                                  FreeBlockDictionary<FreeChunk>::atLeast);
       if (fc != NULL) {
         _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */);  // update _unallocated_blk
-        dictionary()->dictCensusUpdate(fc->size(),
+        dictionary()->dict_census_udpate(fc->size(),
                                        true /*split*/,
                                        false /*birth*/);
         break;
@@ -2862,7 +2864,7 @@
     if (fc == NULL) return;
     // Otherwise, split up that block.
     assert((ssize_t)n >= 1, "Control point invariant");
-    assert(fc->isFree(), "Error: should be a free block");
+    assert(fc->is_free(), "Error: should be a free block");
     _bt.verify_single_block((HeapWord*)fc, fc->size());
     const size_t nn = fc->size() / word_sz;
     n = MIN2(nn, n);
@@ -2893,18 +2895,18 @@
     if (rem > 0) {
       size_t prefix_size = n * word_sz;
       rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size);
-      rem_fc->setSize(rem);
-      rem_fc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
-      rem_fc->linkNext(NULL);
+      rem_fc->set_size(rem);
+      rem_fc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads.
+      rem_fc->link_next(NULL);
       // Above must occur before BOT is updated below.
       assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error");
       OrderAccess::storestore();
       _bt.split_block((HeapWord*)fc, fc->size(), prefix_size);
-      assert(fc->isFree(), "Error");
-      fc->setSize(prefix_size);
+      assert(fc->is_free(), "Error");
+      fc->set_size(prefix_size);
       if (rem >= IndexSetSize) {
         returnChunkToDictionary(rem_fc);
-        dictionary()->dictCensusUpdate(rem, true /*split*/, true /*birth*/);
+        dictionary()->dict_census_udpate(rem, true /*split*/, true /*birth*/);
         rem_fc = NULL;
       }
       // Otherwise, return it to the small list below.
@@ -2914,7 +2916,7 @@
     MutexLockerEx x(_indexedFreeListParLocks[rem],
                     Mutex::_no_safepoint_check_flag);
     _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size());
-    _indexedFreeList[rem].returnChunkAtHead(rem_fc);
+    _indexedFreeList[rem].return_chunk_at_head(rem_fc);
     smallSplitBirth(rem);
   }
   assert((ssize_t)n > 0 && fc != NULL, "Consistency");
@@ -2926,9 +2928,9 @@
   // All but first chunk in this loop
   for (ssize_t i = n-1; i > 0; i--) {
     FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
-    ffc->setSize(word_sz);
-    ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
-    ffc->linkNext(NULL);
+    ffc->set_size(word_sz);
+    ffc->link_prev(NULL); // Mark as a free block for other (parallel) GC threads.
+    ffc->link_next(NULL);
     // Above must occur before BOT is updated below.
     OrderAccess::storestore();
     // splitting from the right, fc_size == (n - i + 1) * wordsize
@@ -2938,25 +2940,25 @@
     _bt.verify_single_block((HeapWord*)ffc, ffc->size());
     _bt.verify_single_block((HeapWord*)fc, fc_size);
     // Push this on "fl".
-    fl->returnChunkAtHead(ffc);
+    fl->return_chunk_at_head(ffc);
   }
   // First chunk
-  assert(fc->isFree() && fc->size() == n*word_sz, "Error: should still be a free block");
+  assert(fc->is_free() && fc->size() == n*word_sz, "Error: should still be a free block");
   // The blocks above should show their new sizes before the first block below
-  fc->setSize(word_sz);
-  fc->linkPrev(NULL);    // idempotent wrt free-ness, see assert above
-  fc->linkNext(NULL);
+  fc->set_size(word_sz);
+  fc->link_prev(NULL);    // idempotent wrt free-ness, see assert above
+  fc->link_next(NULL);
   _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
   _bt.verify_single_block((HeapWord*)fc, fc->size());
-  fl->returnChunkAtHead(fc);
+  fl->return_chunk_at_head(fc);
 
   assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks");
   {
     // Update the stats for this block size.
     MutexLockerEx x(_indexedFreeListParLocks[word_sz],
                     Mutex::_no_safepoint_check_flag);
-    const ssize_t births = _indexedFreeList[word_sz].splitBirths() + n;
-    _indexedFreeList[word_sz].set_splitBirths(births);
+    const ssize_t births = _indexedFreeList[word_sz].split_births() + n;
+    _indexedFreeList[word_sz].set_split_births(births);
     // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n;
     // _indexedFreeList[word_sz].set_surplus(new_surplus);
   }
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,10 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_COMPACTIBLEFREELISTSPACE_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_COMPACTIBLEFREELISTSPACE_HPP
 
-#include "gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeList.hpp"
 #include "gc_implementation/concurrentMarkSweep/promotionInfo.hpp"
+#include "memory/binaryTreeDictionary.hpp"
 #include "memory/blockOffsetTable.inline.hpp"
+#include "memory/freeList.hpp"
 #include "memory/space.hpp"
 
 // Classes in support of keeping track of promotions into a non-Contiguous
@@ -129,10 +129,10 @@
   // Linear allocation blocks
   LinearAllocBlock _smallLinearAllocBlock;
 
-  FreeBlockDictionary::DictionaryChoice _dictionaryChoice;
-  FreeBlockDictionary* _dictionary;    // ptr to dictionary for large size blocks
+  FreeBlockDictionary<FreeChunk>::DictionaryChoice _dictionaryChoice;
+  FreeBlockDictionary<FreeChunk>* _dictionary;    // ptr to dictionary for large size blocks
 
-  FreeList _indexedFreeList[IndexSetSize];
+  FreeList<FreeChunk> _indexedFreeList[IndexSetSize];
                                        // indexed array for small size blocks
   // allocation stategy
   bool       _fitStrategy;      // Use best fit strategy.
@@ -169,7 +169,7 @@
   // If the count of "fl" is negative, it's absolute value indicates a
   // number of free chunks that had been previously "borrowed" from global
   // list of size "word_sz", and must now be decremented.
-  void par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl);
+  void par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList<FreeChunk>* fl);
 
   // Allocation helper functions
   // Allocate using a strategy that takes from the indexed free lists
@@ -215,7 +215,7 @@
   // and return it.  The split off remainder is returned to
   // the free lists.  The old name for getFromListGreater
   // was lookInListGreater.
-  FreeChunk* getFromListGreater(FreeList* fl, size_t numWords);
+  FreeChunk* getFromListGreater(FreeList<FreeChunk>* fl, size_t numWords);
   // Get a chunk in the indexed free list or dictionary,
   // by considering a larger chunk and splitting it.
   FreeChunk* getChunkFromGreater(size_t numWords);
@@ -286,10 +286,10 @@
   // Constructor...
   CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr,
                            bool use_adaptive_freelists,
-                           FreeBlockDictionary::DictionaryChoice);
+                           FreeBlockDictionary<FreeChunk>::DictionaryChoice);
   // accessors
   bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; }
-  FreeBlockDictionary* dictionary() const { return _dictionary; }
+  FreeBlockDictionary<FreeChunk>* dictionary() const { return _dictionary; }
   HeapWord* nearLargestChunk() const { return _nearLargestChunk; }
   void set_nearLargestChunk(HeapWord* v) { _nearLargestChunk = v; }
 
@@ -492,14 +492,14 @@
   void print()                            const;
   void print_on(outputStream* st)         const;
   void prepare_for_verify();
-  void verify(bool allow_dirty)           const;
+  void verify()                           const;
   void verifyFreeLists()                  const PRODUCT_RETURN;
   void verifyIndexedFreeLists()           const;
   void verifyIndexedFreeList(size_t size) const;
   // Verify that the given chunk is in the free lists:
   // i.e. either the binary tree dictionary, the indexed free lists
   // or the linear allocation block.
-  bool verifyChunkInFreeLists(FreeChunk* fc) const;
+  bool verify_chunk_in_free_list(FreeChunk* fc) const;
   // Verify that the given chunk is the linear allocation block
   bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const;
   // Do some basic checks on the the free lists.
@@ -608,7 +608,7 @@
   void coalDeath(size_t size);
   void smallSplitBirth(size_t size);
   void smallSplitDeath(size_t size);
-  void splitBirth(size_t size);
+  void split_birth(size_t size);
   void splitDeath(size_t size);
   void split(size_t from, size_t to1);
 
@@ -622,7 +622,7 @@
   CompactibleFreeListSpace* _cfls;
 
   // Our local free lists.
-  FreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize];
+  FreeList<FreeChunk> _indexedFreeList[CompactibleFreeListSpace::IndexSetSize];
 
   // Initialized from a command-line arg.
 
@@ -635,7 +635,7 @@
   size_t        _num_blocks        [CompactibleFreeListSpace::IndexSetSize];
 
   // Internal work method
-  void get_from_global_pool(size_t word_sz, FreeList* fl);
+  void get_from_global_pool(size_t word_sz, FreeList<FreeChunk>* fl);
 
 public:
   CFLS_LAB(CompactibleFreeListSpace* cfls);
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Tue May 15 11:27:24 2012 -0700
@@ -188,7 +188,7 @@
 ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
      ReservedSpace rs, size_t initial_byte_size, int level,
      CardTableRS* ct, bool use_adaptive_freelists,
-     FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
+     FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
   CardGeneration(rs, initial_byte_size, level, ct),
   _dilatation_factor(((double)MinChunkSize)/((double)(CollectedHeap::min_fill_size()))),
   _debug_collection_type(Concurrent_collection_type)
@@ -1026,7 +1026,7 @@
     // its mark-bit or P-bits not yet set. Such objects need
     // to be safely navigable by block_start().
     assert(oop(res)->klass_or_null() == NULL, "Object should be uninitialized here.");
-    assert(!((FreeChunk*)res)->isFree(), "Error, block will look free but show wrong size");
+    assert(!((FreeChunk*)res)->is_free(), "Error, block will look free but show wrong size");
     collector()->direct_allocated(res, adjustedSize);
     _direct_allocated_words += adjustedSize;
     // allocation counters
@@ -1391,7 +1391,7 @@
   oop obj = oop(obj_ptr);
   OrderAccess::storestore();
   assert(obj->klass_or_null() == NULL, "Object should be uninitialized here.");
-  assert(!((FreeChunk*)obj_ptr)->isFree(), "Error, block will look free but show wrong size");
+  assert(!((FreeChunk*)obj_ptr)->is_free(), "Error, block will look free but show wrong size");
   // IMPORTANT: See note on object initialization for CMS above.
   // Otherwise, copy the object.  Here we must be careful to insert the
   // klass pointer last, since this marks the block as an allocated object.
@@ -1400,7 +1400,7 @@
   // Restore the mark word copied above.
   obj->set_mark(m);
   assert(obj->klass_or_null() == NULL, "Object should be uninitialized here.");
-  assert(!((FreeChunk*)obj_ptr)->isFree(), "Error, block will look free but show wrong size");
+  assert(!((FreeChunk*)obj_ptr)->is_free(), "Error, block will look free but show wrong size");
   OrderAccess::storestore();
 
   if (UseCompressedOops) {
@@ -1421,7 +1421,7 @@
     promoInfo->track((PromotedObject*)obj, old->klass());
   }
   assert(obj->klass_or_null() == NULL, "Object should be uninitialized here.");
-  assert(!((FreeChunk*)obj_ptr)->isFree(), "Error, block will look free but show wrong size");
+  assert(!((FreeChunk*)obj_ptr)->is_free(), "Error, block will look free but show wrong size");
   assert(old->is_oop(), "Will use and dereference old klass ptr below");
 
   // Finally, install the klass pointer (this should be volatile).
@@ -2034,7 +2034,7 @@
            pointer_delta(cms_space->end(), cms_space->compaction_top())
            * HeapWordSize,
       "All the free space should be compacted into one chunk at top");
-    assert(cms_space->dictionary()->totalChunkSize(
+    assert(cms_space->dictionary()->total_chunk_size(
                                       debug_only(cms_space->freelistLock())) == 0 ||
            cms_space->totalSizeInIndexedFreeLists() == 0,
       "All the free space should be in a single chunk");
@@ -3109,21 +3109,21 @@
 }
 
 void
-ConcurrentMarkSweepGeneration::verify(bool allow_dirty /* ignored */) {
+ConcurrentMarkSweepGeneration::verify() {
   // Locks are normally acquired/released in gc_prologue/gc_epilogue, but those
   // are not called when the heap is verified during universe initialization and
   // at vm shutdown.
   if (freelistLock()->owned_by_self()) {
-    cmsSpace()->verify(false /* ignored */);
+    cmsSpace()->verify();
   } else {
     MutexLockerEx fll(freelistLock(), Mutex::_no_safepoint_check_flag);
-    cmsSpace()->verify(false /* ignored */);
-  }
-}
-
-void CMSCollector::verify(bool allow_dirty /* ignored */) {
-  _cmsGen->verify(allow_dirty);
-  _permGen->verify(allow_dirty);
+    cmsSpace()->verify();
+  }
+}
+
+void CMSCollector::verify() {
+  _cmsGen->verify();
+  _permGen->verify();
 }
 
 #ifndef PRODUCT
@@ -6131,7 +6131,7 @@
   double nearLargestPercent = FLSLargestBlockCoalesceProximity;
   HeapWord*  minAddr        = _cmsSpace->bottom();
   HeapWord*  largestAddr    =
-    (HeapWord*) _cmsSpace->dictionary()->findLargestDict();
+    (HeapWord*) _cmsSpace->dictionary()->find_largest_dict();
   if (largestAddr == NULL) {
     // The dictionary appears to be empty.  In this case
     // try to coalesce at the end of the heap.
@@ -7906,7 +7906,7 @@
     _last_fc = NULL;
 
     _sp->initializeIndexedFreeListArrayReturnedBytes();
-    _sp->dictionary()->initializeDictReturnedBytes();
+    _sp->dictionary()->initialize_dict_returned_bytes();
   )
   assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
          "sweep _limit out of bounds");
@@ -7954,13 +7954,13 @@
 
     if (PrintCMSStatistics && CMSVerifyReturnedBytes) {
       size_t indexListReturnedBytes = _sp->sumIndexedFreeListArrayReturnedBytes();
-      size_t dictReturnedBytes = _sp->dictionary()->sumDictReturnedBytes();
-      size_t returnedBytes = indexListReturnedBytes + dictReturnedBytes;
-      gclog_or_tty->print("Returned "SIZE_FORMAT" bytes", returnedBytes);
+      size_t dict_returned_bytes = _sp->dictionary()->sum_dict_returned_bytes();
+      size_t returned_bytes = indexListReturnedBytes + dict_returned_bytes;
+      gclog_or_tty->print("Returned "SIZE_FORMAT" bytes", returned_bytes);
       gclog_or_tty->print("   Indexed List Returned "SIZE_FORMAT" bytes",
         indexListReturnedBytes);
       gclog_or_tty->print_cr("        Dictionary Returned "SIZE_FORMAT" bytes",
-        dictReturnedBytes);
+        dict_returned_bytes);
     }
   }
   if (CMSTraceSweeper) {
@@ -7985,9 +7985,9 @@
   if (CMSTestInFreeList) {
     if (freeRangeInFreeLists) {
       FreeChunk* fc = (FreeChunk*) freeFinger;
-      assert(fc->isFree(), "A chunk on the free list should be free.");
+      assert(fc->is_free(), "A chunk on the free list should be free.");
       assert(fc->size() > 0, "Free range should have a size");
-      assert(_sp->verifyChunkInFreeLists(fc), "Chunk is not in free lists");
+      assert(_sp->verify_chunk_in_free_list(fc), "Chunk is not in free lists");
     }
   }
 }
@@ -8057,7 +8057,7 @@
   assert(addr < _limit, "sweep invariant");
   // check if we should yield
   do_yield_check(addr);
-  if (fc->isFree()) {
+  if (fc->is_free()) {
     // Chunk that is already free
     res = fc->size();
     do_already_free_chunk(fc);
@@ -8145,7 +8145,7 @@
   // Chunks that cannot be coalesced are not in the
   // free lists.
   if (CMSTestInFreeList && !fc->cantCoalesce()) {
-    assert(_sp->verifyChunkInFreeLists(fc),
+    assert(_sp->verify_chunk_in_free_list(fc),
       "free chunk should be in free lists");
   }
   // a chunk that is already free, should not have been
@@ -8171,7 +8171,7 @@
         FreeChunk* nextChunk = (FreeChunk*)(addr + size);
         assert((HeapWord*)nextChunk <= _sp->end(), "Chunk size out of bounds?");
         if ((HeapWord*)nextChunk < _sp->end() &&     // There is another free chunk to the right ...
-            nextChunk->isFree()               &&     // ... which is free...
+            nextChunk->is_free()               &&     // ... which is free...
             nextChunk->cantCoalesce()) {             // ... but can't be coalesced
           // nothing to do
         } else {
@@ -8203,7 +8203,7 @@
           assert(ffc->size() == pointer_delta(addr, freeFinger()),
             "Size of free range is inconsistent with chunk size.");
           if (CMSTestInFreeList) {
-            assert(_sp->verifyChunkInFreeLists(ffc),
+            assert(_sp->verify_chunk_in_free_list(ffc),
               "free range is not in free lists");
           }
           _sp->removeFreeChunkFromFreeLists(ffc);
@@ -8262,7 +8262,7 @@
         assert(ffc->size() == pointer_delta(addr, freeFinger()),
           "Size of free range is inconsistent with chunk size.");
         if (CMSTestInFreeList) {
-          assert(_sp->verifyChunkInFreeLists(ffc),
+          assert(_sp->verify_chunk_in_free_list(ffc),
             "free range is not in free lists");
         }
         _sp->removeFreeChunkFromFreeLists(ffc);
@@ -8351,11 +8351,11 @@
                                                  size_t chunkSize) {
   // do_post_free_or_garbage_chunk() should only be called in the case
   // of the adaptive free list allocator.
-  const bool fcInFreeLists = fc->isFree();
+  const bool fcInFreeLists = fc->is_free();
   assert(_sp->adaptive_freelists(), "Should only be used in this case.");
   assert((HeapWord*)fc <= _limit, "sweep invariant");
   if (CMSTestInFreeList && fcInFreeLists) {
-    assert(_sp->verifyChunkInFreeLists(fc), "free chunk is not in free lists");
+    assert(_sp->verify_chunk_in_free_list(fc), "free chunk is not in free lists");
   }
 
   if (CMSTraceSweeper) {
@@ -8410,7 +8410,7 @@
       assert(ffc->size() == pointer_delta(fc_addr, freeFinger()),
         "Size of free range is inconsistent with chunk size.");
       if (CMSTestInFreeList) {
-        assert(_sp->verifyChunkInFreeLists(ffc),
+        assert(_sp->verify_chunk_in_free_list(ffc),
           "Chunk is not in free lists");
       }
       _sp->coalDeath(ffc->size());
@@ -8459,7 +8459,7 @@
                  " when examining fc = " PTR_FORMAT "(" SIZE_FORMAT ")",
                  _limit, _sp->bottom(), _sp->end(), fc, chunk_size));
   if (eob >= _limit) {
-    assert(eob == _limit || fc->isFree(), "Only a free chunk should allow us to cross over the limit");
+    assert(eob == _limit || fc->is_free(), "Only a free chunk should allow us to cross over the limit");
     if (CMSTraceSweeper) {
       gclog_or_tty->print_cr("_limit " PTR_FORMAT " reached or crossed by block "
                              "[" PTR_FORMAT "," PTR_FORMAT ") in space "
@@ -8482,8 +8482,8 @@
   if (!freeRangeInFreeLists()) {
     if (CMSTestInFreeList) {
       FreeChunk* fc = (FreeChunk*) chunk;
-      fc->setSize(size);
-      assert(!_sp->verifyChunkInFreeLists(fc),
+      fc->set_size(size);
+      assert(!_sp->verify_chunk_in_free_list(fc),
         "chunk should not be in free lists yet");
     }
     if (CMSTraceSweeper) {
@@ -8557,8 +8557,8 @@
 // This is actually very useful in a product build if it can
 // be called from the debugger.  Compile it into the product
 // as needed.
-bool debug_verifyChunkInFreeLists(FreeChunk* fc) {
-  return debug_cms_space->verifyChunkInFreeLists(fc);
+bool debug_verify_chunk_in_free_list(FreeChunk* fc) {
+  return debug_cms_space->verify_chunk_in_free_list(fc);
 }
 #endif
 
@@ -9255,7 +9255,7 @@
       size_t chunk_at_end_old_size = chunk_at_end->size();
       assert(chunk_at_end_old_size >= word_size_change,
         "Shrink is too large");
-      chunk_at_end->setSize(chunk_at_end_old_size -
+      chunk_at_end->set_size(chunk_at_end_old_size -
                           word_size_change);
       _cmsSpace->freed((HeapWord*) chunk_at_end->end(),
         word_size_change);
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,10 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPGENERATION_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CONCURRENTMARKSWEEPGENERATION_HPP
 
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
 #include "gc_implementation/shared/gSpaceCounters.hpp"
 #include "gc_implementation/shared/gcStats.hpp"
 #include "gc_implementation/shared/generationCounters.hpp"
+#include "memory/freeBlockDictionary.hpp"
 #include "memory/generation.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/virtualspace.hpp"
@@ -988,7 +988,7 @@
   CMSGCAdaptivePolicyCounters* gc_adaptive_policy_counters();
 
   // debugging
-  void verify(bool);
+  void verify();
   bool verify_after_remark();
   void verify_ok_to_terminate() const PRODUCT_RETURN;
   void verify_work_stacks_empty() const PRODUCT_RETURN;
@@ -1106,7 +1106,7 @@
   ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
                                 int level, CardTableRS* ct,
                                 bool use_adaptive_freelists,
-                                FreeBlockDictionary::DictionaryChoice);
+                                FreeBlockDictionary<FreeChunk>::DictionaryChoice);
 
   // Accessors
   CMSCollector* collector() const { return _collector; }
@@ -1279,7 +1279,7 @@
 
   // Debugging
   void prepare_for_verify();
-  void verify(bool allow_dirty);
+  void verify();
   void print_statistics()               PRODUCT_RETURN;
 
   // Performance Counters support
@@ -1328,7 +1328,7 @@
   ASConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
                                   int level, CardTableRS* ct,
                                   bool use_adaptive_freelists,
-                                  FreeBlockDictionary::DictionaryChoice
+                                  FreeBlockDictionary<FreeChunk>::DictionaryChoice
                                     dictionaryChoice) :
     ConcurrentMarkSweepGeneration(rs, initial_byte_size, level, ct,
       use_adaptive_freelists, dictionaryChoice) {}
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.cpp	Tue May 15 10:52:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
-#ifdef TARGET_OS_FAMILY_linux
-# include "thread_linux.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_solaris
-# include "thread_solaris.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_windows
-# include "thread_windows.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_bsd
-# include "thread_bsd.inline.hpp"
-#endif
-
-#ifndef PRODUCT
-Mutex* FreeBlockDictionary::par_lock() const {
-  return _lock;
-}
-
-void FreeBlockDictionary::set_par_lock(Mutex* lock) {
-  _lock = lock;
-}
-
-void FreeBlockDictionary::verify_par_locked() const {
-#ifdef ASSERT
-  if (ParallelGCThreads > 0) {
-    Thread* myThread = Thread::current();
-    if (myThread->is_GC_task_thread()) {
-      assert(par_lock() != NULL, "Should be using locking?");
-      assert_lock_strong(par_lock());
-    }
-  }
-#endif // ASSERT
-}
-#endif
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp	Tue May 15 10:52:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREEBLOCKDICTIONARY_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREEBLOCKDICTIONARY_HPP
-
-#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
-#include "memory/allocation.hpp"
-#include "memory/memRegion.hpp"
-#include "runtime/mutex.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/globalDefinitions.hpp"
-#include "utilities/ostream.hpp"
-
-// A FreeBlockDictionary is an abstract superclass that will allow
-// a number of alternative implementations in the future.
-class FreeBlockDictionary: public CHeapObj {
- public:
-  enum Dither {
-    atLeast,
-    exactly,
-    roughly
-  };
-  enum DictionaryChoice {
-    dictionaryBinaryTree = 0,
-    dictionarySplayTree  = 1,
-    dictionarySkipList   = 2
-  };
-
- private:
-  NOT_PRODUCT(Mutex* _lock;)
-
- public:
-  virtual void       removeChunk(FreeChunk* fc) = 0;
-  virtual FreeChunk* getChunk(size_t size, Dither dither = atLeast) = 0;
-  virtual void       returnChunk(FreeChunk* chunk) = 0;
-  virtual size_t     totalChunkSize(debug_only(const Mutex* lock)) const = 0;
-  virtual size_t     maxChunkSize()   const = 0;
-  virtual size_t     minSize()        const = 0;
-  // Reset the dictionary to the initial conditions for a single
-  // block.
-  virtual void       reset(HeapWord* addr, size_t size) = 0;
-  virtual void       reset() = 0;
-
-  virtual void       dictCensusUpdate(size_t size, bool split, bool birth) = 0;
-  virtual bool       coalDictOverPopulated(size_t size) = 0;
-  virtual void       beginSweepDictCensus(double coalSurplusPercent,
-                       float inter_sweep_current, float inter_sweep_estimate,
-                       float intra__sweep_current) = 0;
-  virtual void       endSweepDictCensus(double splitSurplusPercent) = 0;
-  virtual FreeChunk* findLargestDict() const = 0;
-  // verify that the given chunk is in the dictionary.
-  virtual bool verifyChunkInFreeLists(FreeChunk* tc) const = 0;
-
-  // Sigma_{all_free_blocks} (block_size^2)
-  virtual double sum_of_squared_block_sizes() const = 0;
-
-  virtual FreeChunk* find_chunk_ends_at(HeapWord* target) const = 0;
-  virtual void inc_totalSize(size_t v) = 0;
-  virtual void dec_totalSize(size_t v) = 0;
-
-  NOT_PRODUCT (
-    virtual size_t   sumDictReturnedBytes() = 0;
-    virtual void     initializeDictReturnedBytes() = 0;
-    virtual size_t   totalCount() = 0;
-  )
-
-  virtual void       reportStatistics() const {
-    gclog_or_tty->print("No statistics available");
-  }
-
-  virtual void       printDictCensus() const = 0;
-  virtual void       print_free_lists(outputStream* st) const = 0;
-
-  virtual void       verify()         const = 0;
-
-  Mutex* par_lock()                const PRODUCT_RETURN0;
-  void   set_par_lock(Mutex* lock)       PRODUCT_RETURN;
-  void   verify_par_locked()       const PRODUCT_RETURN;
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREEBLOCKDICTIONARY_HPP
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp	Tue May 15 11:27:24 2012 -0700
@@ -23,7 +23,8 @@
  */
 
 #include "precompiled.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
+#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
+#include "memory/freeBlockDictionary.hpp"
 #include "utilities/copy.hpp"
 
 #ifndef PRODUCT
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp	Tue May 15 11:27:24 2012 -0700
@@ -75,20 +75,20 @@
     // calls.  We really want the read of _mark and _prev from this pointer
     // to be volatile but making the fields volatile causes all sorts of
     // compilation errors.
-    return ((volatile FreeChunk*)addr)->isFree();
+    return ((volatile FreeChunk*)addr)->is_free();
   }
 
-  bool isFree() const volatile {
+  bool is_free() const volatile {
     LP64_ONLY(if (UseCompressedOops) return mark()->is_cms_free_chunk(); else)
     return (((intptr_t)_prev) & 0x1) == 0x1;
   }
   bool cantCoalesce() const {
-    assert(isFree(), "can't get coalesce bit on not free");
+    assert(is_free(), "can't get coalesce bit on not free");
     return (((intptr_t)_prev) & 0x2) == 0x2;
   }
   void dontCoalesce() {
     // the block should be free
-    assert(isFree(), "Should look like a free block");
+    assert(is_free(), "Should look like a free block");
     _prev = (FreeChunk*)(((intptr_t)_prev) | 0x2);
   }
   FreeChunk* prev() const {
@@ -103,23 +103,23 @@
     LP64_ONLY(if (UseCompressedOops) return mark()->get_size(); else )
     return _size;
   }
-  void setSize(size_t sz) {
+  void set_size(size_t sz) {
     LP64_ONLY(if (UseCompressedOops) set_mark(markOopDesc::set_size_and_free(sz)); else )
     _size = sz;
   }
 
   FreeChunk* next()   const { return _next; }
 
-  void linkAfter(FreeChunk* ptr) {
-    linkNext(ptr);
-    if (ptr != NULL) ptr->linkPrev(this);
+  void link_after(FreeChunk* ptr) {
+    link_next(ptr);
+    if (ptr != NULL) ptr->link_prev(this);
   }
-  void linkNext(FreeChunk* ptr) { _next = ptr; }
-  void linkPrev(FreeChunk* ptr) {
+  void link_next(FreeChunk* ptr) { _next = ptr; }
+  void link_prev(FreeChunk* ptr) {
     LP64_ONLY(if (UseCompressedOops) _prev = ptr; else)
     _prev = (FreeChunk*)((intptr_t)ptr | 0x1);
   }
-  void clearNext()              { _next = NULL; }
+  void clear_next()              { _next = NULL; }
   void markNotFree() {
     // Set _prev (klass) to null before (if) clearing the mark word below
     _prev = NULL;
@@ -129,7 +129,7 @@
       set_mark(markOopDesc::prototype());
     }
 #endif
-    assert(!isFree(), "Error");
+    assert(!is_free(), "Error");
   }
 
   // Return the address past the end of this chunk
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.cpp	Tue May 15 10:52:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,360 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeList.hpp"
-#include "memory/sharedHeap.hpp"
-#include "runtime/globals.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/vmThread.hpp"
-
-// Free list.  A FreeList is used to access a linked list of chunks
-// of space in the heap.  The head and tail are maintained so that
-// items can be (as in the current implementation) added at the
-// at the tail of the list and removed from the head of the list to
-// maintain a FIFO queue.
-
-FreeList::FreeList() :
-  _head(NULL), _tail(NULL)
-#ifdef ASSERT
-  , _protecting_lock(NULL)
-#endif
-{
-  _size         = 0;
-  _count        = 0;
-  _hint         = 0;
-  init_statistics();
-}
-
-FreeList::FreeList(FreeChunk* fc) :
-  _head(fc), _tail(fc)
-#ifdef ASSERT
-  , _protecting_lock(NULL)
-#endif
-{
-  _size         = fc->size();
-  _count        = 1;
-  _hint         = 0;
-  init_statistics();
-#ifndef PRODUCT
-  _allocation_stats.set_returnedBytes(size() * HeapWordSize);
-#endif
-}
-
-FreeList::FreeList(HeapWord* addr, size_t size) :
-  _head((FreeChunk*) addr), _tail((FreeChunk*) addr)
-#ifdef ASSERT
-  , _protecting_lock(NULL)
-#endif
-{
-  assert(size > sizeof(FreeChunk), "size is too small");
-  head()->setSize(size);
-  _size         = size;
-  _count        = 1;
-  init_statistics();
-#ifndef PRODUCT
-  _allocation_stats.set_returnedBytes(_size * HeapWordSize);
-#endif
-}
-
-void FreeList::reset(size_t hint) {
-  set_count(0);
-  set_head(NULL);
-  set_tail(NULL);
-  set_hint(hint);
-}
-
-void FreeList::init_statistics(bool split_birth) {
-  _allocation_stats.initialize(split_birth);
-}
-
-FreeChunk* FreeList::getChunkAtHead() {
-  assert_proper_lock_protection();
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  FreeChunk* fc = head();
-  if (fc != NULL) {
-    FreeChunk* nextFC = fc->next();
-    if (nextFC != NULL) {
-      // The chunk fc being removed has a "next".  Set the "next" to the
-      // "prev" of fc.
-      nextFC->linkPrev(NULL);
-    } else { // removed tail of list
-      link_tail(NULL);
-    }
-    link_head(nextFC);
-    decrement_count();
-  }
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  return fc;
-}
-
-
-void FreeList::getFirstNChunksFromList(size_t n, FreeList* fl) {
-  assert_proper_lock_protection();
-  assert(fl->count() == 0, "Precondition");
-  if (count() > 0) {
-    int k = 1;
-    fl->set_head(head()); n--;
-    FreeChunk* tl = head();
-    while (tl->next() != NULL && n > 0) {
-      tl = tl->next(); n--; k++;
-    }
-    assert(tl != NULL, "Loop Inv.");
-
-    // First, fix up the list we took from.
-    FreeChunk* new_head = tl->next();
-    set_head(new_head);
-    set_count(count() - k);
-    if (new_head == NULL) {
-      set_tail(NULL);
-    } else {
-      new_head->linkPrev(NULL);
-    }
-    // Now we can fix up the tail.
-    tl->linkNext(NULL);
-    // And return the result.
-    fl->set_tail(tl);
-    fl->set_count(k);
-  }
-}
-
-// Remove this chunk from the list
-void FreeList::removeChunk(FreeChunk*fc) {
-   assert_proper_lock_protection();
-   assert(head() != NULL, "Remove from empty list");
-   assert(fc != NULL, "Remove a NULL chunk");
-   assert(size() == fc->size(), "Wrong list");
-   assert(head() == NULL || head()->prev() == NULL, "list invariant");
-   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-   FreeChunk* prevFC = fc->prev();
-   FreeChunk* nextFC = fc->next();
-   if (nextFC != NULL) {
-     // The chunk fc being removed has a "next".  Set the "next" to the
-     // "prev" of fc.
-     nextFC->linkPrev(prevFC);
-   } else { // removed tail of list
-     link_tail(prevFC);
-   }
-   if (prevFC == NULL) { // removed head of list
-     link_head(nextFC);
-     assert(nextFC == NULL || nextFC->prev() == NULL,
-       "Prev of head should be NULL");
-   } else {
-     prevFC->linkNext(nextFC);
-     assert(tail() != prevFC || prevFC->next() == NULL,
-       "Next of tail should be NULL");
-   }
-   decrement_count();
-   assert(((head() == NULL) + (tail() == NULL) + (count() == 0)) % 3 == 0,
-          "H/T/C Inconsistency");
-   // clear next and prev fields of fc, debug only
-   NOT_PRODUCT(
-     fc->linkPrev(NULL);
-     fc->linkNext(NULL);
-   )
-   assert(fc->isFree(), "Should still be a free chunk");
-   assert(head() == NULL || head()->prev() == NULL, "list invariant");
-   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-   assert(head() == NULL || head()->size() == size(), "wrong item on list");
-   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
-}
-
-// Add this chunk at the head of the list.
-void FreeList::returnChunkAtHead(FreeChunk* chunk, bool record_return) {
-  assert_proper_lock_protection();
-  assert(chunk != NULL, "insert a NULL chunk");
-  assert(size() == chunk->size(), "Wrong size");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  FreeChunk* oldHead = head();
-  assert(chunk != oldHead, "double insertion");
-  chunk->linkAfter(oldHead);
-  link_head(chunk);
-  if (oldHead == NULL) { // only chunk in list
-    assert(tail() == NULL, "inconsistent FreeList");
-    link_tail(chunk);
-  }
-  increment_count(); // of # of chunks in list
-  DEBUG_ONLY(
-    if (record_return) {
-      increment_returnedBytes_by(size()*HeapWordSize);
-    }
-  )
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  assert(head() == NULL || head()->size() == size(), "wrong item on list");
-  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
-}
-
-void FreeList::returnChunkAtHead(FreeChunk* chunk) {
-  assert_proper_lock_protection();
-  returnChunkAtHead(chunk, true);
-}
-
-// Add this chunk at the tail of the list.
-void FreeList::returnChunkAtTail(FreeChunk* chunk, bool record_return) {
-  assert_proper_lock_protection();
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  assert(chunk != NULL, "insert a NULL chunk");
-  assert(size() == chunk->size(), "wrong size");
-
-  FreeChunk* oldTail = tail();
-  assert(chunk != oldTail, "double insertion");
-  if (oldTail != NULL) {
-    oldTail->linkAfter(chunk);
-  } else { // only chunk in list
-    assert(head() == NULL, "inconsistent FreeList");
-    link_head(chunk);
-  }
-  link_tail(chunk);
-  increment_count();  // of # of chunks in list
-  DEBUG_ONLY(
-    if (record_return) {
-      increment_returnedBytes_by(size()*HeapWordSize);
-    }
-  )
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  assert(head() == NULL || head()->size() == size(), "wrong item on list");
-  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
-}
-
-void FreeList::returnChunkAtTail(FreeChunk* chunk) {
-  returnChunkAtTail(chunk, true);
-}
-
-void FreeList::prepend(FreeList* fl) {
-  assert_proper_lock_protection();
-  if (fl->count() > 0) {
-    if (count() == 0) {
-      set_head(fl->head());
-      set_tail(fl->tail());
-      set_count(fl->count());
-    } else {
-      // Both are non-empty.
-      FreeChunk* fl_tail = fl->tail();
-      FreeChunk* this_head = head();
-      assert(fl_tail->next() == NULL, "Well-formedness of fl");
-      fl_tail->linkNext(this_head);
-      this_head->linkPrev(fl_tail);
-      set_head(fl->head());
-      set_count(count() + fl->count());
-    }
-    fl->set_head(NULL);
-    fl->set_tail(NULL);
-    fl->set_count(0);
-  }
-}
-
-// verifyChunkInFreeLists() is used to verify that an item is in this free list.
-// It is used as a debugging aid.
-bool FreeList::verifyChunkInFreeLists(FreeChunk* fc) const {
-  // This is an internal consistency check, not part of the check that the
-  // chunk is in the free lists.
-  guarantee(fc->size() == size(), "Wrong list is being searched");
-  FreeChunk* curFC = head();
-  while (curFC) {
-    // This is an internal consistency check.
-    guarantee(size() == curFC->size(), "Chunk is in wrong list.");
-    if (fc == curFC) {
-      return true;
-    }
-    curFC = curFC->next();
-  }
-  return false;
-}
-
-#ifndef PRODUCT
-void FreeList::verify_stats() const {
-  // The +1 of the LH comparand is to allow some "looseness" in
-  // checking: we usually call this interface when adding a block
-  // and we'll subsequently update the stats; we cannot update the
-  // stats beforehand because in the case of the large-block BT
-  // dictionary for example, this might be the first block and
-  // in that case there would be no place that we could record
-  // the stats (which are kept in the block itself).
-  assert((_allocation_stats.prevSweep() + _allocation_stats.splitBirths()
-          + _allocation_stats.coalBirths() + 1)   // Total Production Stock + 1
-         >= (_allocation_stats.splitDeaths() + _allocation_stats.coalDeaths()
-             + (ssize_t)count()),                // Total Current Stock + depletion
-         err_msg("FreeList " PTR_FORMAT " of size " SIZE_FORMAT
-                 " violates Conservation Principle: "
-                 "prevSweep(" SIZE_FORMAT ")"
-                 " + splitBirths(" SIZE_FORMAT ")"
-                 " + coalBirths(" SIZE_FORMAT ") + 1 >= "
-                 " splitDeaths(" SIZE_FORMAT ")"
-                 " coalDeaths(" SIZE_FORMAT ")"
-                 " + count(" SSIZE_FORMAT ")",
-                 this, _size, _allocation_stats.prevSweep(), _allocation_stats.splitBirths(),
-                 _allocation_stats.splitBirths(), _allocation_stats.splitDeaths(),
-                 _allocation_stats.coalDeaths(), count()));
-}
-
-void FreeList::assert_proper_lock_protection_work() const {
-  assert(_protecting_lock != NULL, "Don't call this directly");
-  assert(ParallelGCThreads > 0, "Don't call this directly");
-  Thread* thr = Thread::current();
-  if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
-    // assert that we are holding the freelist lock
-  } else if (thr->is_GC_task_thread()) {
-    assert(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED");
-  } else if (thr->is_Java_thread()) {
-    assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
-  } else {
-    ShouldNotReachHere();  // unaccounted thread type?
-  }
-}
-#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	Tue May 15 10:52:24 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,335 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
-
-#include "gc_implementation/shared/allocationStats.hpp"
-
-class CompactibleFreeListSpace;
-
-// A class for maintaining a free list of FreeChunk's.  The FreeList
-// maintains a the structure of the list (head, tail, etc.) plus
-// statistics for allocations from the list.  The links between items
-// are not part of FreeList.  The statistics are
-// used to make decisions about coalescing FreeChunk's when they
-// are swept during collection.
-//
-// See the corresponding .cpp file for a description of the specifics
-// for that implementation.
-
-class Mutex;
-class TreeList;
-
-class FreeList VALUE_OBJ_CLASS_SPEC {
-  friend class CompactibleFreeListSpace;
-  friend class VMStructs;
-  friend class PrintTreeCensusClosure;
-
- protected:
-  TreeList* _parent;
-  TreeList* _left;
-  TreeList* _right;
-
- private:
-  FreeChunk*    _head;          // Head of list of free chunks
-  FreeChunk*    _tail;          // Tail of list of free chunks
-  size_t        _size;          // Size in Heap words of each chunk
-  ssize_t       _count;         // Number of entries in list
-  size_t        _hint;          // next larger size list with a positive surplus
-
-  AllocationStats _allocation_stats; // allocation-related statistics
-
-#ifdef ASSERT
-  Mutex*        _protecting_lock;
-#endif
-
-  // Asserts false if the protecting lock (if any) is not held.
-  void assert_proper_lock_protection_work() const PRODUCT_RETURN;
-  void assert_proper_lock_protection() const {
-#ifdef ASSERT
-    if (_protecting_lock != NULL)
-      assert_proper_lock_protection_work();
-#endif
-  }
-
-  // Initialize the allocation statistics.
- protected:
-  void init_statistics(bool split_birth = false);
-  void set_count(ssize_t v) { _count = v;}
-  void increment_count()    {
-    _count++;
-  }
-
-  void decrement_count() {
-    _count--;
-    assert(_count >= 0, "Count should not be negative");
-  }
-
- public:
-  // Constructor
-  // Construct a list without any entries.
-  FreeList();
-  // Construct a list with "fc" as the first (and lone) entry in the list.
-  FreeList(FreeChunk* fc);
-  // Construct a list which will have a FreeChunk at address "addr" and
-  // of size "size" as the first (and lone) entry in the list.
-  FreeList(HeapWord* addr, size_t size);
-
-  // Reset the head, tail, hint, and count of a free list.
-  void reset(size_t hint);
-
-  // Declare the current free list to be protected by the given lock.
-#ifdef ASSERT
-  void set_protecting_lock(Mutex* protecting_lock) {
-    _protecting_lock = protecting_lock;
-  }
-#endif
-
-  // Accessors.
-  FreeChunk* head() const {
-    assert_proper_lock_protection();
-    return _head;
-  }
-  void set_head(FreeChunk* v) {
-    assert_proper_lock_protection();
-    _head = v;
-    assert(!_head || _head->size() == _size, "bad chunk size");
-  }
-  // Set the head of the list and set the prev field of non-null
-  // values to NULL.
-  void link_head(FreeChunk* v) {
-    assert_proper_lock_protection();
-    set_head(v);
-    // If this method is not used (just set the head instead),
-    // this check can be avoided.
-    if (v != NULL) {
-      v->linkPrev(NULL);
-    }
-  }
-
-  FreeChunk* tail() const {
-    assert_proper_lock_protection();
-    return _tail;
-  }
-  void set_tail(FreeChunk* v) {
-    assert_proper_lock_protection();
-    _tail = v;
-    assert(!_tail || _tail->size() == _size, "bad chunk size");
-  }
-  // Set the tail of the list and set the next field of non-null
-  // values to NULL.
-  void link_tail(FreeChunk* v) {
-    assert_proper_lock_protection();
-    set_tail(v);
-    if (v != NULL) {
-      v->clearNext();
-    }
-  }
-
-  // No locking checks in read-accessors: lock-free reads (only) are benign.
-  // Readers are expected to have the lock if they are doing work that
-  // requires atomicity guarantees in sections of code.
-  size_t size() const {
-    return _size;
-  }
-  void set_size(size_t v) {
-    assert_proper_lock_protection();
-    _size = v;
-  }
-  ssize_t count() const {
-    return _count;
-  }
-  size_t hint() const {
-    return _hint;
-  }
-  void set_hint(size_t v) {
-    assert_proper_lock_protection();
-    assert(v == 0 || _size < v, "Bad hint"); _hint = v;
-  }
-
-  // Accessors for statistics
-  AllocationStats* allocation_stats() {
-    assert_proper_lock_protection();
-    return &_allocation_stats;
-  }
-
-  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,
-                       float intra_sweep_estimate) {
-    assert_proper_lock_protection();
-    _allocation_stats.compute_desired(_count,
-                                      inter_sweep_current,
-                                      inter_sweep_estimate,
-                                      intra_sweep_estimate);
-  }
-  ssize_t coalDesired() const {
-    return _allocation_stats.coalDesired();
-  }
-  void set_coalDesired(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_coalDesired(v);
-  }
-
-  ssize_t surplus() const {
-    return _allocation_stats.surplus();
-  }
-  void set_surplus(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_surplus(v);
-  }
-  void increment_surplus() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_surplus();
-  }
-  void decrement_surplus() {
-    assert_proper_lock_protection();
-    _allocation_stats.decrement_surplus();
-  }
-
-  ssize_t bfrSurp() const {
-    return _allocation_stats.bfrSurp();
-  }
-  void set_bfrSurp(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_bfrSurp(v);
-  }
-  ssize_t prevSweep() const {
-    return _allocation_stats.prevSweep();
-  }
-  void set_prevSweep(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_prevSweep(v);
-  }
-  ssize_t beforeSweep() const {
-    return _allocation_stats.beforeSweep();
-  }
-  void set_beforeSweep(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_beforeSweep(v);
-  }
-
-  ssize_t coalBirths() const {
-    return _allocation_stats.coalBirths();
-  }
-  void set_coalBirths(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_coalBirths(v);
-  }
-  void increment_coalBirths() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_coalBirths();
-  }
-
-  ssize_t coalDeaths() const {
-    return _allocation_stats.coalDeaths();
-  }
-  void set_coalDeaths(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_coalDeaths(v);
-  }
-  void increment_coalDeaths() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_coalDeaths();
-  }
-
-  ssize_t splitBirths() const {
-    return _allocation_stats.splitBirths();
-  }
-  void set_splitBirths(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_splitBirths(v);
-  }
-  void increment_splitBirths() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_splitBirths();
-  }
-
-  ssize_t splitDeaths() const {
-    return _allocation_stats.splitDeaths();
-  }
-  void set_splitDeaths(ssize_t v) {
-    assert_proper_lock_protection();
-    _allocation_stats.set_splitDeaths(v);
-  }
-  void increment_splitDeaths() {
-    assert_proper_lock_protection();
-    _allocation_stats.increment_splitDeaths();
-  }
-
-  NOT_PRODUCT(
-    // For debugging.  The "_returnedBytes" in all the lists are summed
-    // and compared with the total number of bytes swept during a
-    // collection.
-    size_t returnedBytes() const { return _allocation_stats.returnedBytes(); }
-    void set_returnedBytes(size_t v) { _allocation_stats.set_returnedBytes(v); }
-    void increment_returnedBytes_by(size_t v) {
-      _allocation_stats.set_returnedBytes(_allocation_stats.returnedBytes() + v);
-    }
-  )
-
-  // Unlink head of list and return it.  Returns NULL if
-  // the list is empty.
-  FreeChunk* getChunkAtHead();
-
-  // Remove the first "n" or "count", whichever is smaller, chunks from the
-  // list, setting "fl", which is required to be empty, to point to them.
-  void getFirstNChunksFromList(size_t n, FreeList* fl);
-
-  // Unlink this chunk from it's free list
-  void removeChunk(FreeChunk* fc);
-
-  // Add this chunk to this free list.
-  void returnChunkAtHead(FreeChunk* fc);
-  void returnChunkAtTail(FreeChunk* fc);
-
-  // Similar to returnChunk* but also records some diagnostic
-  // information.
-  void returnChunkAtHead(FreeChunk* fc, bool record_return);
-  void returnChunkAtTail(FreeChunk* fc, bool record_return);
-
-  // Prepend "fl" (whose size is required to be the same as that of "this")
-  // to the front of "this" list.
-  void prepend(FreeList* fl);
-
-  // Verify that the chunk is in the list.
-  // found.  Return NULL if "fc" is not found.
-  bool verifyChunkInFreeLists(FreeChunk* fc) const;
-
-  // Stats verification
-  void verify_stats() const PRODUCT_RETURN;
-
-  // Printing support
-  static void print_labels_on(outputStream* st, const char* c);
-  void print_on(outputStream* st, const char* c = NULL) const;
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_FREELIST_HPP
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.cpp	Tue May 15 11:27:24 2012 -0700
@@ -121,7 +121,7 @@
 void PromotionInfo::track(PromotedObject* trackOop, klassOop klassOfOop) {
   // make a copy of header as it may need to be spooled
   markOop mark = oop(trackOop)->mark();
-  trackOop->clearNext();
+  trackOop->clear_next();
   if (mark->must_be_preserved_for_cms_scavenge(klassOfOop)) {
     // save non-prototypical header, and mark oop
     saveDisplacedHeader(mark);
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/promotionInfo.hpp	Tue May 15 11:27:24 2012 -0700
@@ -43,7 +43,7 @@
   // whose position will depend on endian-ness of the platform.
   // This is so that there is no interference with the
   // cms_free_bit occupying bit position 7 (lsb == 0)
-  // when we are using compressed oops; see FreeChunk::isFree().
+  // when we are using compressed oops; see FreeChunk::is_free().
   // We cannot move the cms_free_bit down because currently
   // biased locking code assumes that age bits are contiguous
   // with the lock bits. Even if that assumption were relaxed,
@@ -65,7 +65,7 @@
   };
  public:
   inline PromotedObject* next() const {
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
     PromotedObject* res;
     if (UseCompressedOops) {
       // The next pointer is a compressed oop stored in the top 32 bits
@@ -85,27 +85,27 @@
     } else {
       _next |= (intptr_t)x;
     }
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
   }
   inline void setPromotedMark() {
     _next |= promoted_mask;
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
   }
   inline bool hasPromotedMark() const {
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
     return (_next & promoted_mask) == promoted_mask;
   }
   inline void setDisplacedMark() {
     _next |= displaced_mark;
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
   }
   inline bool hasDisplacedMark() const {
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
     return (_next & displaced_mark) != 0;
   }
-  inline void clearNext()        {
+  inline void clear_next()        {
     _next = 0;
-    assert(!((FreeChunk*)this)->isFree(), "Error");
+    assert(!((FreeChunk*)this)->is_free(), "Error");
   }
   debug_only(void *next_addr() { return (void *) &_next; })
 };
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Tue May 15 11:27:24 2012 -0700
@@ -44,11 +44,11 @@
   nonstatic_field(FreeChunk,                   _next,                                         FreeChunk*)                            \
   nonstatic_field(FreeChunk,                   _prev,                                         FreeChunk*)                            \
   nonstatic_field(LinearAllocBlock,            _word_size,                                    size_t)                                \
-  nonstatic_field(FreeList,                    _size,                                         size_t)                                \
-  nonstatic_field(FreeList,                    _count,                                        ssize_t)                               \
-  nonstatic_field(BinaryTreeDictionary,        _totalSize,                                    size_t)                                \
-  nonstatic_field(CompactibleFreeListSpace,    _dictionary,                                   FreeBlockDictionary*)                  \
-  nonstatic_field(CompactibleFreeListSpace,    _indexedFreeList[0],                           FreeList)                              \
+  nonstatic_field(FreeList<FreeChunk>,         _size,                                         size_t)                                \
+  nonstatic_field(FreeList<FreeChunk>,         _count,                                        ssize_t)                               \
+  nonstatic_field(BinaryTreeDictionary<FreeChunk>,_total_size,                                 size_t)                                \
+  nonstatic_field(CompactibleFreeListSpace,    _dictionary,                                   FreeBlockDictionary<FreeChunk>*)       \
+  nonstatic_field(CompactibleFreeListSpace,    _indexedFreeList[0],                           FreeList<FreeChunk>)                   \
   nonstatic_field(CompactibleFreeListSpace,    _smallLinearAllocBlock,                        LinearAllocBlock)
 
 
@@ -70,13 +70,13 @@
   declare_toplevel_type(CompactibleFreeListSpace*)                        \
   declare_toplevel_type(CMSCollector*)                                    \
   declare_toplevel_type(FreeChunk*)                                       \
-  declare_toplevel_type(BinaryTreeDictionary*)                            \
-  declare_toplevel_type(FreeBlockDictionary*)                             \
-  declare_toplevel_type(FreeList*)                                        \
-  declare_toplevel_type(FreeList)                                         \
+  declare_toplevel_type(BinaryTreeDictionary<FreeChunk>*)                 \
+  declare_toplevel_type(FreeBlockDictionary<FreeChunk>*)                  \
+  declare_toplevel_type(FreeList<FreeChunk>*)                             \
+  declare_toplevel_type(FreeList<FreeChunk>)                              \
   declare_toplevel_type(LinearAllocBlock)                                 \
-  declare_toplevel_type(FreeBlockDictionary)                              \
-            declare_type(BinaryTreeDictionary,        FreeBlockDictionary)
+  declare_toplevel_type(FreeBlockDictionary<FreeChunk>)                   \
+            declare_type(BinaryTreeDictionary<FreeChunk>, FreeBlockDictionary<FreeChunk>)
 
 #define VM_INT_CONSTANTS_CMS(declare_constant)                            \
   declare_constant(Generation::ConcurrentMarkSweep)                       \
--- a/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp	Tue May 15 11:27:24 2012 -0700
@@ -29,102 +29,6 @@
 #include "gc_implementation/g1/g1ErgoVerbose.hpp"
 #include "memory/space.inline.hpp"
 
-CSetChooserCache::CSetChooserCache() {
-  for (int i = 0; i < CacheLength; ++i)
-    _cache[i] = NULL;
-  clear();
-}
-
-void CSetChooserCache::clear() {
-  _occupancy = 0;
-  _first = 0;
-  for (int i = 0; i < CacheLength; ++i) {
-    HeapRegion *hr = _cache[i];
-    if (hr != NULL)
-      hr->set_sort_index(-1);
-    _cache[i] = NULL;
-  }
-}
-
-#ifndef PRODUCT
-bool CSetChooserCache::verify() {
-  guarantee(false, "CSetChooserCache::verify(): don't call this any more");
-
-  int index = _first;
-  HeapRegion *prev = NULL;
-  for (int i = 0; i < _occupancy; ++i) {
-    guarantee(_cache[index] != NULL, "cache entry should not be empty");
-    HeapRegion *hr = _cache[index];
-    guarantee(!hr->is_young(), "should not be young!");
-    if (prev != NULL) {
-      guarantee(prev->gc_efficiency() >= hr->gc_efficiency(),
-                "cache should be correctly ordered");
-    }
-    guarantee(hr->sort_index() == get_sort_index(index),
-              "sort index should be correct");
-    index = trim_index(index + 1);
-    prev = hr;
-  }
-
-  for (int i = 0; i < (CacheLength - _occupancy); ++i) {
-    guarantee(_cache[index] == NULL, "cache entry should be empty");
-    index = trim_index(index + 1);
-  }
-
-  guarantee(index == _first, "we should have reached where we started from");
-  return true;
-}
-#endif // PRODUCT
-
-void CSetChooserCache::insert(HeapRegion *hr) {
-  guarantee(false, "CSetChooserCache::insert(): don't call this any more");
-
-  assert(!is_full(), "cache should not be empty");
-  hr->calc_gc_efficiency();
-
-  int empty_index;
-  if (_occupancy == 0) {
-    empty_index = _first;
-  } else {
-    empty_index = trim_index(_first + _occupancy);
-    assert(_cache[empty_index] == NULL, "last slot should be empty");
-    int last_index = trim_index(empty_index - 1);
-    HeapRegion *last = _cache[last_index];
-    assert(last != NULL,"as the cache is not empty, last should not be empty");
-    while (empty_index != _first &&
-           last->gc_efficiency() < hr->gc_efficiency()) {
-      _cache[empty_index] = last;
-      last->set_sort_index(get_sort_index(empty_index));
-      empty_index = last_index;
-      last_index = trim_index(last_index - 1);
-      last = _cache[last_index];
-    }
-  }
-  _cache[empty_index] = hr;
-  hr->set_sort_index(get_sort_index(empty_index));
-
-  ++_occupancy;
-  assert(verify(), "cache should be consistent");
-}
-
-HeapRegion *CSetChooserCache::remove_first() {
-  guarantee(false, "CSetChooserCache::remove_first(): "
-                   "don't call this any more");
-
-  if (_occupancy > 0) {
-    assert(_cache[_first] != NULL, "cache should have at least one region");
-    HeapRegion *ret = _cache[_first];
-    _cache[_first] = NULL;
-    ret->set_sort_index(-1);
-    --_occupancy;
-    _first = trim_index(_first + 1);
-    assert(verify(), "cache should be consistent");
-    return ret;
-  } else {
-    return NULL;
-  }
-}
-
 // Even though we don't use the GC efficiency in our heuristics as
 // much as we used to, we still order according to GC efficiency. This
 // will cause regions with a lot of live objects and large RSets to
@@ -134,7 +38,7 @@
 // the ones we'll skip are ones with both large RSets and a lot of
 // live objects, not the ones with just a lot of live objects if we
 // ordered according to the amount of reclaimable bytes per region.
-static int orderRegions(HeapRegion* hr1, HeapRegion* hr2) {
+static int order_regions(HeapRegion* hr1, HeapRegion* hr2) {
   if (hr1 == NULL) {
     if (hr2 == NULL) {
       return 0;
@@ -156,8 +60,8 @@
   }
 }
 
-static int orderRegions(HeapRegion** hr1p, HeapRegion** hr2p) {
-  return orderRegions(*hr1p, *hr2p);
+static int order_regions(HeapRegion** hr1p, HeapRegion** hr2p) {
+  return order_regions(*hr1p, *hr2p);
 }
 
 CollectionSetChooser::CollectionSetChooser() :
@@ -175,105 +79,74 @@
   //
   // Note: containing object is allocated on C heap since it is CHeapObj.
   //
-  _markedRegions((ResourceObj::set_allocation_type((address)&_markedRegions,
+  _regions((ResourceObj::set_allocation_type((address) &_regions,
                                              ResourceObj::C_HEAP),
                   100), true /* C_Heap */),
-    _curr_index(0), _length(0),
-    _regionLiveThresholdBytes(0), _remainingReclaimableBytes(0),
-    _first_par_unreserved_idx(0) {
-  _regionLiveThresholdBytes =
+    _curr_index(0), _length(0), _first_par_unreserved_idx(0),
+    _region_live_threshold_bytes(0), _remaining_reclaimable_bytes(0) {
+  _region_live_threshold_bytes =
     HeapRegion::GrainBytes * (size_t) G1OldCSetRegionLiveThresholdPercent / 100;
 }
 
 #ifndef PRODUCT
-bool CollectionSetChooser::verify() {
-  guarantee(_length >= 0, err_msg("_length: %d", _length));
-  guarantee(0 <= _curr_index && _curr_index <= _length,
-            err_msg("_curr_index: %d _length: %d", _curr_index, _length));
-  int index = 0;
+void CollectionSetChooser::verify() {
+  guarantee(_length <= regions_length(),
+         err_msg("_length: %u regions length: %u", _length, regions_length()));
+  guarantee(_curr_index <= _length,
+            err_msg("_curr_index: %u _length: %u", _curr_index, _length));
+  uint index = 0;
   size_t sum_of_reclaimable_bytes = 0;
   while (index < _curr_index) {
-    guarantee(_markedRegions.at(index) == NULL,
+    guarantee(regions_at(index) == NULL,
               "all entries before _curr_index should be NULL");
     index += 1;
   }
   HeapRegion *prev = NULL;
   while (index < _length) {
-    HeapRegion *curr = _markedRegions.at(index++);
-    guarantee(curr != NULL, "Regions in _markedRegions array cannot be NULL");
-    int si = curr->sort_index();
+    HeapRegion *curr = regions_at(index++);
+    guarantee(curr != NULL, "Regions in _regions array cannot be NULL");
     guarantee(!curr->is_young(), "should not be young!");
     guarantee(!curr->isHumongous(), "should not be humongous!");
-    guarantee(si > -1 && si == (index-1), "sort index invariant");
     if (prev != NULL) {
-      guarantee(orderRegions(prev, curr) != 1,
+      guarantee(order_regions(prev, curr) != 1,
                 err_msg("GC eff prev: %1.4f GC eff curr: %1.4f",
                         prev->gc_efficiency(), curr->gc_efficiency()));
     }
     sum_of_reclaimable_bytes += curr->reclaimable_bytes();
     prev = curr;
   }
-  guarantee(sum_of_reclaimable_bytes == _remainingReclaimableBytes,
+  guarantee(sum_of_reclaimable_bytes == _remaining_reclaimable_bytes,
             err_msg("reclaimable bytes inconsistent, "
                     "remaining: "SIZE_FORMAT" sum: "SIZE_FORMAT,
-                    _remainingReclaimableBytes, sum_of_reclaimable_bytes));
-  return true;
+                    _remaining_reclaimable_bytes, sum_of_reclaimable_bytes));
 }
-#endif
-
-void CollectionSetChooser::fillCache() {
-  guarantee(false, "fillCache: don't call this any more");
+#endif // !PRODUCT
 
-  while (!_cache.is_full() && (_curr_index < _length)) {
-    HeapRegion* hr = _markedRegions.at(_curr_index);
-    assert(hr != NULL,
-           err_msg("Unexpected NULL hr in _markedRegions at index %d",
-                   _curr_index));
-    _curr_index += 1;
-    assert(!hr->is_young(), "should not be young!");
-    assert(hr->sort_index() == _curr_index-1, "sort_index invariant");
-    _markedRegions.at_put(hr->sort_index(), NULL);
-    _cache.insert(hr);
-    assert(!_cache.is_empty(), "cache should not be empty");
-  }
-  assert(verify(), "cache should be consistent");
-}
-
-void CollectionSetChooser::sortMarkedHeapRegions() {
+void CollectionSetChooser::sort_regions() {
   // First trim any unused portion of the top in the parallel case.
   if (_first_par_unreserved_idx > 0) {
-    if (G1PrintParCleanupStats) {
-      gclog_or_tty->print("     Truncating _markedRegions from %d to %d.\n",
-                          _markedRegions.length(), _first_par_unreserved_idx);
-    }
-    assert(_first_par_unreserved_idx <= _markedRegions.length(),
+    assert(_first_par_unreserved_idx <= regions_length(),
            "Or we didn't reserved enough length");
-    _markedRegions.trunc_to(_first_par_unreserved_idx);
+    regions_trunc_to(_first_par_unreserved_idx);
   }
-  _markedRegions.sort(orderRegions);
-  assert(_length <= _markedRegions.length(), "Requirement");
-  assert(_length == 0 || _markedRegions.at(_length - 1) != NULL,
-         "Testing _length");
-  assert(_length == _markedRegions.length() ||
-                        _markedRegions.at(_length) == NULL, "Testing _length");
-  if (G1PrintParCleanupStats) {
-    gclog_or_tty->print_cr("     Sorted %d marked regions.", _length);
+  _regions.sort(order_regions);
+  assert(_length <= regions_length(), "Requirement");
+#ifdef ASSERT
+  for (uint i = 0; i < _length; i++) {
+    assert(regions_at(i) != NULL, "Should be true by sorting!");
   }
-  for (int i = 0; i < _length; i++) {
-    assert(_markedRegions.at(i) != NULL, "Should be true by sorting!");
-    _markedRegions.at(i)->set_sort_index(i);
-  }
+#endif // ASSERT
   if (G1PrintRegionLivenessInfo) {
     G1PrintRegionLivenessInfoClosure cl(gclog_or_tty, "Post-Sorting");
-    for (int i = 0; i < _length; ++i) {
-      HeapRegion* r = _markedRegions.at(i);
+    for (uint i = 0; i < _length; ++i) {
+      HeapRegion* r = regions_at(i);
       cl.doHeapRegion(r);
     }
   }
-  assert(verify(), "CSet chooser verification");
+  verify();
 }
 
-size_t CollectionSetChooser::calcMinOldCSetLength() {
+uint CollectionSetChooser::calc_min_old_cset_length() {
   // The min old CSet region bound is based on the maximum desired
   // number of mixed GCs after a cycle. I.e., even if some old regions
   // look expensive, we should add them to the CSet anyway to make
@@ -285,16 +158,16 @@
   // that the result is the same during all mixed GCs that follow a cycle.
 
   const size_t region_num = (size_t) _length;
-  const size_t gc_num = (size_t) G1MaxMixedGCNum;
+  const size_t gc_num = (size_t) G1MixedGCCountTarget;
   size_t result = region_num / gc_num;
   // emulate ceiling
   if (result * gc_num < region_num) {
     result += 1;
   }
-  return result;
+  return (uint) result;
 }
 
-size_t CollectionSetChooser::calcMaxOldCSetLength() {
+uint CollectionSetChooser::calc_max_old_cset_length() {
   // The max old CSet region bound is based on the threshold expressed
   // as a percentage of the heap size. I.e., it should bound the
   // number of old regions added to the CSet irrespective of how many
@@ -308,23 +181,23 @@
   if (100 * result < region_num * perc) {
     result += 1;
   }
-  return result;
+  return (uint) result;
 }
 
-void CollectionSetChooser::addMarkedHeapRegion(HeapRegion* hr) {
+void CollectionSetChooser::add_region(HeapRegion* hr) {
   assert(!hr->isHumongous(),
          "Humongous regions shouldn't be added to the collection set");
   assert(!hr->is_young(), "should not be young!");
-  _markedRegions.append(hr);
+  _regions.append(hr);
   _length++;
-  _remainingReclaimableBytes += hr->reclaimable_bytes();
+  _remaining_reclaimable_bytes += hr->reclaimable_bytes();
   hr->calc_gc_efficiency();
 }
 
-void CollectionSetChooser::prepareForAddMarkedHeapRegionsPar(size_t n_regions,
-                                                             size_t chunkSize) {
+void CollectionSetChooser::prepare_for_par_region_addition(uint n_regions,
+                                                           uint chunk_size) {
   _first_par_unreserved_idx = 0;
-  int n_threads = ParallelGCThreads;
+  uint n_threads = (uint) ParallelGCThreads;
   if (UseDynamicNumberOfGCThreads) {
     assert(G1CollectedHeap::heap()->workers()->active_workers() > 0,
       "Should have been set earlier");
@@ -335,57 +208,46 @@
     n_threads = MAX2(G1CollectedHeap::heap()->workers()->active_workers(),
                      1U);
   }
-  size_t max_waste = n_threads * chunkSize;
-  // it should be aligned with respect to chunkSize
-  size_t aligned_n_regions =
-                     (n_regions + (chunkSize - 1)) / chunkSize * chunkSize;
-  assert( aligned_n_regions % chunkSize == 0, "should be aligned" );
-  _markedRegions.at_put_grow((int)(aligned_n_regions + max_waste - 1), NULL);
+  uint max_waste = n_threads * chunk_size;
+  // it should be aligned with respect to chunk_size
+  uint aligned_n_regions = (n_regions + chunk_size - 1) / chunk_size * chunk_size;
+  assert(aligned_n_regions % chunk_size == 0, "should be aligned");
+  regions_at_put_grow(aligned_n_regions + max_waste - 1, NULL);
 }
 
-jint CollectionSetChooser::getParMarkedHeapRegionChunk(jint n_regions) {
-  // Don't do this assert because this can be called at a point
-  // where the loop up stream will not execute again but might
-  // try to claim more chunks (loop test has not been done yet).
-  // assert(_markedRegions.length() > _first_par_unreserved_idx,
-  //  "Striding beyond the marked regions");
-  jint res = Atomic::add(n_regions, &_first_par_unreserved_idx);
-  assert(_markedRegions.length() > res + n_regions - 1,
+uint CollectionSetChooser::claim_array_chunk(uint chunk_size) {
+  uint res = (uint) Atomic::add((jint) chunk_size,
+                                (volatile jint*) &_first_par_unreserved_idx);
+  assert(regions_length() > res + chunk_size - 1,
          "Should already have been expanded");
-  return res - n_regions;
+  return res - chunk_size;
 }
 
-void CollectionSetChooser::setMarkedHeapRegion(jint index, HeapRegion* hr) {
-  assert(_markedRegions.at(index) == NULL, "precondition");
+void CollectionSetChooser::set_region(uint index, HeapRegion* hr) {
+  assert(regions_at(index) == NULL, "precondition");
   assert(!hr->is_young(), "should not be young!");
-  _markedRegions.at_put(index, hr);
+  regions_at_put(index, hr);
   hr->calc_gc_efficiency();
 }
 
-void CollectionSetChooser::updateTotals(jint region_num,
-                                        size_t reclaimable_bytes) {
+void CollectionSetChooser::update_totals(uint region_num,
+                                         size_t reclaimable_bytes) {
   // Only take the lock if we actually need to update the totals.
   if (region_num > 0) {
     assert(reclaimable_bytes > 0, "invariant");
     // We could have just used atomics instead of taking the
     // lock. However, we currently don't have an atomic add for size_t.
     MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
-    _length += (int) region_num;
-    _remainingReclaimableBytes += reclaimable_bytes;
+    _length += region_num;
+    _remaining_reclaimable_bytes += reclaimable_bytes;
   } else {
     assert(reclaimable_bytes == 0, "invariant");
   }
 }
 
-void CollectionSetChooser::clearMarkedHeapRegions() {
-  for (int i = 0; i < _markedRegions.length(); i++) {
-    HeapRegion* r = _markedRegions.at(i);
-    if (r != NULL) {
-      r->set_sort_index(-1);
-    }
-  }
-  _markedRegions.clear();
+void CollectionSetChooser::clear() {
+  _regions.clear();
   _curr_index = 0;
   _length = 0;
-  _remainingReclaimableBytes = 0;
+  _remaining_reclaimable_bytes = 0;
 };
--- a/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp	Tue May 15 11:27:24 2012 -0700
@@ -28,77 +28,42 @@
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "utilities/growableArray.hpp"
 
-class CSetChooserCache VALUE_OBJ_CLASS_SPEC {
-private:
-  enum {
-    CacheLength = 16
-  } PrivateConstants;
-
-  HeapRegion*  _cache[CacheLength];
-  int          _occupancy; // number of regions in cache
-  int          _first;     // (index of) "first" region in the cache
-
-  // adding CacheLength to deal with negative values
-  inline int trim_index(int index) {
-    return (index + CacheLength) % CacheLength;
-  }
-
-  inline int get_sort_index(int index) {
-    return -index-2;
-  }
-  inline int get_index(int sort_index) {
-    return -sort_index-2;
-  }
-
-public:
-  CSetChooserCache(void);
-
-  inline int occupancy(void) { return _occupancy; }
-  inline bool is_full()      { return _occupancy == CacheLength; }
-  inline bool is_empty()     { return _occupancy == 0; }
-
-  void clear(void);
-  void insert(HeapRegion *hr);
-  HeapRegion *remove_first(void);
-  inline HeapRegion *get_first(void) {
-    return _cache[_first];
-  }
-
-#ifndef PRODUCT
-  bool verify (void);
-  bool region_in_cache(HeapRegion *hr) {
-    int sort_index = hr->sort_index();
-    if (sort_index < -1) {
-      int index = get_index(sort_index);
-      guarantee(index < CacheLength, "should be within bounds");
-      return _cache[index] == hr;
-    } else
-      return 0;
-  }
-#endif // PRODUCT
-};
-
 class CollectionSetChooser: public CHeapObj {
 
-  GrowableArray<HeapRegion*> _markedRegions;
+  GrowableArray<HeapRegion*> _regions;
+
+  // Unfortunately, GrowableArray uses ints for length and indexes. To
+  // avoid excessive casting in the rest of the class the following
+  // wrapper methods are provided that use uints.
+
+  uint regions_length()          { return (uint) _regions.length(); }
+  HeapRegion* regions_at(uint i) { return _regions.at((int) i);     }
+  void regions_at_put(uint i, HeapRegion* hr) {
+    _regions.at_put((int) i, hr);
+  }
+  void regions_at_put_grow(uint i, HeapRegion* hr) {
+    _regions.at_put_grow((int) i, hr);
+  }
+  void regions_trunc_to(uint i)  { _regions.trunc_to((uint) i); }
 
   // The index of the next candidate old region to be considered for
   // addition to the CSet.
-  int _curr_index;
+  uint _curr_index;
 
   // The number of candidate old regions added to the CSet chooser.
-  int _length;
+  uint _length;
 
-  CSetChooserCache _cache;
-  jint _first_par_unreserved_idx;
+  // Keeps track of the start of the next array chunk to be claimed by
+  // parallel GC workers.
+  uint _first_par_unreserved_idx;
 
   // If a region has more live bytes than this threshold, it will not
   // be added to the CSet chooser and will not be a candidate for
   // collection.
-  size_t _regionLiveThresholdBytes;
+  size_t _region_live_threshold_bytes;
 
   // The sum of reclaimable bytes over all the regions in the CSet chooser.
-  size_t _remainingReclaimableBytes;
+  size_t _remaining_reclaimable_bytes;
 
 public:
 
@@ -107,9 +72,9 @@
   HeapRegion* peek() {
     HeapRegion* res = NULL;
     if (_curr_index < _length) {
-      res = _markedRegions.at(_curr_index);
+      res = regions_at(_curr_index);
       assert(res != NULL,
-             err_msg("Unexpected NULL hr in _markedRegions at index %d",
+             err_msg("Unexpected NULL hr in _regions at index %u",
                      _curr_index));
     }
     return res;
@@ -121,90 +86,71 @@
   void remove_and_move_to_next(HeapRegion* hr) {
     assert(hr != NULL, "pre-condition");
     assert(_curr_index < _length, "pre-condition");
-    assert(_markedRegions.at(_curr_index) == hr, "pre-condition");
-    hr->set_sort_index(-1);
-    _markedRegions.at_put(_curr_index, NULL);
-    assert(hr->reclaimable_bytes() <= _remainingReclaimableBytes,
+    assert(regions_at(_curr_index) == hr, "pre-condition");
+    regions_at_put(_curr_index, NULL);
+    assert(hr->reclaimable_bytes() <= _remaining_reclaimable_bytes,
            err_msg("remaining reclaimable bytes inconsistent "
                    "from region: "SIZE_FORMAT" remaining: "SIZE_FORMAT,
-                   hr->reclaimable_bytes(), _remainingReclaimableBytes));
-    _remainingReclaimableBytes -= hr->reclaimable_bytes();
+                   hr->reclaimable_bytes(), _remaining_reclaimable_bytes));
+    _remaining_reclaimable_bytes -= hr->reclaimable_bytes();
     _curr_index += 1;
   }
 
   CollectionSetChooser();
 
-  void sortMarkedHeapRegions();
-  void fillCache();
+  void sort_regions();
 
   // Determine whether to add the given region to the CSet chooser or
   // not. Currently, we skip humongous regions (we never add them to
   // the CSet, we only reclaim them during cleanup) and regions whose
   // live bytes are over the threshold.
-  bool shouldAdd(HeapRegion* hr) {
+  bool should_add(HeapRegion* hr) {
     assert(hr->is_marked(), "pre-condition");
     assert(!hr->is_young(), "should never consider young regions");
     return !hr->isHumongous() &&
-            hr->live_bytes() < _regionLiveThresholdBytes;
+            hr->live_bytes() < _region_live_threshold_bytes;
   }
 
   // Calculate the minimum number of old regions we'll add to the CSet
   // during a mixed GC.
-  size_t calcMinOldCSetLength();
+  uint calc_min_old_cset_length();
 
   // Calculate the maximum number of old regions we'll add to the CSet
   // during a mixed GC.
-  size_t calcMaxOldCSetLength();
+  uint calc_max_old_cset_length();
 
   // Serial version.
-  void addMarkedHeapRegion(HeapRegion *hr);
+  void add_region(HeapRegion *hr);
 
-  // Must be called before calls to getParMarkedHeapRegionChunk.
-  // "n_regions" is the number of regions, "chunkSize" the chunk size.
-  void prepareForAddMarkedHeapRegionsPar(size_t n_regions, size_t chunkSize);
-  // Returns the first index in a contiguous chunk of "n_regions" indexes
+  // Must be called before calls to claim_array_chunk().
+  // n_regions is the number of regions, chunk_size the chunk size.
+  void prepare_for_par_region_addition(uint n_regions, uint chunk_size);
+  // Returns the first index in a contiguous chunk of chunk_size indexes
   // that the calling thread has reserved.  These must be set by the
-  // calling thread using "setMarkedHeapRegion" (to NULL if necessary).
-  jint getParMarkedHeapRegionChunk(jint n_regions);
+  // calling thread using set_region() (to NULL if necessary).
+  uint claim_array_chunk(uint chunk_size);
   // Set the marked array entry at index to hr.  Careful to claim the index
   // first if in parallel.
-  void setMarkedHeapRegion(jint index, HeapRegion* hr);
+  void set_region(uint index, HeapRegion* hr);
   // Atomically increment the number of added regions by region_num
   // and the amount of reclaimable bytes by reclaimable_bytes.
-  void updateTotals(jint region_num, size_t reclaimable_bytes);
+  void update_totals(uint region_num, size_t reclaimable_bytes);
 
-  void clearMarkedHeapRegions();
+  void clear();
 
   // Return the number of candidate regions that remain to be collected.
-  size_t remainingRegions() { return _length - _curr_index; }
+  uint remaining_regions() { return _length - _curr_index; }
 
   // Determine whether the CSet chooser has more candidate regions or not.
-  bool isEmpty() { return remainingRegions() == 0; }
+  bool is_empty() { return remaining_regions() == 0; }
 
   // Return the reclaimable bytes that remain to be collected on
   // all the candidate regions in the CSet chooser.
-  size_t remainingReclaimableBytes () { return _remainingReclaimableBytes; }
+  size_t remaining_reclaimable_bytes() { return _remaining_reclaimable_bytes; }
 
-  // Returns true if the used portion of "_markedRegions" is properly
+  // Returns true if the used portion of "_regions" is properly
   // sorted, otherwise asserts false.
-#ifndef PRODUCT
-  bool verify(void);
-  bool regionProperlyOrdered(HeapRegion* r) {
-    int si = r->sort_index();
-    if (si > -1) {
-      guarantee(_curr_index <= si && si < _length,
-                err_msg("curr: %d sort index: %d: length: %d",
-                        _curr_index, si, _length));
-      guarantee(_markedRegions.at(si) == r,
-                err_msg("sort index: %d at: "PTR_FORMAT" r: "PTR_FORMAT,
-                        si, _markedRegions.at(si), r));
-    } else {
-      guarantee(si == -1, err_msg("sort index: %d", si));
-    }
-    return true;
-  }
-#endif
-
+  void verify() PRODUCT_RETURN;
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Tue May 15 11:27:24 2012 -0700
@@ -29,6 +29,7 @@
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
 #include "gc_implementation/g1/g1ErgoVerbose.hpp"
+#include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
 #include "gc_implementation/g1/g1RemSet.hpp"
 #include "gc_implementation/g1/heapRegion.inline.hpp"
@@ -103,16 +104,6 @@
   return (int) (diff >> _shifter);
 }
 
-void CMBitMapRO::mostly_disjoint_range_union(BitMap*   from_bitmap,
-                                             size_t    from_start_index,
-                                             HeapWord* to_start_word,
-                                             size_t    word_num) {
-  _bm.mostly_disjoint_range_union(from_bitmap,
-                                  from_start_index,
-                                  heapWordToOffset(to_start_word),
-                                  word_num);
-}
-
 #ifndef PRODUCT
 bool CMBitMapRO::covers(ReservedSpace rs) const {
   // assert(_bm.map() == _virtual_space.low(), "map inconsistency");
@@ -271,140 +262,6 @@
   }
 }
 
-CMRegionStack::CMRegionStack() : _base(NULL) {}
-
-void CMRegionStack::allocate(size_t size) {
-  _base = NEW_C_HEAP_ARRAY(MemRegion, size);
-  if (_base == NULL) {
-    vm_exit_during_initialization("Failed to allocate CM region mark stack");
-  }
-  _index = 0;
-  _capacity = (jint) size;
-}
-
-CMRegionStack::~CMRegionStack() {
-  if (_base != NULL) {
-    FREE_C_HEAP_ARRAY(oop, _base);
-  }
-}
-
-void CMRegionStack::push_lock_free(MemRegion mr) {
-  guarantee(false, "push_lock_free(): don't call this any more");
-
-  assert(mr.word_size() > 0, "Precondition");
-  while (true) {
-    jint index = _index;
-
-    if (index >= _capacity) {
-      _overflow = true;
-      return;
-    }
-    // Otherwise...
-    jint next_index = index+1;
-    jint res = Atomic::cmpxchg(next_index, &_index, index);
-    if (res == index) {
-      _base[index] = mr;
-      return;
-    }
-    // Otherwise, we need to try again.
-  }
-}
-
-// Lock-free pop of the region stack. Called during the concurrent
-// marking / remark phases. Should only be called in tandem with
-// other lock-free pops.
-MemRegion CMRegionStack::pop_lock_free() {
-  guarantee(false, "pop_lock_free(): don't call this any more");
-
-  while (true) {
-    jint index = _index;
-
-    if (index == 0) {
-      return MemRegion();
-    }
-    // Otherwise...
-    jint next_index = index-1;
-    jint res = Atomic::cmpxchg(next_index, &_index, index);
-    if (res == index) {
-      MemRegion mr = _base[next_index];
-      if (mr.start() != NULL) {
-        assert(mr.end() != NULL, "invariant");
-        assert(mr.word_size() > 0, "invariant");
-        return mr;
-      } else {
-        // that entry was invalidated... let's skip it
-        assert(mr.end() == NULL, "invariant");
-      }
-    }
-    // Otherwise, we need to try again.
-  }
-}
-
-#if 0
-// The routines that manipulate the region stack with a lock are
-// not currently used. They should be retained, however, as a
-// diagnostic aid.
-
-void CMRegionStack::push_with_lock(MemRegion mr) {
-  assert(mr.word_size() > 0, "Precondition");
-  MutexLockerEx x(CMRegionStack_lock, Mutex::_no_safepoint_check_flag);
-
-  if (isFull()) {
-    _overflow = true;
-    return;
-  }
-
-  _base[_index] = mr;
-  _index += 1;
-}
-
-MemRegion CMRegionStack::pop_with_lock() {
-  MutexLockerEx x(CMRegionStack_lock, Mutex::_no_safepoint_check_flag);
-
-  while (true) {
-    if (_index == 0) {
-      return MemRegion();
-    }
-    _index -= 1;
-
-    MemRegion mr = _base[_index];
-    if (mr.start() != NULL) {
-      assert(mr.end() != NULL, "invariant");
-      assert(mr.word_size() > 0, "invariant");
-      return mr;
-    } else {
-      // that entry was invalidated... let's skip it
-      assert(mr.end() == NULL, "invariant");
-    }
-  }
-}
-#endif
-
-bool CMRegionStack::invalidate_entries_into_cset() {
-  guarantee(false, "invalidate_entries_into_cset(): don't call this any more");
-
-  bool result = false;
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  for (int i = 0; i < _oops_do_bound; ++i) {
-    MemRegion mr = _base[i];
-    if (mr.start() != NULL) {
-      assert(mr.end() != NULL, "invariant");
-      assert(mr.word_size() > 0, "invariant");
-      HeapRegion* hr = g1h->heap_region_containing(mr.start());
-      assert(hr != NULL, "invariant");
-      if (hr->in_collection_set()) {
-        // The region points into the collection set
-        _base[i] = MemRegion();
-        result = true;
-      }
-    } else {
-      // that entry was invalidated... let's skip it
-      assert(mr.end() == NULL, "invariant");
-    }
-  }
-  return result;
-}
-
 template<class OopClosureClass>
 bool CMMarkStack::drain(OopClosureClass* cl, CMBitMap* bm, bool yield_after) {
   assert(!_drain_in_progress || !_drain_in_progress_yields || yield_after
@@ -546,8 +403,7 @@
   return MAX2((n_par_threads + 2) / 4, 1U);
 }
 
-ConcurrentMark::ConcurrentMark(ReservedSpace rs,
-                               int max_regions) :
+ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) :
   _markBitMap1(rs, MinObjAlignment - 1),
   _markBitMap2(rs, MinObjAlignment - 1),
 
@@ -558,17 +414,15 @@
   _cleanup_sleep_factor(0.0),
   _cleanup_task_overhead(1.0),
   _cleanup_list("Cleanup List"),
-  _region_bm(max_regions, false /* in_resource_area*/),
+  _region_bm((BitMap::idx_t) max_regions, false /* in_resource_area*/),
   _card_bm((rs.size() + CardTableModRefBS::card_size - 1) >>
            CardTableModRefBS::card_shift,
            false /* in_resource_area*/),
 
   _prevMarkBitMap(&_markBitMap1),
   _nextMarkBitMap(&_markBitMap2),
-  _at_least_one_mark_complete(false),
 
   _markStack(this),
-  _regionStack(),
   // _finger set in set_non_marking_state
 
   _max_task_num(MAX2((uint)ParallelGCThreads, 1U)),
@@ -582,7 +436,6 @@
   _has_aborted(false),
   _restart_for_overflow(false),
   _concurrent_marking_in_progress(false),
-  _should_gray_objects(false),
 
   // _verbose_level set below
 
@@ -611,7 +464,6 @@
   }
 
   _markStack.allocate(MarkStackSize);
-  _regionStack.allocate(G1MarkRegionStackSize);
 
   // Create & start a ConcurrentMark thread.
   _cmThread = new ConcurrentMarkThread(this);
@@ -644,7 +496,7 @@
     _task_queues->register_queue(i, task_queue);
 
     _count_card_bitmaps[i] = BitMap(card_bm_size, false);
-    _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, max_regions);
+    _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, (size_t) max_regions);
 
     _tasks[i] = new CMTask(i, this,
                            _count_marked_bytes[i],
@@ -744,15 +596,7 @@
 
 void ConcurrentMark::update_g1_committed(bool force) {
   // If concurrent marking is not in progress, then we do not need to
-  // update _heap_end. This has a subtle and important
-  // side-effect. Imagine that two evacuation pauses happen between
-  // marking completion and remark. The first one can grow the
-  // heap (hence now the finger is below the heap end). Then, the
-  // second one could unnecessarily push regions on the region
-  // stack. This causes the invariant that the region stack is empty
-  // at the beginning of remark to be false. By ensuring that we do
-  // not observe heap expansions after marking is complete, then we do
-  // not have this problem.
+  // update _heap_end.
   if (!concurrent_marking_in_progress() && !force) return;
 
   MemRegion committed = _g1h->g1_committed();
@@ -1002,7 +846,7 @@
     clear_marking_state(concurrent() /* clear_overflow */);
     force_overflow()->update();
 
-    if (PrintGC) {
+    if (G1Log::fine()) {
       gclog_or_tty->date_stamp(PrintGCDateStamps);
       gclog_or_tty->stamp(PrintGCTimeStamps);
       gclog_or_tty->print_cr("[GC concurrent-mark-reset-for-overflow]");
@@ -1058,86 +902,6 @@
 }
 #endif // !PRODUCT
 
-void ConcurrentMark::grayRegionIfNecessary(MemRegion mr) {
-  guarantee(false, "grayRegionIfNecessary(): don't call this any more");
-
-  // The objects on the region have already been marked "in bulk" by
-  // the caller. We only need to decide whether to push the region on
-  // the region stack or not.
-
-  if (!concurrent_marking_in_progress() || !_should_gray_objects) {
-    // We're done with marking and waiting for remark. We do not need to
-    // push anything else on the region stack.
-    return;
-  }
-
-  HeapWord* finger = _finger;
-
-  if (verbose_low()) {
-    gclog_or_tty->print_cr("[global] attempting to push "
-                           "region ["PTR_FORMAT", "PTR_FORMAT"), finger is at "
-                           PTR_FORMAT, mr.start(), mr.end(), finger);
-  }
-
-  if (mr.start() < finger) {
-    // The finger is always heap region aligned and it is not possible
-    // for mr to span heap regions.
-    assert(mr.end() <= finger, "invariant");
-
-    // Separated the asserts so that we know which one fires.
-    assert(mr.start() <= mr.end(),
-           "region boundaries should fall within the committed space");
-    assert(_heap_start <= mr.start(),
-           "region boundaries should fall within the committed space");
-    assert(mr.end() <= _heap_end,
-           "region boundaries should fall within the committed space");
-    if (verbose_low()) {
-      gclog_or_tty->print_cr("[global] region ["PTR_FORMAT", "PTR_FORMAT") "
-                             "below the finger, pushing it",
-                             mr.start(), mr.end());
-    }
-
-    if (!region_stack_push_lock_free(mr)) {
-      if (verbose_low()) {
-        gclog_or_tty->print_cr("[global] region stack has overflown.");
-      }
-    }
-  }
-}
-
-void ConcurrentMark::markAndGrayObjectIfNecessary(oop p) {
-  guarantee(false, "markAndGrayObjectIfNecessary(): don't call this any more");
-
-  // The object is not marked by the caller. We need to at least mark
-  // it and maybe push in on the stack.
-
-  HeapWord* addr = (HeapWord*)p;
-  if (!_nextMarkBitMap->isMarked(addr)) {
-    // We definitely need to mark it, irrespective whether we bail out
-    // because we're done with marking.
-    if (_nextMarkBitMap->parMark(addr)) {
-      if (!concurrent_marking_in_progress() || !_should_gray_objects) {
-        // If we're done with concurrent marking and we're waiting for
-        // remark, then we're not pushing anything on the stack.
-        return;
-      }
-
-      // No OrderAccess:store_load() is needed. It is implicit in the
-      // CAS done in parMark(addr) above
-      HeapWord* finger = _finger;
-
-      if (addr < finger) {
-        if (!mark_stack_push(oop(addr))) {
-          if (verbose_low()) {
-            gclog_or_tty->print_cr("[global] global stack overflow "
-                                   "during parMark");
-          }
-        }
-      }
-    }
-  }
-}
-
 class CMConcurrentMarkingTask: public AbstractGangTask {
 private:
   ConcurrentMark*       _cm;
@@ -1355,8 +1119,7 @@
     HandleMark hm;  // handle scope
     gclog_or_tty->print(" VerifyDuringGC:(before)");
     Universe::heap()->prepare_for_verify();
-    Universe::verify(/* allow dirty */ true,
-                     /* silent      */ false,
+    Universe::verify(/* silent      */ false,
                      /* option      */ VerifyOption_G1UsePrevMarking);
   }
 
@@ -1395,8 +1158,7 @@
       HandleMark hm;  // handle scope
       gclog_or_tty->print(" VerifyDuringGC:(after)");
       Universe::heap()->prepare_for_verify();
-      Universe::verify(/* allow dirty */ true,
-                       /* silent      */ false,
+      Universe::verify(/* silent      */ false,
                        /* option      */ VerifyOption_G1UseNextMarking);
     }
     assert(!restart_for_overflow(), "sanity");
@@ -1421,42 +1183,31 @@
   g1p->record_concurrent_mark_remark_end();
 }
 
-// Used to calculate the # live objects per region
-// for verification purposes
-class CalcLiveObjectsClosure: public HeapRegionClosure {
-
-  CMBitMapRO* _bm;
+// Base class of the closures that finalize and verify the
+// liveness counting data.
+class CMCountDataClosureBase: public HeapRegionClosure {
+protected:
   ConcurrentMark* _cm;
   BitMap* _region_bm;
   BitMap* _card_bm;
 
-  // Debugging
-  size_t _tot_words_done;
-  size_t _tot_live;
-  size_t _tot_used;
-
-  size_t _region_marked_bytes;
-
-  intptr_t _bottom_card_num;
-
-  void mark_card_num_range(intptr_t start_card_num, intptr_t last_card_num) {
-    assert(start_card_num <= last_card_num, "sanity");
-    BitMap::idx_t start_idx = start_card_num - _bottom_card_num;
-    BitMap::idx_t last_idx = last_card_num - _bottom_card_num;
-
-    for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) {
-      _card_bm->par_at_put(i, 1);
+  void set_card_bitmap_range(BitMap::idx_t start_idx, BitMap::idx_t last_idx) {
+    assert(start_idx <= last_idx, "sanity");
+
+    // Set the inclusive bit range [start_idx, last_idx].
+    // For small ranges (up to 8 cards) use a simple loop; otherwise
+    // use par_at_put_range.
+    if ((last_idx - start_idx) < 8) {
+      for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) {
+        _card_bm->par_set_bit(i);
+      }
+    } else {
+      assert(last_idx < _card_bm->size(), "sanity");
+      // Note BitMap::par_at_put_range() is exclusive.
+      _card_bm->par_at_put_range(start_idx, last_idx+1, true);
     }
   }
 
-public:
-  CalcLiveObjectsClosure(CMBitMapRO *bm, ConcurrentMark *cm,
-                         BitMap* region_bm, BitMap* card_bm) :
-    _bm(bm), _cm(cm), _region_bm(region_bm), _card_bm(card_bm),
-    _region_marked_bytes(0), _tot_words_done(0),
-    _tot_live(0), _tot_used(0),
-    _bottom_card_num(cm->heap_bottom_card_num()) { }
-
   // It takes a region that's not empty (i.e., it has at least one
   // live object in it and sets its corresponding bit on the region
   // bitmap to 1. If the region is "starts humongous" it will also set
@@ -1465,21 +1216,38 @@
   void set_bit_for_region(HeapRegion* hr) {
     assert(!hr->continuesHumongous(), "should have filtered those out");
 
-    size_t index = hr->hrs_index();
+    BitMap::idx_t index = (BitMap::idx_t) hr->hrs_index();
     if (!hr->startsHumongous()) {
       // Normal (non-humongous) case: just set the bit.
-      _region_bm->par_at_put((BitMap::idx_t) index, true);
+      _region_bm->par_at_put(index, true);
     } else {
       // Starts humongous case: calculate how many regions are part of
       // this humongous region and then set the bit range.
       G1CollectedHeap* g1h = G1CollectedHeap::heap();
       HeapRegion *last_hr = g1h->heap_region_containing_raw(hr->end() - 1);
-      size_t end_index = last_hr->hrs_index() + 1;
-      _region_bm->par_at_put_range((BitMap::idx_t) index,
-                                   (BitMap::idx_t) end_index, true);
+      BitMap::idx_t end_index = (BitMap::idx_t) last_hr->hrs_index() + 1;
+      _region_bm->par_at_put_range(index, end_index, true);
     }
   }
 
+public:
+  CMCountDataClosureBase(ConcurrentMark *cm,
+                         BitMap* region_bm, BitMap* card_bm):
+    _cm(cm), _region_bm(region_bm), _card_bm(card_bm) { }
+};
+
+// Closure that calculates the # live objects per region. Used
+// for verification purposes during the cleanup pause.
+class CalcLiveObjectsClosure: public CMCountDataClosureBase {
+  CMBitMapRO* _bm;
+  size_t _region_marked_bytes;
+
+public:
+  CalcLiveObjectsClosure(CMBitMapRO *bm, ConcurrentMark *cm,
+                         BitMap* region_bm, BitMap* card_bm) :
+    CMCountDataClosureBase(cm, region_bm, card_bm),
+    _bm(bm), _region_marked_bytes(0) { }
+
   bool doHeapRegion(HeapRegion* hr) {
 
     if (hr->continuesHumongous()) {
@@ -1501,73 +1269,36 @@
                    "start: "PTR_FORMAT", nextTop: "PTR_FORMAT", end: "PTR_FORMAT,
                    start, nextTop, hr->end()));
 
-    // Record the number of word's we'll examine.
-    size_t words_done = (nextTop - start);
-
     // Find the first marked object at or after "start".
     start = _bm->getNextMarkedWordAddress(start, nextTop);
 
     size_t marked_bytes = 0;
 
-    // Below, the term "card num" means the result of shifting an address
-    // by the card shift -- address 0 corresponds to card number 0.  One
-    // must subtract the card num of the bottom of the heap to obtain a
-    // card table index.
-
-    // The first card num of the sequence of live cards currently being
-    // constructed.  -1 ==> no sequence.
-    intptr_t start_card_num = -1;
-
-    // The last card num of the sequence of live cards currently being
-    // constructed.  -1 ==> no sequence.
-    intptr_t last_card_num = -1;
-
     while (start < nextTop) {
       oop obj = oop(start);
       int obj_sz = obj->size();
-
-      // The card num of the start of the current object.
-      intptr_t obj_card_num =
-        intptr_t(uintptr_t(start) >> CardTableModRefBS::card_shift);
       HeapWord* obj_last = start + obj_sz - 1;
-      intptr_t obj_last_card_num =
-        intptr_t(uintptr_t(obj_last) >> CardTableModRefBS::card_shift);
-
-      if (obj_card_num != last_card_num) {
-        if (start_card_num == -1) {
-          assert(last_card_num == -1, "Both or neither.");
-          start_card_num = obj_card_num;
-        } else {
-          assert(last_card_num != -1, "Both or neither.");
-          assert(obj_card_num >= last_card_num, "Inv");
-          if ((obj_card_num - last_card_num) > 1) {
-            // Mark the last run, and start a new one.
-            mark_card_num_range(start_card_num, last_card_num);
-            start_card_num = obj_card_num;
-          }
-        }
-      }
-      // In any case, we set the last card num.
-      last_card_num = obj_last_card_num;
-
+
+      BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start);
+      BitMap::idx_t last_idx = _cm->card_bitmap_index_for(obj_last);
+
+      // Set the bits in the card BM for this object (inclusive).
+      set_card_bitmap_range(start_idx, last_idx);
+
+      // Add the size of this object to the number of marked bytes.
       marked_bytes += (size_t)obj_sz * HeapWordSize;
 
       // Find the next marked object after this one.
-      start = _bm->getNextMarkedWordAddress(start + 1, nextTop);
-    }
-
-    // Handle the last range, if any.
-    if (start_card_num != -1) {
-      mark_card_num_range(start_card_num, last_card_num);
+      start = _bm->getNextMarkedWordAddress(obj_last + 1, nextTop);
     }
 
     // Mark the allocated-since-marking portion...
     HeapWord* top = hr->top();
     if (nextTop < top) {
-      start_card_num = intptr_t(uintptr_t(nextTop) >> CardTableModRefBS::card_shift);
-      last_card_num = intptr_t(uintptr_t(top) >> CardTableModRefBS::card_shift);
-
-      mark_card_num_range(start_card_num, last_card_num);
+      BitMap::idx_t start_idx = _cm->card_bitmap_index_for(nextTop);
+      BitMap::idx_t last_idx = _cm->card_bitmap_index_for(top - 1);
+
+      set_card_bitmap_range(start_idx, last_idx);
 
       // This definitely means the region has live objects.
       set_bit_for_region(hr);
@@ -1582,19 +1313,10 @@
     // it can be queried by a calling verificiation routine
     _region_marked_bytes = marked_bytes;
 
-    _tot_live += hr->next_live_bytes();
-    _tot_used += hr->used();
-    _tot_words_done = words_done;
-
     return false;
   }
 
   size_t region_marked_bytes() const { return _region_marked_bytes; }
-
-  // Debugging
-  size_t tot_words_done() const      { return _tot_words_done; }
-  size_t tot_live() const            { return _tot_live; }
-  size_t tot_used() const            { return _tot_used; }
 };
 
 // Heap region closure used for verifying the counting data
@@ -1652,17 +1374,6 @@
     MutexLockerEx x((_verbose ? ParGCRareEvent_lock : NULL),
                     Mutex::_no_safepoint_check_flag);
 
-    // Verify that _top_at_conc_count == ntams
-    if (hr->top_at_conc_mark_count() != hr->next_top_at_mark_start()) {
-      if (_verbose) {
-        gclog_or_tty->print_cr("Region " SIZE_FORMAT ": top at conc count incorrect: "
-                               "expected " PTR_FORMAT ", actual: " PTR_FORMAT,
-                               hr->hrs_index(), hr->next_top_at_mark_start(),
-                               hr->top_at_conc_mark_count());
-      }
-      failures += 1;
-    }
-
     // Verify the marked bytes for this region.
     size_t exp_marked_bytes = _calc_cl.region_marked_bytes();
     size_t act_marked_bytes = hr->next_marked_bytes();
@@ -1671,7 +1382,7 @@
     // we have missed accounting some objects during the actual marking.
     if (exp_marked_bytes > act_marked_bytes) {
       if (_verbose) {
-        gclog_or_tty->print_cr("Region " SIZE_FORMAT ": marked bytes mismatch: "
+        gclog_or_tty->print_cr("Region %u: marked bytes mismatch: "
                                "expected: " SIZE_FORMAT ", actual: " SIZE_FORMAT,
                                hr->hrs_index(), exp_marked_bytes, act_marked_bytes);
       }
@@ -1682,15 +1393,16 @@
     // (which was just calculated) region bit maps.
     // We're not OK if the bit in the calculated expected region
     // bitmap is set and the bit in the actual region bitmap is not.
-    BitMap::idx_t index = (BitMap::idx_t)hr->hrs_index();
+    BitMap::idx_t index = (BitMap::idx_t) hr->hrs_index();
 
     bool expected = _exp_region_bm->at(index);
     bool actual = _region_bm->at(index);
     if (expected && !actual) {
       if (_verbose) {
-        gclog_or_tty->print_cr("Region " SIZE_FORMAT ": region bitmap mismatch: "
-                               "expected: %d, actual: %d",
-                               hr->hrs_index(), expected, actual);
+        gclog_or_tty->print_cr("Region %u: region bitmap mismatch: "
+                               "expected: %s, actual: %s",
+                               hr->hrs_index(),
+                               BOOL_TO_STR(expected), BOOL_TO_STR(actual));
       }
       failures += 1;
     }
@@ -1708,9 +1420,10 @@
 
       if (expected && !actual) {
         if (_verbose) {
-          gclog_or_tty->print_cr("Region " SIZE_FORMAT ": card bitmap mismatch at " SIZE_FORMAT ": "
-                                 "expected: %d, actual: %d",
-                                 hr->hrs_index(), i, expected, actual);
+          gclog_or_tty->print_cr("Region %u: card bitmap mismatch at " SIZE_FORMAT ": "
+                                 "expected: %s, actual: %s",
+                                 hr->hrs_index(), i,
+                                 BOOL_TO_STR(expected), BOOL_TO_STR(actual));
         }
         failures += 1;
       }
@@ -1726,7 +1439,7 @@
     _failures += failures;
 
     // We could stop iteration over the heap when we
-    // find the first voilating region by returning true.
+    // find the first violating region by returning true.
     return false;
   }
 };
@@ -1799,68 +1512,19 @@
   int failures() const { return _failures; }
 };
 
-// Final update of count data (during cleanup).
-// Adds [top_at_count, NTAMS) to the marked bytes for each
-// region. Sets the bits in the card bitmap corresponding
-// to the interval [top_at_count, top], and sets the
-// liveness bit for each region containing live data
-// in the region bitmap.
-
-class FinalCountDataUpdateClosure: public HeapRegionClosure {
-  ConcurrentMark* _cm;
-  BitMap* _region_bm;
-  BitMap* _card_bm;
-
-  size_t _total_live_bytes;
-  size_t _total_used_bytes;
-  size_t _total_words_done;
-
-  void set_card_bitmap_range(BitMap::idx_t start_idx, BitMap::idx_t last_idx) {
-    assert(start_idx <= last_idx, "sanity");
-
-    // Set the inclusive bit range [start_idx, last_idx].
-    // For small ranges (up to 8 cards) use a simple loop; otherwise
-    // use par_at_put_range.
-    if ((last_idx - start_idx) <= 8) {
-      for (BitMap::idx_t i = start_idx; i <= last_idx; i += 1) {
-        _card_bm->par_set_bit(i);
-      }
-    } else {
-      assert(last_idx < _card_bm->size(), "sanity");
-      // Note BitMap::par_at_put_range() is exclusive.
-      _card_bm->par_at_put_range(start_idx, last_idx+1, true);
-    }
-  }
-
-  // It takes a region that's not empty (i.e., it has at least one
-  // live object in it and sets its corresponding bit on the region
-  // bitmap to 1. If the region is "starts humongous" it will also set
-  // to 1 the bits on the region bitmap that correspond to its
-  // associated "continues humongous" regions.
-  void set_bit_for_region(HeapRegion* hr) {
-    assert(!hr->continuesHumongous(), "should have filtered those out");
-
-    size_t index = hr->hrs_index();
-    if (!hr->startsHumongous()) {
-      // Normal (non-humongous) case: just set the bit.
-      _region_bm->par_set_bit((BitMap::idx_t) index);
-    } else {
-      // Starts humongous case: calculate how many regions are part of
-      // this humongous region and then set the bit range.
-      G1CollectedHeap* g1h = G1CollectedHeap::heap();
-      HeapRegion *last_hr = g1h->heap_region_containing_raw(hr->end() - 1);
-      size_t end_index = last_hr->hrs_index() + 1;
-      _region_bm->par_at_put_range((BitMap::idx_t) index,
-                                   (BitMap::idx_t) end_index, true);
-    }
-  }
-
+// Closure that finalizes the liveness counting data.
+// Used during the cleanup pause.
+// Sets the bits corresponding to the interval [NTAMS, top]
+// (which contains the implicitly live objects) in the
+// card liveness bitmap. Also sets the bit for each region,
+// containing live data, in the region liveness bitmap.
+
+class FinalCountDataUpdateClosure: public CMCountDataClosureBase {
  public:
   FinalCountDataUpdateClosure(ConcurrentMark* cm,
                               BitMap* region_bm,
                               BitMap* card_bm) :
-    _cm(cm), _region_bm(region_bm), _card_bm(card_bm),
-    _total_words_done(0), _total_live_bytes(0), _total_used_bytes(0) { }
+    CMCountDataClosureBase(cm, region_bm, card_bm) { }
 
   bool doHeapRegion(HeapRegion* hr) {
 
@@ -1875,28 +1539,10 @@
       return false;
     }
 
-    HeapWord* start = hr->top_at_conc_mark_count();
     HeapWord* ntams = hr->next_top_at_mark_start();
     HeapWord* top   = hr->top();
 
-    assert(hr->bottom() <= start && start <= hr->end() &&
-           hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions.");
-
-    size_t words_done = ntams - hr->bottom();
-
-    if (start < ntams) {
-      // Region was changed between remark and cleanup pauses
-      // We need to add (ntams - start) to the marked bytes
-      // for this region, and set bits for the range
-      // [ card_idx(start), card_idx(ntams) ) in the card bitmap.
-      size_t live_bytes = (ntams - start) * HeapWordSize;
-      hr->add_to_marked_bytes(live_bytes);
-
-      // Record the new top at conc count
-      hr->set_top_at_conc_mark_count(ntams);
-
-      // The setting of the bits in the card bitmap takes place below
-    }
+    assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions.");
 
     // Mark the allocated-since-marking portion...
     if (ntams < top) {
@@ -1904,8 +1550,8 @@
       set_bit_for_region(hr);
     }
 
-    // Now set the bits for [start, top]
-    BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start);
+    // Now set the bits for [ntams, top]
+    BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams);
     BitMap::idx_t last_idx = _cm->card_bitmap_index_for(top);
     set_card_bitmap_range(start_idx, last_idx);
 
@@ -1914,16 +1560,8 @@
       set_bit_for_region(hr);
     }
 
-    _total_words_done += words_done;
-    _total_used_bytes += hr->used();
-    _total_live_bytes += hr->next_marked_bytes();
-
     return false;
   }
-
-  size_t total_words_done() const { return _total_words_done; }
-  size_t total_live_bytes() const { return _total_live_bytes; }
-  size_t total_used_bytes() const { return _total_used_bytes; }
 };
 
 class G1ParFinalCountTask: public AbstractGangTask {
@@ -1935,9 +1573,6 @@
 
   uint    _n_workers;
 
-  size_t *_live_bytes;
-  size_t *_used_bytes;
-
 public:
   G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm)
     : AbstractGangTask("G1 final counting"),
@@ -1945,8 +1580,7 @@
       _actual_region_bm(region_bm), _actual_card_bm(card_bm),
       _n_workers(0) {
     // Use the value already set as the number of active threads
-    // in the call to run_task().  Needed for the allocation of
-    // _live_bytes and _used_bytes.
+    // in the call to run_task().
     if (G1CollectedHeap::use_parallel_gc_threads()) {
       assert( _g1h->workers()->active_workers() > 0,
         "Should have been previously set");
@@ -1954,14 +1588,6 @@
     } else {
       _n_workers = 1;
     }
-
-    _live_bytes = NEW_C_HEAP_ARRAY(size_t, _n_workers);
-    _used_bytes = NEW_C_HEAP_ARRAY(size_t, _n_workers);
-  }
-
-  ~G1ParFinalCountTask() {
-    FREE_C_HEAP_ARRAY(size_t, _live_bytes);
-    FREE_C_HEAP_ARRAY(size_t, _used_bytes);
   }
 
   void work(uint worker_id) {
@@ -1979,23 +1605,6 @@
     } else {
       _g1h->heap_region_iterate(&final_update_cl);
     }
-
-    _live_bytes[worker_id] = final_update_cl.total_live_bytes();
-    _used_bytes[worker_id] = final_update_cl.total_used_bytes();
-  }
-
-  size_t live_bytes()  {
-    size_t live_bytes = 0;
-    for (uint i = 0; i < _n_workers; ++i)
-      live_bytes += _live_bytes[i];
-    return live_bytes;
-  }
-
-  size_t used_bytes()  {
-    size_t used_bytes = 0;
-    for (uint i = 0; i < _n_workers; ++i)
-      used_bytes += _used_bytes[i];
-    return used_bytes;
   }
 };
 
@@ -2005,7 +1614,7 @@
   G1CollectedHeap* _g1;
   int _worker_num;
   size_t _max_live_bytes;
-  size_t _regions_claimed;
+  uint _regions_claimed;
   size_t _freed_bytes;
   FreeRegionList* _local_cleanup_list;
   OldRegionSet* _old_proxy_set;
@@ -2058,7 +1667,7 @@
   }
 
   size_t max_live_bytes() { return _max_live_bytes; }
-  size_t regions_claimed() { return _regions_claimed; }
+  uint regions_claimed() { return _regions_claimed; }
   double claimed_region_time_sec() { return _claimed_region_time; }
   double max_region_time_sec() { return _max_region_time; }
 };
@@ -2130,15 +1739,6 @@
 
       HeapRegionRemSet::finish_cleanup_task(&hrrs_cleanup_task);
     }
-    double end = os::elapsedTime();
-    if (G1PrintParCleanupStats) {
-      gclog_or_tty->print("     Worker thread %d [%8.3f..%8.3f = %8.3f ms] "
-                          "claimed %u regions (tot = %8.3f ms, max = %8.3f ms).\n",
-                          worker_id, start, end, (end-start)*1000.0,
-                          g1_note_end.regions_claimed(),
-                          g1_note_end.claimed_region_time_sec()*1000.0,
-                          g1_note_end.max_region_time_sec()*1000.0);
-    }
   }
   size_t max_live_bytes() { return _max_live_bytes; }
   size_t freed_bytes() { return _freed_bytes; }
@@ -2185,8 +1785,7 @@
     HandleMark hm;  // handle scope
     gclog_or_tty->print(" VerifyDuringGC:(before)");
     Universe::heap()->prepare_for_verify();
-    Universe::verify(/* allow dirty */ true,
-                     /* silent      */ false,
+    Universe::verify(/* silent      */ false,
                      /* option      */ VerifyOption_G1UsePrevMarking);
   }
 
@@ -2250,30 +1849,11 @@
     guarantee(g1_par_verify_task.failures() == 0, "Unexpected accounting failures");
   }
 
-  size_t known_garbage_bytes =
-    g1_par_count_task.used_bytes() - g1_par_count_task.live_bytes();
-  g1p->set_known_garbage_bytes(known_garbage_bytes);
-
   size_t start_used_bytes = g1h->used();
-  _at_least_one_mark_complete = true;
   g1h->set_marking_complete();
 
-  ergo_verbose4(ErgoConcCycles,
-           "finish cleanup",
-           ergo_format_byte("occupancy")
-           ergo_format_byte("capacity")
-           ergo_format_byte_perc("known garbage"),
-           start_used_bytes, g1h->capacity(),
-           known_garbage_bytes,
-           ((double) known_garbage_bytes / (double) g1h->capacity()) * 100.0);
-
   double count_end = os::elapsedTime();
   double this_final_counting_time = (count_end - start);
-  if (G1PrintParCleanupStats) {
-    gclog_or_tty->print_cr("Cleanup:");
-    gclog_or_tty->print_cr("  Finalize counting: %8.3f ms",
-                           this_final_counting_time*1000.0);
-  }
   _total_counting_time += this_final_counting_time;
 
   if (G1PrintRegionLivenessInfo) {
@@ -2287,7 +1867,6 @@
   g1h->reset_gc_time_stamp();
 
   // Note end of marking in all heap regions.
-  double note_end_start = os::elapsedTime();
   G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list);
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     g1h->set_par_threads((int)n_workers);
@@ -2306,11 +1885,6 @@
     // regions that there will be more free regions coming soon.
     g1h->set_free_regions_coming();
   }
-  double note_end_end = os::elapsedTime();
-  if (G1PrintParCleanupStats) {
-    gclog_or_tty->print_cr("  note end of marking: %8.3f ms.",
-                           (note_end_end - note_end_start)*1000.0);
-  }
 
   // call below, since it affects the metric by which we sort the heap
   // regions.
@@ -2342,16 +1916,13 @@
   double end = os::elapsedTime();
   _cleanup_times.add((end - start) * 1000.0);
 
-  if (PrintGC || PrintGCDetails) {
+  if (G1Log::fine()) {
     g1h->print_size_transition(gclog_or_tty,
                                start_used_bytes,
                                g1h->used(),
                                g1h->capacity());
   }
 
-  size_t cleaned_up_bytes = start_used_bytes - g1h->used();
-  g1p->decrease_known_garbage_bytes(cleaned_up_bytes);
-
   // Clean up will have freed any regions completely full of garbage.
   // Update the soft reference policy with the new heap occupancy.
   Universe::update_heap_info_at_gc();
@@ -2368,8 +1939,7 @@
     HandleMark hm;  // handle scope
     gclog_or_tty->print(" VerifyDuringGC:(after)");
     Universe::heap()->prepare_for_verify();
-    Universe::verify(/* allow dirty */ true,
-                     /* silent      */ false,
+    Universe::verify(/* silent      */ false,
                      /* option      */ VerifyOption_G1UsePrevMarking);
   }
 
@@ -2386,7 +1956,7 @@
 
   if (G1ConcRegionFreeingVerbose) {
     gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
-                           "cleanup list has "SIZE_FORMAT" entries",
+                           "cleanup list has %u entries",
                            _cleanup_list.length());
   }
 
@@ -2408,9 +1978,8 @@
         _cleanup_list.is_empty()) {
       if (G1ConcRegionFreeingVerbose) {
         gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
-                               "appending "SIZE_FORMAT" entries to the "
-                               "secondary_free_list, clean list still has "
-                               SIZE_FORMAT" entries",
+                               "appending %u entries to the secondary_free_list, "
+                               "cleanup list still has %u entries",
                                tmp_free_list.length(),
                                _cleanup_list.length());
       }
@@ -2683,11 +2252,10 @@
   // Inner scope to exclude the cleaning of the string and symbol
   // tables from the displayed time.
   {
-    bool verbose = PrintGC && PrintGCDetails;
-    if (verbose) {
+    if (G1Log::finer()) {
       gclog_or_tty->put(' ');
     }
-    TraceTime t("GC ref-proc", verbose, false, gclog_or_tty);
+    TraceTime t("GC ref-proc", G1Log::finer(), false, gclog_or_tty);
 
     ReferenceProcessor* rp = g1h->ref_processor_cm();
 
@@ -3066,89 +2634,6 @@
 
 #endif // PRODUCT
 
-// This note is for drainAllSATBBuffers and the code in between.
-// In the future we could reuse a task to do this work during an
-// evacuation pause (since now tasks are not active and can be claimed
-// during an evacuation pause). This was a late change to the code and
-// is currently not being taken advantage of.
-
-void ConcurrentMark::deal_with_reference(oop obj) {
-  if (verbose_high()) {
-    gclog_or_tty->print_cr("[global] we're dealing with reference "PTR_FORMAT,
-                           (void*) obj);
-  }
-
-  HeapWord* objAddr = (HeapWord*) obj;
-  assert(obj->is_oop_or_null(true /* ignore mark word */), "Error");
-  if (_g1h->is_in_g1_reserved(objAddr)) {
-    assert(obj != NULL, "null check is implicit");
-    if (!_nextMarkBitMap->isMarked(objAddr)) {
-      // Only get the containing region if the object is not marked on the
-      // bitmap (otherwise, it's a waste of time since we won't do
-      // anything with it).
-      HeapRegion* hr = _g1h->heap_region_containing_raw(obj);
-      if (!hr->obj_allocated_since_next_marking(obj)) {
-        if (verbose_high()) {
-          gclog_or_tty->print_cr("[global] "PTR_FORMAT" is not considered "
-                                 "marked", (void*) obj);
-        }
-
-        // we need to mark it first
-        if (_nextMarkBitMap->parMark(objAddr)) {
-          // No OrderAccess:store_load() is needed. It is implicit in the
-          // CAS done in parMark(objAddr) above
-          HeapWord* finger = _finger;
-          if (objAddr < finger) {
-            if (verbose_high()) {
-              gclog_or_tty->print_cr("[global] below the global finger "
-                                     "("PTR_FORMAT"), pushing it", finger);
-            }
-            if (!mark_stack_push(obj)) {
-              if (verbose_low()) {
-                gclog_or_tty->print_cr("[global] global stack overflow during "
-                                       "deal_with_reference");
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
-class CMGlobalObjectClosure : public ObjectClosure {
-private:
-  ConcurrentMark* _cm;
-
-public:
-  void do_object(oop obj) {
-    _cm->deal_with_reference(obj);
-  }
-
-  CMGlobalObjectClosure(ConcurrentMark* cm) : _cm(cm) { }
-};
-
-void ConcurrentMark::drainAllSATBBuffers() {
-  guarantee(false, "drainAllSATBBuffers(): don't call this any more");
-
-  CMGlobalObjectClosure oc(this);
-  SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
-  satb_mq_set.set_closure(&oc);
-
-  while (satb_mq_set.apply_closure_to_completed_buffer()) {
-    if (verbose_medium()) {
-      gclog_or_tty->print_cr("[global] processed an SATB buffer");
-    }
-  }
-
-  // no need to check whether we should do this, as this is only
-  // called during an evacuation pause
-  satb_mq_set.iterate_closure_all_threads();
-
-  satb_mq_set.set_closure(NULL);
-  assert(satb_mq_set.completed_buffers_num() == 0, "invariant");
-}
-
 void ConcurrentMark::clearRangePrevBitmap(MemRegion mr) {
   // Note we are overriding the read-only view of the prev map here, via
   // the cast.
@@ -3257,63 +2742,6 @@
   return NULL;
 }
 
-bool ConcurrentMark::invalidate_aborted_regions_in_cset() {
-  guarantee(false, "invalidate_aborted_regions_in_cset(): "
-                   "don't call this any more");
-
-  bool result = false;
-  for (int i = 0; i < (int)_max_task_num; ++i) {
-    CMTask* the_task = _tasks[i];
-    MemRegion mr = the_task->aborted_region();
-    if (mr.start() != NULL) {
-      assert(mr.end() != NULL, "invariant");
-      assert(mr.word_size() > 0, "invariant");
-      HeapRegion* hr = _g1h->heap_region_containing(mr.start());
-      assert(hr != NULL, "invariant");
-      if (hr->in_collection_set()) {
-        // The region points into the collection set
-        the_task->set_aborted_region(MemRegion());
-        result = true;
-      }
-    }
-  }
-  return result;
-}
-
-bool ConcurrentMark::has_aborted_regions() {
-  for (int i = 0; i < (int)_max_task_num; ++i) {
-    CMTask* the_task = _tasks[i];
-    MemRegion mr = the_task->aborted_region();
-    if (mr.start() != NULL) {
-      assert(mr.end() != NULL, "invariant");
-      assert(mr.word_size() > 0, "invariant");
-      return true;
-    }
-  }
-  return false;
-}
-
-void ConcurrentMark::oops_do(OopClosure* cl) {
-  if (_markStack.size() > 0 && verbose_low()) {
-    gclog_or_tty->print_cr("[global] scanning the global marking stack, "
-                           "size = %d", _markStack.size());
-  }
-  // we first iterate over the contents of the mark stack...
-  _markStack.oops_do(cl);
-
-  for (int i = 0; i < (int)_max_task_num; ++i) {
-    OopTaskQueue* queue = _task_queues->queue((int)i);
-
-    if (queue->size() > 0 && verbose_low()) {
-      gclog_or_tty->print_cr("[global] scanning task queue of task %d, "
-                             "size = %d", i, queue->size());
-    }
-
-    // ...then over the contents of the all the task queues.
-    queue->oops_do(cl);
-  }
-}
-
 #ifndef PRODUCT
 enum VerifyNoCSetOopsPhase {
   VerifyNoCSetOopsStack,
@@ -3445,8 +2873,6 @@
 void ConcurrentMark::clear_marking_state(bool clear_overflow) {
   _markStack.setEmpty();
   _markStack.clear_overflow();
-  _regionStack.setEmpty();
-  _regionStack.clear_overflow();
   if (clear_overflow) {
     clear_has_overflown();
   } else {
@@ -3457,8 +2883,6 @@
   for (int i = 0; i < (int)_max_task_num; ++i) {
     OopTaskQueue* queue = _task_queues->queue(i);
     queue->set_empty();
-    // Clear any partial regions from the CMTasks
-    _tasks[i]->clear_aborted_region();
   }
 }
 
@@ -3525,7 +2949,7 @@
     assert(limit_idx <= end_idx, "or else use atomics");
 
     // Aggregate the "stripe" in the count data associated with hr.
-    size_t hrs_index = hr->hrs_index();
+    uint hrs_index = hr->hrs_index();
     size_t marked_bytes = 0;
 
     for (int i = 0; (size_t)i < _max_task_num; i += 1) {
@@ -3558,9 +2982,6 @@
     // Update the marked bytes for this region.
     hr->add_to_marked_bytes(marked_bytes);
 
-    // Now set the top at count to NTAMS.
-    hr->set_top_at_conc_mark_count(limit);
-
     // Next heap region
     return false;
   }
@@ -3633,7 +3054,7 @@
   // of the final counting task.
   _region_bm.clear();
 
-  size_t max_regions = _g1h->max_regions();
+  uint max_regions = _g1h->max_regions();
   assert(_max_task_num != 0, "unitialized");
 
   for (int i = 0; (size_t) i < _max_task_num; i += 1) {
@@ -3643,7 +3064,7 @@
     assert(task_card_bm->size() == _card_bm.size(), "size mismatch");
     assert(marked_bytes_array != NULL, "uninitialized");
 
-    memset(marked_bytes_array, 0, (max_regions * sizeof(size_t)));
+    memset(marked_bytes_array, 0, (size_t) max_regions * sizeof(size_t));
     task_card_bm->clear();
   }
 }
@@ -3658,327 +3079,6 @@
   }
 }
 
-// Closures used by ConcurrentMark::complete_marking_in_collection_set().
-
-class CSetMarkOopClosure: public OopClosure {
-  friend class CSetMarkBitMapClosure;
-
-  G1CollectedHeap* _g1h;
-  CMBitMap*        _bm;
-  ConcurrentMark*  _cm;
-  oop*             _ms;
-  jint*            _array_ind_stack;
-  int              _ms_size;
-  int              _ms_ind;
-  int              _array_increment;
-  uint             _worker_id;
-
-  bool push(oop obj, int arr_ind = 0) {
-    if (_ms_ind == _ms_size) {
-      gclog_or_tty->print_cr("Mark stack is full.");
-      return false;
-    }
-    _ms[_ms_ind] = obj;
-    if (obj->is_objArray()) {
-      _array_ind_stack[_ms_ind] = arr_ind;
-    }
-    _ms_ind++;
-    return true;
-  }
-
-  oop pop() {
-    if (_ms_ind == 0) {
-      return NULL;
-    } else {
-      _ms_ind--;
-      return _ms[_ms_ind];
-    }
-  }
-
-  template <class T> bool drain() {
-    while (_ms_ind > 0) {
-      oop obj = pop();
-      assert(obj != NULL, "Since index was non-zero.");
-      if (obj->is_objArray()) {
-        jint arr_ind = _array_ind_stack[_ms_ind];
-        objArrayOop aobj = objArrayOop(obj);
-        jint len = aobj->length();
-        jint next_arr_ind = arr_ind + _array_increment;
-        if (next_arr_ind < len) {
-          push(obj, next_arr_ind);
-        }
-        // Now process this portion of this one.
-        int lim = MIN2(next_arr_ind, len);
-        for (int j = arr_ind; j < lim; j++) {
-          do_oop(aobj->objArrayOopDesc::obj_at_addr<T>(j));
-        }
-      } else {
-        obj->oop_iterate(this);
-      }
-      if (abort()) return false;
-    }
-    return true;
-  }
-
-public:
-  CSetMarkOopClosure(ConcurrentMark* cm, int ms_size, uint worker_id) :
-    _g1h(G1CollectedHeap::heap()),
-    _cm(cm),
-    _bm(cm->nextMarkBitMap()),
-    _ms_size(ms_size), _ms_ind(0),
-    _ms(NEW_C_HEAP_ARRAY(oop, ms_size)),
-    _array_ind_stack(NEW_C_HEAP_ARRAY(jint, ms_size)),
-    _array_increment(MAX2(ms_size/8, 16)),
-    _worker_id(worker_id) { }
-
-  ~CSetMarkOopClosure() {
-    FREE_C_HEAP_ARRAY(oop, _ms);
-    FREE_C_HEAP_ARRAY(jint, _array_ind_stack);
-  }
-
-  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
-  virtual void do_oop(      oop* p) { do_oop_work(p); }
-
-  template <class T> void do_oop_work(T* p) {
-    T heap_oop = oopDesc::load_heap_oop(p);
-    if (oopDesc::is_null(heap_oop)) return;
-    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-    if (obj->is_forwarded()) {
-      // If the object has already been forwarded, we have to make sure
-      // that it's marked.  So follow the forwarding pointer.  Note that
-      // this does the right thing for self-forwarding pointers in the
-      // evacuation failure case.
-      obj = obj->forwardee();
-    }
-    HeapRegion* hr = _g1h->heap_region_containing(obj);
-    if (hr != NULL) {
-      if (hr->in_collection_set()) {
-        if (_g1h->is_obj_ill(obj)) {
-          if (_bm->parMark((HeapWord*)obj)) {
-            if (!push(obj)) {
-              gclog_or_tty->print_cr("Setting abort in CSetMarkOopClosure because push failed.");
-              set_abort();
-            }
-          }
-        }
-      } else {
-        // Outside the collection set; we need to gray it
-        _cm->deal_with_reference(obj);
-      }
-    }
-  }
-};
-
-class CSetMarkBitMapClosure: public BitMapClosure {
-  G1CollectedHeap*   _g1h;
-  CMBitMap*          _bitMap;
-  ConcurrentMark*    _cm;
-  CSetMarkOopClosure _oop_cl;
-  uint               _worker_id;
-
-public:
-  CSetMarkBitMapClosure(ConcurrentMark* cm, int ms_size, int worker_id) :
-    _g1h(G1CollectedHeap::heap()),
-    _bitMap(cm->nextMarkBitMap()),
-    _oop_cl(cm, ms_size, worker_id),
-    _worker_id(worker_id) { }
-
-  bool do_bit(size_t offset) {
-    // convert offset into a HeapWord*
-    HeapWord* addr = _bitMap->offsetToHeapWord(offset);
-    assert(_bitMap->endWord() && addr < _bitMap->endWord(),
-           "address out of range");
-    assert(_bitMap->isMarked(addr), "tautology");
-    oop obj = oop(addr);
-    if (!obj->is_forwarded()) {
-      if (!_oop_cl.push(obj)) return false;
-      if (UseCompressedOops) {
-        if (!_oop_cl.drain<narrowOop>()) return false;
-      } else {
-        if (!_oop_cl.drain<oop>()) return false;
-      }
-    }
-    // Otherwise...
-    return true;
-  }
-};
-
-class CompleteMarkingInCSetHRClosure: public HeapRegionClosure {
-  CMBitMap*             _bm;
-  CSetMarkBitMapClosure _bit_cl;
-  uint                  _worker_id;
-
-  enum SomePrivateConstants {
-    MSSize = 1000
-  };
-
-public:
-  CompleteMarkingInCSetHRClosure(ConcurrentMark* cm, int worker_id) :
-    _bm(cm->nextMarkBitMap()),
-    _bit_cl(cm, MSSize, worker_id),
-    _worker_id(worker_id) { }
-
-  bool doHeapRegion(HeapRegion* hr) {
-    if (hr->claimHeapRegion(HeapRegion::CompleteMarkCSetClaimValue)) {
-      // The current worker has successfully claimed the region.
-      if (!hr->evacuation_failed()) {
-        MemRegion mr = MemRegion(hr->bottom(), hr->next_top_at_mark_start());
-        if (!mr.is_empty()) {
-          bool done = false;
-          while (!done) {
-            done = _bm->iterate(&_bit_cl, mr);
-          }
-        }
-      }
-    }
-    return false;
-  }
-};
-
-class G1ParCompleteMarkInCSetTask: public AbstractGangTask {
-protected:
-  G1CollectedHeap* _g1h;
-  ConcurrentMark*  _cm;
-
-public:
-  G1ParCompleteMarkInCSetTask(G1CollectedHeap* g1h,
-                              ConcurrentMark* cm) :
-    AbstractGangTask("Complete Mark in CSet"),
-    _g1h(g1h), _cm(cm) { }
-
-  void work(uint worker_id) {
-    CompleteMarkingInCSetHRClosure cmplt(_cm, worker_id);
-    HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id);
-    _g1h->collection_set_iterate_from(hr, &cmplt);
-  }
-};
-
-void ConcurrentMark::complete_marking_in_collection_set() {
-  guarantee(false, "complete_marking_in_collection_set(): "
-                   "don't call this any more");
-
-  G1CollectedHeap* g1h =  G1CollectedHeap::heap();
-
-  if (!g1h->mark_in_progress()) {
-    g1h->g1_policy()->record_mark_closure_time(0.0);
-    return;
-  }
-
-  double start = os::elapsedTime();
-  G1ParCompleteMarkInCSetTask complete_mark_task(g1h, this);
-
-  assert(g1h->check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
-
-  if (G1CollectedHeap::use_parallel_gc_threads()) {
-    int n_workers = g1h->workers()->active_workers();
-    g1h->set_par_threads(n_workers);
-    g1h->workers()->run_task(&complete_mark_task);
-    g1h->set_par_threads(0);
-  } else {
-    complete_mark_task.work(0);
-  }
-
-  assert(g1h->check_cset_heap_region_claim_values(HeapRegion::CompleteMarkCSetClaimValue), "sanity");
-
-  // Reset the claim values in the regions in the collection set.
-  g1h->reset_cset_heap_region_claim_values();
-
-  assert(g1h->check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
-
-  double end_time = os::elapsedTime();
-  double elapsed_time_ms = (end_time - start) * 1000.0;
-  g1h->g1_policy()->record_mark_closure_time(elapsed_time_ms);
-}
-
-// The next two methods deal with the following optimisation. Some
-// objects are gray by being marked and located above the finger. If
-// they are copied, during an evacuation pause, below the finger then
-// the need to be pushed on the stack. The observation is that, if
-// there are no regions in the collection set located above the
-// finger, then the above cannot happen, hence we do not need to
-// explicitly gray any objects when copying them to below the
-// finger. The global stack will be scanned to ensure that, if it
-// points to objects being copied, it will update their
-// location. There is a tricky situation with the gray objects in
-// region stack that are being coped, however. See the comment in
-// newCSet().
-
-void ConcurrentMark::newCSet() {
-  guarantee(false, "newCSet(): don't call this any more");
-
-  if (!concurrent_marking_in_progress()) {
-    // nothing to do if marking is not in progress
-    return;
-  }
-
-  // find what the lowest finger is among the global and local fingers
-  _min_finger = _finger;
-  for (int i = 0; i < (int)_max_task_num; ++i) {
-    CMTask* task = _tasks[i];
-    HeapWord* task_finger = task->finger();
-    if (task_finger != NULL && task_finger < _min_finger) {
-      _min_finger = task_finger;
-    }
-  }
-
-  _should_gray_objects = false;
-
-  // This fixes a very subtle and fustrating bug. It might be the case
-  // that, during en evacuation pause, heap regions that contain
-  // objects that are gray (by being in regions contained in the
-  // region stack) are included in the collection set. Since such gray
-  // objects will be moved, and because it's not easy to redirect
-  // region stack entries to point to a new location (because objects
-  // in one region might be scattered to multiple regions after they
-  // are copied), one option is to ensure that all marked objects
-  // copied during a pause are pushed on the stack. Notice, however,
-  // that this problem can only happen when the region stack is not
-  // empty during an evacuation pause. So, we make the fix a bit less
-  // conservative and ensure that regions are pushed on the stack,
-  // irrespective whether all collection set regions are below the
-  // finger, if the region stack is not empty. This is expected to be
-  // a rare case, so I don't think it's necessary to be smarted about it.
-  if (!region_stack_empty() || has_aborted_regions()) {
-    _should_gray_objects = true;
-  }
-}
-
-void ConcurrentMark::registerCSetRegion(HeapRegion* hr) {
-  guarantee(false, "registerCSetRegion(): don't call this any more");
-
-  if (!concurrent_marking_in_progress()) return;
-
-  HeapWord* region_end = hr->end();
-  if (region_end > _min_finger) {
-    _should_gray_objects = true;
-  }
-}
-
-// Resets the region fields of active CMTasks whose values point
-// into the collection set.
-void ConcurrentMark::reset_active_task_region_fields_in_cset() {
-  guarantee(false, "reset_active_task_region_fields_in_cset(): "
-                   "don't call this any more");
-
-  assert(SafepointSynchronize::is_at_safepoint(), "should be in STW");
-  assert(parallel_marking_threads() <= _max_task_num, "sanity");
-
-  for (int i = 0; i < (int)parallel_marking_threads(); i += 1) {
-    CMTask* task = _tasks[i];
-    HeapWord* task_finger = task->finger();
-    if (task_finger != NULL) {
-      assert(_g1h->is_in_g1_reserved(task_finger), "not in heap");
-      HeapRegion* finger_region = _g1h->heap_region_containing(task_finger);
-      if (finger_region->in_collection_set()) {
-        // The task's current region is in the collection set.
-        // This region will be evacuated in the current GC and
-        // the region fields in the task will be stale.
-        task->giveup_current_region();
-      }
-    }
-  }
-}
-
 // abandon current marking iteration due to a Full GC
 void ConcurrentMark::abort() {
   // Clear all marks to force marking thread to do nothing
@@ -4112,36 +3212,21 @@
   CMBitMap*                   _nextMarkBitMap;
   ConcurrentMark*             _cm;
   CMTask*                     _task;
-  // true if we're scanning a heap region claimed by the task (so that
-  // we move the finger along), false if we're not, i.e. currently when
-  // scanning a heap region popped from the region stack (so that we
-  // do not move the task finger along; it'd be a mistake if we did so).
-  bool                        _scanning_heap_region;
 
 public:
-  CMBitMapClosure(CMTask *task,
-                  ConcurrentMark* cm,
-                  CMBitMap* nextMarkBitMap)
-    :  _task(task), _cm(cm), _nextMarkBitMap(nextMarkBitMap) { }
-
-  void set_scanning_heap_region(bool scanning_heap_region) {
-    _scanning_heap_region = scanning_heap_region;
-  }
+  CMBitMapClosure(CMTask *task, ConcurrentMark* cm, CMBitMap* nextMarkBitMap) :
+    _task(task), _cm(cm), _nextMarkBitMap(nextMarkBitMap) { }
 
   bool do_bit(size_t offset) {
     HeapWord* addr = _nextMarkBitMap->offsetToHeapWord(offset);
     assert(_nextMarkBitMap->isMarked(addr), "invariant");
     assert( addr < _cm->finger(), "invariant");
 
-    if (_scanning_heap_region) {
-      statsOnly( _task->increase_objs_found_on_bitmap() );
-      assert(addr >= _task->finger(), "invariant");
-      // We move that task's local finger along.
-      _task->move_finger_to(addr);
-    } else {
-      // We move the task's region finger along.
-      _task->move_region_finger_to(addr);
-    }
+    statsOnly( _task->increase_objs_found_on_bitmap() );
+    assert(addr >= _task->finger(), "invariant");
+
+    // We move that task's local finger along.
+    _task->move_finger_to(addr);
 
     _task->scan_object(oop(addr));
     // we only partially drain the local queue and global stack
@@ -4249,8 +3334,6 @@
   _curr_region   = NULL;
   _finger        = NULL;
   _region_limit  = NULL;
-
-  _region_finger = NULL;
 }
 
 void CMTask::set_cm_oop_closure(G1CMOopClosure* cm_oop_closure) {
@@ -4271,7 +3354,6 @@
 
   _nextMarkBitMap                = nextMarkBitMap;
   clear_region_fields();
-  assert(_aborted_region.is_empty(), "should have been cleared");
 
   _calls                         = 0;
   _elapsed_time_ms               = 0.0;
@@ -4288,7 +3370,6 @@
   _global_max_size               = 0;
   _global_transfers_to           = 0;
   _global_transfers_from         = 0;
-  _region_stack_pops             = 0;
   _regions_claimed               = 0;
   _objs_found_on_bitmap          = 0;
   _satb_buffers_processed        = 0;
@@ -4663,110 +3744,6 @@
   decrease_limits();
 }
 
-void CMTask::drain_region_stack(BitMapClosure* bc) {
-  assert(_cm->region_stack_empty(), "region stack should be empty");
-  assert(_aborted_region.is_empty(), "aborted region should be empty");
-  return;
-
-  if (has_aborted()) return;
-
-  assert(_region_finger == NULL,
-         "it should be NULL when we're not scanning a region");
-
-  if (!_cm->region_stack_empty() || !_aborted_region.is_empty()) {
-    if (_cm->verbose_low()) {
-      gclog_or_tty->print_cr("[%d] draining region stack, size = %d",
-                             _task_id, _cm->region_stack_size());
-    }
-
-    MemRegion mr;
-
-    if (!_aborted_region.is_empty()) {
-      mr = _aborted_region;
-      _aborted_region = MemRegion();
-
-      if (_cm->verbose_low()) {
-        gclog_or_tty->print_cr("[%d] scanning aborted region "
-                               "[ " PTR_FORMAT ", " PTR_FORMAT " )",
-                               _task_id, mr.start(), mr.end());
-      }
-    } else {
-      mr = _cm->region_stack_pop_lock_free();
-      // it returns MemRegion() if the pop fails
-      statsOnly(if (mr.start() != NULL) ++_region_stack_pops );
-    }
-
-    while (mr.start() != NULL) {
-      if (_cm->verbose_medium()) {
-        gclog_or_tty->print_cr("[%d] we are scanning region "
-                               "["PTR_FORMAT", "PTR_FORMAT")",
-                               _task_id, mr.start(), mr.end());
-      }
-
-      assert(mr.end() <= _cm->finger(),
-             "otherwise the region shouldn't be on the stack");
-      assert(!mr.is_empty(), "Only non-empty regions live on the region stack");
-      if (_nextMarkBitMap->iterate(bc, mr)) {
-        assert(!has_aborted(),
-               "cannot abort the task without aborting the bitmap iteration");
-
-        // We finished iterating over the region without aborting.
-        regular_clock_call();
-        if (has_aborted()) {
-          mr = MemRegion();
-        } else {
-          mr = _cm->region_stack_pop_lock_free();
-          // it returns MemRegion() if the pop fails
-          statsOnly(if (mr.start() != NULL) ++_region_stack_pops );
-        }
-      } else {
-        assert(has_aborted(), "currently the only way to do so");
-
-        // The only way to abort the bitmap iteration is to return
-        // false from the do_bit() method. However, inside the
-        // do_bit() method we move the _region_finger to point to the
-        // object currently being looked at. So, if we bail out, we
-        // have definitely set _region_finger to something non-null.
-        assert(_region_finger != NULL, "invariant");
-
-        // Make sure that any previously aborted region has been
-        // cleared.
-        assert(_aborted_region.is_empty(), "aborted region not cleared");
-
-        // The iteration was actually aborted. So now _region_finger
-        // points to the address of the object we last scanned. If we
-        // leave it there, when we restart this task, we will rescan
-        // the object. It is easy to avoid this. We move the finger by
-        // enough to point to the next possible object header (the
-        // bitmap knows by how much we need to move it as it knows its
-        // granularity).
-        MemRegion newRegion =
-          MemRegion(_nextMarkBitMap->nextWord(_region_finger), mr.end());
-
-        if (!newRegion.is_empty()) {
-          if (_cm->verbose_low()) {
-            gclog_or_tty->print_cr("[%d] recording unscanned region"
-                                   "[" PTR_FORMAT "," PTR_FORMAT ") in CMTask",
-                                   _task_id,
-                                   newRegion.start(), newRegion.end());
-          }
-          // Now record the part of the region we didn't scan to
-          // make sure this task scans it later.
-          _aborted_region = newRegion;
-        }
-        // break from while
-        mr = MemRegion();
-      }
-      _region_finger = NULL;
-    }
-
-    if (_cm->verbose_low()) {
-      gclog_or_tty->print_cr("[%d] drained region stack, size = %d",
-                             _task_id, _cm->region_stack_size());
-    }
-  }
-}
-
 void CMTask::print_stats() {
   gclog_or_tty->print_cr("Marking Stats, task = %d, calls = %d",
                          _task_id, _calls);
@@ -4795,8 +3772,7 @@
                          _global_pushes, _global_pops, _global_max_size);
   gclog_or_tty->print_cr("                transfers to = %d, transfers from = %d",
                          _global_transfers_to,_global_transfers_from);
-  gclog_or_tty->print_cr("  Regions: claimed = %d, Region Stack: pops = %d",
-                         _regions_claimed, _region_stack_pops);
+  gclog_or_tty->print_cr("  Regions: claimed = %d", _regions_claimed);
   gclog_or_tty->print_cr("  SATB buffers: processed = %d", _satb_buffers_processed);
   gclog_or_tty->print_cr("  Steals: attempts = %d, successes = %d",
                          _steal_attempts, _steals);
@@ -4855,15 +3831,7 @@
       popping by other tasks. Only when there is no more work, tasks
       will totally drain the global mark stack.
 
-      (4) Global Region Stack. Entries on it correspond to areas of
-      the bitmap that need to be scanned since they contain gray
-      objects. Pushes on the region stack only happen during
-      evacuation pauses and typically correspond to areas covered by
-      GC LABS. If it overflows, then the marking phase should restart
-      and iterate over the bitmap to identify gray objects. Tasks will
-      try to totally drain the region stack as soon as possible.
-
-      (5) SATB Buffer Queue. This is where completed SATB buffers are
+      (4) SATB Buffer Queue. This is where completed SATB buffers are
       made available. Buffers are regularly removed from this queue
       and scanned for roots, so that the queue doesn't get too
       long. During remark, all completed buffers are processed, as
@@ -4875,12 +3843,12 @@
 
       (1) When the marking phase has been aborted (after a Full GC).
 
-      (2) When a global overflow (either on the global stack or the
-      region stack) has been triggered. Before the task aborts, it
-      will actually sync up with the other tasks to ensure that all
-      the marking data structures (local queues, stacks, fingers etc.)
-      are re-initialised so that when do_marking_step() completes,
-      the marking phase can immediately restart.
+      (2) When a global overflow (on the global stack) has been
+      triggered. Before the task aborts, it will actually sync up with
+      the other tasks to ensure that all the marking data structures
+      (local queues, stacks, fingers etc.)  are re-initialised so that
+      when do_marking_step() completes, the marking phase can
+      immediately restart.
 
       (3) When enough completed SATB buffers are available. The
       do_marking_step() method only tries to drain SATB buffers right
@@ -4923,13 +3891,6 @@
   assert(time_target_ms >= 1.0, "minimum granularity is 1ms");
   assert(concurrent() == _cm->concurrent(), "they should be the same");
 
-  assert(concurrent() || _cm->region_stack_empty(),
-         "the region stack should have been cleared before remark");
-  assert(concurrent() || !_cm->has_aborted_regions(),
-         "aborted regions should have been cleared before remark");
-  assert(_region_finger == NULL,
-         "this should be non-null only when a region is being scanned");
-
   G1CollectorPolicy* g1_policy = _g1h->g1_policy();
   assert(_task_queues != NULL, "invariant");
   assert(_task_queue != NULL, "invariant");
@@ -4978,10 +3939,10 @@
   set_cm_oop_closure(&cm_oop_closure);
 
   if (_cm->has_overflown()) {
-    // This can happen if the region stack or the mark stack overflows
-    // during a GC pause and this task, after a yield point,
-    // restarts. We have to abort as we need to get into the overflow
-    // protocol which happens right at the end of this task.
+    // This can happen if the mark stack overflows during a GC pause
+    // and this task, after a yield point, restarts. We have to abort
+    // as we need to get into the overflow protocol which happens
+    // right at the end of this task.
     set_has_aborted();
   }
 
@@ -4994,17 +3955,6 @@
   drain_local_queue(true);
   drain_global_stack(true);
 
-  // Then totally drain the region stack.  We will not look at
-  // it again before the next invocation of this method. Entries on
-  // the region stack are only added during evacuation pauses, for
-  // which we have to yield. When we do, we abort the task anyway so
-  // it will look at the region stack again when it restarts.
-  bitmap_closure.set_scanning_heap_region(false);
-  drain_region_stack(&bitmap_closure);
-  // ...then partially drain the local queue and the global stack
-  drain_local_queue(true);
-  drain_global_stack(true);
-
   do {
     if (!has_aborted() && _curr_region != NULL) {
       // This means that we're already holding on to a region.
@@ -5034,9 +3984,7 @@
 
       // Let's iterate over the bitmap of the part of the
       // region that is left.
-      bitmap_closure.set_scanning_heap_region(true);
-      if (mr.is_empty() ||
-          _nextMarkBitMap->iterate(&bitmap_closure, mr)) {
+      if (mr.is_empty() || _nextMarkBitMap->iterate(&bitmap_closure, mr)) {
         // We successfully completed iterating over the region. Now,
         // let's give up the region.
         giveup_current_region();
@@ -5061,9 +4009,9 @@
         HeapWord* new_finger = _nextMarkBitMap->nextWord(_finger);
         // Check if bitmap iteration was aborted while scanning the last object
         if (new_finger >= _region_limit) {
-            giveup_current_region();
+          giveup_current_region();
         } else {
-            move_finger_to(new_finger);
+          move_finger_to(new_finger);
         }
       }
     }
@@ -5119,9 +4067,7 @@
 
   if (!has_aborted()) {
     // We cannot check whether the global stack is empty, since other
-    // tasks might be pushing objects to it concurrently. We also cannot
-    // check if the region stack is empty because if a thread is aborting
-    // it can push a partially done region back.
+    // tasks might be pushing objects to it concurrently.
     assert(_cm->out_of_regions(),
            "at this point we should be out of regions");
 
@@ -5145,9 +4091,7 @@
     // we could. Let's try to do some stealing...
 
     // We cannot check whether the global stack is empty, since other
-    // tasks might be pushing objects to it concurrently. We also cannot
-    // check if the region stack is empty because if a thread is aborting
-    // it can push a partially done region back.
+    // tasks might be pushing objects to it concurrently.
     assert(_cm->out_of_regions() && _task_queue->size() == 0,
            "only way to reach here");
 
@@ -5194,9 +4138,7 @@
   // termination protocol.
   if (do_termination && !has_aborted()) {
     // We cannot check whether the global stack is empty, since other
-    // tasks might be concurrently pushing objects on it. We also cannot
-    // check if the region stack is empty because if a thread is aborting
-    // it can push a partially done region back.
+    // tasks might be concurrently pushing objects on it.
     // Separated the asserts so that we know which one fires.
     assert(_cm->out_of_regions(), "only way to reach here");
     assert(_task_queue->size() == 0, "only way to reach here");
@@ -5233,13 +4175,10 @@
       // that, if a condition is false, we can immediately find out
       // which one.
       guarantee(_cm->out_of_regions(), "only way to reach here");
-      guarantee(_aborted_region.is_empty(), "only way to reach here");
-      guarantee(_cm->region_stack_empty(), "only way to reach here");
       guarantee(_cm->mark_stack_empty(), "only way to reach here");
       guarantee(_task_queue->size() == 0, "only way to reach here");
       guarantee(!_cm->has_overflown(), "only way to reach here");
       guarantee(!_cm->mark_stack_overflow(), "only way to reach here");
-      guarantee(!_cm->region_stack_overflow(), "only way to reach here");
 
       if (_cm->verbose_low()) {
         gclog_or_tty->print_cr("[%d] all tasks terminated", _task_id);
@@ -5342,7 +4281,6 @@
     _task_queue(task_queue),
     _task_queues(task_queues),
     _cm_oop_closure(NULL),
-    _aborted_region(MemRegion()),
     _marked_bytes_array(marked_bytes),
     _card_bm(card_bm) {
   guarantee(task_queue != NULL, "invariant");
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Tue May 15 11:27:24 2012 -0700
@@ -42,9 +42,7 @@
 class G1CMIsAliveClosure: public BoolObjectClosure {
   G1CollectedHeap* _g1;
  public:
-  G1CMIsAliveClosure(G1CollectedHeap* g1) :
-    _g1(g1)
-  {}
+  G1CMIsAliveClosure(G1CollectedHeap* g1) : _g1(g1) { }
 
   void do_object(oop obj) {
     ShouldNotCallThis();
@@ -111,11 +109,6 @@
     return offsetToHeapWord(heapWordToOffset(addr) + 1);
   }
 
-  void mostly_disjoint_range_union(BitMap*   from_bitmap,
-                                   size_t    from_start_index,
-                                   HeapWord* to_start_word,
-                                   size_t    word_num);
-
   // debugging
   NOT_PRODUCT(bool covers(ReservedSpace rs) const;)
 };
@@ -258,60 +251,6 @@
   void oops_do(OopClosure* f);
 };
 
-class CMRegionStack VALUE_OBJ_CLASS_SPEC {
-  MemRegion* _base;
-  jint _capacity;
-  jint _index;
-  jint _oops_do_bound;
-  bool _overflow;
-public:
-  CMRegionStack();
-  ~CMRegionStack();
-  void allocate(size_t size);
-
-  // This is lock-free; assumes that it will only be called in parallel
-  // with other "push" operations (no pops).
-  void push_lock_free(MemRegion mr);
-
-  // Lock-free; assumes that it will only be called in parallel
-  // with other "pop" operations (no pushes).
-  MemRegion pop_lock_free();
-
-#if 0
-  // The routines that manipulate the region stack with a lock are
-  // not currently used. They should be retained, however, as a
-  // diagnostic aid.
-
-  // These two are the implementations that use a lock. They can be
-  // called concurrently with each other but they should not be called
-  // concurrently with the lock-free versions (push() / pop()).
-  void push_with_lock(MemRegion mr);
-  MemRegion pop_with_lock();
-#endif
-
-  bool isEmpty()    { return _index == 0; }
-  bool isFull()     { return _index == _capacity; }
-
-  bool overflow() { return _overflow; }
-  void clear_overflow() { _overflow = false; }
-
-  int  size() { return _index; }
-
-  // It iterates over the entries in the region stack and it
-  // invalidates (i.e. assigns MemRegion()) the ones that point to
-  // regions in the collection set.
-  bool invalidate_entries_into_cset();
-
-  // This gives an upper bound up to which the iteration in
-  // invalidate_entries_into_cset() will reach. This prevents
-  // newly-added entries to be unnecessarily scanned.
-  void set_oops_do_bound() {
-    _oops_do_bound = _index;
-  }
-
-  void setEmpty()   { _index = 0; clear_overflow(); }
-};
-
 class ForceOverflowSettings VALUE_OBJ_CLASS_SPEC {
 private:
 #ifndef PRODUCT
@@ -408,7 +347,6 @@
   friend class ConcurrentMarkThread;
   friend class CMTask;
   friend class CMBitMapClosure;
-  friend class CSetMarkOopClosure;
   friend class CMGlobalObjectClosure;
   friend class CMRemarkTask;
   friend class CMConcurrentMarkingTask;
@@ -443,7 +381,6 @@
   CMBitMap                _markBitMap2;
   CMBitMapRO*             _prevMarkBitMap; // completed mark bitmap
   CMBitMap*               _nextMarkBitMap; // under-construction mark bitmap
-  bool                    _at_least_one_mark_complete;
 
   BitMap                  _region_bm;
   BitMap                  _card_bm;
@@ -457,7 +394,6 @@
 
   // For gray objects
   CMMarkStack             _markStack; // Grey objects behind global finger.
-  CMRegionStack           _regionStack; // Grey regions behind global finger.
   HeapWord* volatile      _finger;  // the global finger, region aligned,
                                     // always points to the end of the
                                     // last claimed region
@@ -502,18 +438,6 @@
   // verbose level
   CMVerboseLevel          _verbose_level;
 
-  // These two fields are used to implement the optimisation that
-  // avoids pushing objects on the global/region stack if there are
-  // no collection set regions above the lowest finger.
-
-  // This is the lowest finger (among the global and local fingers),
-  // which is calculated before a new collection set is chosen.
-  HeapWord* _min_finger;
-  // If this flag is true, objects/regions that are marked below the
-  // finger should be pushed on the stack(s). If this is flag is
-  // false, it is safe not to push them on the stack(s).
-  bool      _should_gray_objects;
-
   // All of these times are in ms.
   NumberSeq _init_times;
   NumberSeq _remark_times;
@@ -604,7 +528,7 @@
   CMTaskQueueSet* task_queues()  { return _task_queues; }
 
   // Access / manipulation of the overflow flag which is set to
-  // indicate that the global stack or region stack has overflown
+  // indicate that the global stack has overflown
   bool has_overflown()           { return _has_overflown; }
   void set_has_overflown()       { _has_overflown = true; }
   void clear_has_overflown()     { _has_overflown = false; }
@@ -684,68 +608,6 @@
   bool mark_stack_overflow()              { return _markStack.overflow(); }
   bool mark_stack_empty()                 { return _markStack.isEmpty(); }
 
-  // (Lock-free) Manipulation of the region stack
-  bool region_stack_push_lock_free(MemRegion mr) {
-    // Currently we only call the lock-free version during evacuation
-    // pauses.
-    assert(SafepointSynchronize::is_at_safepoint(), "world should be stopped");
-
-    _regionStack.push_lock_free(mr);
-    if (_regionStack.overflow()) {
-      set_has_overflown();
-      return false;
-    }
-    return true;
-  }
-
-  // Lock-free version of region-stack pop. Should only be
-  // called in tandem with other lock-free pops.
-  MemRegion region_stack_pop_lock_free() {
-    return _regionStack.pop_lock_free();
-  }
-
-#if 0
-  // The routines that manipulate the region stack with a lock are
-  // not currently used. They should be retained, however, as a
-  // diagnostic aid.
-
-  bool region_stack_push_with_lock(MemRegion mr) {
-    // Currently we only call the lock-based version during either
-    // concurrent marking or remark.
-    assert(!SafepointSynchronize::is_at_safepoint() || !concurrent(),
-           "if we are at a safepoint it should be the remark safepoint");
-
-    _regionStack.push_with_lock(mr);
-    if (_regionStack.overflow()) {
-      set_has_overflown();
-      return false;
-    }
-    return true;
-  }
-
-  MemRegion region_stack_pop_with_lock() {
-    // Currently we only call the lock-based version during either
-    // concurrent marking or remark.
-    assert(!SafepointSynchronize::is_at_safepoint() || !concurrent(),
-           "if we are at a safepoint it should be the remark safepoint");
-
-    return _regionStack.pop_with_lock();
-  }
-#endif
-
-  int region_stack_size()               { return _regionStack.size(); }
-  bool region_stack_overflow()          { return _regionStack.overflow(); }
-  bool region_stack_empty()             { return _regionStack.isEmpty(); }
-
-  // Iterate over any regions that were aborted while draining the
-  // region stack (any such regions are saved in the corresponding
-  // CMTask) and invalidate (i.e. assign to the empty MemRegion())
-  // any regions that point into the collection set.
-  bool invalidate_aborted_regions_in_cset();
-
-  // Returns true if there are any aborted memory regions.
-  bool has_aborted_regions();
-
   CMRootRegions* root_regions() { return &_root_regions; }
 
   bool concurrent_marking_in_progress() {
@@ -774,11 +636,7 @@
     return _task_queues->steal(task_num, hash_seed, obj);
   }
 
-  // It grays an object by first marking it. Then, if it's behind the
-  // global finger, it also pushes it on the global stack.
-  void deal_with_reference(oop obj);
-
-  ConcurrentMark(ReservedSpace rs, int max_regions);
+  ConcurrentMark(ReservedSpace rs, uint max_regions);
   ~ConcurrentMark();
 
   ConcurrentMarkThread* cmThread() { return _cmThread; }
@@ -810,22 +668,6 @@
   inline void grayRoot(oop obj, size_t word_size,
                        uint worker_id, HeapRegion* hr = NULL);
 
-  // It's used during evacuation pauses to gray a region, if
-  // necessary, and it's MT-safe. It assumes that the caller has
-  // marked any objects on that region. If _should_gray_objects is
-  // true and we're still doing concurrent marking, the region is
-  // pushed on the region stack, if it is located below the global
-  // finger, otherwise we do nothing.
-  void grayRegionIfNecessary(MemRegion mr);
-
-  // It's used during evacuation pauses to mark and, if necessary,
-  // gray a single object and it's MT-safe. It assumes the caller did
-  // not mark the object. If _should_gray_objects is true and we're
-  // still doing concurrent marking, the objects is pushed on the
-  // global stack, if it is located below the global finger, otherwise
-  // we do nothing.
-  void markAndGrayObjectIfNecessary(oop p);
-
   // It iterates over the heap and for each object it comes across it
   // will dump the contents of its reference fields, as well as
   // liveness information for the object and its referents. The dump
@@ -869,10 +711,6 @@
   // Do concurrent phase of marking, to a tentative transitive closure.
   void markFromRoots();
 
-  // Process all unprocessed SATB buffers. It is called at the
-  // beginning of an evacuation pause.
-  void drainAllSATBBuffers();
-
   void checkpointRootsFinal(bool clear_all_soft_refs);
   void checkpointRootsFinalWork();
   void cleanup();
@@ -899,10 +737,6 @@
     _markStack.note_end_of_gc();
   }
 
-  // Iterate over the oops in the mark stack and all local queues. It
-  // also calls invalidate_entries_into_cset() on the region stack.
-  void oops_do(OopClosure* f);
-
   // Verify that there are no CSet oops on the stacks (taskqueues /
   // global mark stack), enqueued SATB buffers, per-thread SATB
   // buffers, and fingers (global / per-task). The boolean parameters
@@ -919,40 +753,6 @@
   // unless the force parameter is true.
   void update_g1_committed(bool force = false);
 
-  void complete_marking_in_collection_set();
-
-  // It indicates that a new collection set is being chosen.
-  void newCSet();
-
-  // It registers a collection set heap region with CM. This is used
-  // to determine whether any heap regions are located above the finger.
-  void registerCSetRegion(HeapRegion* hr);
-
-  // Resets the region fields of any active CMTask whose region fields
-  // are in the collection set (i.e. the region currently claimed by
-  // the CMTask will be evacuated and may be used, subsequently, as
-  // an alloc region). When this happens the region fields in the CMTask
-  // are stale and, hence, should be cleared causing the worker thread
-  // to claim a new region.
-  void reset_active_task_region_fields_in_cset();
-
-  // Registers the maximum region-end associated with a set of
-  // regions with CM. Again this is used to determine whether any
-  // heap regions are located above the finger.
-  void register_collection_set_finger(HeapWord* max_finger) {
-    // max_finger is the highest heap region end of the regions currently
-    // contained in the collection set. If this value is larger than
-    // _min_finger then we need to gray objects.
-    // This routine is like registerCSetRegion but for an entire
-    // collection of regions.
-    if (max_finger > _min_finger) {
-      _should_gray_objects = true;
-    }
-  }
-
-  // Returns "true" if at least one mark has been completed.
-  bool at_least_one_mark_complete() { return _at_least_one_mark_complete; }
-
   bool isMarked(oop p) const {
     assert(p != NULL && p->is_oop(), "expected an oop");
     HeapWord* addr = (HeapWord*)p;
@@ -1164,23 +964,6 @@
   // limit of the region this task is scanning, NULL if we're not scanning one
   HeapWord*                   _region_limit;
 
-  // This is used only when we scan regions popped from the region
-  // stack. It records what the last object on such a region we
-  // scanned was. It is used to ensure that, if we abort region
-  // iteration, we do not rescan the first part of the region. This
-  // should be NULL when we're not scanning a region from the region
-  // stack.
-  HeapWord*                   _region_finger;
-
-  // If we abort while scanning a region we record the remaining
-  // unscanned portion and check this field when marking restarts.
-  // This avoids having to push on the region stack while other
-  // marking threads may still be popping regions.
-  // If we were to push the unscanned portion directly to the
-  // region stack then we would need to using locking versions
-  // of the push and pop operations.
-  MemRegion                   _aborted_region;
-
   // the number of words this task has scanned
   size_t                      _words_scanned;
   // When _words_scanned reaches this limit, the regular clock is
@@ -1268,8 +1051,6 @@
   int                         _global_transfers_to;
   int                         _global_transfers_from;
 
-  int                         _region_stack_pops;
-
   int                         _regions_claimed;
   int                         _objs_found_on_bitmap;
 
@@ -1347,15 +1128,6 @@
   bool has_timed_out()          { return _has_timed_out; }
   bool claimed()                { return _claimed; }
 
-  // Support routines for the partially scanned region that may be
-  // recorded as a result of aborting while draining the CMRegionStack
-  MemRegion aborted_region()    { return _aborted_region; }
-  void set_aborted_region(MemRegion mr)
-                                { _aborted_region = mr; }
-
-  // Clears any recorded partially scanned region
-  void clear_aborted_region()   { set_aborted_region(MemRegion()); }
-
   void set_cm_oop_closure(G1CMOopClosure* cm_oop_closure);
 
   // It grays the object by marking it and, if necessary, pushing it
@@ -1385,22 +1157,12 @@
   // buffers are available.
   void drain_satb_buffers();
 
-  // It keeps popping regions from the region stack and processing
-  // them until the region stack is empty.
-  void drain_region_stack(BitMapClosure* closure);
-
   // moves the local finger to a new location
   inline void move_finger_to(HeapWord* new_finger) {
     assert(new_finger >= _finger && new_finger < _region_limit, "invariant");
     _finger = new_finger;
   }
 
-  // moves the region finger to a new location
-  inline void move_region_finger_to(HeapWord* new_finger) {
-    assert(new_finger < _cm->finger(), "invariant");
-    _region_finger = new_finger;
-  }
-
   CMTask(int task_num, ConcurrentMark *cm,
          size_t* marked_bytes, BitMap* card_bm,
          CMTaskQueue* task_queue, CMTaskQueueSet* task_queues);
--- a/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp	Tue May 15 11:27:24 2012 -0700
@@ -49,7 +49,7 @@
   HeapWord* start = mr.start();
   HeapWord* last = mr.last();
   size_t region_size_bytes = mr.byte_size();
-  size_t index = hr->hrs_index();
+  uint index = hr->hrs_index();
 
   assert(!hr->continuesHumongous(), "should not be HC region");
   assert(hr == g1h->heap_region_containing(start), "sanity");
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Tue May 15 11:27:24 2012 -0700
@@ -26,6 +26,7 @@
 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
+#include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/g1MMUTracker.hpp"
 #include "gc_implementation/g1/vm_operations_g1.hpp"
 #include "memory/resourceArea.hpp"
@@ -104,7 +105,7 @@
 
       double scan_start = os::elapsedTime();
       if (!cm()->has_aborted()) {
-        if (PrintGC) {
+        if (G1Log::fine()) {
           gclog_or_tty->date_stamp(PrintGCDateStamps);
           gclog_or_tty->stamp(PrintGCTimeStamps);
           gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]");
@@ -113,7 +114,7 @@
         _cm->scanRootRegions();
 
         double scan_end = os::elapsedTime();
-        if (PrintGC) {
+        if (G1Log::fine()) {
           gclog_or_tty->date_stamp(PrintGCDateStamps);
           gclog_or_tty->stamp(PrintGCTimeStamps);
           gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf]",
@@ -122,7 +123,7 @@
       }
 
       double mark_start_sec = os::elapsedTime();
-      if (PrintGC) {
+      if (G1Log::fine()) {
         gclog_or_tty->date_stamp(PrintGCDateStamps);
         gclog_or_tty->stamp(PrintGCTimeStamps);
         gclog_or_tty->print_cr("[GC concurrent-mark-start]");
@@ -146,7 +147,7 @@
             os::sleep(current_thread, sleep_time_ms, false);
           }
 
-          if (PrintGC) {
+          if (G1Log::fine()) {
             gclog_or_tty->date_stamp(PrintGCDateStamps);
             gclog_or_tty->stamp(PrintGCTimeStamps);
             gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf sec]",
@@ -155,7 +156,7 @@
 
           CMCheckpointRootsFinalClosure final_cl(_cm);
           sprintf(verbose_str, "GC remark");
-          VM_CGC_Operation op(&final_cl, verbose_str);
+          VM_CGC_Operation op(&final_cl, verbose_str, true /* needs_pll */);
           VMThread::execute(&op);
         }
         if (cm()->restart_for_overflow() &&
@@ -165,7 +166,7 @@
         }
 
         if (cm()->restart_for_overflow()) {
-          if (PrintGC) {
+          if (G1Log::fine()) {
             gclog_or_tty->date_stamp(PrintGCDateStamps);
             gclog_or_tty->stamp(PrintGCTimeStamps);
             gclog_or_tty->print_cr("[GC concurrent-mark-restart-for-overflow]");
@@ -189,7 +190,7 @@
 
         CMCleanUp cl_cl(_cm);
         sprintf(verbose_str, "GC cleanup");
-        VM_CGC_Operation op(&cl_cl, verbose_str);
+        VM_CGC_Operation op(&cl_cl, verbose_str, false /* needs_pll */);
         VMThread::execute(&op);
       } else {
         // We don't want to update the marking status if a GC pause
@@ -211,7 +212,7 @@
         // reclaimed by cleanup.
 
         double cleanup_start_sec = os::elapsedTime();
-        if (PrintGC) {
+        if (G1Log::fine()) {
           gclog_or_tty->date_stamp(PrintGCDateStamps);
           gclog_or_tty->stamp(PrintGCTimeStamps);
           gclog_or_tty->print_cr("[GC concurrent-cleanup-start]");
@@ -232,7 +233,7 @@
         g1h->reset_free_regions_coming();
 
         double cleanup_end_sec = os::elapsedTime();
-        if (PrintGC) {
+        if (G1Log::fine()) {
           gclog_or_tty->date_stamp(PrintGCDateStamps);
           gclog_or_tty->stamp(PrintGCTimeStamps);
           gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]",
@@ -273,7 +274,7 @@
       _sts.leave();
 
       if (cm()->has_aborted()) {
-        if (PrintGC) {
+        if (G1Log::fine()) {
           gclog_or_tty->date_stamp(PrintGCDateStamps);
           gclog_or_tty->stamp(PrintGCTimeStamps);
           gclog_or_tty->print_cr("[GC concurrent-mark-abort]");
--- a/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,7 @@
 }
 
 void G1AllocRegion::fill_in_ext_msg(ar_ext_msg* msg, const char* message) {
-  msg->append("[%s] %s c: "SIZE_FORMAT" b: %s r: "PTR_FORMAT" u: "SIZE_FORMAT,
+  msg->append("[%s] %s c: %u b: %s r: "PTR_FORMAT" u: "SIZE_FORMAT,
               _name, message, _count, BOOL_TO_STR(_bot_updates),
               _alloc_region, _used_bytes_before);
 }
@@ -215,7 +215,7 @@
       jio_snprintf(rest_buffer, buffer_length, "");
     }
 
-    tty->print_cr("[%s] "SIZE_FORMAT" %s : %s %s",
+    tty->print_cr("[%s] %u %s : %s %s",
                   _name, _count, hr_buffer, str, rest_buffer);
   }
 }
--- a/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,7 +64,7 @@
   // the region that is re-used using the set() method. This count can
   // be used in any heuristics that might want to bound how many
   // distinct regions this object can used during an active interval.
-  size_t _count;
+  uint _count;
 
   // When we set up a new active region we save its used bytes in this
   // field so that, when we retire it, we can calculate how much space
@@ -136,7 +136,7 @@
     return (_alloc_region == _dummy_region) ? NULL : _alloc_region;
   }
 
-  size_t count() { return _count; }
+  uint count() { return _count; }
 
   // The following two are the building blocks for the allocation method.
 
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Tue May 15 11:27:24 2012 -0700
@@ -33,6 +33,7 @@
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
 #include "gc_implementation/g1/g1ErgoVerbose.hpp"
 #include "gc_implementation/g1/g1EvacFailure.hpp"
+#include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/g1MarkSweep.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
 #include "gc_implementation/g1/g1RemSet.inline.hpp"
@@ -233,7 +234,7 @@
 bool YoungList::check_list_well_formed() {
   bool ret = true;
 
-  size_t length = 0;
+  uint length = 0;
   HeapRegion* curr = _head;
   HeapRegion* last = NULL;
   while (curr != NULL) {
@@ -252,7 +253,7 @@
 
   if (!ret) {
     gclog_or_tty->print_cr("### YOUNG LIST seems not well formed!");
-    gclog_or_tty->print_cr("###   list has %d entries, _length is %d",
+    gclog_or_tty->print_cr("###   list has %u entries, _length is %u",
                            length, _length);
   }
 
@@ -263,7 +264,7 @@
   bool ret = true;
 
   if (_length != 0) {
-    gclog_or_tty->print_cr("### YOUNG LIST should have 0 length, not %d",
+    gclog_or_tty->print_cr("### YOUNG LIST should have 0 length, not %u",
                   _length);
     ret = false;
   }
@@ -336,8 +337,7 @@
     _g1h->g1_policy()->add_region_to_incremental_cset_rhs(curr);
     young_index_in_cset += 1;
   }
-  assert((size_t) young_index_in_cset == _survivor_length,
-         "post-condition");
+  assert((uint) young_index_in_cset == _survivor_length, "post-condition");
   _g1h->g1_policy()->note_stop_adding_survivor_regions();
 
   _head   = _survivor_head;
@@ -368,16 +368,11 @@
     if (curr == NULL)
       gclog_or_tty->print_cr("  empty");
     while (curr != NULL) {
-      gclog_or_tty->print_cr("  [%08x-%08x], t: %08x, P: %08x, N: %08x, C: %08x, "
-                             "age: %4d, y: %d, surv: %d",
-                             curr->bottom(), curr->end(),
-                             curr->top(),
+      gclog_or_tty->print_cr("  "HR_FORMAT", P: "PTR_FORMAT "N: "PTR_FORMAT", age: %4d",
+                             HR_FORMAT_PARAMS(curr),
                              curr->prev_top_at_mark_start(),
                              curr->next_top_at_mark_start(),
-                             curr->top_at_conc_mark_count(),
-                             curr->age_in_surv_rate_group_cond(),
-                             curr->is_young(),
-                             curr->is_survivor());
+                             curr->age_in_surv_rate_group_cond());
       curr = curr->get_next_young_region();
     }
   }
@@ -532,7 +527,7 @@
     if (!_secondary_free_list.is_empty()) {
       if (G1ConcRegionFreeingVerbose) {
         gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
-                               "secondary_free_list has "SIZE_FORMAT" entries",
+                               "secondary_free_list has %u entries",
                                _secondary_free_list.length());
       }
       // It looks as if there are free regions available on the
@@ -618,12 +613,12 @@
   return res;
 }
 
-size_t G1CollectedHeap::humongous_obj_allocate_find_first(size_t num_regions,
-                                                          size_t word_size) {
+uint G1CollectedHeap::humongous_obj_allocate_find_first(uint num_regions,
+                                                        size_t word_size) {
   assert(isHumongous(word_size), "word_size should be humongous");
   assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition");
 
-  size_t first = G1_NULL_HRS_INDEX;
+  uint first = G1_NULL_HRS_INDEX;
   if (num_regions == 1) {
     // Only one region to allocate, no need to go through the slower
     // path. The caller will attempt the expasion if this fails, so
@@ -649,7 +644,7 @@
     if (free_regions() >= num_regions) {
       first = _hrs.find_contiguous(num_regions);
       if (first != G1_NULL_HRS_INDEX) {
-        for (size_t i = first; i < first + num_regions; ++i) {
+        for (uint i = first; i < first + num_regions; ++i) {
           HeapRegion* hr = region_at(i);
           assert(hr->is_empty(), "sanity");
           assert(is_on_master_free_list(hr), "sanity");
@@ -663,15 +658,15 @@
 }
 
 HeapWord*
-G1CollectedHeap::humongous_obj_allocate_initialize_regions(size_t first,
-                                                           size_t num_regions,
+G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first,
+                                                           uint num_regions,
                                                            size_t word_size) {
   assert(first != G1_NULL_HRS_INDEX, "pre-condition");
   assert(isHumongous(word_size), "word_size should be humongous");
   assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition");
 
   // Index of last region in the series + 1.
-  size_t last = first + num_regions;
+  uint last = first + num_regions;
 
   // We need to initialize the region(s) we just discovered. This is
   // a bit tricky given that it can happen concurrently with
@@ -682,7 +677,7 @@
   // a specific order.
 
   // The word size sum of all the regions we will allocate.
-  size_t word_size_sum = num_regions * HeapRegion::GrainWords;
+  size_t word_size_sum = (size_t) num_regions * HeapRegion::GrainWords;
   assert(word_size <= word_size_sum, "sanity");
 
   // This will be the "starts humongous" region.
@@ -721,7 +716,7 @@
   // Then, if there are any, we will set up the "continues
   // humongous" regions.
   HeapRegion* hr = NULL;
-  for (size_t i = first + 1; i < last; ++i) {
+  for (uint i = first + 1; i < last; ++i) {
     hr = region_at(i);
     hr->set_continuesHumongous(first_hr);
   }
@@ -767,7 +762,7 @@
   // last one) is actually used when we will free up the humongous
   // region in free_humongous_region().
   hr = NULL;
-  for (size_t i = first + 1; i < last; ++i) {
+  for (uint i = first + 1; i < last; ++i) {
     hr = region_at(i);
     if ((i + 1) == last) {
       // last continues humongous region
@@ -803,14 +798,14 @@
 
   verify_region_sets_optional();
 
-  size_t num_regions =
-         round_to(word_size, HeapRegion::GrainWords) / HeapRegion::GrainWords;
-  size_t x_size = expansion_regions();
-  size_t fs = _hrs.free_suffix();
-  size_t first = humongous_obj_allocate_find_first(num_regions, word_size);
+  size_t word_size_rounded = round_to(word_size, HeapRegion::GrainWords);
+  uint num_regions = (uint) (word_size_rounded / HeapRegion::GrainWords);
+  uint x_num = expansion_regions();
+  uint fs = _hrs.free_suffix();
+  uint first = humongous_obj_allocate_find_first(num_regions, word_size);
   if (first == G1_NULL_HRS_INDEX) {
     // The only thing we can do now is attempt expansion.
-    if (fs + x_size >= num_regions) {
+    if (fs + x_num >= num_regions) {
       // If the number of regions we're trying to allocate for this
       // object is at most the number of regions in the free suffix,
       // then the call to humongous_obj_allocate_find_first() above
@@ -993,7 +988,7 @@
     // iteration (after taking the Heap_lock).
     result = _mutator_alloc_region.attempt_allocation(word_size,
                                                       false /* bot_updates */);
-    if (result != NULL ){
+    if (result != NULL) {
       return result;
     }
 
@@ -1253,12 +1248,13 @@
     IsGCActiveMark x;
 
     // Timing
-    bool system_gc = (gc_cause() == GCCause::_java_lang_system_gc);
-    assert(!system_gc || explicit_gc, "invariant");
-    gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
-    TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t(system_gc ? "Full GC (System.gc())" : "Full GC",
-                PrintGC, true, gclog_or_tty);
+    assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant");
+    gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
+    TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
+
+    char verbose_str[128];
+    sprintf(verbose_str, "Full GC (%s)", GCCause::to_string(gc_cause()));
+    TraceTime t(verbose_str, G1Log::fine(), true, gclog_or_tty);
 
     TraceCollectorStats tcs(g1mm()->full_collection_counters());
     TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());
@@ -1290,8 +1286,7 @@
       HandleMark hm;  // Discard invalid handles created during verification
       gclog_or_tty->print(" VerifyBeforeGC:");
       prepare_for_verify();
-      Universe::verify(/* allow dirty */ true,
-                       /* silent      */ false,
+      Universe::verify(/* silent      */ false,
                        /* option      */ VerifyOption_G1UsePrevMarking);
 
     }
@@ -1365,8 +1360,7 @@
       HandleMark hm;  // Discard invalid handles created during verification
       gclog_or_tty->print(" VerifyAfterGC:");
       prepare_for_verify();
-      Universe::verify(/* allow dirty */ false,
-                       /* silent      */ false,
+      Universe::verify(/* silent      */ false,
                        /* option      */ VerifyOption_G1UsePrevMarking);
 
     }
@@ -1444,7 +1438,7 @@
       heap_region_iterate(&rebuild_rs);
     }
 
-    if (PrintGC) {
+    if (G1Log::fine()) {
       print_size_transition(gclog_or_tty, g1h_prev_used, used(), capacity());
     }
 
@@ -1782,7 +1776,7 @@
     ReservedSpace::page_align_size_down(shrink_bytes);
   aligned_shrink_bytes = align_size_down(aligned_shrink_bytes,
                                          HeapRegion::GrainBytes);
-  size_t num_regions_deleted = 0;
+  uint num_regions_deleted = 0;
   MemRegion mr = _hrs.shrink_by(aligned_shrink_bytes, &num_regions_deleted);
   HeapWord* old_end = (HeapWord*) _g1_storage.high();
   assert(mr.end() == old_end, "post-condition");
@@ -1917,6 +1911,8 @@
   CollectedHeap::pre_initialize();
   os::enable_vtime();
 
+  G1Log::init();
+
   // Necessary to satisfy locking discipline assertions.
 
   MutexLocker x(Heap_lock);
@@ -2003,7 +1999,7 @@
   _reserved.set_start((HeapWord*)heap_rs.base());
   _reserved.set_end((HeapWord*)(heap_rs.base() + heap_rs.size()));
 
-  _expansion_regions = max_byte_size/HeapRegion::GrainBytes;
+  _expansion_regions = (uint) (max_byte_size / HeapRegion::GrainBytes);
 
   // Create the gen rem set (and barrier set) for the entire reserved region.
   _rem_set = collector_policy()->create_rem_set(_reserved, 2);
@@ -2040,7 +2036,7 @@
 
   // 6843694 - ensure that the maximum region index can fit
   // in the remembered set structures.
-  const size_t max_region_idx = ((size_t)1 << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1;
+  const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1;
   guarantee((max_regions() - 1) <= max_region_idx, "too many regions");
 
   size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1;
@@ -2056,13 +2052,14 @@
   _g1h = this;
 
    _in_cset_fast_test_length = max_regions();
-   _in_cset_fast_test_base = NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length);
+   _in_cset_fast_test_base =
+                   NEW_C_HEAP_ARRAY(bool, (size_t) _in_cset_fast_test_length);
 
    // We're biasing _in_cset_fast_test to avoid subtracting the
    // beginning of the heap every time we want to index; basically
    // it's the same with what we do with the card table.
    _in_cset_fast_test = _in_cset_fast_test_base -
-                ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes);
+               ((uintx) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes);
 
    // Clear the _cset_fast_test bitmap in anticipation of adding
    // regions to the incremental collection set for the first
@@ -2071,7 +2068,7 @@
 
   // Create the ConcurrentMark data structure and thread.
   // (Must do this late, so that "max_regions" is defined.)
-  _cm       = new ConcurrentMark(heap_rs, (int) max_regions());
+  _cm       = new ConcurrentMark(heap_rs, max_regions());
   _cmThread = _cm->cmThread();
 
   // Initialize the from_card cache structure of HeapRegionRemSet.
@@ -2437,20 +2434,22 @@
                                  true,  /* should_initiate_conc_mark */
                                  g1_policy()->max_pause_time_ms(),
                                  cause);
+
       VMThread::execute(&op);
       if (!op.pause_succeeded()) {
-        // Another GC got scheduled and prevented us from scheduling
-        // the initial-mark GC. It's unlikely that the GC that
-        // pre-empted us was also an initial-mark GC. So, we'll retry
-        // the initial-mark GC.
-
         if (full_gc_count_before == total_full_collections()) {
-          retry_gc = true;
+          retry_gc = op.should_retry_gc();
         } else {
           // A Full GC happened while we were trying to schedule the
           // initial-mark GC. No point in starting a new cycle given
           // that the whole heap was collected anyway.
         }
+
+        if (retry_gc) {
+          if (GC_locker::is_active_and_needs_gc()) {
+            GC_locker::stall_until_clear();
+          }
+        }
       }
     } else {
       if (cause == GCCause::_gc_locker
@@ -2578,7 +2577,7 @@
                                                  uint worker,
                                                  uint no_of_par_workers,
                                                  jint claim_value) {
-  const size_t regions = n_regions();
+  const uint regions = n_regions();
   const uint max_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
                              no_of_par_workers :
                              1);
@@ -2586,11 +2585,11 @@
          no_of_par_workers == workers()->total_workers(),
          "Non dynamic should use fixed number of workers");
   // try to spread out the starting points of the workers
-  const size_t start_index = regions / max_workers * (size_t) worker;
+  const uint start_index = regions / max_workers * worker;
 
   // each worker will actually look at all regions
-  for (size_t count = 0; count < regions; ++count) {
-    const size_t index = (start_index + count) % regions;
+  for (uint count = 0; count < regions; ++count) {
+    const uint index = (start_index + count) % regions;
     assert(0 <= index && index < regions, "sanity");
     HeapRegion* r = region_at(index);
     // we'll ignore "continues humongous" regions (we'll process them
@@ -2612,7 +2611,7 @@
         // result, we might end up processing them twice. So, we'll do
         // them first (notice: most closures will ignore them anyway) and
         // then we'll do the "starts humongous" region.
-        for (size_t ch_index = index + 1; ch_index < regions; ++ch_index) {
+        for (uint ch_index = index + 1; ch_index < regions; ++ch_index) {
           HeapRegion* chr = region_at(ch_index);
 
           // if the region has already been claimed or it's not
@@ -2680,8 +2679,9 @@
 class CheckClaimValuesClosure : public HeapRegionClosure {
 private:
   jint _claim_value;
-  size_t _failures;
+  uint _failures;
   HeapRegion* _sh_region;
+
 public:
   CheckClaimValuesClosure(jint claim_value) :
     _claim_value(claim_value), _failures(0), _sh_region(NULL) { }
@@ -2709,9 +2709,7 @@
     }
     return false;
   }
-  size_t failures() {
-    return _failures;
-  }
+  uint failures() { return _failures; }
 };
 
 bool G1CollectedHeap::check_heap_region_claim_values(jint claim_value) {
@@ -2721,17 +2719,15 @@
 }
 
 class CheckClaimValuesInCSetHRClosure: public HeapRegionClosure {
-  jint   _claim_value;
-  size_t _failures;
+private:
+  jint _claim_value;
+  uint _failures;
 
 public:
   CheckClaimValuesInCSetHRClosure(jint claim_value) :
-    _claim_value(claim_value),
-    _failures(0) { }
-
-  size_t failures() {
-    return _failures;
-  }
+    _claim_value(claim_value), _failures(0) { }
+
+  uint failures() { return _failures; }
 
   bool doHeapRegion(HeapRegion* hr) {
     assert(hr->in_collection_set(), "how?");
@@ -2798,14 +2794,14 @@
 
   result = g1_policy()->collection_set();
   if (G1CollectedHeap::use_parallel_gc_threads()) {
-    size_t cs_size = g1_policy()->cset_region_length();
+    uint cs_size = g1_policy()->cset_region_length();
     uint active_workers = workers()->active_workers();
     assert(UseDynamicNumberOfGCThreads ||
              active_workers == workers()->total_workers(),
              "Unless dynamic should use total workers");
 
-    size_t end_ind   = (cs_size * worker_i) / active_workers;
-    size_t start_ind = 0;
+    uint end_ind   = (cs_size * worker_i) / active_workers;
+    uint start_ind = 0;
 
     if (worker_i > 0 &&
         _worker_cset_start_region_time_stamp[worker_i - 1] == gc_time_stamp) {
@@ -2815,7 +2811,7 @@
       result = _worker_cset_start_region[worker_i - 1];
     }
 
-    for (size_t i = start_ind; i < end_ind; i++) {
+    for (uint i = start_ind; i < end_ind; i++) {
       result = result->next_in_collection_set();
     }
   }
@@ -3031,7 +3027,6 @@
 
 class VerifyRegionClosure: public HeapRegionClosure {
 private:
-  bool         _allow_dirty;
   bool         _par;
   VerifyOption _vo;
   bool         _failures;
@@ -3039,9 +3034,8 @@
   // _vo == UsePrevMarking -> use "prev" marking information,
   // _vo == UseNextMarking -> use "next" marking information,
   // _vo == UseMarkWord    -> use mark word from object header.
-  VerifyRegionClosure(bool allow_dirty, bool par, VerifyOption vo)
-    : _allow_dirty(allow_dirty),
-      _par(par),
+  VerifyRegionClosure(bool par, VerifyOption vo)
+    : _par(par),
       _vo(vo),
       _failures(false) {}
 
@@ -3054,7 +3048,7 @@
               "Should be unclaimed at verify points.");
     if (!r->continuesHumongous()) {
       bool failures = false;
-      r->verify(_allow_dirty, _vo, &failures);
+      r->verify(_vo, &failures);
       if (failures) {
         _failures = true;
       } else {
@@ -3122,7 +3116,6 @@
 class G1ParVerifyTask: public AbstractGangTask {
 private:
   G1CollectedHeap* _g1h;
-  bool             _allow_dirty;
   VerifyOption     _vo;
   bool             _failures;
 
@@ -3130,10 +3123,9 @@
   // _vo == UsePrevMarking -> use "prev" marking information,
   // _vo == UseNextMarking -> use "next" marking information,
   // _vo == UseMarkWord    -> use mark word from object header.
-  G1ParVerifyTask(G1CollectedHeap* g1h, bool allow_dirty, VerifyOption vo) :
+  G1ParVerifyTask(G1CollectedHeap* g1h, VerifyOption vo) :
     AbstractGangTask("Parallel verify task"),
     _g1h(g1h),
-    _allow_dirty(allow_dirty),
     _vo(vo),
     _failures(false) { }
 
@@ -3143,7 +3135,7 @@
 
   void work(uint worker_id) {
     HandleMark hm;
-    VerifyRegionClosure blk(_allow_dirty, true, _vo);
+    VerifyRegionClosure blk(true, _vo);
     _g1h->heap_region_par_iterate_chunked(&blk, worker_id,
                                           _g1h->workers()->active_workers(),
                                           HeapRegion::ParVerifyClaimValue);
@@ -3153,12 +3145,11 @@
   }
 };
 
-void G1CollectedHeap::verify(bool allow_dirty, bool silent) {
-  verify(allow_dirty, silent, VerifyOption_G1UsePrevMarking);
-}
-
-void G1CollectedHeap::verify(bool allow_dirty,
-                             bool silent,
+void G1CollectedHeap::verify(bool silent) {
+  verify(silent, VerifyOption_G1UsePrevMarking);
+}
+
+void G1CollectedHeap::verify(bool silent,
                              VerifyOption vo) {
   if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) {
     if (!silent) { gclog_or_tty->print("Roots (excluding permgen) "); }
@@ -3210,7 +3201,7 @@
       assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
              "sanity check");
 
-      G1ParVerifyTask task(this, allow_dirty, vo);
+      G1ParVerifyTask task(this, vo);
       assert(UseDynamicNumberOfGCThreads ||
         workers()->active_workers() == workers()->total_workers(),
         "If not dynamic should be using all the workers");
@@ -3232,7 +3223,7 @@
       assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
              "sanity check");
     } else {
-      VerifyRegionClosure blk(allow_dirty, false, vo);
+      VerifyRegionClosure blk(false, vo);
       heap_region_iterate(&blk);
       if (blk.failures()) {
         failures = true;
@@ -3282,12 +3273,12 @@
             _g1_storage.high_boundary());
   st->cr();
   st->print("  region size " SIZE_FORMAT "K, ", HeapRegion::GrainBytes / K);
-  size_t young_regions = _young_list->length();
-  st->print(SIZE_FORMAT " young (" SIZE_FORMAT "K), ",
-            young_regions, young_regions * HeapRegion::GrainBytes / K);
-  size_t survivor_regions = g1_policy()->recorded_survivor_regions();
-  st->print(SIZE_FORMAT " survivors (" SIZE_FORMAT "K)",
-            survivor_regions, survivor_regions * HeapRegion::GrainBytes / K);
+  uint young_regions = _young_list->length();
+  st->print("%u young (" SIZE_FORMAT "K), ", young_regions,
+            (size_t) young_regions * HeapRegion::GrainBytes / K);
+  uint survivor_regions = g1_policy()->recorded_survivor_regions();
+  st->print("%u survivors (" SIZE_FORMAT "K)", survivor_regions,
+            (size_t) survivor_regions * HeapRegion::GrainBytes / K);
   st->cr();
   perm()->as_gen()->print_on(st);
 }
@@ -3297,7 +3288,11 @@
 
   // Print the per-region information.
   st->cr();
-  st->print_cr("Heap Regions: (Y=young(eden), SU=young(survivor), HS=humongous(starts), HC=humongous(continues), CS=collection set, F=free, TS=gc time stamp, PTAMS=previous top-at-mark-start, NTAMS=next top-at-mark-start)");
+  st->print_cr("Heap Regions: (Y=young(eden), SU=young(survivor), "
+               "HS=humongous(starts), HC=humongous(continues), "
+               "CS=collection set, F=free, TS=gc time stamp, "
+               "PTAMS=previous top-at-mark-start, "
+               "NTAMS=next top-at-mark-start)");
   PrintRegionClosure blk(st);
   heap_region_iterate(&blk);
 }
@@ -3475,16 +3470,16 @@
 
 void
 G1CollectedHeap::setup_surviving_young_words() {
-  guarantee( _surviving_young_words == NULL, "pre-condition" );
-  size_t array_length = g1_policy()->young_cset_region_length();
-  _surviving_young_words = NEW_C_HEAP_ARRAY(size_t, array_length);
+  assert(_surviving_young_words == NULL, "pre-condition");
+  uint array_length = g1_policy()->young_cset_region_length();
+  _surviving_young_words = NEW_C_HEAP_ARRAY(size_t, (size_t) array_length);
   if (_surviving_young_words == NULL) {
     vm_exit_out_of_memory(sizeof(size_t) * array_length,
                           "Not enough space for young surv words summary.");
   }
-  memset(_surviving_young_words, 0, array_length * sizeof(size_t));
+  memset(_surviving_young_words, 0, (size_t) array_length * sizeof(size_t));
 #ifdef ASSERT
-  for (size_t i = 0;  i < array_length; ++i) {
+  for (uint i = 0;  i < array_length; ++i) {
     assert( _surviving_young_words[i] == 0, "memset above" );
   }
 #endif // !ASSERT
@@ -3493,9 +3488,10 @@
 void
 G1CollectedHeap::update_surviving_young_words(size_t* surv_young_words) {
   MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
-  size_t array_length = g1_policy()->young_cset_region_length();
-  for (size_t i = 0; i < array_length; ++i)
+  uint array_length = g1_policy()->young_cset_region_length();
+  for (uint i = 0; i < array_length; ++i) {
     _surviving_young_words[i] += surv_young_words[i];
+  }
 }
 
 void
@@ -3593,26 +3589,23 @@
 
   // Inner scope for scope based logging, timers, and stats collection
   {
-    char verbose_str[128];
-    sprintf(verbose_str, "GC pause ");
-    if (g1_policy()->gcs_are_young()) {
-      strcat(verbose_str, "(young)");
-    } else {
-      strcat(verbose_str, "(mixed)");
-    }
     if (g1_policy()->during_initial_mark_pause()) {
-      strcat(verbose_str, " (initial-mark)");
       // We are about to start a marking cycle, so we increment the
       // full collection counter.
       increment_total_full_collections();
     }
-
-    // if PrintGCDetails is on, we'll print long statistics information
+    // if the log level is "finer" is on, we'll print long statistics information
     // in the collector policy code, so let's not print this as the output
     // is messy if we do.
-    gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
-    TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    TraceTime t(verbose_str, PrintGC && !PrintGCDetails, true, gclog_or_tty);
+    gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
+    TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
+
+    char verbose_str[128];
+    sprintf(verbose_str, "GC pause (%s) (%s)%s",
+      GCCause::to_string(gc_cause()),
+      g1_policy()->gcs_are_young() ? "young" : "mixed",
+      g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
+    TraceTime t(verbose_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty);
 
     TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
     TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());
@@ -3645,8 +3638,7 @@
         HandleMark hm;  // Discard invalid handles created during verification
         gclog_or_tty->print(" VerifyBeforeGC:");
         prepare_for_verify();
-        Universe::verify(/* allow dirty */ false,
-                         /* silent      */ false,
+        Universe::verify(/* silent      */ false,
                          /* option      */ VerifyOption_G1UsePrevMarking);
       }
 
@@ -3890,8 +3882,7 @@
           HandleMark hm;  // Discard invalid handles created during verification
           gclog_or_tty->print(" VerifyAfterGC:");
           prepare_for_verify();
-          Universe::verify(/* allow dirty */ true,
-                           /* silent      */ false,
+          Universe::verify(/* silent      */ false,
                            /* option      */ VerifyOption_G1UsePrevMarking);
         }
 
@@ -3929,8 +3920,8 @@
   }
 
   // The closing of the inner scope, immediately above, will complete
-  // the PrintGC logging output. The record_collection_pause_end() call
-  // above will complete the logging output of PrintGCDetails.
+  // logging at the "fine" level. The record_collection_pause_end() call
+  // above will complete logging at the "finer" level.
   //
   // It is not yet to safe, however, to tell the concurrent mark to
   // start as we have some optional output below. We don't want the
@@ -4066,7 +4057,6 @@
 
 void G1CollectedHeap::remove_self_forwarding_pointers() {
   assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
-  assert(g1_policy()->assertMarkedBytesDataOK(), "Should be!");
 
   G1ParRemoveSelfForwardPtrsTask rsfp_task(this);
 
@@ -4084,7 +4074,6 @@
   reset_cset_heap_region_claim_values();
 
   assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
-  assert(g1_policy()->assertMarkedBytesDataOK(), "Should be!");
 
   // Now restore saved marks, if any.
   if (_objs_with_preserved_marks != NULL) {
@@ -4246,16 +4235,16 @@
   // non-young regions (where the age is -1)
   // We also add a few elements at the beginning and at the end in
   // an attempt to eliminate cache contention
-  size_t real_length = 1 + _g1h->g1_policy()->young_cset_region_length();
-  size_t array_length = PADDING_ELEM_NUM +
-                        real_length +
-                        PADDING_ELEM_NUM;
+  uint real_length = 1 + _g1h->g1_policy()->young_cset_region_length();
+  uint array_length = PADDING_ELEM_NUM +
+                      real_length +
+                      PADDING_ELEM_NUM;
   _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length);
   if (_surviving_young_words_base == NULL)
     vm_exit_out_of_memory(array_length * sizeof(size_t),
                           "Not enough space for young surv histo.");
   _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
-  memset(_surviving_young_words, 0, real_length * sizeof(size_t));
+  memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t));
 
   _alloc_buffers[GCAllocForSurvived] = &_surviving_alloc_buffer;
   _alloc_buffers[GCAllocForTenured]  = &_tenured_alloc_buffer;
@@ -4353,7 +4342,8 @@
   _during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()),
   _mark_in_progress(_g1->mark_in_progress()) { }
 
-void G1ParCopyHelper::mark_object(oop obj) {
+template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
+void G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object>::mark_object(oop obj) {
 #ifdef ASSERT
   HeapRegion* hr = _g1->heap_region_containing(obj);
   assert(hr != NULL, "sanity");
@@ -4364,7 +4354,9 @@
   _cm->grayRoot(obj, (size_t) obj->size(), _worker_id);
 }
 
-void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) {
+template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
+void G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object>
+  ::mark_forwarded_object(oop from_obj, oop to_obj) {
 #ifdef ASSERT
   assert(from_obj->is_forwarded(), "from obj should be forwarded");
   assert(from_obj->forwardee() == to_obj, "to obj should be the forwardee");
@@ -4386,8 +4378,10 @@
   _cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id);
 }
 
-oop G1ParCopyHelper::copy_to_survivor_space(oop old) {
-  size_t    word_sz = old->size();
+template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
+oop G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object>
+  ::copy_to_survivor_space(oop old) {
+  size_t word_sz = old->size();
   HeapRegion* from_region = _g1->heap_region_containing_raw(old);
   // +1 to make the -1 indexes valid...
   int       young_index = from_region->young_index_in_cset()+1;
@@ -4455,8 +4449,8 @@
     } else {
       // No point in using the slower heap_region_containing() method,
       // given that we know obj is in the heap.
-      _scanner->set_region(_g1->heap_region_containing_raw(obj));
-      obj->oop_iterate_backwards(_scanner);
+      _scanner.set_region(_g1->heap_region_containing_raw(obj));
+      obj->oop_iterate_backwards(&_scanner);
     }
   } else {
     _par_scan_state->undo_allocation(alloc_purpose, obj_ptr, word_sz);
@@ -4673,67 +4667,74 @@
     double start_time_ms = os::elapsedTime() * 1000.0;
     _g1h->g1_policy()->record_gc_worker_start_time(worker_id, start_time_ms);
 
-    ResourceMark rm;
-    HandleMark   hm;
-
-    ReferenceProcessor*             rp = _g1h->ref_processor_stw();
-
-    G1ParScanThreadState            pss(_g1h, worker_id);
-    G1ParScanHeapEvacClosure        scan_evac_cl(_g1h, &pss, rp);
-    G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp);
-    G1ParScanPartialArrayClosure    partial_scan_cl(_g1h, &pss, rp);
-
-    pss.set_evac_closure(&scan_evac_cl);
-    pss.set_evac_failure_closure(&evac_failure_cl);
-    pss.set_partial_scan_closure(&partial_scan_cl);
-
-    G1ParScanExtRootClosure        only_scan_root_cl(_g1h, &pss, rp);
-    G1ParScanPermClosure           only_scan_perm_cl(_g1h, &pss, rp);
-
-    G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss, rp);
-    G1ParScanAndMarkPermClosure    scan_mark_perm_cl(_g1h, &pss, rp);
-
-    OopClosure*                    scan_root_cl = &only_scan_root_cl;
-    OopsInHeapRegionClosure*       scan_perm_cl = &only_scan_perm_cl;
-
-    if (_g1h->g1_policy()->during_initial_mark_pause()) {
-      // We also need to mark copied objects.
-      scan_root_cl = &scan_mark_root_cl;
-      scan_perm_cl = &scan_mark_perm_cl;
+    {
+      ResourceMark rm;
+      HandleMark   hm;
+
+      ReferenceProcessor*             rp = _g1h->ref_processor_stw();
+
+      G1ParScanThreadState            pss(_g1h, worker_id);
+      G1ParScanHeapEvacClosure        scan_evac_cl(_g1h, &pss, rp);
+      G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp);
+      G1ParScanPartialArrayClosure    partial_scan_cl(_g1h, &pss, rp);
+
+      pss.set_evac_closure(&scan_evac_cl);
+      pss.set_evac_failure_closure(&evac_failure_cl);
+      pss.set_partial_scan_closure(&partial_scan_cl);
+
+      G1ParScanExtRootClosure        only_scan_root_cl(_g1h, &pss, rp);
+      G1ParScanPermClosure           only_scan_perm_cl(_g1h, &pss, rp);
+
+      G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss, rp);
+      G1ParScanAndMarkPermClosure    scan_mark_perm_cl(_g1h, &pss, rp);
+
+      OopClosure*                    scan_root_cl = &only_scan_root_cl;
+      OopsInHeapRegionClosure*       scan_perm_cl = &only_scan_perm_cl;
+
+      if (_g1h->g1_policy()->during_initial_mark_pause()) {
+        // We also need to mark copied objects.
+        scan_root_cl = &scan_mark_root_cl;
+        scan_perm_cl = &scan_mark_perm_cl;
+      }
+
+      G1ParPushHeapRSClosure          push_heap_rs_cl(_g1h, &pss);
+
+      pss.start_strong_roots();
+      _g1h->g1_process_strong_roots(/* not collecting perm */ false,
+                                    SharedHeap::SO_AllClasses,
+                                    scan_root_cl,
+                                    &push_heap_rs_cl,
+                                    scan_perm_cl,
+                                    worker_id);
+      pss.end_strong_roots();
+
+      {
+        double start = os::elapsedTime();
+        G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator);
+        evac.do_void();
+        double elapsed_ms = (os::elapsedTime()-start)*1000.0;
+        double term_ms = pss.term_time()*1000.0;
+        _g1h->g1_policy()->record_obj_copy_time(worker_id, elapsed_ms-term_ms);
+        _g1h->g1_policy()->record_termination(worker_id, term_ms, pss.term_attempts());
+      }
+      _g1h->g1_policy()->record_thread_age_table(pss.age_table());
+      _g1h->update_surviving_young_words(pss.surviving_young_words()+1);
+
+      // Clean up any par-expanded rem sets.
+      HeapRegionRemSet::par_cleanup();
+
+      if (ParallelGCVerbose) {
+        MutexLocker x(stats_lock());
+        pss.print_termination_stats(worker_id);
+      }
+
+      assert(pss.refs()->is_empty(), "should be empty");
+
+      // Close the inner scope so that the ResourceMark and HandleMark
+      // destructors are executed here and are included as part of the
+      // "GC Worker Time".
     }
 
-    G1ParPushHeapRSClosure          push_heap_rs_cl(_g1h, &pss);
-
-    pss.start_strong_roots();
-    _g1h->g1_process_strong_roots(/* not collecting perm */ false,
-                                  SharedHeap::SO_AllClasses,
-                                  scan_root_cl,
-                                  &push_heap_rs_cl,
-                                  scan_perm_cl,
-                                  worker_id);
-    pss.end_strong_roots();
-
-    {
-      double start = os::elapsedTime();
-      G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator);
-      evac.do_void();
-      double elapsed_ms = (os::elapsedTime()-start)*1000.0;
-      double term_ms = pss.term_time()*1000.0;
-      _g1h->g1_policy()->record_obj_copy_time(worker_id, elapsed_ms-term_ms);
-      _g1h->g1_policy()->record_termination(worker_id, term_ms, pss.term_attempts());
-    }
-    _g1h->g1_policy()->record_thread_age_table(pss.age_table());
-    _g1h->update_surviving_young_words(pss.surviving_young_words()+1);
-
-    // Clean up any par-expanded rem sets.
-    HeapRegionRemSet::par_cleanup();
-
-    if (ParallelGCVerbose) {
-      MutexLocker x(stats_lock());
-      pss.print_termination_stats(worker_id);
-    }
-
-    assert(pss.refs()->is_empty(), "should be empty");
     double end_time_ms = os::elapsedTime() * 1000.0;
     _g1h->g1_policy()->record_gc_worker_end_time(worker_id, end_time_ms);
   }
@@ -4741,6 +4742,67 @@
 
 // *** Common G1 Evacuation Stuff
 
+// Closures that support the filtering of CodeBlobs scanned during
+// external root scanning.
+
+// Closure applied to reference fields in code blobs (specifically nmethods)
+// to determine whether an nmethod contains references that point into
+// the collection set. Used as a predicate when walking code roots so
+// that only nmethods that point into the collection set are added to the
+// 'marked' list.
+
+class G1FilteredCodeBlobToOopClosure : public CodeBlobToOopClosure {
+
+  class G1PointsIntoCSOopClosure : public OopClosure {
+    G1CollectedHeap* _g1;
+    bool _points_into_cs;
+  public:
+    G1PointsIntoCSOopClosure(G1CollectedHeap* g1) :
+      _g1(g1), _points_into_cs(false) { }
+
+    bool points_into_cs() const { return _points_into_cs; }
+
+    template <class T>
+    void do_oop_nv(T* p) {
+      if (!_points_into_cs) {
+        T heap_oop = oopDesc::load_heap_oop(p);
+        if (!oopDesc::is_null(heap_oop) &&
+            _g1->in_cset_fast_test(oopDesc::decode_heap_oop_not_null(heap_oop))) {
+          _points_into_cs = true;
+        }
+      }
+    }
+
+    virtual void do_oop(oop* p)        { do_oop_nv(p); }
+    virtual void do_oop(narrowOop* p)  { do_oop_nv(p); }
+  };
+
+  G1CollectedHeap* _g1;
+
+public:
+  G1FilteredCodeBlobToOopClosure(G1CollectedHeap* g1, OopClosure* cl) :
+    CodeBlobToOopClosure(cl, true), _g1(g1) { }
+
+  virtual void do_code_blob(CodeBlob* cb) {
+    nmethod* nm = cb->as_nmethod_or_null();
+    if (nm != NULL && !(nm->test_oops_do_mark())) {
+      G1PointsIntoCSOopClosure predicate_cl(_g1);
+      nm->oops_do(&predicate_cl);
+
+      if (predicate_cl.points_into_cs()) {
+        // At least one of the reference fields or the oop relocations
+        // in the nmethod points into the collection set. We have to
+        // 'mark' this nmethod.
+        // Note: Revisit the following if CodeBlobToOopClosure::do_code_blob()
+        // or MarkingCodeBlobClosure::do_code_blob() change.
+        if (!nm->test_set_oops_do_mark()) {
+          do_newly_marked_nmethod(nm);
+        }
+      }
+    }
+  }
+};
+
 // This method is run in a GC worker.
 
 void
@@ -4762,7 +4824,7 @@
 
   // Walk the code cache w/o buffering, because StarTask cannot handle
   // unaligned oop locations.
-  CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, /*do_marking=*/ true);
+  G1FilteredCodeBlobToOopClosure eager_scan_code_roots(this, scan_non_heap_roots);
 
   process_strong_roots(false, // no scoping; this is parallel code
                        collecting_perm_gen, so,
@@ -5376,25 +5438,39 @@
   rem_set()->prepare_for_younger_refs_iterate(true);
 
   assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
-  double start_par = os::elapsedTime();
-
-  if (G1CollectedHeap::use_parallel_gc_threads()) {
-    // The individual threads will set their evac-failure closures.
+  double start_par_time_sec = os::elapsedTime();
+  double end_par_time_sec;
+
+  {
     StrongRootsScope srs(this);
-    if (ParallelGCVerbose) G1ParScanThreadState::print_termination_stats_hdr();
-    // These tasks use ShareHeap::_process_strong_tasks
-    assert(UseDynamicNumberOfGCThreads ||
-           workers()->active_workers() == workers()->total_workers(),
-           "If not dynamic should be using all the  workers");
-    workers()->run_task(&g1_par_task);
-  } else {
-    StrongRootsScope srs(this);
-    g1_par_task.set_for_termination(n_workers);
-    g1_par_task.work(0);
-  }
-
-  double par_time = (os::elapsedTime() - start_par) * 1000.0;
-  g1_policy()->record_par_time(par_time);
+
+    if (G1CollectedHeap::use_parallel_gc_threads()) {
+      // The individual threads will set their evac-failure closures.
+      if (ParallelGCVerbose) G1ParScanThreadState::print_termination_stats_hdr();
+      // These tasks use ShareHeap::_process_strong_tasks
+      assert(UseDynamicNumberOfGCThreads ||
+             workers()->active_workers() == workers()->total_workers(),
+             "If not dynamic should be using all the  workers");
+      workers()->run_task(&g1_par_task);
+    } else {
+      g1_par_task.set_for_termination(n_workers);
+      g1_par_task.work(0);
+    }
+    end_par_time_sec = os::elapsedTime();
+
+    // Closing the inner scope will execute the destructor
+    // for the StrongRootsScope object. We record the current
+    // elapsed time before closing the scope so that time
+    // taken for the SRS destructor is NOT included in the
+    // reported parallel time.
+  }
+
+  double par_time_ms = (end_par_time_sec - start_par_time_sec) * 1000.0;
+  g1_policy()->record_par_time(par_time_ms);
+
+  double code_root_fixup_time_ms =
+        (os::elapsedTime() - end_par_time_sec) * 1000.0;
+  g1_policy()->record_code_root_fixup_time(code_root_fixup_time_ms);
 
   set_par_threads(0);
 
@@ -5425,9 +5501,9 @@
 
   if (evacuation_failed()) {
     remove_self_forwarding_pointers();
-    if (PrintGCDetails) {
+    if (G1Log::finer()) {
       gclog_or_tty->print(" (to-space overflow)");
-    } else if (PrintGC) {
+    } else if (G1Log::fine()) {
       gclog_or_tty->print("--");
     }
   }
@@ -5502,8 +5578,8 @@
   hr->set_notHumongous();
   free_region(hr, &hr_pre_used, free_list, par);
 
-  size_t i = hr->hrs_index() + 1;
-  size_t num = 1;
+  uint i = hr->hrs_index() + 1;
+  uint num = 1;
   while (i < n_regions()) {
     HeapRegion* curr_hr = region_at(i);
     if (!curr_hr->continuesHumongous()) {
@@ -5712,7 +5788,7 @@
     if (cur->is_young()) {
       int index = cur->young_index_in_cset();
       assert(index != -1, "invariant");
-      assert((size_t) index < policy->young_cset_region_length(), "invariant");
+      assert((uint) index < policy->young_cset_region_length(), "invariant");
       size_t words_survived = _surviving_young_words[index];
       cur->record_surv_words_in_group(words_survived);
 
@@ -6052,7 +6128,7 @@
 // Methods for the GC alloc regions
 
 HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size,
-                                                 size_t count,
+                                                 uint count,
                                                  GCAllocPurpose ap) {
   assert(FreeList_lock->owned_by_self(), "pre-condition");
 
@@ -6124,7 +6200,7 @@
   FreeRegionList*     _free_list;
   OldRegionSet*       _old_set;
   HumongousRegionSet* _humongous_set;
-  size_t              _region_count;
+  uint                _region_count;
 
 public:
   VerifyRegionListsClosure(OldRegionSet* old_set,
@@ -6133,7 +6209,7 @@
     _old_set(old_set), _humongous_set(humongous_set),
     _free_list(free_list), _region_count(0) { }
 
-  size_t region_count()      { return _region_count;      }
+  uint region_count() { return _region_count; }
 
   bool doHeapRegion(HeapRegion* hr) {
     _region_count += 1;
@@ -6155,7 +6231,7 @@
   }
 };
 
-HeapRegion* G1CollectedHeap::new_heap_region(size_t hrs_index,
+HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
                                              HeapWord* bottom) {
   HeapWord* end = bottom + HeapRegion::GrainWords;
   MemRegion mr(bottom, end);
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Tue May 15 11:27:24 2012 -0700
@@ -85,8 +85,8 @@
 
   HeapRegion* _curr;
 
-  size_t      _length;
-  size_t      _survivor_length;
+  uint        _length;
+  uint        _survivor_length;
 
   size_t      _last_sampled_rs_lengths;
   size_t      _sampled_rs_lengths;
@@ -101,8 +101,8 @@
 
   void         empty_list();
   bool         is_empty() { return _length == 0; }
-  size_t       length() { return _length; }
-  size_t       survivor_length() { return _survivor_length; }
+  uint         length() { return _length; }
+  uint         survivor_length() { return _survivor_length; }
 
   // Currently we do not keep track of the used byte sum for the
   // young list and the survivors and it'd be quite a lot of work to
@@ -111,10 +111,10 @@
   // we'll report the more accurate information then.
   size_t       eden_used_bytes() {
     assert(length() >= survivor_length(), "invariant");
-    return (length() - survivor_length()) * HeapRegion::GrainBytes;
+    return (size_t) (length() - survivor_length()) * HeapRegion::GrainBytes;
   }
   size_t       survivor_used_bytes() {
-    return survivor_length() * HeapRegion::GrainBytes;
+    return (size_t) survivor_length() * HeapRegion::GrainBytes;
   }
 
   void rs_length_sampling_init();
@@ -199,7 +199,8 @@
   friend class OldGCAllocRegion;
 
   // Closures used in implementation.
-  friend class G1ParCopyHelper;
+  template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
+  friend class G1ParCopyClosure;
   friend class G1IsAliveClosure;
   friend class G1EvacuateFollowersClosure;
   friend class G1ParScanThreadState;
@@ -246,7 +247,7 @@
   MasterHumongousRegionSet  _humongous_set;
 
   // The number of regions we could create by expansion.
-  size_t _expansion_regions;
+  uint _expansion_regions;
 
   // The block offset table for the G1 heap.
   G1BlockOffsetSharedArray* _bot_shared;
@@ -338,7 +339,7 @@
   bool* _in_cset_fast_test_base;
 
   // The length of the _in_cset_fast_test_base array.
-  size_t _in_cset_fast_test_length;
+  uint _in_cset_fast_test_length;
 
   volatile unsigned _gc_time_stamp;
 
@@ -457,14 +458,14 @@
   // length and remove them from the master free list. Return the
   // index of the first region or G1_NULL_HRS_INDEX if the search
   // was unsuccessful.
-  size_t humongous_obj_allocate_find_first(size_t num_regions,
-                                           size_t word_size);
+  uint humongous_obj_allocate_find_first(uint num_regions,
+                                         size_t word_size);
 
   // Initialize a contiguous set of free regions of length num_regions
   // and starting at index first so that they appear as a single
   // humongous region.
-  HeapWord* humongous_obj_allocate_initialize_regions(size_t first,
-                                                      size_t num_regions,
+  HeapWord* humongous_obj_allocate_initialize_regions(uint first,
+                                                      uint num_regions,
                                                       size_t word_size);
 
   // Attempt to allocate a humongous object of the given size. Return
@@ -573,7 +574,7 @@
                                    size_t allocated_bytes);
 
   // For GC alloc regions.
-  HeapRegion* new_gc_alloc_region(size_t word_size, size_t count,
+  HeapRegion* new_gc_alloc_region(size_t word_size, uint count,
                                   GCAllocPurpose ap);
   void retire_gc_alloc_region(HeapRegion* alloc_region,
                               size_t allocated_bytes, GCAllocPurpose ap);
@@ -640,7 +641,7 @@
   void register_region_with_in_cset_fast_test(HeapRegion* r) {
     assert(_in_cset_fast_test_base != NULL, "sanity");
     assert(r->in_collection_set(), "invariant");
-    size_t index = r->hrs_index();
+    uint index = r->hrs_index();
     assert(index < _in_cset_fast_test_length, "invariant");
     assert(!_in_cset_fast_test_base[index], "invariant");
     _in_cset_fast_test_base[index] = true;
@@ -654,7 +655,7 @@
     if (_g1_committed.contains((HeapWord*) obj)) {
       // no need to subtract the bottom of the heap from obj,
       // _in_cset_fast_test is biased
-      size_t index = ((size_t) obj) >> HeapRegion::LogOfHRGrainBytes;
+      uintx index = (uintx) obj >> HeapRegion::LogOfHRGrainBytes;
       bool ret = _in_cset_fast_test[index];
       // let's make sure the result is consistent with what the slower
       // test returns
@@ -669,7 +670,7 @@
   void clear_cset_fast_test() {
     assert(_in_cset_fast_test_base != NULL, "sanity");
     memset(_in_cset_fast_test_base, false,
-        _in_cset_fast_test_length * sizeof(bool));
+           (size_t) _in_cset_fast_test_length * sizeof(bool));
   }
 
   // This is called at the end of either a concurrent cycle or a Full
@@ -1100,23 +1101,23 @@
   }
 
   // The total number of regions in the heap.
-  size_t n_regions() { return _hrs.length(); }
+  uint n_regions() { return _hrs.length(); }
 
   // The max number of regions in the heap.
-  size_t max_regions() { return _hrs.max_length(); }
+  uint max_regions() { return _hrs.max_length(); }
 
   // The number of regions that are completely free.
-  size_t free_regions() { return _free_list.length(); }
+  uint free_regions() { return _free_list.length(); }
 
   // The number of regions that are not completely free.
-  size_t used_regions() { return n_regions() - free_regions(); }
+  uint used_regions() { return n_regions() - free_regions(); }
 
   // The number of regions available for "regular" expansion.
-  size_t expansion_regions() { return _expansion_regions; }
+  uint expansion_regions() { return _expansion_regions; }
 
   // Factory method for HeapRegion instances. It will return NULL if
   // the allocation fails.
-  HeapRegion* new_heap_region(size_t hrs_index, HeapWord* bottom);
+  HeapRegion* new_heap_region(uint hrs_index, HeapWord* bottom);
 
   void verify_not_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
   void verify_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
@@ -1300,7 +1301,7 @@
   void heap_region_iterate_from(HeapRegion* r, HeapRegionClosure* blk) const;
 
   // Return the region with the given index. It assumes the index is valid.
-  HeapRegion* region_at(size_t index) const { return _hrs.at(index); }
+  HeapRegion* region_at(uint index) const { return _hrs.at(index); }
 
   // Divide the heap region sequence into "chunks" of some size (the number
   // of regions divided by the number of parallel threads times some
@@ -1503,10 +1504,10 @@
   // Currently there is only one place where this is called with
   // vo == UseMarkWord, which is to verify the marking during a
   // full GC.
-  void verify(bool allow_dirty, bool silent, VerifyOption vo);
+  void verify(bool silent, VerifyOption vo);
 
   // Override; it uses the "prev" marking information
-  virtual void verify(bool allow_dirty, bool silent);
+  virtual void verify(bool silent);
   virtual void print_on(outputStream* st) const;
   virtual void print_extended_on(outputStream* st) const;
 
@@ -1676,202 +1677,6 @@
   size_t _max_heap_capacity;
 };
 
-#define use_local_bitmaps         1
-#define verify_local_bitmaps      0
-#define oop_buffer_length       256
-
-#ifndef PRODUCT
-class GCLabBitMap;
-class GCLabBitMapClosure: public BitMapClosure {
-private:
-  ConcurrentMark* _cm;
-  GCLabBitMap*    _bitmap;
-
-public:
-  GCLabBitMapClosure(ConcurrentMark* cm,
-                     GCLabBitMap* bitmap) {
-    _cm     = cm;
-    _bitmap = bitmap;
-  }
-
-  virtual bool do_bit(size_t offset);
-};
-#endif // !PRODUCT
-
-class GCLabBitMap: public BitMap {
-private:
-  ConcurrentMark* _cm;
-
-  int       _shifter;
-  size_t    _bitmap_word_covers_words;
-
-  // beginning of the heap
-  HeapWord* _heap_start;
-
-  // this is the actual start of the GCLab
-  HeapWord* _real_start_word;
-
-  // this is the actual end of the GCLab
-  HeapWord* _real_end_word;
-
-  // this is the first word, possibly located before the actual start
-  // of the GCLab, that corresponds to the first bit of the bitmap
-  HeapWord* _start_word;
-
-  // size of a GCLab in words
-  size_t _gclab_word_size;
-
-  static int shifter() {
-    return MinObjAlignment - 1;
-  }
-
-  // how many heap words does a single bitmap word corresponds to?
-  static size_t bitmap_word_covers_words() {
-    return BitsPerWord << shifter();
-  }
-
-  size_t gclab_word_size() const {
-    return _gclab_word_size;
-  }
-
-  // Calculates actual GCLab size in words
-  size_t gclab_real_word_size() const {
-    return bitmap_size_in_bits(pointer_delta(_real_end_word, _start_word))
-           / BitsPerWord;
-  }
-
-  static size_t bitmap_size_in_bits(size_t gclab_word_size) {
-    size_t bits_in_bitmap = gclab_word_size >> shifter();
-    // We are going to ensure that the beginning of a word in this
-    // bitmap also corresponds to the beginning of a word in the
-    // global marking bitmap. To handle the case where a GCLab
-    // starts from the middle of the bitmap, we need to add enough
-    // space (i.e. up to a bitmap word) to ensure that we have
-    // enough bits in the bitmap.
-    return bits_in_bitmap + BitsPerWord - 1;
-  }
-public:
-  GCLabBitMap(HeapWord* heap_start, size_t gclab_word_size)
-    : BitMap(bitmap_size_in_bits(gclab_word_size)),
-      _cm(G1CollectedHeap::heap()->concurrent_mark()),
-      _shifter(shifter()),
-      _bitmap_word_covers_words(bitmap_word_covers_words()),
-      _heap_start(heap_start),
-      _gclab_word_size(gclab_word_size),
-      _real_start_word(NULL),
-      _real_end_word(NULL),
-      _start_word(NULL) {
-    guarantee(false, "GCLabBitMap::GCLabBitmap(): don't call this any more");
-  }
-
-  inline unsigned heapWordToOffset(HeapWord* addr) {
-    unsigned offset = (unsigned) pointer_delta(addr, _start_word) >> _shifter;
-    assert(offset < size(), "offset should be within bounds");
-    return offset;
-  }
-
-  inline HeapWord* offsetToHeapWord(size_t offset) {
-    HeapWord* addr =  _start_word + (offset << _shifter);
-    assert(_real_start_word <= addr && addr < _real_end_word, "invariant");
-    return addr;
-  }
-
-  bool fields_well_formed() {
-    bool ret1 = (_real_start_word == NULL) &&
-                (_real_end_word == NULL) &&
-                (_start_word == NULL);
-    if (ret1)
-      return true;
-
-    bool ret2 = _real_start_word >= _start_word &&
-      _start_word < _real_end_word &&
-      (_real_start_word + _gclab_word_size) == _real_end_word &&
-      (_start_word + _gclab_word_size + _bitmap_word_covers_words)
-                                                              > _real_end_word;
-    return ret2;
-  }
-
-  inline bool mark(HeapWord* addr) {
-    guarantee(use_local_bitmaps, "invariant");
-    assert(fields_well_formed(), "invariant");
-
-    if (addr >= _real_start_word && addr < _real_end_word) {
-      assert(!isMarked(addr), "should not have already been marked");
-
-      // first mark it on the bitmap
-      at_put(heapWordToOffset(addr), true);
-
-      return true;
-    } else {
-      return false;
-    }
-  }
-
-  inline bool isMarked(HeapWord* addr) {
-    guarantee(use_local_bitmaps, "invariant");
-    assert(fields_well_formed(), "invariant");
-
-    return at(heapWordToOffset(addr));
-  }
-
-  void set_buffer(HeapWord* start) {
-    guarantee(false, "set_buffer(): don't call this any more");
-
-    guarantee(use_local_bitmaps, "invariant");
-    clear();
-
-    assert(start != NULL, "invariant");
-    _real_start_word = start;
-    _real_end_word   = start + _gclab_word_size;
-
-    size_t diff =
-      pointer_delta(start, _heap_start) % _bitmap_word_covers_words;
-    _start_word = start - diff;
-
-    assert(fields_well_formed(), "invariant");
-  }
-
-#ifndef PRODUCT
-  void verify() {
-    // verify that the marks have been propagated
-    GCLabBitMapClosure cl(_cm, this);
-    iterate(&cl);
-  }
-#endif // PRODUCT
-
-  void retire() {
-    guarantee(false, "retire(): don't call this any more");
-
-    guarantee(use_local_bitmaps, "invariant");
-    assert(fields_well_formed(), "invariant");
-
-    if (_start_word != NULL) {
-      CMBitMap*       mark_bitmap = _cm->nextMarkBitMap();
-
-      // this means that the bitmap was set up for the GCLab
-      assert(_real_start_word != NULL && _real_end_word != NULL, "invariant");
-
-      mark_bitmap->mostly_disjoint_range_union(this,
-                                0, // always start from the start of the bitmap
-                                _start_word,
-                                gclab_real_word_size());
-      _cm->grayRegionIfNecessary(MemRegion(_real_start_word, _real_end_word));
-
-#ifndef PRODUCT
-      if (use_local_bitmaps && verify_local_bitmaps)
-        verify();
-#endif // PRODUCT
-    } else {
-      assert(_real_start_word == NULL && _real_end_word == NULL, "invariant");
-    }
-  }
-
-  size_t bitmap_size_in_words() const {
-    return (bitmap_size_in_bits(gclab_word_size()) + BitsPerWord - 1) / BitsPerWord;
-  }
-
-};
-
 class G1ParGCAllocBuffer: public ParGCAllocBuffer {
 private:
   bool        _retired;
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Tue May 15 11:27:24 2012 -0700
@@ -29,6 +29,7 @@
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
 #include "gc_implementation/g1/g1ErgoVerbose.hpp"
+#include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "gc_implementation/shared/gcPolicyCounters.hpp"
 #include "runtime/arguments.hpp"
@@ -140,7 +141,6 @@
   _summary(new Summary()),
 
   _cur_clear_ct_time_ms(0.0),
-  _mark_closure_time_ms(0.0),
   _root_region_scan_wait_time_ms(0.0),
 
   _cur_ref_proc_time_ms(0.0),
@@ -192,11 +192,6 @@
   _in_marking_window(false),
   _in_marking_window_im(false),
 
-  _known_garbage_ratio(0.0),
-  _known_garbage_bytes(0),
-
-  _young_gc_eff_seq(new TruncatedSeq(TruncatedSeqLength)),
-
   _recent_prev_end_times_for_all_gcs_sec(
                                 new TruncatedSeq(NumPrevPausesForHeuristics)),
 
@@ -431,31 +426,36 @@
   }
 
   if (FLAG_IS_CMDLINE(NewSize)) {
-     _min_desired_young_length = MAX2((size_t) 1, NewSize / HeapRegion::GrainBytes);
+    _min_desired_young_length = MAX2((uint) (NewSize / HeapRegion::GrainBytes),
+                                     1U);
     if (FLAG_IS_CMDLINE(MaxNewSize)) {
-      _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes);
+      _max_desired_young_length =
+                             MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes),
+                                  1U);
       _sizer_kind = SizerMaxAndNewSize;
       _adaptive_size = _min_desired_young_length == _max_desired_young_length;
     } else {
       _sizer_kind = SizerNewSizeOnly;
     }
   } else if (FLAG_IS_CMDLINE(MaxNewSize)) {
-    _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes);
+    _max_desired_young_length =
+                             MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes),
+                                  1U);
     _sizer_kind = SizerMaxNewSizeOnly;
   }
 }
 
-size_t G1YoungGenSizer::calculate_default_min_length(size_t new_number_of_heap_regions) {
-  size_t default_value = (new_number_of_heap_regions * G1DefaultMinNewGenPercent) / 100;
-  return MAX2((size_t)1, default_value);
+uint G1YoungGenSizer::calculate_default_min_length(uint new_number_of_heap_regions) {
+  uint default_value = (new_number_of_heap_regions * G1DefaultMinNewGenPercent) / 100;
+  return MAX2(1U, default_value);
 }
 
-size_t G1YoungGenSizer::calculate_default_max_length(size_t new_number_of_heap_regions) {
-  size_t default_value = (new_number_of_heap_regions * G1DefaultMaxNewGenPercent) / 100;
-  return MAX2((size_t)1, default_value);
+uint G1YoungGenSizer::calculate_default_max_length(uint new_number_of_heap_regions) {
+  uint default_value = (new_number_of_heap_regions * G1DefaultMaxNewGenPercent) / 100;
+  return MAX2(1U, default_value);
 }
 
-void G1YoungGenSizer::heap_size_changed(size_t new_number_of_heap_regions) {
+void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) {
   assert(new_number_of_heap_regions > 0, "Heap must be initialized");
 
   switch (_sizer_kind) {
@@ -512,16 +512,16 @@
   _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 3);
 }
 
-bool G1CollectorPolicy::predict_will_fit(size_t young_length,
+bool G1CollectorPolicy::predict_will_fit(uint young_length,
                                          double base_time_ms,
-                                         size_t base_free_regions,
+                                         uint base_free_regions,
                                          double target_pause_time_ms) {
   if (young_length >= base_free_regions) {
     // end condition 1: not enough space for the young regions
     return false;
   }
 
-  double accum_surv_rate = accum_yg_surv_rate_pred((int)(young_length - 1));
+  double accum_surv_rate = accum_yg_surv_rate_pred((int) young_length - 1);
   size_t bytes_to_copy =
                (size_t) (accum_surv_rate * (double) HeapRegion::GrainBytes);
   double copy_time_ms = predict_object_copy_time_ms(bytes_to_copy);
@@ -533,7 +533,7 @@
   }
 
   size_t free_bytes =
-                  (base_free_regions - young_length) * HeapRegion::GrainBytes;
+                   (base_free_regions - young_length) * HeapRegion::GrainBytes;
   if ((2.0 * sigma()) * (double) bytes_to_copy > (double) free_bytes) {
     // end condition 3: out-of-space (conservatively!)
     return false;
@@ -543,25 +543,25 @@
   return true;
 }
 
-void G1CollectorPolicy::record_new_heap_size(size_t new_number_of_regions) {
+void G1CollectorPolicy::record_new_heap_size(uint new_number_of_regions) {
   // re-calculate the necessary reserve
   double reserve_regions_d = (double) new_number_of_regions * _reserve_factor;
   // We use ceiling so that if reserve_regions_d is > 0.0 (but
   // smaller than 1.0) we'll get 1.
-  _reserve_regions = (size_t) ceil(reserve_regions_d);
+  _reserve_regions = (uint) ceil(reserve_regions_d);
 
   _young_gen_sizer->heap_size_changed(new_number_of_regions);
 }
 
-size_t G1CollectorPolicy::calculate_young_list_desired_min_length(
-                                                     size_t base_min_length) {
-  size_t desired_min_length = 0;
+uint G1CollectorPolicy::calculate_young_list_desired_min_length(
+                                                       uint base_min_length) {
+  uint desired_min_length = 0;
   if (adaptive_young_list_length()) {
     if (_alloc_rate_ms_seq->num() > 3) {
       double now_sec = os::elapsedTime();
       double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0;
       double alloc_rate_ms = predict_alloc_rate_ms();
-      desired_min_length = (size_t) ceil(alloc_rate_ms * when_ms);
+      desired_min_length = (uint) ceil(alloc_rate_ms * when_ms);
     } else {
       // otherwise we don't have enough info to make the prediction
     }
@@ -571,7 +571,7 @@
   return MAX2(_young_gen_sizer->min_desired_young_length(), desired_min_length);
 }
 
-size_t G1CollectorPolicy::calculate_young_list_desired_max_length() {
+uint G1CollectorPolicy::calculate_young_list_desired_max_length() {
   // Here, we might want to also take into account any additional
   // constraints (i.e., user-defined minimum bound). Currently, we
   // effectively don't set this bound.
@@ -588,11 +588,11 @@
   // Calculate the absolute and desired min bounds.
 
   // This is how many young regions we already have (currently: the survivors).
-  size_t base_min_length = recorded_survivor_regions();
+  uint base_min_length = recorded_survivor_regions();
   // This is the absolute minimum young length, which ensures that we
   // can allocate one eden region in the worst-case.
-  size_t absolute_min_length = base_min_length + 1;
-  size_t desired_min_length =
+  uint absolute_min_length = base_min_length + 1;
+  uint desired_min_length =
                      calculate_young_list_desired_min_length(base_min_length);
   if (desired_min_length < absolute_min_length) {
     desired_min_length = absolute_min_length;
@@ -601,16 +601,16 @@
   // Calculate the absolute and desired max bounds.
 
   // We will try our best not to "eat" into the reserve.
-  size_t absolute_max_length = 0;
+  uint absolute_max_length = 0;
   if (_free_regions_at_end_of_collection > _reserve_regions) {
     absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions;
   }
-  size_t desired_max_length = calculate_young_list_desired_max_length();
+  uint desired_max_length = calculate_young_list_desired_max_length();
   if (desired_max_length > absolute_max_length) {
     desired_max_length = absolute_max_length;
   }
 
-  size_t young_list_target_length = 0;
+  uint young_list_target_length = 0;
   if (adaptive_young_list_length()) {
     if (gcs_are_young()) {
       young_list_target_length =
@@ -648,11 +648,11 @@
   update_max_gc_locker_expansion();
 }
 
-size_t
+uint
 G1CollectorPolicy::calculate_young_list_target_length(size_t rs_lengths,
-                                                   size_t base_min_length,
-                                                   size_t desired_min_length,
-                                                   size_t desired_max_length) {
+                                                     uint base_min_length,
+                                                     uint desired_min_length,
+                                                     uint desired_max_length) {
   assert(adaptive_young_list_length(), "pre-condition");
   assert(gcs_are_young(), "only call this for young GCs");
 
@@ -667,9 +667,9 @@
   // will be reflected in the predictions by the
   // survivor_regions_evac_time prediction.
   assert(desired_min_length > base_min_length, "invariant");
-  size_t min_young_length = desired_min_length - base_min_length;
+  uint min_young_length = desired_min_length - base_min_length;
   assert(desired_max_length > base_min_length, "invariant");
-  size_t max_young_length = desired_max_length - base_min_length;
+  uint max_young_length = desired_max_length - base_min_length;
 
   double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0;
   double survivor_regions_evac_time = predict_survivor_regions_evac_time();
@@ -679,8 +679,8 @@
   double base_time_ms =
     predict_base_elapsed_time_ms(pending_cards, scanned_cards) +
     survivor_regions_evac_time;
-  size_t available_free_regions = _free_regions_at_end_of_collection;
-  size_t base_free_regions = 0;
+  uint available_free_regions = _free_regions_at_end_of_collection;
+  uint base_free_regions = 0;
   if (available_free_regions > _reserve_regions) {
     base_free_regions = available_free_regions - _reserve_regions;
   }
@@ -717,9 +717,9 @@
       // the new max. This way we maintain the loop invariants.
 
       assert(min_young_length < max_young_length, "invariant");
-      size_t diff = (max_young_length - min_young_length) / 2;
+      uint diff = (max_young_length - min_young_length) / 2;
       while (diff > 0) {
-        size_t young_length = min_young_length + diff;
+        uint young_length = min_young_length + diff;
         if (predict_will_fit(young_length, base_time_ms,
                              base_free_regions, target_pause_time_ms)) {
           min_young_length = young_length;
@@ -863,8 +863,6 @@
   _last_young_gc = false;
   clear_initiate_conc_mark_if_possible();
   clear_during_initial_mark_pause();
-  _known_garbage_bytes = 0;
-  _known_garbage_ratio = 0.0;
   _in_marking_window = false;
   _in_marking_window_im = false;
 
@@ -877,7 +875,7 @@
   // Reset survivors SurvRateGroup.
   _survivor_surv_rate_group->reset();
   update_young_list_target_length();
-  _collectionSetChooser->clearMarkedHeapRegions();
+  _collectionSetChooser->clear();
 }
 
 void G1CollectorPolicy::record_stop_world_start() {
@@ -886,10 +884,11 @@
 
 void G1CollectorPolicy::record_collection_pause_start(double start_time_sec,
                                                       size_t start_used) {
-  if (PrintGCDetails) {
+  if (G1Log::finer()) {
     gclog_or_tty->stamp(PrintGCTimeStamps);
-    gclog_or_tty->print("[GC pause");
-    gclog_or_tty->print(" (%s)", gcs_are_young() ? "young" : "mixed");
+    gclog_or_tty->print("[GC pause (%s) (%s)",
+      GCCause::to_string(_g1->gc_cause()),
+      gcs_are_young() ? "young" : "mixed");
   }
 
   // We only need to do this here as the policy will only be applied
@@ -944,9 +943,6 @@
     _cur_aux_times_set[i] = false;
   }
 
-  // This is initialized to zero here and is set during
-  // the evacuation pause if marking is in progress.
-  _cur_satb_drain_time_ms = 0.0;
   // This is initialized to zero here and is set during the evacuation
   // pause if we actually waited for the root region scanning to finish.
   _root_region_scan_wait_time_ms = 0.0;
@@ -1026,11 +1022,16 @@
     if (val > max)
       max = val;
     total += val;
-    buf.append("  %3.1lf", val);
+    if (G1Log::finest()) {
+      buf.append("  %.1lf", val);
+    }
   }
-  buf.append_and_print_cr("");
+
+  if (G1Log::finest()) {
+    buf.append_and_print_cr("");
+  }
   double avg = total / (double) no_of_gc_threads();
-  buf.append_and_print_cr(" Avg: %5.1lf, Min: %5.1lf, Max: %5.1lf, Diff: %5.1lf]",
+  buf.append_and_print_cr(" Avg: %.1lf Min: %.1lf Max: %.1lf Diff: %.1lf]",
     avg, min, max, max - min);
 }
 
@@ -1227,7 +1228,7 @@
 
   // These values are used to update the summary information that is
   // displayed when TraceGen0Time is enabled, and are output as part
-  // of the PrintGCDetails output, in the non-parallel case.
+  // of the "finer" output, in the non-parallel case.
 
   double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms);
   double satb_filtering_time = avg_value(_par_last_satb_filtering_times_ms);
@@ -1246,11 +1247,6 @@
 
   double other_time_ms = elapsed_ms;
 
-  // Subtract the SATB drain time. It's initialized to zero at the
-  // start of the pause and is updated during the pause if marking
-  // is in progress.
-  other_time_ms -= _cur_satb_drain_time_ms;
-
   // Subtract the root region scanning wait time. It's initialized to
   // zero at the start of the pause.
   other_time_ms -= _root_region_scan_wait_time_ms;
@@ -1261,15 +1257,13 @@
     other_time_ms -= known_time;
   }
 
+  // Now subtract the time taken to fix up roots in generated code
+  other_time_ms -= _cur_collection_code_root_fixup_time_ms;
+
   // Subtract the time taken to clean the card table from the
   // current value of "other time"
   other_time_ms -= _cur_clear_ct_time_ms;
 
-  // Subtract the time spent completing marking in the collection
-  // set. Note if marking is not in progress during the pause
-  // the value of _mark_closure_time_ms will be zero.
-  other_time_ms -= _mark_closure_time_ms;
-
   // TraceGen0Time and TraceGen1Time summary info updating.
   _all_pause_times_ms->add(elapsed_ms);
 
@@ -1280,16 +1274,8 @@
     MainBodySummary* body_summary = _summary->main_body_summary();
     assert(body_summary != NULL, "should not be null!");
 
-    // This will be non-zero iff marking is currently in progress (i.e.
-    // _g1->mark_in_progress() == true) and the currrent pause was not
-    // an initial mark pause. Since the body_summary items are NumberSeqs,
-    // however, they have to be consistent and updated in lock-step with
-    // each other. Therefore we unconditionally record the SATB drain
-    // time - even if it's zero.
-    body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms);
     body_summary->record_root_region_scan_wait_time_ms(
                                                _root_region_scan_wait_time_ms);
-
     body_summary->record_ext_root_scan_time_ms(ext_root_scan_time);
     body_summary->record_satb_filtering_time_ms(satb_filtering_time);
     body_summary->record_update_rs_time_ms(update_rs_time);
@@ -1305,7 +1291,6 @@
       body_summary->record_parallel_other_time_ms(parallel_other_time);
     }
 
-    body_summary->record_mark_closure_time_ms(_mark_closure_time_ms);
     body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms);
 
     // We exempt parallel collection from this check because Alloc Buffer
@@ -1336,7 +1321,7 @@
     // given that humongous object allocations do not really affect
     // either the pause's duration nor when the next pause will take
     // place we can safely ignore them here.
-    size_t regions_allocated = eden_cset_region_length();
+    uint regions_allocated = eden_cset_region_length();
     double alloc_rate_ms = (double) regions_allocated / app_time_ms;
     _alloc_rate_ms_seq->add(alloc_rate_ms);
 
@@ -1376,8 +1361,7 @@
     }
   }
 
-  // PrintGCDetails output
-  if (PrintGCDetails) {
+  if (G1Log::finer()) {
     bool print_marking_info =
       _g1->mark_in_progress() && !last_pause_included_initial_mark;
 
@@ -1396,15 +1380,19 @@
         print_par_stats(2, "SATB Filtering", _par_last_satb_filtering_times_ms);
       }
       print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
-      print_par_sizes(3, "Processed Buffers", _par_last_update_rs_processed_buffers);
+      if (G1Log::finest()) {
+        print_par_sizes(3, "Processed Buffers", _par_last_update_rs_processed_buffers);
+      }
       print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
       print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
       print_par_stats(2, "Termination", _par_last_termination_times_ms);
-      print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts);
-      print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms);
+      if (G1Log::finest()) {
+        print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts);
+      }
 
       for (int i = 0; i < _parallel_gc_threads; i++) {
-        _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - _par_last_gc_worker_start_times_ms[i];
+        _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] -
+                                          _par_last_gc_worker_start_times_ms[i];
 
         double worker_known_time = _par_last_ext_root_scan_times_ms[i] +
                                    _par_last_satb_filtering_times_ms[i] +
@@ -1413,23 +1401,26 @@
                                    _par_last_obj_copy_times_ms[i] +
                                    _par_last_termination_times_ms[i];
 
-        _par_last_gc_worker_other_times_ms[i] = _cur_collection_par_time_ms - worker_known_time;
+        _par_last_gc_worker_other_times_ms[i] = _par_last_gc_worker_times_ms[i] -
+                                                worker_known_time;
       }
-      print_par_stats(2, "GC Worker", _par_last_gc_worker_times_ms);
+
       print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms);
+      print_par_stats(2, "GC Worker Total", _par_last_gc_worker_times_ms);
+      print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms);
     } else {
       print_stats(1, "Ext Root Scanning", ext_root_scan_time);
       if (print_marking_info) {
         print_stats(1, "SATB Filtering", satb_filtering_time);
       }
       print_stats(1, "Update RS", update_rs_time);
-      print_stats(2, "Processed Buffers", (int)update_rs_processed_buffers);
+      if (G1Log::finest()) {
+        print_stats(2, "Processed Buffers", (int)update_rs_processed_buffers);
+      }
       print_stats(1, "Scan RS", scan_rs_time);
       print_stats(1, "Object Copying", obj_copy_time);
     }
-    if (print_marking_info) {
-      print_stats(1, "Complete CSet Marking", _mark_closure_time_ms);
-    }
+    print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
     print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
 #ifndef PRODUCT
     print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms);
@@ -1459,16 +1450,6 @@
     }
   }
 
-  // Update the efficiency-since-mark vars.
-  double proc_ms = elapsed_ms * (double) _parallel_gc_threads;
-  if (elapsed_ms < MIN_TIMER_GRANULARITY) {
-    // This usually happens due to the timer not having the required
-    // granularity. Some Linuxes are the usual culprits.
-    // We'll just set it to something (arbitrarily) small.
-    proc_ms = 1.0;
-  }
-  double cur_efficiency = (double) freed_bytes / proc_ms;
-
   bool new_in_marking_window = _in_marking_window;
   bool new_in_marking_window_im = false;
   if (during_initial_mark_pause()) {
@@ -1503,10 +1484,6 @@
     }
   }
 
-  if (_last_gc_was_young && !_during_marking) {
-    _young_gc_eff_seq->add(cur_efficiency);
-  }
-
   _short_lived_surv_rate_group->start_adding_regions();
   // do that for any other surv rate groupsx
 
@@ -1514,8 +1491,9 @@
     double pause_time_ms = elapsed_ms;
 
     size_t diff = 0;
-    if (_max_pending_cards >= _pending_cards)
+    if (_max_pending_cards >= _pending_cards) {
       diff = _max_pending_cards - _pending_cards;
+    }
     _pending_card_diff_seq->add((double) diff);
 
     double cost_per_card_ms = 0.0;
@@ -1577,8 +1555,7 @@
     }
 
     double all_other_time_ms = pause_time_ms -
-      (update_rs_time + scan_rs_time + obj_copy_time +
-       _mark_closure_time_ms + termination_time);
+      (update_rs_time + scan_rs_time + obj_copy_time + termination_time);
 
     double young_other_time_ms = 0.0;
     if (young_cset_region_length() > 0) {
@@ -1621,7 +1598,7 @@
   double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
   adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms);
 
-  assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end.");
+  _collectionSetChooser->verify();
 }
 
 #define EXT_SIZE_FORMAT "%d%s"
@@ -1630,7 +1607,7 @@
   proper_unit_for_byte_size((bytes))
 
 void G1CollectorPolicy::print_heap_transition() {
-  if (PrintGCDetails) {
+  if (G1Log::finer()) {
     YoungList* young_list = _g1->young_list();
     size_t eden_bytes = young_list->eden_used_bytes();
     size_t survivor_bytes = young_list->survivor_used_bytes();
@@ -1657,7 +1634,7 @@
       EXT_SIZE_PARAMS(capacity));
 
     _prev_eden_capacity = eden_capacity;
-  } else if (PrintGC) {
+  } else if (G1Log::fine()) {
     _g1->print_size_transition(gclog_or_tty,
                                _cur_collection_pause_used_at_start_bytes,
                                _g1->used(), _g1->capacity());
@@ -1706,41 +1683,6 @@
 }
 
 double
-G1CollectorPolicy::
-predict_young_collection_elapsed_time_ms(size_t adjustment) {
-  guarantee( adjustment == 0 || adjustment == 1, "invariant" );
-
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  size_t young_num = g1h->young_list()->length();
-  if (young_num == 0)
-    return 0.0;
-
-  young_num += adjustment;
-  size_t pending_cards = predict_pending_cards();
-  size_t rs_lengths = g1h->young_list()->sampled_rs_lengths() +
-                      predict_rs_length_diff();
-  size_t card_num;
-  if (gcs_are_young()) {
-    card_num = predict_young_card_num(rs_lengths);
-  } else {
-    card_num = predict_non_young_card_num(rs_lengths);
-  }
-  size_t young_byte_size = young_num * HeapRegion::GrainBytes;
-  double accum_yg_surv_rate =
-    _short_lived_surv_rate_group->accum_surv_rate(adjustment);
-
-  size_t bytes_to_copy =
-    (size_t) (accum_yg_surv_rate * (double) HeapRegion::GrainBytes);
-
-  return
-    predict_rs_update_time_ms(pending_cards) +
-    predict_rs_scan_time_ms(card_num) +
-    predict_object_copy_time_ms(bytes_to_copy) +
-    predict_young_other_time_ms(young_num) +
-    predict_constant_other_time_ms();
-}
-
-double
 G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) {
   size_t rs_length = predict_rs_length_diff();
   size_t card_num;
@@ -1785,8 +1727,7 @@
   return region_elapsed_time_ms;
 }
 
-size_t
-G1CollectorPolicy::predict_bytes_to_copy(HeapRegion* hr) {
+size_t G1CollectorPolicy::predict_bytes_to_copy(HeapRegion* hr) {
   size_t bytes_to_copy;
   if (hr->is_marked())
     bytes_to_copy = hr->max_live_bytes();
@@ -1800,8 +1741,8 @@
 }
 
 void
-G1CollectorPolicy::init_cset_region_lengths(size_t eden_cset_region_length,
-                                          size_t survivor_cset_region_length) {
+G1CollectorPolicy::init_cset_region_lengths(uint eden_cset_region_length,
+                                            uint survivor_cset_region_length) {
   _eden_cset_region_length     = eden_cset_region_length;
   _survivor_cset_region_length = survivor_cset_region_length;
   _old_cset_region_length      = 0;
@@ -1973,7 +1914,6 @@
         print_summary(1, "Object Copy", body_summary->get_obj_copy_seq());
       }
     }
-    print_summary(1, "Mark Closure", body_summary->get_mark_closure_seq());
     print_summary(1, "Clear CT", body_summary->get_clear_ct_seq());
     print_summary(1, "Other", summary->get_other_seq());
     {
@@ -1982,17 +1922,15 @@
         if (parallel) {
           // parallel
           NumberSeq* other_parts[] = {
-            body_summary->get_satb_drain_seq(),
             body_summary->get_root_region_scan_wait_seq(),
             body_summary->get_parallel_seq(),
             body_summary->get_clear_ct_seq()
           };
           calc_other_times_ms = NumberSeq(summary->get_total_seq(),
-                                          4, other_parts);
+                                          3, other_parts);
         } else {
           // serial
           NumberSeq* other_parts[] = {
-            body_summary->get_satb_drain_seq(),
             body_summary->get_root_region_scan_wait_seq(),
             body_summary->get_update_rs_seq(),
             body_summary->get_ext_root_scan_seq(),
@@ -2001,7 +1939,7 @@
             body_summary->get_obj_copy_seq()
           };
           calc_other_times_ms = NumberSeq(summary->get_total_seq(),
-                                          7, other_parts);
+                                          6, other_parts);
         }
         check_other_times(1,  summary->get_other_seq(), &calc_other_times_ms);
       }
@@ -2068,7 +2006,7 @@
 }
 #endif // PRODUCT
 
-size_t G1CollectorPolicy::max_regions(int purpose) {
+uint G1CollectorPolicy::max_regions(int purpose) {
   switch (purpose) {
     case GCAllocForSurvived:
       return _max_survivor_regions;
@@ -2081,13 +2019,13 @@
 }
 
 void G1CollectorPolicy::update_max_gc_locker_expansion() {
-  size_t expansion_region_num = 0;
+  uint expansion_region_num = 0;
   if (GCLockerEdenExpansionPercent > 0) {
     double perc = (double) GCLockerEdenExpansionPercent / 100.0;
     double expansion_region_num_d = perc * (double) _young_list_target_length;
     // We use ceiling so that if expansion_region_num_d is > 0.0 (but
     // less than 1.0) we'll get 1.
-    expansion_region_num = (size_t) ceil(expansion_region_num_d);
+    expansion_region_num = (uint) ceil(expansion_region_num_d);
   } else {
     assert(expansion_region_num == 0, "sanity");
   }
@@ -2101,34 +2039,12 @@
                  (double) _young_list_target_length / (double) SurvivorRatio;
   // We use ceiling so that if max_survivor_regions_d is > 0.0 (but
   // smaller than 1.0) we'll get 1.
-  _max_survivor_regions = (size_t) ceil(max_survivor_regions_d);
+  _max_survivor_regions = (uint) ceil(max_survivor_regions_d);
 
   _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold(
         HeapRegion::GrainWords * _max_survivor_regions);
 }
 
-#ifndef PRODUCT
-class HRSortIndexIsOKClosure: public HeapRegionClosure {
-  CollectionSetChooser* _chooser;
-public:
-  HRSortIndexIsOKClosure(CollectionSetChooser* chooser) :
-    _chooser(chooser) {}
-
-  bool doHeapRegion(HeapRegion* r) {
-    if (!r->continuesHumongous()) {
-      assert(_chooser->regionProperlyOrdered(r), "Ought to be.");
-    }
-    return false;
-  }
-};
-
-bool G1CollectorPolicy::assertMarkedBytesDataOK() {
-  HRSortIndexIsOKClosure cl(_collectionSetChooser);
-  _g1->heap_region_iterate(&cl);
-  return true;
-}
-#endif
-
 bool G1CollectorPolicy::force_initial_mark_if_outside_cycle(
                                                      GCCause::Cause gc_cause) {
   bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle();
@@ -2226,8 +2142,8 @@
       // We will skip any region that's currently used as an old GC
       // alloc region (we should not consider those for collection
       // before we fill them up).
-      if (_hrSorted->shouldAdd(r) && !_g1h->is_old_gc_alloc_region(r)) {
-        _hrSorted->addMarkedHeapRegion(r);
+      if (_hrSorted->should_add(r) && !_g1h->is_old_gc_alloc_region(r)) {
+        _hrSorted->add_region(r);
       }
     }
     return false;
@@ -2237,16 +2153,14 @@
 class ParKnownGarbageHRClosure: public HeapRegionClosure {
   G1CollectedHeap* _g1h;
   CollectionSetChooser* _hrSorted;
-  jint _marked_regions_added;
+  uint _marked_regions_added;
   size_t _reclaimable_bytes_added;
-  jint _chunk_size;
-  jint _cur_chunk_idx;
-  jint _cur_chunk_end; // Cur chunk [_cur_chunk_idx, _cur_chunk_end)
-  int _worker;
-  int _invokes;
+  uint _chunk_size;
+  uint _cur_chunk_idx;
+  uint _cur_chunk_end; // Cur chunk [_cur_chunk_idx, _cur_chunk_end)
 
   void get_new_chunk() {
-    _cur_chunk_idx = _hrSorted->getParMarkedHeapRegionChunk(_chunk_size);
+    _cur_chunk_idx = _hrSorted->claim_array_chunk(_chunk_size);
     _cur_chunk_end = _cur_chunk_idx + _chunk_size;
   }
   void add_region(HeapRegion* r) {
@@ -2254,7 +2168,7 @@
       get_new_chunk();
     }
     assert(_cur_chunk_idx < _cur_chunk_end, "postcondition");
-    _hrSorted->setMarkedHeapRegion(_cur_chunk_idx, r);
+    _hrSorted->set_region(_cur_chunk_idx, r);
     _marked_regions_added++;
     _reclaimable_bytes_added += r->reclaimable_bytes();
     _cur_chunk_idx++;
@@ -2262,104 +2176,79 @@
 
 public:
   ParKnownGarbageHRClosure(CollectionSetChooser* hrSorted,
-                           jint chunk_size,
-                           int worker) :
+                           uint chunk_size) :
       _g1h(G1CollectedHeap::heap()),
-      _hrSorted(hrSorted), _chunk_size(chunk_size), _worker(worker),
+      _hrSorted(hrSorted), _chunk_size(chunk_size),
       _marked_regions_added(0), _reclaimable_bytes_added(0),
-      _cur_chunk_idx(0), _cur_chunk_end(0), _invokes(0) { }
+      _cur_chunk_idx(0), _cur_chunk_end(0) { }
 
   bool doHeapRegion(HeapRegion* r) {
-    // We only include humongous regions in collection
-    // sets when concurrent mark shows that their contained object is
-    // unreachable.
-    _invokes++;
-
     // Do we have any marking information for this region?
     if (r->is_marked()) {
       // We will skip any region that's currently used as an old GC
       // alloc region (we should not consider those for collection
       // before we fill them up).
-      if (_hrSorted->shouldAdd(r) && !_g1h->is_old_gc_alloc_region(r)) {
+      if (_hrSorted->should_add(r) && !_g1h->is_old_gc_alloc_region(r)) {
         add_region(r);
       }
     }
     return false;
   }
-  jint marked_regions_added() { return _marked_regions_added; }
+  uint marked_regions_added() { return _marked_regions_added; }
   size_t reclaimable_bytes_added() { return _reclaimable_bytes_added; }
-  int invokes() { return _invokes; }
 };
 
 class ParKnownGarbageTask: public AbstractGangTask {
   CollectionSetChooser* _hrSorted;
-  jint _chunk_size;
+  uint _chunk_size;
   G1CollectedHeap* _g1;
 public:
-  ParKnownGarbageTask(CollectionSetChooser* hrSorted, jint chunk_size) :
+  ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size) :
     AbstractGangTask("ParKnownGarbageTask"),
     _hrSorted(hrSorted), _chunk_size(chunk_size),
     _g1(G1CollectedHeap::heap()) { }
 
   void work(uint worker_id) {
-    ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted,
-                                               _chunk_size,
-                                               worker_id);
+    ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size);
+
     // Back to zero for the claim value.
     _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id,
                                          _g1->workers()->active_workers(),
                                          HeapRegion::InitialClaimValue);
-    jint regions_added = parKnownGarbageCl.marked_regions_added();
+    uint regions_added = parKnownGarbageCl.marked_regions_added();
     size_t reclaimable_bytes_added =
                                    parKnownGarbageCl.reclaimable_bytes_added();
-    _hrSorted->updateTotals(regions_added, reclaimable_bytes_added);
-    if (G1PrintParCleanupStats) {
-      gclog_or_tty->print_cr("     Thread %d called %d times, added %d regions to list.",
-                 worker_id, parKnownGarbageCl.invokes(), regions_added);
-    }
+    _hrSorted->update_totals(regions_added, reclaimable_bytes_added);
   }
 };
 
 void
 G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) {
-  double start_sec;
-  if (G1PrintParCleanupStats) {
-    start_sec = os::elapsedTime();
-  }
+  _collectionSetChooser->clear();
 
-  _collectionSetChooser->clearMarkedHeapRegions();
-  double clear_marked_end_sec;
-  if (G1PrintParCleanupStats) {
-    clear_marked_end_sec = os::elapsedTime();
-    gclog_or_tty->print_cr("  clear marked regions: %8.3f ms.",
-                           (clear_marked_end_sec - start_sec) * 1000.0);
-  }
-
+  uint region_num = _g1->n_regions();
   if (G1CollectedHeap::use_parallel_gc_threads()) {
-    const size_t OverpartitionFactor = 4;
-    size_t WorkUnit;
+    const uint OverpartitionFactor = 4;
+    uint WorkUnit;
     // The use of MinChunkSize = 8 in the original code
     // causes some assertion failures when the total number of
     // region is less than 8.  The code here tries to fix that.
     // Should the original code also be fixed?
     if (no_of_gc_threads > 0) {
-      const size_t MinWorkUnit =
-        MAX2(_g1->n_regions() / no_of_gc_threads, (size_t) 1U);
-      WorkUnit =
-        MAX2(_g1->n_regions() / (no_of_gc_threads * OverpartitionFactor),
-             MinWorkUnit);
+      const uint MinWorkUnit = MAX2(region_num / no_of_gc_threads, 1U);
+      WorkUnit = MAX2(region_num / (no_of_gc_threads * OverpartitionFactor),
+                      MinWorkUnit);
     } else {
       assert(no_of_gc_threads > 0,
         "The active gc workers should be greater than 0");
       // In a product build do something reasonable to avoid a crash.
-      const size_t MinWorkUnit =
-        MAX2(_g1->n_regions() / ParallelGCThreads, (size_t) 1U);
+      const uint MinWorkUnit = MAX2(region_num / (uint) ParallelGCThreads, 1U);
       WorkUnit =
-        MAX2(_g1->n_regions() / (ParallelGCThreads * OverpartitionFactor),
+        MAX2(region_num / (uint) (ParallelGCThreads * OverpartitionFactor),
              MinWorkUnit);
     }
-    _collectionSetChooser->prepareForAddMarkedHeapRegionsPar(_g1->n_regions(),
-                                                             WorkUnit);
+    _collectionSetChooser->prepare_for_par_region_addition(_g1->n_regions(),
+                                                           WorkUnit);
     ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser,
                                             (int) WorkUnit);
     _g1->workers()->run_task(&parKnownGarbageTask);
@@ -2370,20 +2259,10 @@
     KnownGarbageClosure knownGarbagecl(_collectionSetChooser);
     _g1->heap_region_iterate(&knownGarbagecl);
   }
-  double known_garbage_end_sec;
-  if (G1PrintParCleanupStats) {
-    known_garbage_end_sec = os::elapsedTime();
-    gclog_or_tty->print_cr("  compute known garbage: %8.3f ms.",
-                      (known_garbage_end_sec - clear_marked_end_sec) * 1000.0);
-  }
 
-  _collectionSetChooser->sortMarkedHeapRegions();
+  _collectionSetChooser->sort_regions();
+
   double end_sec = os::elapsedTime();
-  if (G1PrintParCleanupStats) {
-    gclog_or_tty->print_cr("  sorting: %8.3f ms.",
-                           (end_sec - known_garbage_end_sec) * 1000.0);
-  }
-
   double elapsed_time_ms = (end_sec - _mark_cleanup_start_sec) * 1000.0;
   _concurrent_mark_cleanup_times_ms->add(elapsed_time_ms);
   _cur_mark_stop_world_time_ms += elapsed_time_ms;
@@ -2581,16 +2460,10 @@
   while (csr != NULL) {
     HeapRegion* next = csr->next_in_collection_set();
     assert(csr->in_collection_set(), "bad CS");
-    st->print_cr("  [%08x-%08x], t: %08x, P: %08x, N: %08x, C: %08x, "
-                 "age: %4d, y: %d, surv: %d",
-                        csr->bottom(), csr->end(),
-                        csr->top(),
-                        csr->prev_top_at_mark_start(),
-                        csr->next_top_at_mark_start(),
-                        csr->top_at_conc_mark_count(),
-                        csr->age_in_surv_rate_group_cond(),
-                        csr->is_young(),
-                        csr->is_survivor());
+    st->print_cr("  "HR_FORMAT", P: "PTR_FORMAT "N: "PTR_FORMAT", age: %4d",
+                 HR_FORMAT_PARAMS(csr),
+                 csr->prev_top_at_mark_start(), csr->next_top_at_mark_start(),
+                 csr->age_in_surv_rate_group_cond());
     csr = next;
   }
 }
@@ -2599,16 +2472,16 @@
 bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str,
                                                 const char* false_action_str) {
   CollectionSetChooser* cset_chooser = _collectionSetChooser;
-  if (cset_chooser->isEmpty()) {
+  if (cset_chooser->is_empty()) {
     ergo_verbose0(ErgoMixedGCs,
                   false_action_str,
                   ergo_format_reason("candidate old regions not available"));
     return false;
   }
-  size_t reclaimable_bytes = cset_chooser->remainingReclaimableBytes();
+  size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes();
   size_t capacity_bytes = _g1->capacity();
   double perc = (double) reclaimable_bytes * 100.0 / (double) capacity_bytes;
-  double threshold = (double) G1OldReclaimableThresholdPercent;
+  double threshold = (double) G1HeapWastePercent;
   if (perc < threshold) {
     ergo_verbose4(ErgoMixedGCs,
               false_action_str,
@@ -2616,7 +2489,7 @@
               ergo_format_region("candidate old regions")
               ergo_format_byte_perc("reclaimable")
               ergo_format_perc("threshold"),
-              cset_chooser->remainingRegions(),
+              cset_chooser->remaining_regions(),
               reclaimable_bytes, perc, threshold);
     return false;
   }
@@ -2627,7 +2500,7 @@
                 ergo_format_region("candidate old regions")
                 ergo_format_byte_perc("reclaimable")
                 ergo_format_perc("threshold"),
-                cset_chooser->remainingRegions(),
+                cset_chooser->remaining_regions(),
                 reclaimable_bytes, perc, threshold);
   return true;
 }
@@ -2671,8 +2544,8 @@
   // pause are appended to the RHS of the young list, i.e.
   //   [Newly Young Regions ++ Survivors from last pause].
 
-  size_t survivor_region_length = young_list->survivor_length();
-  size_t eden_region_length = young_list->length() - survivor_region_length;
+  uint survivor_region_length = young_list->survivor_length();
+  uint eden_region_length = young_list->length() - survivor_region_length;
   init_cset_region_lengths(eden_region_length, survivor_region_length);
   hr = young_list->first_survivor_region();
   while (hr != NULL) {
@@ -2710,11 +2583,11 @@
 
   if (!gcs_are_young()) {
     CollectionSetChooser* cset_chooser = _collectionSetChooser;
-    assert(cset_chooser->verify(), "CSet Chooser verification - pre");
-    const size_t min_old_cset_length = cset_chooser->calcMinOldCSetLength();
-    const size_t max_old_cset_length = cset_chooser->calcMaxOldCSetLength();
+    cset_chooser->verify();
+    const uint min_old_cset_length = cset_chooser->calc_min_old_cset_length();
+    const uint max_old_cset_length = cset_chooser->calc_max_old_cset_length();
 
-    size_t expensive_region_num = 0;
+    uint expensive_region_num = 0;
     bool check_time_remaining = adaptive_young_list_length();
     HeapRegion* hr = cset_chooser->peek();
     while (hr != NULL) {
@@ -2799,7 +2672,7 @@
                     time_remaining_ms);
     }
 
-    assert(cset_chooser->verify(), "CSet Chooser verification - post");
+    cset_chooser->verify();
   }
 
   stop_incremental_cset_building();
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Tue May 15 11:27:24 2012 -0700
@@ -64,7 +64,6 @@
 };
 
 class MainBodySummary: public CHeapObj {
-  define_num_seq(satb_drain) // optional
   define_num_seq(root_region_scan_wait)
   define_num_seq(parallel) // parallel only
     define_num_seq(ext_root_scan)
@@ -74,7 +73,6 @@
     define_num_seq(obj_copy)
     define_num_seq(termination) // parallel only
     define_num_seq(parallel_other) // parallel only
-  define_num_seq(mark_closure)
   define_num_seq(clear_ct)
 };
 
@@ -130,19 +128,19 @@
     SizerNewRatio
   };
   SizerKind _sizer_kind;
-  size_t _min_desired_young_length;
-  size_t _max_desired_young_length;
+  uint _min_desired_young_length;
+  uint _max_desired_young_length;
   bool _adaptive_size;
-  size_t calculate_default_min_length(size_t new_number_of_heap_regions);
-  size_t calculate_default_max_length(size_t new_number_of_heap_regions);
+  uint calculate_default_min_length(uint new_number_of_heap_regions);
+  uint calculate_default_max_length(uint new_number_of_heap_regions);
 
 public:
   G1YoungGenSizer();
-  void heap_size_changed(size_t new_number_of_heap_regions);
-  size_t min_desired_young_length() {
+  void heap_size_changed(uint new_number_of_heap_regions);
+  uint min_desired_young_length() {
     return _min_desired_young_length;
   }
-  size_t max_desired_young_length() {
+  uint max_desired_young_length() {
     return _max_desired_young_length;
   }
   bool adaptive_young_list_length() {
@@ -177,9 +175,11 @@
 
   double _cur_collection_start_sec;
   size_t _cur_collection_pause_used_at_start_bytes;
-  size_t _cur_collection_pause_used_regions_at_start;
+  uint   _cur_collection_pause_used_regions_at_start;
   double _cur_collection_par_time_ms;
-  double _cur_satb_drain_time_ms;
+
+  double _cur_collection_code_root_fixup_time_ms;
+
   double _cur_clear_ct_time_ms;
   double _cur_ref_proc_time_ms;
   double _cur_ref_enq_time_ms;
@@ -226,20 +226,20 @@
   double* _par_last_gc_worker_times_ms;
 
   // Each workers 'other' time i.e. the elapsed time of the parallel
-  // phase of the pause minus the sum of the individual sub-phase
-  // times for a given worker thread.
+  // code executed by a worker minus the sum of the individual sub-phase
+  // times for that worker thread.
   double* _par_last_gc_worker_other_times_ms;
 
   // indicates whether we are in young or mixed GC mode
   bool _gcs_are_young;
 
-  size_t _young_list_target_length;
-  size_t _young_list_fixed_length;
+  uint _young_list_target_length;
+  uint _young_list_fixed_length;
   size_t _prev_eden_capacity; // used for logging
 
   // The max number of regions we can extend the eden by while the GC
   // locker is active. This should be >= _young_list_target_length;
-  size_t _young_list_max_length;
+  uint _young_list_max_length;
 
   bool                  _last_gc_was_young;
 
@@ -257,7 +257,7 @@
   double                _gc_overhead_perc;
 
   double _reserve_factor;
-  size_t _reserve_regions;
+  uint _reserve_regions;
 
   bool during_marking() {
     return _during_marking;
@@ -288,22 +288,20 @@
 
   TruncatedSeq* _cost_per_byte_ms_during_cm_seq;
 
-  TruncatedSeq* _young_gc_eff_seq;
-
   G1YoungGenSizer* _young_gen_sizer;
 
-  size_t _eden_cset_region_length;
-  size_t _survivor_cset_region_length;
-  size_t _old_cset_region_length;
+  uint _eden_cset_region_length;
+  uint _survivor_cset_region_length;
+  uint _old_cset_region_length;
 
-  void init_cset_region_lengths(size_t eden_cset_region_length,
-                                size_t survivor_cset_region_length);
+  void init_cset_region_lengths(uint eden_cset_region_length,
+                                uint survivor_cset_region_length);
 
-  size_t eden_cset_region_length()     { return _eden_cset_region_length;     }
-  size_t survivor_cset_region_length() { return _survivor_cset_region_length; }
-  size_t old_cset_region_length()      { return _old_cset_region_length;      }
+  uint eden_cset_region_length()     { return _eden_cset_region_length;     }
+  uint survivor_cset_region_length() { return _survivor_cset_region_length; }
+  uint old_cset_region_length()      { return _old_cset_region_length;      }
 
-  size_t _free_regions_at_end_of_collection;
+  uint _free_regions_at_end_of_collection;
 
   size_t _recorded_rs_lengths;
   size_t _max_rs_lengths;
@@ -315,9 +313,6 @@
 
   size_t _rs_lengths_prediction;
 
-  size_t _known_garbage_bytes;
-  double _known_garbage_ratio;
-
   double sigma() { return _sigma; }
 
   // A function that prevents us putting too much stock in small sample
@@ -488,7 +483,6 @@
            get_new_prediction(_non_young_other_cost_per_region_ms_seq);
   }
 
-  double predict_young_collection_elapsed_time_ms(size_t adjustment);
   double predict_base_elapsed_time_ms(size_t pending_cards);
   double predict_base_elapsed_time_ms(size_t pending_cards,
                                       size_t scanned_cards);
@@ -497,10 +491,10 @@
 
   void set_recorded_rs_lengths(size_t rs_lengths);
 
-  size_t cset_region_length()       { return young_cset_region_length() +
-                                             old_cset_region_length(); }
-  size_t young_cset_region_length() { return eden_cset_region_length() +
-                                             survivor_cset_region_length(); }
+  uint cset_region_length()       { return young_cset_region_length() +
+                                           old_cset_region_length(); }
+  uint young_cset_region_length() { return eden_cset_region_length() +
+                                           survivor_cset_region_length(); }
 
   void record_young_free_cset_time_ms(double time_ms) {
     _recorded_young_free_cset_time_ms = time_ms;
@@ -510,10 +504,6 @@
     _recorded_non_young_free_cset_time_ms = time_ms;
   }
 
-  double predict_young_gc_eff() {
-    return get_new_neg_prediction(_young_gc_eff_seq);
-  }
-
   double predict_survivor_regions_evac_time();
 
   void cset_regions_freed() {
@@ -523,20 +513,6 @@
     // also call it on any more surv rate groups
   }
 
-  void set_known_garbage_bytes(size_t known_garbage_bytes) {
-    _known_garbage_bytes = known_garbage_bytes;
-    size_t heap_bytes = _g1->capacity();
-    _known_garbage_ratio = (double) _known_garbage_bytes / (double) heap_bytes;
-  }
-
-  void decrease_known_garbage_bytes(size_t known_garbage_bytes) {
-    guarantee( _known_garbage_bytes >= known_garbage_bytes, "invariant" );
-
-    _known_garbage_bytes -= known_garbage_bytes;
-    size_t heap_bytes = _g1->capacity();
-    _known_garbage_ratio = (double) _known_garbage_bytes / (double) heap_bytes;
-  }
-
   G1MMUTracker* mmu_tracker() {
     return _mmu_tracker;
   }
@@ -709,7 +685,6 @@
   double _cur_mark_stop_world_time_ms;
   double _mark_remark_start_sec;
   double _mark_cleanup_start_sec;
-  double _mark_closure_time_ms;
   double _root_region_scan_wait_time_ms;
 
   // Update the young list target length either by setting it to the
@@ -722,12 +697,12 @@
   // Calculate and return the minimum desired young list target
   // length. This is the minimum desired young list length according
   // to the user's inputs.
-  size_t calculate_young_list_desired_min_length(size_t base_min_length);
+  uint calculate_young_list_desired_min_length(uint base_min_length);
 
   // Calculate and return the maximum desired young list target
   // length. This is the maximum desired young list length according
   // to the user's inputs.
-  size_t calculate_young_list_desired_max_length();
+  uint calculate_young_list_desired_max_length();
 
   // Calculate and return the maximum young list target length that
   // can fit into the pause time goal. The parameters are: rs_lengths
@@ -735,18 +710,18 @@
   // be, base_min_length is the alreay existing number of regions in
   // the young list, min_length and max_length are the desired min and
   // max young list length according to the user's inputs.
-  size_t calculate_young_list_target_length(size_t rs_lengths,
-                                            size_t base_min_length,
-                                            size_t desired_min_length,
-                                            size_t desired_max_length);
+  uint calculate_young_list_target_length(size_t rs_lengths,
+                                          uint base_min_length,
+                                          uint desired_min_length,
+                                          uint desired_max_length);
 
   // Check whether a given young length (young_length) fits into the
   // given target pause time and whether the prediction for the amount
   // of objects to be copied for the given length will fit into the
   // given free space (expressed by base_free_regions).  It is used by
   // calculate_young_list_target_length().
-  bool predict_will_fit(size_t young_length, double base_time_ms,
-                        size_t base_free_regions, double target_pause_time_ms);
+  bool predict_will_fit(uint young_length, double base_time_ms,
+                        uint base_free_regions, double target_pause_time_ms);
 
   // Count the number of bytes used in the CS.
   void count_CS_bytes_used();
@@ -775,7 +750,7 @@
   }
 
   // This should be called after the heap is resized.
-  void record_new_heap_size(size_t new_number_of_regions);
+  void record_new_heap_size(uint new_number_of_regions);
 
   void init();
 
@@ -809,10 +784,6 @@
   void record_concurrent_mark_init_end(double
                                            mark_init_elapsed_time_ms);
 
-  void record_mark_closure_time(double mark_closure_time_ms) {
-    _mark_closure_time_ms = mark_closure_time_ms;
-  }
-
   void record_root_region_scan_wait_time(double time_ms) {
     _root_region_scan_wait_time_ms = time_ms;
   }
@@ -846,11 +817,6 @@
     _par_last_satb_filtering_times_ms[worker_i] = ms;
   }
 
-  void record_satb_drain_time(double ms) {
-    assert(_g1->mark_in_progress(), "shouldn't be here otherwise");
-    _cur_satb_drain_time_ms = ms;
-  }
-
   void record_update_rs_time(int thread, double ms) {
     _par_last_update_rs_times_ms[thread] = ms;
   }
@@ -897,6 +863,10 @@
     _cur_collection_par_time_ms = ms;
   }
 
+  void record_code_root_fixup_time(double ms) {
+    _cur_collection_code_root_fixup_time_ms = ms;
+  }
+
   void record_aux_start_time(int i) {
     guarantee(i < _aux_num, "should be within range");
     _cur_aux_start_times_ms[i] = os::elapsedTime() * 1000.0;
@@ -940,10 +910,9 @@
     return _bytes_copied_during_gc;
   }
 
-  // Determine whether the next GC should be mixed. Called to determine
-  // whether to start mixed GCs or whether to carry on doing mixed
-  // GCs. The two action strings are used in the ergo output when the
-  // method returns true or false.
+  // Determine whether there are candidate regions so that the
+  // next GC should be mixed. The two action strings are used
+  // in the ergo output when the method returns true or false.
   bool next_gc_should_be_mixed(const char* true_action_str,
                                const char* false_action_str);
 
@@ -1034,12 +1003,6 @@
   // exceeded the desired limit, return an amount to expand by.
   size_t expansion_amount();
 
-#ifndef PRODUCT
-  // Check any appropriate marked bytes info, asserting false if
-  // something's wrong, else returning "true".
-  bool assertMarkedBytesDataOK();
-#endif
-
   // Print tracing information.
   void print_tracing_info() const;
 
@@ -1056,18 +1019,18 @@
   }
 
   bool is_young_list_full() {
-    size_t young_list_length = _g1->young_list()->length();
-    size_t young_list_target_length = _young_list_target_length;
+    uint young_list_length = _g1->young_list()->length();
+    uint young_list_target_length = _young_list_target_length;
     return young_list_length >= young_list_target_length;
   }
 
   bool can_expand_young_list() {
-    size_t young_list_length = _g1->young_list()->length();
-    size_t young_list_max_length = _young_list_max_length;
+    uint young_list_length = _g1->young_list()->length();
+    uint young_list_max_length = _young_list_max_length;
     return young_list_length < young_list_max_length;
   }
 
-  size_t young_list_max_length() {
+  uint young_list_max_length() {
     return _young_list_max_length;
   }
 
@@ -1082,19 +1045,6 @@
     return _young_gen_sizer->adaptive_young_list_length();
   }
 
-  inline double get_gc_eff_factor() {
-    double ratio = _known_garbage_ratio;
-
-    double square = ratio * ratio;
-    // square = square * square;
-    double ret = square * 9.0 + 1.0;
-#if 0
-    gclog_or_tty->print_cr("ratio = %1.2lf, ret = %1.2lf", ratio, ret);
-#endif // 0
-    guarantee(0.0 <= ret && ret < 10.0, "invariant!");
-    return ret;
-  }
-
 private:
   //
   // Survivor regions policy.
@@ -1105,7 +1055,7 @@
   int _tenuring_threshold;
 
   // The limit on the number of regions allocated for survivors.
-  size_t _max_survivor_regions;
+  uint _max_survivor_regions;
 
   // For reporting purposes.
   size_t _eden_bytes_before_gc;
@@ -1113,7 +1063,7 @@
   size_t _capacity_before_gc;
 
   // The amount of survor regions after a collection.
-  size_t _recorded_survivor_regions;
+  uint _recorded_survivor_regions;
   // List of survivor regions.
   HeapRegion* _recorded_survivor_head;
   HeapRegion* _recorded_survivor_tail;
@@ -1135,9 +1085,9 @@
     return purpose == GCAllocForSurvived;
   }
 
-  static const size_t REGIONS_UNLIMITED = ~(size_t)0;
+  static const uint REGIONS_UNLIMITED = (uint) -1;
 
-  size_t max_regions(int purpose);
+  uint max_regions(int purpose);
 
   // The limit on regions for a particular purpose is reached.
   void note_alloc_region_limit_reached(int purpose) {
@@ -1154,7 +1104,7 @@
     _survivor_surv_rate_group->stop_adding_regions();
   }
 
-  void record_survivor_regions(size_t      regions,
+  void record_survivor_regions(uint regions,
                                HeapRegion* head,
                                HeapRegion* tail) {
     _recorded_survivor_regions = regions;
@@ -1162,12 +1112,11 @@
     _recorded_survivor_tail    = tail;
   }
 
-  size_t recorded_survivor_regions() {
+  uint recorded_survivor_regions() {
     return _recorded_survivor_regions;
   }
 
-  void record_thread_age_table(ageTable* age_table)
-  {
+  void record_thread_age_table(ageTable* age_table) {
     _survivors_age_table.merge_par(age_table);
   }
 
--- a/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -120,7 +120,7 @@
 
 // Single parameter format strings
 #define ergo_format_str(_name_)      ", " _name_ ": %s"
-#define ergo_format_region(_name_)   ", " _name_ ": "SIZE_FORMAT" regions"
+#define ergo_format_region(_name_)   ", " _name_ ": %u regions"
 #define ergo_format_byte(_name_)     ", " _name_ ": "SIZE_FORMAT" bytes"
 #define ergo_format_double(_name_)   ", " _name_ ": %1.2f"
 #define ergo_format_perc(_name_)     ", " _name_ ": %1.2f %%"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/g1Log.cpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/g1_globals.hpp"
+#include "gc_implementation/g1/g1Log.hpp"
+#include "runtime/globals.hpp"
+
+G1Log::LogLevel G1Log::_level = G1Log::LevelNone;
+
+// If G1LogLevel has not been set up we will use the values of PrintGC
+// and PrintGCDetails for the logging level.
+// - PrintGC maps to "fine".
+// - PrintGCDetails maps to "finer".
+void G1Log::init() {
+  if (G1LogLevel != NULL && G1LogLevel[0] != '\0') {
+    if (strncmp("none", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
+      _level = LevelNone;
+    } else if (strncmp("fine", G1LogLevel, 4) == 0 && G1LogLevel[4] == '\0') {
+      _level = LevelFine;
+    } else if (strncmp("finer", G1LogLevel, 5) == 0 && G1LogLevel[5] == '\0') {
+      _level = LevelFiner;
+    } else if (strncmp("finest", G1LogLevel, 6) == 0 && G1LogLevel[6] == '\0') {
+      _level = LevelFinest;
+    } else {
+      warning("Unknown logging level '%s', should be one of 'fine', 'finer' or 'finest'.", G1LogLevel);
+    }
+  } else {
+    if (PrintGCDetails) {
+      _level = LevelFiner;
+    } else if (PrintGC) {
+      _level = LevelFine;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/g1Log.hpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1LOG_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1LOG_HPP
+
+#include "memory/allocation.hpp"
+
+class G1Log : public AllStatic {
+  typedef enum {
+    LevelNone,
+    LevelFine,
+    LevelFiner,
+    LevelFinest
+  } LogLevel;
+
+  static LogLevel _level;
+
+ public:
+  inline static bool fine() {
+    return _level >= LevelFine;
+  }
+
+  inline static bool finer() {
+    return _level >= LevelFiner;
+  }
+
+  inline static bool finest() {
+    return _level == LevelFinest;
+  }
+
+  static void init();
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1LOG_HPP
--- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Tue May 15 11:27:24 2012 -0700
@@ -29,6 +29,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "code/codeCache.hpp"
 #include "code/icBuffer.hpp"
+#include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/g1MarkSweep.hpp"
 #include "memory/gcLocker.hpp"
 #include "memory/genCollectedHeap.hpp"
@@ -126,7 +127,7 @@
 void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
                                     bool clear_all_softrefs) {
   // Recursively traverse all live objects and mark them
-  TraceTime tm("phase 1", PrintGC && Verbose, true, gclog_or_tty);
+  TraceTime tm("phase 1", G1Log::fine() && Verbose, true, gclog_or_tty);
   GenMarkSweep::trace(" 1");
 
   SharedHeap* sh = SharedHeap::heap();
@@ -192,8 +193,7 @@
     // fail. At the end of the GC, the orginal mark word values
     // (including hash values) are restored to the appropriate
     // objects.
-    Universe::heap()->verify(/* allow dirty */ true,
-                             /* silent      */ false,
+    Universe::heap()->verify(/* silent      */ false,
                              /* option      */ VerifyOption_G1UseMarkWord);
 
     G1CollectedHeap* g1h = G1CollectedHeap::heap();
@@ -291,7 +291,7 @@
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   Generation* pg = g1h->perm_gen();
 
-  TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty);
+  TraceTime tm("phase 2", G1Log::fine() && Verbose, true, gclog_or_tty);
   GenMarkSweep::trace("2");
 
   FindFirstRegionClosure cl;
@@ -335,7 +335,7 @@
   Generation* pg = g1h->perm_gen();
 
   // Adjust the pointers to reflect the new locations
-  TraceTime tm("phase 3", PrintGC && Verbose, true, gclog_or_tty);
+  TraceTime tm("phase 3", G1Log::fine() && Verbose, true, gclog_or_tty);
   GenMarkSweep::trace("3");
 
   SharedHeap* sh = SharedHeap::heap();
@@ -399,7 +399,7 @@
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   Generation* pg = g1h->perm_gen();
 
-  TraceTime tm("phase 4", PrintGC && Verbose, true, gclog_or_tty);
+  TraceTime tm("phase 4", G1Log::fine() && Verbose, true, gclog_or_tty);
   GenMarkSweep::trace("4");
 
   pg->compact();
--- a/src/share/vm/gc_implementation/g1/g1MonitoringSupport.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1MonitoringSupport.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,9 @@
                G1MonitoringSupport::pad_capacity(0, 3) /* min_capacity */,
                G1MonitoringSupport::pad_capacity(g1mm->young_gen_max(), 3),
                G1MonitoringSupport::pad_capacity(0, 3) /* curr_capacity */) {
-  update_all();
+  if (UsePerfData) {
+    update_all();
+  }
 }
 
 G1OldGenerationCounters::G1OldGenerationCounters(G1MonitoringSupport* g1mm,
@@ -53,7 +55,9 @@
                G1MonitoringSupport::pad_capacity(0) /* min_capacity */,
                G1MonitoringSupport::pad_capacity(g1mm->old_gen_max()),
                G1MonitoringSupport::pad_capacity(0) /* curr_capacity */) {
-  update_all();
+  if (UsePerfData) {
+    update_all();
+  }
 }
 
 void G1YoungGenerationCounters::update_all() {
@@ -149,10 +153,6 @@
     pad_capacity(0) /* max_capacity */,
     pad_capacity(0) /* init_capacity */,
     _young_collection_counters);
-  // Given that this survivor space is not used, we update it here
-  // once to reflect that its used space is 0 so that we don't have to
-  // worry about updating it again later.
-  _from_counters->update_used(0);
 
   //  name "generation.0.space.2"
   // See _old_space_counters for additional counters
@@ -160,6 +160,13 @@
     pad_capacity(overall_reserved()) /* max_capacity */,
     pad_capacity(survivor_space_committed()) /* init_capacity */,
     _young_collection_counters);
+
+  if (UsePerfData) {
+    // Given that this survivor space is not used, we update it here
+    // once to reflect that its used space is 0 so that we don't have to
+    // worry about updating it again later.
+    _from_counters->update_used(0);
+  }
 }
 
 void G1MonitoringSupport::recalculate_sizes() {
@@ -170,19 +177,19 @@
   // values we read here are possible (i.e., at a STW phase at the end
   // of a GC).
 
-  size_t young_list_length = g1->young_list()->length();
-  size_t survivor_list_length = g1->g1_policy()->recorded_survivor_regions();
+  uint young_list_length = g1->young_list()->length();
+  uint survivor_list_length = g1->g1_policy()->recorded_survivor_regions();
   assert(young_list_length >= survivor_list_length, "invariant");
-  size_t eden_list_length = young_list_length - survivor_list_length;
+  uint eden_list_length = young_list_length - survivor_list_length;
   // Max length includes any potential extensions to the young gen
   // we'll do when the GC locker is active.
-  size_t young_list_max_length = g1->g1_policy()->young_list_max_length();
+  uint young_list_max_length = g1->g1_policy()->young_list_max_length();
   assert(young_list_max_length >= survivor_list_length, "invariant");
-  size_t eden_list_max_length = young_list_max_length - survivor_list_length;
+  uint eden_list_max_length = young_list_max_length - survivor_list_length;
 
   _overall_used = g1->used_unlocked();
-  _eden_used = eden_list_length * HeapRegion::GrainBytes;
-  _survivor_used = survivor_list_length * HeapRegion::GrainBytes;
+  _eden_used = (size_t) eden_list_length * HeapRegion::GrainBytes;
+  _survivor_used = (size_t) survivor_list_length * HeapRegion::GrainBytes;
   _young_region_num = young_list_length;
   _old_used = subtract_up_to_zero(_overall_used, _eden_used + _survivor_used);
 
@@ -200,7 +207,7 @@
   committed -= _survivor_committed + _old_committed;
 
   // Next, calculate and remove the committed size for the eden.
-  _eden_committed = eden_list_max_length * HeapRegion::GrainBytes;
+  _eden_committed = (size_t) eden_list_max_length * HeapRegion::GrainBytes;
   // Somewhat defensive: be robust in case there are inaccuracies in
   // the calculations
   _eden_committed = MIN2(_eden_committed, committed);
@@ -230,10 +237,10 @@
   // When a new eden region is allocated, only the eden_used size is
   // affected (since we have recalculated everything else at the last GC).
 
-  size_t young_region_num = g1h()->young_list()->length();
+  uint young_region_num = g1h()->young_list()->length();
   if (young_region_num > _young_region_num) {
-    size_t diff = young_region_num - _young_region_num;
-    _eden_used += diff * HeapRegion::GrainBytes;
+    uint diff = young_region_num - _young_region_num;
+    _eden_used += (size_t) diff * HeapRegion::GrainBytes;
     // Somewhat defensive: cap the eden used size to make sure it
     // never exceeds the committed size.
     _eden_used = MIN2(_eden_used, _eden_committed);
--- a/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -147,7 +147,7 @@
   size_t _overall_committed;
   size_t _overall_used;
 
-  size_t _young_region_num;
+  uint   _young_region_num;
   size_t _young_gen_committed;
   size_t _eden_committed;
   size_t _eden_used;
--- a/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Tue May 15 11:27:24 2012 -0700
@@ -118,9 +118,11 @@
   virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
 };
 
+template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
+class G1ParCopyClosure : public G1ParClosureSuper {
+  G1ParScanClosure _scanner;
+  template <class T> void do_oop_work(T* p);
 
-class G1ParCopyHelper : public G1ParClosureSuper {
-  G1ParScanClosure *_scanner;
 protected:
   // Mark the object if it's not already marked. This is used to mark
   // objects pointed to by roots that are guaranteed not to move
@@ -135,22 +137,10 @@
   oop copy_to_survivor_space(oop obj);
 
 public:
-  G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state,
-                  G1ParScanClosure *scanner) :
-    G1ParClosureSuper(g1, par_scan_state), _scanner(scanner) { }
-};
-
-template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
-class G1ParCopyClosure : public G1ParCopyHelper {
-  G1ParScanClosure _scanner;
-
-  template <class T> void do_oop_work(T* p);
-
-public:
   G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state,
                    ReferenceProcessor* rp) :
       _scanner(g1, par_scan_state, rp),
-      G1ParCopyHelper(g1, par_scan_state, &_scanner) {
+      G1ParClosureSuper(g1, par_scan_state) {
     assert(_ref_processor == NULL, "sanity");
   }
 
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Tue May 15 11:27:24 2012 -0700
@@ -26,7 +26,6 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1_GLOBALS_HPP
 
 #include "runtime/globals.hpp"
-
 //
 // Defines all globals flags used by the garbage-first compiler.
 //
@@ -69,9 +68,6 @@
   diagnostic(bool, G1TraceConcRefinement, false,                            \
           "Trace G1 concurrent refinement")                                 \
                                                                             \
-  product(intx, G1MarkRegionStackSize, 1024 * 1024,                         \
-          "Size of the region stack for concurrent marking.")               \
-                                                                            \
   product(double, G1ConcMarkStepDurationMillis, 10.0,                       \
           "Target duration of individual concurrent marking steps "         \
           "in milliseconds.")                                               \
@@ -131,9 +127,6 @@
             "Prints the liveness information for all regions in the heap "  \
             "at the end of a marking cycle.")                               \
                                                                             \
-  develop(bool, G1PrintParCleanupStats, false,                              \
-          "When true, print extra stats about parallel cleanup.")           \
-                                                                            \
   product(intx, G1UpdateBufferSize, 256,                                    \
           "Size of an update buffer")                                       \
                                                                             \
@@ -299,21 +292,23 @@
           "Percentage (0-100) of the heap size to use as maximum "          \
           "young gen size.")                                                \
                                                                             \
-  develop(uintx, G1OldCSetRegionLiveThresholdPercent, 95,                   \
+  develop(uintx, G1OldCSetRegionLiveThresholdPercent, 90,                   \
           "Threshold for regions to be added to the collection set. "       \
           "Regions with more live bytes that this will not be collected.")  \
                                                                             \
-  develop(uintx, G1OldReclaimableThresholdPercent, 1,                       \
-          "Threshold for the remaining old reclaimable bytes, expressed "   \
-          "as a percentage of the heap size. If the old reclaimable bytes " \
-          "are under this we will not collect them with more mixed GCs.")   \
+  product(uintx, G1HeapWastePercent, 5,                                     \
+          "Amount of space, expressed as a percentage of the heap size, "   \
+          "that G1 is willing not to collect to avoid expensive GCs.")      \
                                                                             \
-  develop(uintx, G1MaxMixedGCNum, 4,                                        \
-          "The maximum desired number of mixed GCs after a marking cycle.") \
+  product(uintx, G1MixedGCCountTarget, 4,                                   \
+          "The target number of mixed GCs after a marking cycle.")          \
                                                                             \
   develop(uintx, G1OldCSetRegionThresholdPercent, 10,                       \
           "An upper bound for the number of old CSet regions expressed "    \
-          "as a percentage of the heap size.")
+          "as a percentage of the heap size.")                              \
+                                                                            \
+  experimental(ccstr, G1LogLevel, NULL,                                     \
+          "Log level for G1 logging: fine, finer, finest")
 
 G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
 
--- a/src/share/vm/gc_implementation/g1/heapRegion.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp	Tue May 15 11:27:24 2012 -0700
@@ -334,7 +334,7 @@
 
   guarantee(GrainWords == 0, "we should only set it once");
   GrainWords = GrainBytes >> LogHeapWordSize;
-  guarantee((size_t)(1 << LogOfHRGrainWords) == GrainWords, "sanity");
+  guarantee((size_t) 1 << LogOfHRGrainWords == GrainWords, "sanity");
 
   guarantee(CardsPerRegion == 0, "we should only set it once");
   CardsPerRegion = GrainBytes >> CardTableModRefBS::card_shift;
@@ -370,7 +370,6 @@
     _claimed = InitialClaimValue;
   }
   zero_marked_bytes();
-  set_sort_index(-1);
 
   _offsets.resize(HeapRegion::GrainWords);
   init_top_at_mark_start();
@@ -482,17 +481,16 @@
 #endif // _MSC_VER
 
 
-HeapRegion::
-HeapRegion(size_t hrs_index, G1BlockOffsetSharedArray* sharedOffsetArray,
-           MemRegion mr, bool is_zeroed)
-  : G1OffsetTableContigSpace(sharedOffsetArray, mr, is_zeroed),
+HeapRegion::HeapRegion(uint hrs_index,
+                       G1BlockOffsetSharedArray* sharedOffsetArray,
+                       MemRegion mr, bool is_zeroed) :
+    G1OffsetTableContigSpace(sharedOffsetArray, mr, is_zeroed),
     _hrs_index(hrs_index),
     _humongous_type(NotHumongous), _humongous_start_region(NULL),
     _in_collection_set(false),
     _next_in_special_set(NULL), _orig_end(NULL),
     _claimed(InitialClaimValue), _evacuation_failed(false),
-    _prev_marked_bytes(0), _next_marked_bytes(0), _sort_index(-1),
-    _gc_efficiency(0.0),
+    _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
     _young_type(NotYoung), _next_young_region(NULL),
     _next_dirty_cards_region(NULL), _next(NULL), _pending_removal(false),
 #ifdef ASSERT
@@ -512,9 +510,6 @@
   _rem_set =  new HeapRegionRemSet(sharedOffsetArray, this);
 
   assert(HeapRegionRemSet::num_par_rem_sets() > 0, "Invariant.");
-  // In case the region is allocated during a pause, note the top.
-  // We haven't done any counting on a brand new region.
-  _top_at_conc_mark_count = bottom();
 }
 
 class NextCompactionHeapRegionClosure: public HeapRegionClosure {
@@ -587,14 +582,12 @@
     // we find to be self-forwarded on the next bitmap. So all
     // objects need to be below NTAMS.
     _next_top_at_mark_start = top();
-    set_top_at_conc_mark_count(bottom());
     _next_marked_bytes = 0;
   } else if (during_conc_mark) {
     // During concurrent mark, all objects in the CSet (including
     // the ones we find to be self-forwarded) are implicitly live.
     // So all objects need to be above NTAMS.
     _next_top_at_mark_start = bottom();
-    set_top_at_conc_mark_count(bottom());
     _next_marked_bytes = 0;
   }
 }
@@ -779,16 +772,15 @@
   G1OffsetTableContigSpace::print_on(st);
 }
 
-void HeapRegion::verify(bool allow_dirty) const {
+void HeapRegion::verify() const {
   bool dummy = false;
-  verify(allow_dirty, VerifyOption_G1UsePrevMarking, /* failures */ &dummy);
+  verify(VerifyOption_G1UsePrevMarking, /* failures */ &dummy);
 }
 
 // This really ought to be commoned up into OffsetTableContigSpace somehow.
 // We would need a mechanism to make that code skip dead objects.
 
-void HeapRegion::verify(bool allow_dirty,
-                        VerifyOption vo,
+void HeapRegion::verify(VerifyOption vo,
                         bool* failures) const {
   G1CollectedHeap* g1 = G1CollectedHeap::heap();
   *failures = false;
--- a/src/share/vm/gc_implementation/g1/heapRegion.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp	Tue May 15 11:27:24 2012 -0700
@@ -52,12 +52,15 @@
 class HeapRegion;
 class HeapRegionSetBase;
 
-#define HR_FORMAT SIZE_FORMAT":(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]"
+#define HR_FORMAT "%u:(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]"
 #define HR_FORMAT_PARAMS(_hr_) \
                 (_hr_)->hrs_index(), \
                 (_hr_)->is_survivor() ? "S" : (_hr_)->is_young() ? "E" : "-", \
                 (_hr_)->bottom(), (_hr_)->top(), (_hr_)->end()
 
+// sentinel value for hrs_index
+#define G1_NULL_HRS_INDEX ((uint) -1)
+
 // A dirty card to oop closure for heap regions. It
 // knows how to get the G1 heap and how to use the bitmap
 // in the concurrent marker used by G1 to filter remembered
@@ -235,7 +238,7 @@
 
  protected:
   // The index of this region in the heap region sequence.
-  size_t  _hrs_index;
+  uint  _hrs_index;
 
   HumongousType _humongous_type;
   // For a humongous region, region in which it starts.
@@ -278,12 +281,8 @@
   size_t _prev_marked_bytes;    // Bytes known to be live via last completed marking.
   size_t _next_marked_bytes;    // Bytes known to be live via in-progress marking.
 
-  // See "sort_index" method.  -1 means is not in the array.
-  int _sort_index;
-
-  // <PREDICTION>
+  // The calculated GC efficiency of the region.
   double _gc_efficiency;
-  // </PREDICTION>
 
   enum YoungType {
     NotYoung,                   // a region is not young
@@ -307,9 +306,6 @@
   // If a collection pause is in progress, this is the top at the start
   // of that pause.
 
-  // We've counted the marked bytes of objects below here.
-  HeapWord* _top_at_conc_mark_count;
-
   void init_top_at_mark_start() {
     assert(_prev_marked_bytes == 0 &&
            _next_marked_bytes == 0,
@@ -317,7 +313,6 @@
     HeapWord* bot = bottom();
     _prev_top_at_mark_start = bot;
     _next_top_at_mark_start = bot;
-    _top_at_conc_mark_count = bot;
   }
 
   void set_young_type(YoungType new_type) {
@@ -342,7 +337,7 @@
 
  public:
   // If "is_zeroed" is "true", the region "mr" can be assumed to contain zeros.
-  HeapRegion(size_t hrs_index,
+  HeapRegion(uint hrs_index,
              G1BlockOffsetSharedArray* sharedOffsetArray,
              MemRegion mr, bool is_zeroed);
 
@@ -373,10 +368,9 @@
     ScrubRemSetClaimValue      = 3,
     ParVerifyClaimValue        = 4,
     RebuildRSClaimValue        = 5,
-    CompleteMarkCSetClaimValue = 6,
-    ParEvacFailureClaimValue   = 7,
-    AggregateCountClaimValue   = 8,
-    VerifyCountClaimValue      = 9
+    ParEvacFailureClaimValue   = 6,
+    AggregateCountClaimValue   = 7,
+    VerifyCountClaimValue      = 8
   };
 
   inline HeapWord* par_allocate_no_bot_updates(size_t word_size) {
@@ -390,7 +384,7 @@
 
   // If this region is a member of a HeapRegionSeq, the index in that
   // sequence, otherwise -1.
-  size_t hrs_index() const { return _hrs_index; }
+  uint hrs_index() const { return _hrs_index; }
 
   // The number of bytes marked live in the region in the last marking phase.
   size_t marked_bytes()    { return _prev_marked_bytes; }
@@ -627,29 +621,6 @@
   // last mark phase ended.
   bool is_marked() { return _prev_top_at_mark_start != bottom(); }
 
-  // If "is_marked()" is true, then this is the index of the region in
-  // an array constructed at the end of marking of the regions in a
-  // "desirability" order.
-  int sort_index() {
-    return _sort_index;
-  }
-  void set_sort_index(int i) {
-    _sort_index = i;
-  }
-
-  void init_top_at_conc_mark_count() {
-    _top_at_conc_mark_count = bottom();
-  }
-
-  void set_top_at_conc_mark_count(HeapWord *cur) {
-    assert(bottom() <= cur && cur <= end(), "Sanity.");
-    _top_at_conc_mark_count = cur;
-  }
-
-  HeapWord* top_at_conc_mark_count() {
-    return _top_at_conc_mark_count;
-  }
-
   void reset_during_compaction() {
     guarantee( isHumongous() && startsHumongous(),
                "should only be called for humongous regions");
@@ -745,7 +716,6 @@
     _evacuation_failed = b;
 
     if (b) {
-      init_top_at_conc_mark_count();
       _next_marked_bytes = 0;
     }
   }
@@ -824,10 +794,10 @@
   // Currently there is only one place where this is called with
   // vo == UseMarkWord, which is to verify the marking during a
   // full GC.
-  void verify(bool allow_dirty, VerifyOption vo, bool *failures) const;
+  void verify(VerifyOption vo, bool *failures) const;
 
   // Override; it uses the "prev" marking information
-  virtual void verify(bool allow_dirty) const;
+  virtual void verify() const;
 };
 
 // HeapRegionClosure is used for iterating over regions.
--- a/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp	Tue May 15 11:27:24 2012 -0700
@@ -56,7 +56,6 @@
 }
 
 inline void HeapRegion::note_start_of_marking() {
-  init_top_at_conc_mark_count();
   _next_marked_bytes = 0;
   _next_top_at_mark_start = top();
 }
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -577,7 +577,7 @@
 #endif
 
 void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) {
-  size_t cur_hrs_ind = hr()->hrs_index();
+  size_t cur_hrs_ind = (size_t) hr()->hrs_index();
 
 #if HRRS_VERBOSE
   gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").",
@@ -841,7 +841,7 @@
 #endif
 
   // Set the corresponding coarse bit.
-  size_t max_hrs_index = max->hr()->hrs_index();
+  size_t max_hrs_index = (size_t) max->hr()->hrs_index();
   if (!_coarse_map.at(max_hrs_index)) {
     _coarse_map.at_put(max_hrs_index, true);
     _n_coarse_entries++;
@@ -866,17 +866,20 @@
 void OtherRegionsTable::scrub(CardTableModRefBS* ctbs,
                               BitMap* region_bm, BitMap* card_bm) {
   // First eliminated garbage regions from the coarse map.
-  if (G1RSScrubVerbose)
-    gclog_or_tty->print_cr("Scrubbing region "SIZE_FORMAT":",
-                           hr()->hrs_index());
+  if (G1RSScrubVerbose) {
+    gclog_or_tty->print_cr("Scrubbing region %u:", hr()->hrs_index());
+  }
 
   assert(_coarse_map.size() == region_bm->size(), "Precondition");
-  if (G1RSScrubVerbose)
-    gclog_or_tty->print("   Coarse map: before = %d...", _n_coarse_entries);
+  if (G1RSScrubVerbose) {
+    gclog_or_tty->print("   Coarse map: before = "SIZE_FORMAT"...",
+                        _n_coarse_entries);
+  }
   _coarse_map.set_intersection(*region_bm);
   _n_coarse_entries = _coarse_map.count_one_bits();
-  if (G1RSScrubVerbose)
-    gclog_or_tty->print_cr("   after = %d.", _n_coarse_entries);
+  if (G1RSScrubVerbose) {
+    gclog_or_tty->print_cr("   after = "SIZE_FORMAT".", _n_coarse_entries);
+  }
 
   // Now do the fine-grained maps.
   for (size_t i = 0; i < _max_fine_entries; i++) {
@@ -885,23 +888,27 @@
     while (cur != NULL) {
       PosParPRT* nxt = cur->next();
       // If the entire region is dead, eliminate.
-      if (G1RSScrubVerbose)
-        gclog_or_tty->print_cr("     For other region "SIZE_FORMAT":",
+      if (G1RSScrubVerbose) {
+        gclog_or_tty->print_cr("     For other region %u:",
                                cur->hr()->hrs_index());
-      if (!region_bm->at(cur->hr()->hrs_index())) {
+      }
+      if (!region_bm->at((size_t) cur->hr()->hrs_index())) {
         *prev = nxt;
         cur->set_next(NULL);
         _n_fine_entries--;
-        if (G1RSScrubVerbose)
+        if (G1RSScrubVerbose) {
           gclog_or_tty->print_cr("          deleted via region map.");
+        }
         PosParPRT::free(cur);
       } else {
         // Do fine-grain elimination.
-        if (G1RSScrubVerbose)
+        if (G1RSScrubVerbose) {
           gclog_or_tty->print("          occ: before = %4d.", cur->occupied());
+        }
         cur->scrub(ctbs, card_bm);
-        if (G1RSScrubVerbose)
+        if (G1RSScrubVerbose) {
           gclog_or_tty->print_cr("          after = %4d.", cur->occupied());
+        }
         // Did that empty the table completely?
         if (cur->occupied() == 0) {
           *prev = nxt;
@@ -1003,7 +1010,7 @@
 
 void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) {
   MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
-  size_t hrs_ind = from_hr->hrs_index();
+  size_t hrs_ind = (size_t) from_hr->hrs_index();
   size_t ind = hrs_ind & _mod_max_fine_entries_mask;
   if (del_single_region_table(ind, from_hr)) {
     assert(!_coarse_map.at(hrs_ind), "Inv");
@@ -1011,7 +1018,7 @@
     _coarse_map.par_at_put(hrs_ind, 0);
   }
   // Check to see if any of the fcc entries come from here.
-  size_t hr_ind = hr()->hrs_index();
+  size_t hr_ind = (size_t) hr()->hrs_index();
   for (int tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) {
     int fcc_ent = _from_card_cache[tid][hr_ind];
     if (fcc_ent != -1) {
@@ -1223,7 +1230,7 @@
     if ((size_t)_coarse_cur_region_index < _coarse_map->size()) {
       _coarse_cur_region_cur_card = 0;
       HeapWord* r_bot =
-        _g1h->region_at(_coarse_cur_region_index)->bottom();
+        _g1h->region_at((uint) _coarse_cur_region_index)->bottom();
       _cur_region_card_offset = _bosa->index_for(r_bot);
     } else {
       return false;
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Tue May 15 11:27:24 2012 -0700
@@ -329,13 +329,13 @@
 
   // Declare the heap size (in # of regions) to the HeapRegionRemSet(s).
   // (Uses it to initialize from_card_cache).
-  static void init_heap(size_t max_regions) {
-    OtherRegionsTable::init_from_card_cache(max_regions);
+  static void init_heap(uint max_regions) {
+    OtherRegionsTable::init_from_card_cache((size_t) max_regions);
   }
 
   // Declares that only regions i s.t. 0 <= i < new_n_regs are in use.
-  static void shrink_heap(size_t new_n_regs) {
-    OtherRegionsTable::shrink_from_card_cache(new_n_regs);
+  static void shrink_heap(uint new_n_regs) {
+    OtherRegionsTable::shrink_from_card_cache((size_t) new_n_regs);
   }
 
 #ifndef PRODUCT
--- a/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,16 +31,15 @@
 
 // Private
 
-size_t HeapRegionSeq::find_contiguous_from(size_t from, size_t num) {
-  size_t len = length();
+uint HeapRegionSeq::find_contiguous_from(uint from, uint num) {
+  uint len = length();
   assert(num > 1, "use this only for sequences of length 2 or greater");
   assert(from <= len,
-         err_msg("from: "SIZE_FORMAT" should be valid and <= than "SIZE_FORMAT,
-                 from, len));
+         err_msg("from: %u should be valid and <= than %u", from, len));
 
-  size_t curr = from;
-  size_t first = G1_NULL_HRS_INDEX;
-  size_t num_so_far = 0;
+  uint curr = from;
+  uint first = G1_NULL_HRS_INDEX;
+  uint num_so_far = 0;
   while (curr < len && num_so_far < num) {
     if (at(curr)->is_empty()) {
       if (first == G1_NULL_HRS_INDEX) {
@@ -60,7 +59,7 @@
     // we found enough space for the humongous object
     assert(from <= first && first < len, "post-condition");
     assert(first < curr && (curr - first) == num, "post-condition");
-    for (size_t i = first; i < first + num; ++i) {
+    for (uint i = first; i < first + num; ++i) {
       assert(at(i)->is_empty(), "post-condition");
     }
     return first;
@@ -73,10 +72,10 @@
 // Public
 
 void HeapRegionSeq::initialize(HeapWord* bottom, HeapWord* end,
-                               size_t max_length) {
-  assert((size_t) bottom % HeapRegion::GrainBytes == 0,
+                               uint max_length) {
+  assert((uintptr_t) bottom % HeapRegion::GrainBytes == 0,
          "bottom should be heap region aligned");
-  assert((size_t) end % HeapRegion::GrainBytes == 0,
+  assert((uintptr_t) end % HeapRegion::GrainBytes == 0,
          "end should be heap region aligned");
 
   _length = 0;
@@ -88,8 +87,8 @@
   _max_length = max_length;
 
   _regions = NEW_C_HEAP_ARRAY(HeapRegion*, max_length);
-  memset(_regions, 0, max_length * sizeof(HeapRegion*));
-  _regions_biased = _regions - ((size_t) bottom >> _region_shift);
+  memset(_regions, 0, (size_t) max_length * sizeof(HeapRegion*));
+  _regions_biased = _regions - ((uintx) bottom >> _region_shift);
 
   assert(&_regions[0] == &_regions_biased[addr_to_index_biased(bottom)],
          "bottom should be included in the region with index 0");
@@ -105,7 +104,7 @@
   assert(_heap_bottom <= next_bottom, "invariant");
   while (next_bottom < new_end) {
     assert(next_bottom < _heap_end, "invariant");
-    size_t index = length();
+    uint index = length();
 
     assert(index < _max_length, "otherwise we cannot expand further");
     if (index == 0) {
@@ -139,9 +138,9 @@
   return MemRegion(old_end, next_bottom);
 }
 
-size_t HeapRegionSeq::free_suffix() {
-  size_t res = 0;
-  size_t index = length();
+uint HeapRegionSeq::free_suffix() {
+  uint res = 0;
+  uint index = length();
   while (index > 0) {
     index -= 1;
     if (!at(index)->is_empty()) {
@@ -152,27 +151,24 @@
   return res;
 }
 
-size_t HeapRegionSeq::find_contiguous(size_t num) {
+uint HeapRegionSeq::find_contiguous(uint num) {
   assert(num > 1, "use this only for sequences of length 2 or greater");
   assert(_next_search_index <= length(),
-         err_msg("_next_search_indeex: "SIZE_FORMAT" "
-                 "should be valid and <= than "SIZE_FORMAT,
+         err_msg("_next_search_index: %u should be valid and <= than %u",
                  _next_search_index, length()));
 
-  size_t start = _next_search_index;
-  size_t res = find_contiguous_from(start, num);
+  uint start = _next_search_index;
+  uint res = find_contiguous_from(start, num);
   if (res == G1_NULL_HRS_INDEX && start > 0) {
     // Try starting from the beginning. If _next_search_index was 0,
     // no point in doing this again.
     res = find_contiguous_from(0, num);
   }
   if (res != G1_NULL_HRS_INDEX) {
-    assert(res < length(),
-           err_msg("res: "SIZE_FORMAT" should be valid", res));
+    assert(res < length(), err_msg("res: %u should be valid", res));
     _next_search_index = res + num;
     assert(_next_search_index <= length(),
-           err_msg("_next_search_indeex: "SIZE_FORMAT" "
-                   "should be valid and <= than "SIZE_FORMAT,
+           err_msg("_next_search_index: %u should be valid and <= than %u",
                    _next_search_index, length()));
   }
   return res;
@@ -183,20 +179,20 @@
 }
 
 void HeapRegionSeq::iterate_from(HeapRegion* hr, HeapRegionClosure* blk) const {
-  size_t hr_index = 0;
+  uint hr_index = 0;
   if (hr != NULL) {
-    hr_index = (size_t) hr->hrs_index();
+    hr_index = hr->hrs_index();
   }
 
-  size_t len = length();
-  for (size_t i = hr_index; i < len; i += 1) {
+  uint len = length();
+  for (uint i = hr_index; i < len; i += 1) {
     bool res = blk->doHeapRegion(at(i));
     if (res) {
       blk->incomplete();
       return;
     }
   }
-  for (size_t i = 0; i < hr_index; i += 1) {
+  for (uint i = 0; i < hr_index; i += 1) {
     bool res = blk->doHeapRegion(at(i));
     if (res) {
       blk->incomplete();
@@ -206,7 +202,7 @@
 }
 
 MemRegion HeapRegionSeq::shrink_by(size_t shrink_bytes,
-                                   size_t* num_regions_deleted) {
+                                   uint* num_regions_deleted) {
   // Reset this in case it's currently pointing into the regions that
   // we just removed.
   _next_search_index = 0;
@@ -218,7 +214,7 @@
   assert(_allocated_length > 0, "we should have at least one region committed");
 
   // around the loop, i will be the next region to be removed
-  size_t i = length() - 1;
+  uint i = length() - 1;
   assert(i > 0, "we should never remove all regions");
   // [last_start, end) is the MemRegion that covers the regions we will remove.
   HeapWord* end = at(i)->end();
@@ -249,29 +245,24 @@
 #ifndef PRODUCT
 void HeapRegionSeq::verify_optional() {
   guarantee(_length <= _allocated_length,
-            err_msg("invariant: _length: "SIZE_FORMAT" "
-                    "_allocated_length: "SIZE_FORMAT,
+            err_msg("invariant: _length: %u _allocated_length: %u",
                     _length, _allocated_length));
   guarantee(_allocated_length <= _max_length,
-            err_msg("invariant: _allocated_length: "SIZE_FORMAT" "
-                    "_max_length: "SIZE_FORMAT,
+            err_msg("invariant: _allocated_length: %u _max_length: %u",
                     _allocated_length, _max_length));
   guarantee(_next_search_index <= _length,
-            err_msg("invariant: _next_search_index: "SIZE_FORMAT" "
-                    "_length: "SIZE_FORMAT,
+            err_msg("invariant: _next_search_index: %u _length: %u",
                     _next_search_index, _length));
 
   HeapWord* prev_end = _heap_bottom;
-  for (size_t i = 0; i < _allocated_length; i += 1) {
+  for (uint i = 0; i < _allocated_length; i += 1) {
     HeapRegion* hr = _regions[i];
-    guarantee(hr != NULL, err_msg("invariant: i: "SIZE_FORMAT, i));
+    guarantee(hr != NULL, err_msg("invariant: i: %u", i));
     guarantee(hr->bottom() == prev_end,
-              err_msg("invariant i: "SIZE_FORMAT" "HR_FORMAT" "
-                      "prev_end: "PTR_FORMAT,
+              err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT,
                       i, HR_FORMAT_PARAMS(hr), prev_end));
     guarantee(hr->hrs_index() == i,
-              err_msg("invariant: i: "SIZE_FORMAT" hrs_index(): "SIZE_FORMAT,
-                      i, hr->hrs_index()));
+              err_msg("invariant: i: %u hrs_index(): %u", i, hr->hrs_index()));
     if (i < _length) {
       // Asserts will fire if i is >= _length
       HeapWord* addr = hr->bottom();
@@ -290,8 +281,8 @@
       prev_end = hr->end();
     }
   }
-  for (size_t i = _allocated_length; i < _max_length; i += 1) {
-    guarantee(_regions[i] == NULL, err_msg("invariant i: "SIZE_FORMAT, i));
+  for (uint i = _allocated_length; i < _max_length; i += 1) {
+    guarantee(_regions[i] == NULL, err_msg("invariant i: %u", i));
   }
 }
 #endif // PRODUCT
--- a/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,6 @@
 class HeapRegionClosure;
 class FreeRegionList;
 
-#define G1_NULL_HRS_INDEX ((size_t) -1)
-
 // This class keeps track of the region metadata (i.e., HeapRegion
 // instances). They are kept in the _regions array in address
 // order. A region's index in the array corresponds to its index in
@@ -65,7 +63,7 @@
   HeapRegion** _regions_biased;
 
   // The number of regions committed in the heap.
-  size_t _length;
+  uint _length;
 
   // The address of the first reserved word in the heap.
   HeapWord* _heap_bottom;
@@ -74,32 +72,32 @@
   HeapWord* _heap_end;
 
   // The log of the region byte size.
-  size_t _region_shift;
+  uint _region_shift;
 
   // A hint for which index to start searching from for humongous
   // allocations.
-  size_t _next_search_index;
+  uint _next_search_index;
 
   // The number of regions for which we have allocated HeapRegions for.
-  size_t _allocated_length;
+  uint _allocated_length;
 
   // The maximum number of regions in the heap.
-  size_t _max_length;
+  uint _max_length;
 
   // Find a contiguous set of empty regions of length num, starting
   // from the given index.
-  size_t find_contiguous_from(size_t from, size_t num);
+  uint find_contiguous_from(uint from, uint num);
 
   // Map a heap address to a biased region index. Assume that the
   // address is valid.
-  inline size_t addr_to_index_biased(HeapWord* addr) const;
+  inline uintx addr_to_index_biased(HeapWord* addr) const;
 
-  void increment_length(size_t* length) {
+  void increment_length(uint* length) {
     assert(*length < _max_length, "pre-condition");
     *length += 1;
   }
 
-  void decrement_length(size_t* length) {
+  void decrement_length(uint* length) {
     assert(*length > 0, "pre-condition");
     *length -= 1;
   }
@@ -108,11 +106,11 @@
   // Empty contructor, we'll initialize it with the initialize() method.
   HeapRegionSeq() { }
 
-  void initialize(HeapWord* bottom, HeapWord* end, size_t max_length);
+  void initialize(HeapWord* bottom, HeapWord* end, uint max_length);
 
   // Return the HeapRegion at the given index. Assume that the index
   // is valid.
-  inline HeapRegion* at(size_t index) const;
+  inline HeapRegion* at(uint index) const;
 
   // If addr is within the committed space return its corresponding
   // HeapRegion, otherwise return NULL.
@@ -123,10 +121,10 @@
   inline HeapRegion* addr_to_region_unsafe(HeapWord* addr) const;
 
   // Return the number of regions that have been committed in the heap.
-  size_t length() const { return _length; }
+  uint length() const { return _length; }
 
   // Return the maximum number of regions in the heap.
-  size_t max_length() const { return _max_length; }
+  uint max_length() const { return _max_length; }
 
   // Expand the sequence to reflect that the heap has grown from
   // old_end to new_end. Either create new HeapRegions, or re-use
@@ -139,12 +137,12 @@
 
   // Return the number of contiguous regions at the end of the sequence
   // that are available for allocation.
-  size_t free_suffix();
+  uint free_suffix();
 
   // Find a contiguous set of empty regions of length num and return
   // the index of the first region or G1_NULL_HRS_INDEX if the
   // search was unsuccessful.
-  size_t find_contiguous(size_t num);
+  uint find_contiguous(uint num);
 
   // Apply blk->doHeapRegion() on all committed regions in address order,
   // terminating the iteration early if doHeapRegion() returns true.
@@ -159,7 +157,7 @@
   // sequence. Return a MemRegion that corresponds to the address
   // range of the uncommitted regions. Assume shrink_bytes is page and
   // heap region aligned.
-  MemRegion shrink_by(size_t shrink_bytes, size_t* num_regions_deleted);
+  MemRegion shrink_by(size_t shrink_bytes, uint* num_regions_deleted);
 
   // Do some sanity checking.
   void verify_optional() PRODUCT_RETURN;
--- a/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,11 +28,11 @@
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "gc_implementation/g1/heapRegionSeq.hpp"
 
-inline size_t HeapRegionSeq::addr_to_index_biased(HeapWord* addr) const {
+inline uintx HeapRegionSeq::addr_to_index_biased(HeapWord* addr) const {
   assert(_heap_bottom <= addr && addr < _heap_end,
          err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT" end: "PTR_FORMAT,
                  addr, _heap_bottom, _heap_end));
-  size_t index = (size_t) addr >> _region_shift;
+  uintx index = (uintx) addr >> _region_shift;
   return index;
 }
 
@@ -40,7 +40,7 @@
   assert(_heap_bottom <= addr && addr < _heap_end,
          err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT" end: "PTR_FORMAT,
                  addr, _heap_bottom, _heap_end));
-  size_t index_biased = addr_to_index_biased(addr);
+  uintx index_biased = addr_to_index_biased(addr);
   HeapRegion* hr = _regions_biased[index_biased];
   assert(hr != NULL, "invariant");
   return hr;
@@ -55,7 +55,7 @@
   return NULL;
 }
 
-inline HeapRegion* HeapRegionSeq::at(size_t index) const {
+inline HeapRegion* HeapRegionSeq::at(uint index) const {
   assert(index < length(), "pre-condition");
   HeapRegion* hr = _regions[index];
   assert(hr != NULL, "sanity");
--- a/src/share/vm/gc_implementation/g1/heapRegionSet.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionSet.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,28 +25,26 @@
 #include "precompiled.hpp"
 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
 
-size_t HeapRegionSetBase::_unrealistically_long_length = 0;
+uint HeapRegionSetBase::_unrealistically_long_length = 0;
 HRSPhase HeapRegionSetBase::_phase = HRSPhaseNone;
 
 //////////////////// HeapRegionSetBase ////////////////////
 
-void HeapRegionSetBase::set_unrealistically_long_length(size_t len) {
+void HeapRegionSetBase::set_unrealistically_long_length(uint len) {
   guarantee(_unrealistically_long_length == 0, "should only be set once");
   _unrealistically_long_length = len;
 }
 
-size_t HeapRegionSetBase::calculate_region_num(HeapRegion* hr) {
+uint HeapRegionSetBase::calculate_region_num(HeapRegion* hr) {
   assert(hr->startsHumongous(), "pre-condition");
   assert(hr->capacity() % HeapRegion::GrainBytes == 0, "invariant");
-  size_t region_num = hr->capacity() >> HeapRegion::LogOfHRGrainBytes;
+  uint region_num = (uint) (hr->capacity() >> HeapRegion::LogOfHRGrainBytes);
   assert(region_num > 0, "sanity");
   return region_num;
 }
 
 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) {
-  msg->append("[%s] %s "
-              "ln: "SIZE_FORMAT" rn: "SIZE_FORMAT" "
-              "cy: "SIZE_FORMAT" ud: "SIZE_FORMAT,
+  msg->append("[%s] %s ln: %u rn: %u cy: "SIZE_FORMAT" ud: "SIZE_FORMAT,
               name(), message, length(), region_num(),
               total_capacity_bytes(), total_used_bytes());
   fill_in_ext_msg_extra(msg);
@@ -170,13 +168,11 @@
          hrs_ext_msg(this, "verification should be in progress"));
 
   guarantee(length() == _calc_length,
-            hrs_err_msg("[%s] length: "SIZE_FORMAT" should be == "
-                        "calc length: "SIZE_FORMAT,
+            hrs_err_msg("[%s] length: %u should be == calc length: %u",
                         name(), length(), _calc_length));
 
   guarantee(region_num() == _calc_region_num,
-            hrs_err_msg("[%s] region num: "SIZE_FORMAT" should be == "
-                        "calc region num: "SIZE_FORMAT,
+            hrs_err_msg("[%s] region num: %u should be == calc region num: %u",
                         name(), region_num(), _calc_region_num));
 
   guarantee(total_capacity_bytes() == _calc_total_capacity_bytes,
@@ -211,8 +207,8 @@
   out->print_cr("    humongous         : %s", BOOL_TO_STR(regions_humongous()));
   out->print_cr("    empty             : %s", BOOL_TO_STR(regions_empty()));
   out->print_cr("  Attributes");
-  out->print_cr("    length            : "SIZE_FORMAT_W(14), length());
-  out->print_cr("    region num        : "SIZE_FORMAT_W(14), region_num());
+  out->print_cr("    length            : %14u", length());
+  out->print_cr("    region num        : %14u", region_num());
   out->print_cr("    total capacity    : "SIZE_FORMAT_W(14)" bytes",
                 total_capacity_bytes());
   out->print_cr("    total used        : "SIZE_FORMAT_W(14)" bytes",
@@ -243,14 +239,12 @@
   if (proxy_set->is_empty()) return;
 
   assert(proxy_set->length() <= _length,
-         hrs_err_msg("[%s] proxy set length: "SIZE_FORMAT" "
-                     "should be <= length: "SIZE_FORMAT,
+         hrs_err_msg("[%s] proxy set length: %u should be <= length: %u",
                      name(), proxy_set->length(), _length));
   _length -= proxy_set->length();
 
   assert(proxy_set->region_num() <= _region_num,
-         hrs_err_msg("[%s] proxy set region num: "SIZE_FORMAT" "
-                     "should be <= region num: "SIZE_FORMAT,
+         hrs_err_msg("[%s] proxy set region num: %u should be <= region num: %u",
                      name(), proxy_set->region_num(), _region_num));
   _region_num -= proxy_set->region_num();
 
@@ -369,17 +363,17 @@
   verify_optional();
 }
 
-void HeapRegionLinkedList::remove_all_pending(size_t target_count) {
+void HeapRegionLinkedList::remove_all_pending(uint target_count) {
   hrs_assert_mt_safety_ok(this);
   assert(target_count > 1, hrs_ext_msg(this, "pre-condition"));
   assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
 
   verify_optional();
-  DEBUG_ONLY(size_t old_length = length();)
+  DEBUG_ONLY(uint old_length = length();)
 
   HeapRegion* curr = _head;
   HeapRegion* prev = NULL;
-  size_t count = 0;
+  uint count = 0;
   while (curr != NULL) {
     hrs_assert_region_ok(this, curr, this);
     HeapRegion* next = curr->next();
@@ -387,7 +381,7 @@
     if (curr->pending_removal()) {
       assert(count < target_count,
              hrs_err_msg("[%s] should not come across more regions "
-                         "pending for removal than target_count: "SIZE_FORMAT,
+                         "pending for removal than target_count: %u",
                          name(), target_count));
 
       if (prev == NULL) {
@@ -422,12 +416,11 @@
   }
 
   assert(count == target_count,
-         hrs_err_msg("[%s] count: "SIZE_FORMAT" should be == "
-                     "target_count: "SIZE_FORMAT, name(), count, target_count));
+         hrs_err_msg("[%s] count: %u should be == target_count: %u",
+                     name(), count, target_count));
   assert(length() + target_count == old_length,
          hrs_err_msg("[%s] new length should be consistent "
-                     "new length: "SIZE_FORMAT" old length: "SIZE_FORMAT" "
-                     "target_count: "SIZE_FORMAT,
+                     "new length: %u old length: %u target_count: %u",
                      name(), length(), old_length, target_count));
 
   verify_optional();
@@ -444,16 +437,16 @@
   HeapRegion* curr  = _head;
   HeapRegion* prev1 = NULL;
   HeapRegion* prev0 = NULL;
-  size_t      count = 0;
+  uint        count = 0;
   while (curr != NULL) {
     verify_next_region(curr);
 
     count += 1;
     guarantee(count < _unrealistically_long_length,
-              hrs_err_msg("[%s] the calculated length: "SIZE_FORMAT" "
+              hrs_err_msg("[%s] the calculated length: %u "
                           "seems very long, is there maybe a cycle? "
                           "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" "
-                          "prev1: "PTR_FORMAT" length: "SIZE_FORMAT,
+                          "prev1: "PTR_FORMAT" length: %u",
                           name(), count, curr, prev0, prev1, length()));
 
     prev1 = prev0;
--- a/src/share/vm/gc_implementation/g1/heapRegionSet.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionSet.hpp	Tue May 15 11:27:24 2012 -0700
@@ -62,20 +62,20 @@
   friend class VMStructs;
 
 protected:
-  static size_t calculate_region_num(HeapRegion* hr);
+  static uint calculate_region_num(HeapRegion* hr);
 
-  static size_t _unrealistically_long_length;
+  static uint _unrealistically_long_length;
 
   // The number of regions added to the set. If the set contains
   // only humongous regions, this reflects only 'starts humongous'
   // regions and does not include 'continues humongous' ones.
-  size_t _length;
+  uint _length;
 
   // The total number of regions represented by the set. If the set
   // does not contain humongous regions, this should be the same as
   // _length. If the set contains only humongous regions, this will
   // include the 'continues humongous' regions.
-  size_t _region_num;
+  uint _region_num;
 
   // We don't keep track of the total capacity explicitly, we instead
   // recalculate it based on _region_num and the heap region size.
@@ -86,8 +86,8 @@
   const char* _name;
 
   bool        _verify_in_progress;
-  size_t      _calc_length;
-  size_t      _calc_region_num;
+  uint        _calc_length;
+  uint        _calc_region_num;
   size_t      _calc_total_capacity_bytes;
   size_t      _calc_total_used_bytes;
 
@@ -153,18 +153,18 @@
   HeapRegionSetBase(const char* name);
 
 public:
-  static void set_unrealistically_long_length(size_t len);
+  static void set_unrealistically_long_length(uint len);
 
   const char* name() { return _name; }
 
-  size_t length() { return _length; }
+  uint length() { return _length; }
 
   bool is_empty() { return _length == 0; }
 
-  size_t region_num() { return _region_num; }
+  uint region_num() { return _region_num; }
 
   size_t total_capacity_bytes() {
-    return region_num() << HeapRegion::LogOfHRGrainBytes;
+    return (size_t) region_num() << HeapRegion::LogOfHRGrainBytes;
   }
 
   size_t total_used_bytes() { return _total_used_bytes; }
@@ -341,7 +341,7 @@
   // of regions that are pending for removal in the list, and
   // target_count should be > 1 (currently, we never need to remove a
   // single region using this).
-  void remove_all_pending(size_t target_count);
+  void remove_all_pending(uint target_count);
 
   virtual void verify();
 
--- a/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,15 +54,15 @@
   assert(_length > 0, hrs_ext_msg(this, "pre-condition"));
   _length -= 1;
 
-  size_t region_num_diff;
+  uint region_num_diff;
   if (!hr->isHumongous()) {
     region_num_diff = 1;
   } else {
     region_num_diff = calculate_region_num(hr);
   }
   assert(region_num_diff <= _region_num,
-         hrs_err_msg("[%s] region's region num: "SIZE_FORMAT" "
-                     "should be <= region num: "SIZE_FORMAT,
+         hrs_err_msg("[%s] region's region num: %u "
+                     "should be <= region num: %u",
                      name(), region_num_diff, _region_num));
   _region_num -= region_num_diff;
 
--- a/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -481,8 +481,7 @@
 
 bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) {
 #if SPARSE_PRT_VERBOSE
-  gclog_or_tty->print_cr("  Adding card %d from region %d to region "
-                         SIZE_FORMAT" sparse.",
+  gclog_or_tty->print_cr("  Adding card %d from region %d to region %u sparse.",
                          card_index, region_id, _hr->hrs_index());
 #endif
   if (_next->occupied_entries() * 2 > _next->capacity()) {
@@ -534,7 +533,7 @@
   _next = new RSHashTable(last->capacity() * 2);
 
 #if SPARSE_PRT_VERBOSE
-  gclog_or_tty->print_cr("  Expanded sparse table for "SIZE_FORMAT" to %d.",
+  gclog_or_tty->print_cr("  Expanded sparse table for %u to %d.",
                          _hr->hrs_index(), _next->capacity());
 #endif
   for (size_t i = 0; i < last->capacity(); i++) {
--- a/src/share/vm/gc_implementation/g1/survRateGroup.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/survRateGroup.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,33 +38,36 @@
     _summary_surv_rates(NULL),
     _surv_rate(NULL),
     _accum_surv_rate_pred(NULL),
-    _surv_rate_pred(NULL)
-{
+    _surv_rate_pred(NULL),
+    _stats_arrays_length(0) {
   reset();
   if (summary_surv_rates_len > 0) {
     size_t length = summary_surv_rates_len;
-      _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length);
-    if (_summary_surv_rates == NULL) {
-      vm_exit_out_of_memory(sizeof(NumberSeq*) * length,
-                            "Not enough space for surv rate summary");
+    _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length);
+    for (size_t i = 0; i < length; ++i) {
+      _summary_surv_rates[i] = new NumberSeq();
     }
-    for (size_t i = 0; i < length; ++i)
-      _summary_surv_rates[i] = new NumberSeq();
   }
 
   start_adding_regions();
 }
 
-
-void SurvRateGroup::reset()
-{
+void SurvRateGroup::reset() {
   _all_regions_allocated = 0;
   _setup_seq_num         = 0;
-  _stats_arrays_length   = 0;
   _accum_surv_rate       = 0.0;
   _last_pred             = 0.0;
   // the following will set up the arrays with length 1
   _region_num            = 1;
+
+  // The call to stop_adding_regions() will use "new" to refill
+  // the _surv_rate_pred array, so we need to make sure to call
+  // "delete".
+  for (size_t i = 0; i < _stats_arrays_length; ++i) {
+    delete _surv_rate_pred[i];
+  }
+  _stats_arrays_length = 0;
+
   stop_adding_regions();
   guarantee( _stats_arrays_length == 1, "invariant" );
   guarantee( _surv_rate_pred[0] != NULL, "invariant" );
@@ -73,72 +76,47 @@
   _region_num = 0;
 }
 
-
 void
 SurvRateGroup::start_adding_regions() {
   _setup_seq_num   = _stats_arrays_length;
   _region_num      = 0;
   _accum_surv_rate = 0.0;
-
-#if 0
-  gclog_or_tty->print_cr("[%s] start adding regions, seq num %d, length %d",
-                         _name, _setup_seq_num, _region_num);
-#endif // 0
 }
 
 void
 SurvRateGroup::stop_adding_regions() {
-
-#if 0
-  gclog_or_tty->print_cr("[%s] stop adding regions, length %d", _name, _region_num);
-#endif // 0
-
   if (_region_num > _stats_arrays_length) {
     double* old_surv_rate = _surv_rate;
     double* old_accum_surv_rate_pred = _accum_surv_rate_pred;
     TruncatedSeq** old_surv_rate_pred = _surv_rate_pred;
 
     _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num);
-    if (_surv_rate == NULL) {
-      vm_exit_out_of_memory(sizeof(double) * _region_num,
-                            "Not enough space for surv rate array.");
-    }
     _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num);
-    if (_accum_surv_rate_pred == NULL) {
-      vm_exit_out_of_memory(sizeof(double) * _region_num,
-                         "Not enough space for accum surv rate pred array.");
-    }
     _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num);
-    if (_surv_rate == NULL) {
-      vm_exit_out_of_memory(sizeof(TruncatedSeq*) * _region_num,
-                            "Not enough space for surv rate pred array.");
-    }
 
-    for (size_t i = 0; i < _stats_arrays_length; ++i)
+    for (size_t i = 0; i < _stats_arrays_length; ++i) {
       _surv_rate_pred[i] = old_surv_rate_pred[i];
-
-#if 0
-    gclog_or_tty->print_cr("[%s] stop adding regions, new seqs %d to %d",
-                  _name, _array_length, _region_num - 1);
-#endif // 0
-
+    }
     for (size_t i = _stats_arrays_length; i < _region_num; ++i) {
       _surv_rate_pred[i] = new TruncatedSeq(10);
-      // _surv_rate_pred[i]->add(last_pred);
     }
 
     _stats_arrays_length = _region_num;
 
-    if (old_surv_rate != NULL)
+    if (old_surv_rate != NULL) {
       FREE_C_HEAP_ARRAY(double, old_surv_rate);
-    if (old_accum_surv_rate_pred != NULL)
+    }
+    if (old_accum_surv_rate_pred != NULL) {
       FREE_C_HEAP_ARRAY(double, old_accum_surv_rate_pred);
-    if (old_surv_rate_pred != NULL)
-      FREE_C_HEAP_ARRAY(NumberSeq*, old_surv_rate_pred);
+    }
+    if (old_surv_rate_pred != NULL) {
+      FREE_C_HEAP_ARRAY(TruncatedSeq*, old_surv_rate_pred);
+    }
   }
 
-  for (size_t i = 0; i < _stats_arrays_length; ++i)
+  for (size_t i = 0; i < _stats_arrays_length; ++i) {
     _surv_rate[i] = 0.0;
+  }
 }
 
 double
@@ -187,12 +165,6 @@
 SurvRateGroup::all_surviving_words_recorded(bool propagate) {
   if (propagate && _region_num > 0) { // conservative
     double surv_rate = _surv_rate_pred[_region_num-1]->last();
-
-#if 0
-    gclog_or_tty->print_cr("propagating %1.2lf from %d to %d",
-                  surv_rate, _curr_length, _array_length - 1);
-#endif // 0
-
     for (size_t i = _region_num; i < _stats_arrays_length; ++i) {
       guarantee( _surv_rate[i] <= 0.00001,
                  "the slot should not have been updated" );
--- a/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp	Tue May 15 11:27:24 2012 -0700
@@ -34,7 +34,7 @@
   static_field(HeapRegion, GrainBytes, size_t)                                \
                                                                               \
   nonstatic_field(HeapRegionSeq,   _regions, HeapRegion**)                    \
-  nonstatic_field(HeapRegionSeq,   _length,  size_t)                          \
+  nonstatic_field(HeapRegionSeq,   _length,  uint)                            \
                                                                               \
   nonstatic_field(G1CollectedHeap, _hrs,                HeapRegionSeq)        \
   nonstatic_field(G1CollectedHeap, _g1_committed,       MemRegion)            \
@@ -50,8 +50,8 @@
   nonstatic_field(G1MonitoringSupport, _old_committed,      size_t)           \
   nonstatic_field(G1MonitoringSupport, _old_used,           size_t)           \
                                                                               \
-  nonstatic_field(HeapRegionSetBase,   _length,             size_t)           \
-  nonstatic_field(HeapRegionSetBase,   _region_num,         size_t)           \
+  nonstatic_field(HeapRegionSetBase,   _length,             uint)             \
+  nonstatic_field(HeapRegionSetBase,   _region_num,         uint)             \
   nonstatic_field(HeapRegionSetBase,   _total_used_bytes,   size_t)           \
 
 
--- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Tue May 15 11:27:24 2012 -0700
@@ -26,6 +26,7 @@
 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
+#include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/vm_operations_g1.hpp"
 #include "gc_implementation/shared/isGCActiveMark.hpp"
 #include "gc_implementation/g1/vm_operations_g1.hpp"
@@ -34,7 +35,8 @@
 VM_G1CollectForAllocation::VM_G1CollectForAllocation(
                                                   unsigned int gc_count_before,
                                                   size_t word_size)
-  : VM_G1OperationWithAllocRequest(gc_count_before, word_size) {
+  : VM_G1OperationWithAllocRequest(gc_count_before, word_size,
+                                   GCCause::_allocation_failure) {
   guarantee(word_size > 0, "an allocation should always be requested");
 }
 
@@ -57,9 +59,10 @@
                                       bool           should_initiate_conc_mark,
                                       double         target_pause_time_ms,
                                       GCCause::Cause gc_cause)
-  : VM_G1OperationWithAllocRequest(gc_count_before, word_size),
+  : VM_G1OperationWithAllocRequest(gc_count_before, word_size, gc_cause),
     _should_initiate_conc_mark(should_initiate_conc_mark),
     _target_pause_time_ms(target_pause_time_ms),
+    _should_retry_gc(false),
     _full_collections_completed_before(0) {
   guarantee(target_pause_time_ms > 0.0,
             err_msg("target_pause_time_ms = %1.6lf should be positive",
@@ -70,6 +73,22 @@
   _gc_cause = gc_cause;
 }
 
+bool VM_G1IncCollectionPause::doit_prologue() {
+  bool res = VM_GC_Operation::doit_prologue();
+  if (!res) {
+    if (_should_initiate_conc_mark) {
+      // The prologue can fail for a couple of reasons. The first is that another GC
+      // got scheduled and prevented the scheduling of the initial mark GC. The
+      // second is that the GC locker may be active and the heap can't be expanded.
+      // In both cases we want to retry the GC so that the initial mark pause is
+      // actually scheduled. In the second case, however, we should stall until
+      // until the GC locker is no longer active and then retry the initial mark GC.
+      _should_retry_gc = true;
+    }
+  }
+  return res;
+}
+
 void VM_G1IncCollectionPause::doit() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   assert(!_should_initiate_conc_mark ||
@@ -106,11 +125,25 @@
     // next GC pause to be an initial mark; it returns false if a
     // marking cycle is already in progress.
     //
-    // If a marking cycle is already in progress just return and skip
-    // the pause - the requesting thread should block in doit_epilogue
-    // until the marking cycle is complete.
+    // If a marking cycle is already in progress just return and skip the
+    // pause below - if the reason for requesting this initial mark pause
+    // was due to a System.gc() then the requesting thread should block in
+    // doit_epilogue() until the marking cycle is complete.
+    //
+    // If this initial mark pause was requested as part of a humongous
+    // allocation then we know that the marking cycle must just have
+    // been started by another thread (possibly also allocating a humongous
+    // object) as there was no active marking cycle when the requesting
+    // thread checked before calling collect() in
+    // attempt_allocation_humongous(). Retrying the GC, in this case,
+    // will cause the requesting thread to spin inside collect() until the
+    // just started marking cycle is complete - which may be a while. So
+    // we do NOT retry the GC.
     if (!res) {
-      assert(_word_size == 0, "ExplicitGCInvokesConcurrent shouldn't be allocating");
+      assert(_word_size == 0, "Concurrent Full GC/Humongous Object IM shouldn't be allocating");
+      if (_gc_cause != GCCause::_g1_humongous_allocation) {
+        _should_retry_gc = true;
+      }
       return;
     }
   }
@@ -123,6 +156,13 @@
                                       true /* expect_null_cur_alloc_region */);
   } else {
     assert(_result == NULL, "invariant");
+    if (!_pause_succeeded) {
+      // Another possible reason reason for the pause to not be successful
+      // is that, again, the GC locker is active (and has become active
+      // since the prologue was executed). In this case we should retry
+      // the pause after waiting for the GC locker to become inactive.
+      _should_retry_gc = true;
+    }
   }
 }
 
@@ -168,6 +208,7 @@
 }
 
 void VM_CGC_Operation::acquire_pending_list_lock() {
+  assert(_needs_pll, "don't call this otherwise");
   // The caller may block while communicating
   // with the SLT thread in order to acquire/release the PLL.
   ConcurrentMarkThread::slt()->
@@ -175,6 +216,7 @@
 }
 
 void VM_CGC_Operation::release_and_notify_pending_list_lock() {
+  assert(_needs_pll, "don't call this otherwise");
   // The caller may block while communicating
   // with the SLT thread in order to acquire/release the PLL.
   ConcurrentMarkThread::slt()->
@@ -182,9 +224,9 @@
 }
 
 void VM_CGC_Operation::doit() {
-  gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
-  TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-  TraceTime t(_printGCMessage, PrintGC, true, gclog_or_tty);
+  gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
+  TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
+  TraceTime t(_printGCMessage, G1Log::fine(), true, gclog_or_tty);
   SharedHeap* sh = SharedHeap::heap();
   // This could go away if CollectedHeap gave access to _gc_is_active...
   if (sh != NULL) {
@@ -198,7 +240,9 @@
 bool VM_CGC_Operation::doit_prologue() {
   // Note the relative order of the locks must match that in
   // VM_GC_Operation::doit_prologue() or deadlocks can occur
-  acquire_pending_list_lock();
+  if (_needs_pll) {
+    acquire_pending_list_lock();
+  }
 
   Heap_lock->lock();
   SharedHeap::heap()->_thread_holds_heap_lock_for_gc = true;
@@ -210,5 +254,7 @@
   // VM_GC_Operation::doit_epilogue()
   SharedHeap::heap()->_thread_holds_heap_lock_for_gc = false;
   Heap_lock->unlock();
-  release_and_notify_pending_list_lock();
+  if (_needs_pll) {
+    release_and_notify_pending_list_lock();
+  }
 }
--- a/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,8 +43,9 @@
 
 public:
   VM_G1OperationWithAllocRequest(unsigned int gc_count_before,
-                                 size_t       word_size)
-    : VM_GC_Operation(gc_count_before, GCCause::_allocation_failure),
+                                 size_t       word_size,
+                                 GCCause::Cause gc_cause)
+    : VM_GC_Operation(gc_count_before, gc_cause),
       _word_size(word_size), _result(NULL), _pause_succeeded(false) { }
   HeapWord* result() { return _result; }
   bool pause_succeeded() { return _pause_succeeded; }
@@ -77,6 +78,7 @@
 class VM_G1IncCollectionPause: public VM_G1OperationWithAllocRequest {
 private:
   bool         _should_initiate_conc_mark;
+  bool         _should_retry_gc;
   double       _target_pause_time_ms;
   unsigned int _full_collections_completed_before;
 public:
@@ -86,11 +88,13 @@
                           double         target_pause_time_ms,
                           GCCause::Cause gc_cause);
   virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; }
+  virtual bool doit_prologue();
   virtual void doit();
   virtual void doit_epilogue();
   virtual const char* name() const {
     return "garbage-first incremental collection pause";
   }
+  bool should_retry_gc() const { return _should_retry_gc; }
 };
 
 // Concurrent GC stop-the-world operations such as remark and cleanup;
@@ -98,6 +102,7 @@
 class VM_CGC_Operation: public VM_Operation {
   VoidClosure* _cl;
   const char* _printGCMessage;
+  bool _needs_pll;
 
 protected:
   // java.lang.ref.Reference support
@@ -105,8 +110,8 @@
   void release_and_notify_pending_list_lock();
 
 public:
-  VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg)
-    : _cl(cl), _printGCMessage(printGCMsg) { }
+  VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg, bool needs_pll)
+    : _cl(cl), _printGCMessage(printGCMsg), _needs_pll(needs_pll) { }
   virtual VMOp_Type type() const { return VMOp_CGC_Operation; }
   virtual void doit();
   virtual bool doit_prologue();
--- a/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp	Tue May 15 11:27:24 2012 -0700
@@ -42,7 +42,7 @@
 
  protected:
   template <class T> void do_oop_work(T* p) {
-    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
+    oop obj = oopDesc::load_decode_heap_oop(p);
     if (_young_gen->is_in_reserved(obj) &&
         !_card_table->addr_is_marked_imprecise(p)) {
       // Don't overwrite the first missing card mark
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Tue May 15 11:27:24 2012 -0700
@@ -911,23 +911,23 @@
 }
 
 
-void ParallelScavengeHeap::verify(bool allow_dirty, bool silent, VerifyOption option /* ignored */) {
+void ParallelScavengeHeap::verify(bool silent, VerifyOption option /* ignored */) {
   // Why do we need the total_collections()-filter below?
   if (total_collections() > 0) {
     if (!silent) {
       gclog_or_tty->print("permanent ");
     }
-    perm_gen()->verify(allow_dirty);
+    perm_gen()->verify();
 
     if (!silent) {
       gclog_or_tty->print("tenured ");
     }
-    old_gen()->verify(allow_dirty);
+    old_gen()->verify();
 
     if (!silent) {
       gclog_or_tty->print("eden ");
     }
-    young_gen()->verify(allow_dirty);
+    young_gen()->verify();
   }
 }
 
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Tue May 15 11:27:24 2012 -0700
@@ -257,7 +257,7 @@
   virtual void gc_threads_do(ThreadClosure* tc) const;
   virtual void print_tracing_info() const;
 
-  void verify(bool allow_dirty, bool silent, VerifyOption option /* ignored */);
+  void verify(bool silent, VerifyOption option /* ignored */);
 
   void print_heap_change(size_t prev_used);
 
--- a/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -477,8 +477,8 @@
 }
 #endif
 
-void PSOldGen::verify(bool allow_dirty) {
-  object_space()->verify(allow_dirty);
+void PSOldGen::verify() {
+  object_space()->verify();
 }
 class VerifyObjectStartArrayClosure : public ObjectClosure {
   PSOldGen* _gen;
--- a/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -174,7 +174,7 @@
   virtual void print_on(outputStream* st) const;
   void print_used_change(size_t prev_used) const;
 
-  void verify(bool allow_dirty);
+  void verify();
   void verify_object_start_array();
 
   // These should not used
--- a/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp	Tue May 15 11:27:24 2012 -0700
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONMANAGER_INLINE_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONMANAGER_INLINE_HPP
 
+#include "gc_implementation/parallelScavenge/psOldGen.hpp"
 #include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
 
--- a/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -937,10 +937,10 @@
   }
 }
 
-void PSYoungGen::verify(bool allow_dirty) {
-  eden_space()->verify(allow_dirty);
-  from_space()->verify(allow_dirty);
-  to_space()->verify(allow_dirty);
+void PSYoungGen::verify() {
+  eden_space()->verify();
+  from_space()->verify();
+  to_space()->verify();
 }
 
 #ifndef PRODUCT
--- a/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -181,7 +181,7 @@
   void print_used_change(size_t prev_used) const;
   virtual const char* name() const { return "PSYoungGen"; }
 
-  void verify(bool allow_dirty);
+  void verify();
 
   // Space boundary invariant checker
   void space_invariants() PRODUCT_RETURN;
--- a/src/share/vm/gc_implementation/shared/allocationStats.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/shared/allocationStats.hpp	Tue May 15 11:27:24 2012 -0700
@@ -39,7 +39,7 @@
   // 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)
+  //     + split_births(between) - split_deaths(between)
   // The above number divided by the time since the 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
@@ -51,34 +51,34 @@
   AdaptivePaddedAverage _demand_rate_estimate;
 
   ssize_t     _desired;         // Demand stimate computed as described above
-  ssize_t     _coalDesired;     // desired +/- small-percent for tuning coalescing
+  ssize_t     _coal_desired;     // 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.
+  ssize_t     _bfr_surp;         // surplus at start of current sweep
+  ssize_t     _prev_sweep;       // count from end of previous sweep
+  ssize_t     _before_sweep;     // count from before current sweep
+  ssize_t     _coal_births;      // additional chunks from coalescing
+  ssize_t     _coal_deaths;      // loss from coalescing
+  ssize_t     _split_births;     // additional chunks from splitting
+  ssize_t     _split_deaths;     // loss from splitting
+  size_t      _returned_bytes;   // number of bytes returned to list.
  public:
   void initialize(bool split_birth = false) {
     AdaptivePaddedAverage* dummy =
       new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight,
                                                          CMS_FLSPadding);
     _desired = 0;
-    _coalDesired = 0;
+    _coal_desired = 0;
     _surplus = 0;
-    _bfrSurp = 0;
-    _prevSweep = 0;
-    _beforeSweep = 0;
-    _coalBirths = 0;
-    _coalDeaths = 0;
-    _splitBirths = (split_birth ? 1 : 0);
-    _splitDeaths = 0;
-    _returnedBytes = 0;
+    _bfr_surp = 0;
+    _prev_sweep = 0;
+    _before_sweep = 0;
+    _coal_births = 0;
+    _coal_deaths = 0;
+    _split_births = (split_birth ? 1 : 0);
+    _split_deaths = 0;
+    _returned_bytes = 0;
   }
 
   AllocationStats() {
@@ -99,12 +99,12 @@
     // vulnerable to noisy glitches. In such cases, we
     // ignore the current sample and use currently available
     // historical estimates.
-    assert(prevSweep() + splitBirths() + coalBirths()        // "Total Production Stock"
-           >= splitDeaths() + coalDeaths() + (ssize_t)count, // "Current stock + depletion"
+    assert(prev_sweep() + split_births() + coal_births()        // "Total Production Stock"
+           >= split_deaths() + coal_deaths() + (ssize_t)count, // "Current stock + depletion"
            "Conservation Principle");
     if (inter_sweep_current > _threshold) {
-      ssize_t demand = prevSweep() - (ssize_t)count + splitBirths() + coalBirths()
-                       - splitDeaths() - coalDeaths();
+      ssize_t demand = prev_sweep() - (ssize_t)count + split_births() + coal_births()
+                       - split_deaths() - coal_deaths();
       assert(demand >= 0,
              err_msg("Demand (" SSIZE_FORMAT ") should be non-negative for "
                      PTR_FORMAT " (size=" SIZE_FORMAT ")",
@@ -130,40 +130,40 @@
   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 coal_desired() const { return _coal_desired; }
+  void set_coal_desired(ssize_t v) { _coal_desired = 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 bfr_surp() const { return _bfr_surp; }
+  void set_bfr_surp(ssize_t v) { _bfr_surp = v; }
+  ssize_t prev_sweep() const { return _prev_sweep; }
+  void set_prev_sweep(ssize_t v) { _prev_sweep = v; }
+  ssize_t before_sweep() const { return _before_sweep; }
+  void set_before_sweep(ssize_t v) { _before_sweep = v; }
 
-  ssize_t coalBirths() const { return _coalBirths; }
-  void set_coalBirths(ssize_t v) { _coalBirths = v; }
-  void increment_coalBirths() { _coalBirths++; }
+  ssize_t coal_births() const { return _coal_births; }
+  void set_coal_births(ssize_t v) { _coal_births = v; }
+  void increment_coal_births() { _coal_births++; }
 
-  ssize_t coalDeaths() const { return _coalDeaths; }
-  void set_coalDeaths(ssize_t v) { _coalDeaths = v; }
-  void increment_coalDeaths() { _coalDeaths++; }
+  ssize_t coal_deaths() const { return _coal_deaths; }
+  void set_coal_deaths(ssize_t v) { _coal_deaths = v; }
+  void increment_coal_deaths() { _coal_deaths++; }
 
-  ssize_t splitBirths() const { return _splitBirths; }
-  void set_splitBirths(ssize_t v) { _splitBirths = v; }
-  void increment_splitBirths() { _splitBirths++; }
+  ssize_t split_births() const { return _split_births; }
+  void set_split_births(ssize_t v) { _split_births = v; }
+  void increment_split_births() { _split_births++; }
 
-  ssize_t splitDeaths() const { return _splitDeaths; }
-  void set_splitDeaths(ssize_t v) { _splitDeaths = v; }
-  void increment_splitDeaths() { _splitDeaths++; }
+  ssize_t split_deaths() const { return _split_deaths; }
+  void set_split_deaths(ssize_t v) { _split_deaths = v; }
+  void increment_split_deaths() { _split_deaths++; }
 
   NOT_PRODUCT(
-    size_t returnedBytes() const { return _returnedBytes; }
-    void set_returnedBytes(size_t v) { _returnedBytes = v; }
+    size_t returned_bytes() const { return _returned_bytes; }
+    void set_returned_bytes(size_t v) { _returned_bytes = v; }
   )
 };
 
--- a/src/share/vm/gc_implementation/shared/immutableSpace.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/shared/immutableSpace.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,7 +70,7 @@
 
 #endif
 
-void ImmutableSpace::verify(bool allow_dirty) {
+void ImmutableSpace::verify() {
   HeapWord* p = bottom();
   HeapWord* t = end();
   HeapWord* prev_p = NULL;
--- a/src/share/vm/gc_implementation/shared/immutableSpace.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/shared/immutableSpace.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,7 +65,7 @@
   // Debugging
   virtual void print() const            PRODUCT_RETURN;
   virtual void print_short() const      PRODUCT_RETURN;
-  virtual void verify(bool allow_dirty);
+  virtual void verify();
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_IMMUTABLESPACE_HPP
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,29 +91,37 @@
     MutableSpace *s = ls->space();
     if (s->top() < top()) { // For all spaces preceding the one containing top()
       if (s->free_in_words() > 0) {
-        size_t area_touched_words = pointer_delta(s->end(), s->top());
-        CollectedHeap::fill_with_object(s->top(), area_touched_words);
+        intptr_t cur_top = (intptr_t)s->top();
+        size_t words_left_to_fill = pointer_delta(s->end(), s->top());;
+        while (words_left_to_fill > 0) {
+          size_t words_to_fill = MIN2(words_left_to_fill, CollectedHeap::filler_array_max_size());
+          assert(words_to_fill >= CollectedHeap::min_fill_size(),
+            err_msg("Remaining size ("SIZE_FORMAT ") is too small to fill (based on " SIZE_FORMAT " and " SIZE_FORMAT ")",
+            words_to_fill, words_left_to_fill, CollectedHeap::filler_array_max_size()));
+          CollectedHeap::fill_with_object((HeapWord*)cur_top, words_to_fill);
+          if (!os::numa_has_static_binding()) {
+            size_t touched_words = words_to_fill;
 #ifndef ASSERT
-        if (!ZapUnusedHeapArea) {
-          area_touched_words = MIN2((size_t)align_object_size(typeArrayOopDesc::header_size(T_INT)),
-                                    area_touched_words);
-        }
+            if (!ZapUnusedHeapArea) {
+              touched_words = MIN2((size_t)align_object_size(typeArrayOopDesc::header_size(T_INT)),
+                touched_words);
+            }
 #endif
-        if (!os::numa_has_static_binding()) {
-          MemRegion invalid;
-          HeapWord *crossing_start = (HeapWord*)round_to((intptr_t)s->top(), os::vm_page_size());
-          HeapWord *crossing_end = (HeapWord*)round_to((intptr_t)(s->top() + area_touched_words),
-                                                       os::vm_page_size());
-          if (crossing_start != crossing_end) {
-            // If object header crossed a small page boundary we mark the area
-            // as invalid rounding it to a page_size().
-            HeapWord *start = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom());
-            HeapWord *end = MIN2((HeapWord*)round_to((intptr_t)(s->top() + area_touched_words), page_size()),
-                                 s->end());
-            invalid = MemRegion(start, end);
+            MemRegion invalid;
+            HeapWord *crossing_start = (HeapWord*)round_to(cur_top, os::vm_page_size());
+            HeapWord *crossing_end = (HeapWord*)round_to(cur_top + touched_words, os::vm_page_size());
+            if (crossing_start != crossing_end) {
+              // If object header crossed a small page boundary we mark the area
+              // as invalid rounding it to a page_size().
+              HeapWord *start = MAX2((HeapWord*)round_down(cur_top, page_size()), s->bottom());
+              HeapWord *end = MIN2((HeapWord*)round_to(cur_top + touched_words, page_size()), s->end());
+              invalid = MemRegion(start, end);
+            }
+
+            ls->add_invalid_region(invalid);
           }
-
-          ls->add_invalid_region(invalid);
+          cur_top = cur_top + (words_to_fill * HeapWordSize);
+          words_left_to_fill -= words_to_fill;
         }
       }
     } else {
@@ -883,12 +891,12 @@
   }
 }
 
-void MutableNUMASpace::verify(bool allow_dirty) {
+void MutableNUMASpace::verify() {
   // This can be called after setting an arbitary value to the space's top,
   // so an object can cross the chunk boundary. We ensure the parsablity
   // of the space and just walk the objects in linear fashion.
   ensure_parsability();
-  MutableSpace::verify(allow_dirty);
+  MutableSpace::verify();
 }
 
 // Scan pages and gather stats about page placement and size.
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -225,7 +225,7 @@
   // Debugging
   virtual void print_on(outputStream* st) const;
   virtual void print_short_on(outputStream* st) const;
-  virtual void verify(bool allow_dirty);
+  virtual void verify();
 
   virtual void set_top(HeapWord* value);
 };
--- a/src/share/vm/gc_implementation/shared/mutableSpace.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/shared/mutableSpace.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -246,7 +246,7 @@
                  bottom(), top(), end());
 }
 
-void MutableSpace::verify(bool allow_dirty) {
+void MutableSpace::verify() {
   HeapWord* p = bottom();
   HeapWord* t = top();
   HeapWord* prev_p = NULL;
--- a/src/share/vm/gc_implementation/shared/mutableSpace.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_implementation/shared/mutableSpace.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@
   virtual void print_on(outputStream* st) const;
   virtual void print_short() const;
   virtual void print_short_on(outputStream* st) const;
-  virtual void verify(bool allow_dirty);
+  virtual void verify();
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_MUTABLESPACE_HPP
--- a/src/share/vm/gc_interface/collectedHeap.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_interface/collectedHeap.cpp	Tue May 15 11:27:24 2012 -0700
@@ -85,7 +85,7 @@
   const size_t max_len = size_t(arrayOopDesc::max_array_length(T_INT));
   const size_t elements_per_word = HeapWordSize / sizeof(jint);
   _filler_array_max_size = align_object_size(filler_array_hdr_size() +
-                                             max_len * elements_per_word);
+                                             max_len / elements_per_word);
 
   _barrier_set = NULL;
   _is_gc_active = false;
@@ -303,10 +303,6 @@
   return align_object_size(filler_array_hdr_size()); // align to MinObjAlignment
 }
 
-size_t CollectedHeap::filler_array_max_size() {
-  return _filler_array_max_size;
-}
-
 #ifdef ASSERT
 void CollectedHeap::fill_args_check(HeapWord* start, size_t words)
 {
@@ -333,10 +329,11 @@
 
   const size_t payload_size = words - filler_array_hdr_size();
   const size_t len = payload_size * HeapWordSize / sizeof(jint);
+  assert((int)len >= 0, err_msg("size too large " SIZE_FORMAT " becomes %d", words, (int)len));
 
   // Set the length first for concurrent GC.
   ((arrayOop)start)->set_length((int)len);
-  post_allocation_setup_common(Universe::intArrayKlassObj(), start, words);
+  post_allocation_setup_common(Universe::intArrayKlassObj(), start);
   DEBUG_ONLY(zap_filler_array(start, words, zap);)
 }
 
@@ -349,8 +346,7 @@
     fill_with_array(start, words, zap);
   } else if (words > 0) {
     assert(words == min_fill_size(), "unaligned size");
-    post_allocation_setup_common(SystemDictionary::Object_klass(), start,
-                                 words);
+    post_allocation_setup_common(SystemDictionary::Object_klass(), start);
   }
 }
 
@@ -480,7 +476,7 @@
     assert(ScavengeRootsInCode > 0, "must be");
     obj = common_mem_allocate_init(size, CHECK_NULL);
   }
-  post_allocation_setup_common(klass, obj, size);
+  post_allocation_setup_common(klass, obj);
   assert(Universe::is_bootstrapping() ||
          !((oop)obj)->blueprint()->oop_is_array(), "must not be an array");
   NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
--- a/src/share/vm/gc_interface/collectedHeap.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_interface/collectedHeap.hpp	Tue May 15 11:27:24 2012 -0700
@@ -128,7 +128,6 @@
   // Reinitialize tlabs before resuming mutators.
   virtual void resize_all_tlabs();
 
- protected:
   // Allocate from the current thread's TLAB, with broken-out slow path.
   inline static HeapWord* allocate_from_tlab(Thread* thread, size_t size);
   static HeapWord* allocate_from_tlab_slow(Thread* thread, size_t size);
@@ -150,18 +149,14 @@
   inline static HeapWord* common_permanent_mem_allocate_init(size_t size, TRAPS);
 
   // Helper functions for (VM) allocation.
-  inline static void post_allocation_setup_common(KlassHandle klass,
-                                                  HeapWord* obj, size_t size);
+  inline static void post_allocation_setup_common(KlassHandle klass, HeapWord* obj);
   inline static void post_allocation_setup_no_klass_install(KlassHandle klass,
-                                                            HeapWord* objPtr,
-                                                            size_t size);
+                                                            HeapWord* objPtr);
 
-  inline static void post_allocation_setup_obj(KlassHandle klass,
-                                               HeapWord* obj, size_t size);
+  inline static void post_allocation_setup_obj(KlassHandle klass, HeapWord* obj);
 
   inline static void post_allocation_setup_array(KlassHandle klass,
-                                                 HeapWord* obj, size_t size,
-                                                 int length);
+                                                 HeapWord* obj, int length);
 
   // Clears an allocated object.
   inline static void init_obj(HeapWord* obj, size_t size);
@@ -169,7 +164,6 @@
   // Filler object utilities.
   static inline size_t filler_array_hdr_size();
   static inline size_t filler_array_min_size();
-  static inline size_t filler_array_max_size();
 
   DEBUG_ONLY(static void fill_args_check(HeapWord* start, size_t words);)
   DEBUG_ONLY(static void zap_filler_array(HeapWord* start, size_t words, bool zap = true);)
@@ -197,6 +191,10 @@
     G1CollectedHeap
   };
 
+  static inline size_t filler_array_max_size() {
+    return _filler_array_max_size;
+  }
+
   virtual CollectedHeap::Name kind() const { return CollectedHeap::Abstract; }
 
   /**
@@ -366,9 +364,7 @@
   inline static oop permanent_obj_allocate_no_klass_install(KlassHandle klass,
                                                             int size,
                                                             TRAPS);
-  inline static void post_allocation_install_obj_klass(KlassHandle klass,
-                                                       oop obj,
-                                                       int size);
+  inline static void post_allocation_install_obj_klass(KlassHandle klass, oop obj);
   inline static oop permanent_array_allocate(KlassHandle klass, int size, int length, TRAPS);
 
   // Raw memory allocation facilities
@@ -662,11 +658,8 @@
     }
   }
 
-  // Allocate GCHeapLog during VM startup
-  static void initialize_heap_log();
-
   // Heap verification
-  virtual void verify(bool allow_dirty, bool silent, VerifyOption option) = 0;
+  virtual void verify(bool silent, VerifyOption option) = 0;
 
   // Non product verification and debugging.
 #ifndef PRODUCT
--- a/src/share/vm/gc_interface/collectedHeap.inline.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,15 +50,13 @@
 // Inline allocation implementations.
 
 void CollectedHeap::post_allocation_setup_common(KlassHandle klass,
-                                                 HeapWord* obj,
-                                                 size_t size) {
-  post_allocation_setup_no_klass_install(klass, obj, size);
-  post_allocation_install_obj_klass(klass, oop(obj), (int) size);
+                                                 HeapWord* obj) {
+  post_allocation_setup_no_klass_install(klass, obj);
+  post_allocation_install_obj_klass(klass, oop(obj));
 }
 
 void CollectedHeap::post_allocation_setup_no_klass_install(KlassHandle klass,
-                                                           HeapWord* objPtr,
-                                                           size_t size) {
+                                                           HeapWord* objPtr) {
   oop obj = (oop)objPtr;
 
   assert(obj != NULL, "NULL object pointer");
@@ -71,8 +69,7 @@
 }
 
 void CollectedHeap::post_allocation_install_obj_klass(KlassHandle klass,
-                                                   oop obj,
-                                                   int size) {
+                                                   oop obj) {
   // These asserts are kind of complicated because of klassKlass
   // and the beginning of the world.
   assert(klass() != NULL || !Universe::is_fully_initialized(), "NULL klass");
@@ -101,9 +98,8 @@
 }
 
 void CollectedHeap::post_allocation_setup_obj(KlassHandle klass,
-                                              HeapWord* obj,
-                                              size_t size) {
-  post_allocation_setup_common(klass, obj, size);
+                                              HeapWord* obj) {
+  post_allocation_setup_common(klass, obj);
   assert(Universe::is_bootstrapping() ||
          !((oop)obj)->blueprint()->oop_is_array(), "must not be an array");
   // notify jvmti and dtrace
@@ -112,14 +108,13 @@
 
 void CollectedHeap::post_allocation_setup_array(KlassHandle klass,
                                                 HeapWord* obj,
-                                                size_t size,
                                                 int length) {
   // Set array length before setting the _klass field
   // in post_allocation_setup_common() because the klass field
   // indicates that the object is parsable by concurrent GC.
   assert(length >= 0, "length should be non-negative");
   ((arrayOop)obj)->set_length(length);
-  post_allocation_setup_common(klass, obj, size);
+  post_allocation_setup_common(klass, obj);
   assert(((oop)obj)->blueprint()->oop_is_array(), "must be an array");
   // notify jvmti and dtrace (must be after length is set for dtrace)
   post_allocation_notify(klass, (oop)obj);
@@ -256,7 +251,7 @@
   assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
   assert(size >= 0, "int won't convert to size_t");
   HeapWord* obj = common_mem_allocate_init(size, CHECK_NULL);
-  post_allocation_setup_obj(klass, obj, size);
+  post_allocation_setup_obj(klass, obj);
   NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
   return (oop)obj;
 }
@@ -269,7 +264,7 @@
   assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
   assert(size >= 0, "int won't convert to size_t");
   HeapWord* obj = common_mem_allocate_init(size, CHECK_NULL);
-  post_allocation_setup_array(klass, obj, size, length);
+  post_allocation_setup_array(klass, obj, length);
   NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
   return (oop)obj;
 }
@@ -283,7 +278,7 @@
   assert(size >= 0, "int won't convert to size_t");
   HeapWord* obj = common_mem_allocate_noinit(size, CHECK_NULL);
   ((oop)obj)->set_klass_gap(0);
-  post_allocation_setup_array(klass, obj, size, length);
+  post_allocation_setup_array(klass, obj, length);
 #ifndef PRODUCT
   const size_t hs = oopDesc::header_size()+1;
   Universe::heap()->check_for_non_bad_heap_word_value(obj+hs, size-hs);
@@ -293,7 +288,7 @@
 
 oop CollectedHeap::permanent_obj_allocate(KlassHandle klass, int size, TRAPS) {
   oop obj = permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL);
-  post_allocation_install_obj_klass(klass, obj, size);
+  post_allocation_install_obj_klass(klass, obj);
   NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj,
                                                               size));
   return obj;
@@ -306,7 +301,7 @@
   assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
   assert(size >= 0, "int won't convert to size_t");
   HeapWord* obj = common_permanent_mem_allocate_init(size, CHECK_NULL);
-  post_allocation_setup_no_klass_install(klass, obj, size);
+  post_allocation_setup_no_klass_install(klass, obj);
 #ifndef PRODUCT
   const size_t hs = oopDesc::header_size();
   Universe::heap()->check_for_bad_heap_word_value(obj+hs, size-hs);
@@ -322,7 +317,7 @@
   assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
   assert(size >= 0, "int won't convert to size_t");
   HeapWord* obj = common_permanent_mem_allocate_init(size, CHECK_NULL);
-  post_allocation_setup_array(klass, obj, size, length);
+  post_allocation_setup_array(klass, obj, length);
   NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
   return (oop)obj;
 }
--- a/src/share/vm/memory/barrierSet.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/barrierSet.hpp	Tue May 15 11:27:24 2012 -0700
@@ -181,6 +181,8 @@
   // within the heap, this function tells whether they are met.
   virtual bool is_aligned(HeapWord* addr) = 0;
 
+  // Print a description of the memory for the barrier set
+  virtual void print_on(outputStream* st) const = 0;
 };
 
 #endif // SHARE_VM_MEMORY_BARRIERSET_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/binaryTreeDictionary.cpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,1343 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/shared/allocationStats.hpp"
+#include "memory/binaryTreeDictionary.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/ostream.hpp"
+#ifndef SERIALGC
+#include "gc_implementation/shared/spaceDecorator.hpp"
+#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
+#endif // SERIALGC
+
+////////////////////////////////////////////////////////////////////////////////
+// A binary tree based search structure for free blocks.
+// This is currently used in the Concurrent Mark&Sweep implementation.
+////////////////////////////////////////////////////////////////////////////////
+
+template <class Chunk>
+TreeChunk<Chunk>* TreeChunk<Chunk>::as_TreeChunk(Chunk* fc) {
+  // Do some assertion checking here.
+  return (TreeChunk<Chunk>*) fc;
+}
+
+template <class Chunk>
+void TreeChunk<Chunk>::verify_tree_chunk_list() const {
+  TreeChunk<Chunk>* nextTC = (TreeChunk<Chunk>*)next();
+  if (prev() != NULL) { // interior list node shouldn'r have tree fields
+    guarantee(embedded_list()->parent() == NULL && embedded_list()->left() == NULL &&
+              embedded_list()->right()  == NULL, "should be clear");
+  }
+  if (nextTC != NULL) {
+    guarantee(as_TreeChunk(nextTC->prev()) == this, "broken chain");
+    guarantee(nextTC->size() == size(), "wrong size");
+    nextTC->verify_tree_chunk_list();
+  }
+}
+
+
+template <class Chunk>
+TreeList<Chunk>* TreeList<Chunk>::as_TreeList(TreeChunk<Chunk>* tc) {
+  // This first free chunk in the list will be the tree list.
+  assert(tc->size() >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "Chunk is too small for a TreeChunk");
+  TreeList<Chunk>* tl = tc->embedded_list();
+  tc->set_list(tl);
+#ifdef ASSERT
+  tl->set_protecting_lock(NULL);
+#endif
+  tl->set_hint(0);
+  tl->set_size(tc->size());
+  tl->link_head(tc);
+  tl->link_tail(tc);
+  tl->set_count(1);
+  tl->init_statistics(true /* split_birth */);
+  tl->set_parent(NULL);
+  tl->set_left(NULL);
+  tl->set_right(NULL);
+  return tl;
+}
+
+template <class Chunk>
+TreeList<Chunk>* TreeList<Chunk>::as_TreeList(HeapWord* addr, size_t size) {
+  TreeChunk<Chunk>* tc = (TreeChunk<Chunk>*) addr;
+  assert(size >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "Chunk is too small for a TreeChunk");
+  // The space in the heap will have been mangled initially but
+  // is not remangled when a free chunk is returned to the free list
+  // (since it is used to maintain the chunk on the free list).
+  assert((ZapUnusedHeapArea &&
+          SpaceMangler::is_mangled((HeapWord*) tc->size_addr()) &&
+          SpaceMangler::is_mangled((HeapWord*) tc->prev_addr()) &&
+          SpaceMangler::is_mangled((HeapWord*) tc->next_addr())) ||
+          (tc->size() == 0 && tc->prev() == NULL && tc->next() == NULL),
+    "Space should be clear or mangled");
+  tc->set_size(size);
+  tc->link_prev(NULL);
+  tc->link_next(NULL);
+  TreeList<Chunk>* tl = TreeList<Chunk>::as_TreeList(tc);
+  return tl;
+}
+
+template <class Chunk>
+TreeList<Chunk>* TreeList<Chunk>::remove_chunk_replace_if_needed(TreeChunk<Chunk>* tc) {
+
+  TreeList<Chunk>* retTL = this;
+  Chunk* list = head();
+  assert(!list || list != list->next(), "Chunk on list twice");
+  assert(tc != NULL, "Chunk being removed is NULL");
+  assert(parent() == NULL || this == parent()->left() ||
+    this == parent()->right(), "list is inconsistent");
+  assert(tc->is_free(), "Header is not marked correctly");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk* prevFC = tc->prev();
+  TreeChunk<Chunk>* nextTC = TreeChunk<Chunk>::as_TreeChunk(tc->next());
+  assert(list != NULL, "should have at least the target chunk");
+
+  // Is this the first item on the list?
+  if (tc == list) {
+    // The "getChunk..." functions for a TreeList<Chunk> will not return the
+    // first chunk in the list unless it is the last chunk in the list
+    // because the first chunk is also acting as the tree node.
+    // When coalescing happens, however, the first chunk in the a tree
+    // list can be the start of a free range.  Free ranges are removed
+    // from the free lists so that they are not available to be
+    // allocated when the sweeper yields (giving up the free list lock)
+    // to allow mutator activity.  If this chunk is the first in the
+    // list and is not the last in the list, do the work to copy the
+    // TreeList<Chunk> from the first chunk to the next chunk and update all
+    // the TreeList<Chunk> pointers in the chunks in the list.
+    if (nextTC == NULL) {
+      assert(prevFC == NULL, "Not last chunk in the list");
+      set_tail(NULL);
+      set_head(NULL);
+    } else {
+      // copy embedded list.
+      nextTC->set_embedded_list(tc->embedded_list());
+      retTL = nextTC->embedded_list();
+      // Fix the pointer to the list in each chunk in the list.
+      // This can be slow for a long list.  Consider having
+      // an option that does not allow the first chunk on the
+      // list to be coalesced.
+      for (TreeChunk<Chunk>* curTC = nextTC; curTC != NULL;
+          curTC = TreeChunk<Chunk>::as_TreeChunk(curTC->next())) {
+        curTC->set_list(retTL);
+      }
+      // Fix the parent to point to the new TreeList<Chunk>.
+      if (retTL->parent() != NULL) {
+        if (this == retTL->parent()->left()) {
+          retTL->parent()->set_left(retTL);
+        } else {
+          assert(this == retTL->parent()->right(), "Parent is incorrect");
+          retTL->parent()->set_right(retTL);
+        }
+      }
+      // Fix the children's parent pointers to point to the
+      // new list.
+      assert(right() == retTL->right(), "Should have been copied");
+      if (retTL->right() != NULL) {
+        retTL->right()->set_parent(retTL);
+      }
+      assert(left() == retTL->left(), "Should have been copied");
+      if (retTL->left() != NULL) {
+        retTL->left()->set_parent(retTL);
+      }
+      retTL->link_head(nextTC);
+      assert(nextTC->is_free(), "Should be a free chunk");
+    }
+  } else {
+    if (nextTC == NULL) {
+      // Removing chunk at tail of list
+      link_tail(prevFC);
+    }
+    // Chunk is interior to the list
+    prevFC->link_after(nextTC);
+  }
+
+  // Below this point the embeded TreeList<Chunk> being used for the
+  // tree node may have changed. Don't use "this"
+  // TreeList<Chunk>*.
+  // chunk should still be a free chunk (bit set in _prev)
+  assert(!retTL->head() || retTL->size() == retTL->head()->size(),
+    "Wrong sized chunk in list");
+  debug_only(
+    tc->link_prev(NULL);
+    tc->link_next(NULL);
+    tc->set_list(NULL);
+    bool prev_found = false;
+    bool next_found = false;
+    for (Chunk* curFC = retTL->head();
+         curFC != NULL; curFC = curFC->next()) {
+      assert(curFC != tc, "Chunk is still in list");
+      if (curFC == prevFC) {
+        prev_found = true;
+      }
+      if (curFC == nextTC) {
+        next_found = true;
+      }
+    }
+    assert(prevFC == NULL || prev_found, "Chunk was lost from list");
+    assert(nextTC == NULL || next_found, "Chunk was lost from list");
+    assert(retTL->parent() == NULL ||
+           retTL == retTL->parent()->left() ||
+           retTL == retTL->parent()->right(),
+           "list is inconsistent");
+  )
+  retTL->decrement_count();
+
+  assert(tc->is_free(), "Should still be a free chunk");
+  assert(retTL->head() == NULL || retTL->head()->prev() == NULL,
+    "list invariant");
+  assert(retTL->tail() == NULL || retTL->tail()->next() == NULL,
+    "list invariant");
+  return retTL;
+}
+
+template <class Chunk>
+void TreeList<Chunk>::return_chunk_at_tail(TreeChunk<Chunk>* chunk) {
+  assert(chunk != NULL, "returning NULL chunk");
+  assert(chunk->list() == this, "list should be set for chunk");
+  assert(tail() != NULL, "The tree list is embedded in the first chunk");
+  // which means that the list can never be empty.
+  assert(!verify_chunk_in_free_list(chunk), "Double entry");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk* fc = tail();
+  fc->link_after(chunk);
+  link_tail(chunk);
+
+  assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
+  FreeList<Chunk>::increment_count();
+  debug_only(increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+}
+
+// Add this chunk at the head of the list.  "At the head of the list"
+// is defined to be after the chunk pointer to by head().  This is
+// because the TreeList<Chunk> is embedded in the first TreeChunk<Chunk> in the
+// list.  See the definition of TreeChunk<Chunk>.
+template <class Chunk>
+void TreeList<Chunk>::return_chunk_at_head(TreeChunk<Chunk>* chunk) {
+  assert(chunk->list() == this, "list should be set for chunk");
+  assert(head() != NULL, "The tree list is embedded in the first chunk");
+  assert(chunk != NULL, "returning NULL chunk");
+  assert(!verify_chunk_in_free_list(chunk), "Double entry");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk* fc = head()->next();
+  if (fc != NULL) {
+    chunk->link_after(fc);
+  } else {
+    assert(tail() == NULL, "List is inconsistent");
+    link_tail(chunk);
+  }
+  head()->link_after(chunk);
+  assert(!head() || size() == head()->size(), "Wrong sized chunk in list");
+  FreeList<Chunk>::increment_count();
+  debug_only(increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+}
+
+template <class Chunk>
+TreeChunk<Chunk>* TreeList<Chunk>::head_as_TreeChunk() {
+  assert(head() == NULL || TreeChunk<Chunk>::as_TreeChunk(head())->list() == this,
+    "Wrong type of chunk?");
+  return TreeChunk<Chunk>::as_TreeChunk(head());
+}
+
+template <class Chunk>
+TreeChunk<Chunk>* TreeList<Chunk>::first_available() {
+  assert(head() != NULL, "The head of the list cannot be NULL");
+  Chunk* fc = head()->next();
+  TreeChunk<Chunk>* retTC;
+  if (fc == NULL) {
+    retTC = head_as_TreeChunk();
+  } else {
+    retTC = TreeChunk<Chunk>::as_TreeChunk(fc);
+  }
+  assert(retTC->list() == this, "Wrong type of chunk.");
+  return retTC;
+}
+
+// Returns the block with the largest heap address amongst
+// those in the list for this size; potentially slow and expensive,
+// use with caution!
+template <class Chunk>
+TreeChunk<Chunk>* TreeList<Chunk>::largest_address() {
+  assert(head() != NULL, "The head of the list cannot be NULL");
+  Chunk* fc = head()->next();
+  TreeChunk<Chunk>* retTC;
+  if (fc == NULL) {
+    retTC = head_as_TreeChunk();
+  } else {
+    // walk down the list and return the one with the highest
+    // heap address among chunks of this size.
+    Chunk* last = fc;
+    while (fc->next() != NULL) {
+      if ((HeapWord*)last < (HeapWord*)fc) {
+        last = fc;
+      }
+      fc = fc->next();
+    }
+    retTC = TreeChunk<Chunk>::as_TreeChunk(last);
+  }
+  assert(retTC->list() == this, "Wrong type of chunk.");
+  return retTC;
+}
+
+template <class Chunk>
+BinaryTreeDictionary<Chunk>::BinaryTreeDictionary(bool adaptive_freelists, bool splay) :
+  _splay(splay), _adaptive_freelists(adaptive_freelists),
+  _total_size(0), _total_free_blocks(0), _root(0) {}
+
+template <class Chunk>
+BinaryTreeDictionary<Chunk>::BinaryTreeDictionary(MemRegion mr,
+                                           bool adaptive_freelists,
+                                           bool splay):
+  _adaptive_freelists(adaptive_freelists), _splay(splay)
+{
+  assert(mr.word_size() >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "minimum chunk size");
+
+  reset(mr);
+  assert(root()->left() == NULL, "reset check failed");
+  assert(root()->right() == NULL, "reset check failed");
+  assert(root()->head()->next() == NULL, "reset check failed");
+  assert(root()->head()->prev() == NULL, "reset check failed");
+  assert(total_size() == root()->size(), "reset check failed");
+  assert(total_free_blocks() == 1, "reset check failed");
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::inc_total_size(size_t inc) {
+  _total_size = _total_size + inc;
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::dec_total_size(size_t dec) {
+  _total_size = _total_size - dec;
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::reset(MemRegion mr) {
+  assert(mr.word_size() >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "minimum chunk size");
+  set_root(TreeList<Chunk>::as_TreeList(mr.start(), mr.word_size()));
+  set_total_size(mr.word_size());
+  set_total_free_blocks(1);
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::reset(HeapWord* addr, size_t byte_size) {
+  MemRegion mr(addr, heap_word_size(byte_size));
+  reset(mr);
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::reset() {
+  set_root(NULL);
+  set_total_size(0);
+  set_total_free_blocks(0);
+}
+
+// Get a free block of size at least size from tree, or NULL.
+// If a splay step is requested, the removal algorithm (only) incorporates
+// a splay step as follows:
+// . the search proceeds down the tree looking for a possible
+//   match. At the (closest) matching location, an appropriate splay step is applied
+//   (zig, zig-zig or zig-zag). A chunk of the appropriate size is then returned
+//   if available, and if it's the last chunk, the node is deleted. A deteleted
+//   node is replaced in place by its tree successor.
+template <class Chunk>
+TreeChunk<Chunk>*
+BinaryTreeDictionary<Chunk>::get_chunk_from_tree(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither, bool splay)
+{
+  TreeList<Chunk> *curTL, *prevTL;
+  TreeChunk<Chunk>* retTC = NULL;
+  assert(size >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "minimum chunk size");
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+  // starting at the root, work downwards trying to find match.
+  // Remember the last node of size too great or too small.
+  for (prevTL = curTL = root(); curTL != NULL;) {
+    if (curTL->size() == size) {        // exact match
+      break;
+    }
+    prevTL = curTL;
+    if (curTL->size() < size) {        // proceed to right sub-tree
+      curTL = curTL->right();
+    } else {                           // proceed to left sub-tree
+      assert(curTL->size() > size, "size inconsistency");
+      curTL = curTL->left();
+    }
+  }
+  if (curTL == NULL) { // couldn't find exact match
+
+    if (dither == FreeBlockDictionary<Chunk>::exactly) return NULL;
+
+    // try and find the next larger size by walking back up the search path
+    for (curTL = prevTL; curTL != NULL;) {
+      if (curTL->size() >= size) break;
+      else curTL = curTL->parent();
+    }
+    assert(curTL == NULL || curTL->count() > 0,
+      "An empty list should not be in the tree");
+  }
+  if (curTL != NULL) {
+    assert(curTL->size() >= size, "size inconsistency");
+    if (adaptive_freelists()) {
+
+      // A candidate chunk has been found.  If it is already under
+      // populated, get a chunk associated with the hint for this
+      // chunk.
+      if (curTL->surplus() <= 0) {
+        /* Use the hint to find a size with a surplus, and reset the hint. */
+        TreeList<Chunk>* hintTL = curTL;
+        while (hintTL->hint() != 0) {
+          assert(hintTL->hint() == 0 || hintTL->hint() > hintTL->size(),
+            "hint points in the wrong direction");
+          hintTL = find_list(hintTL->hint());
+          assert(curTL != hintTL, "Infinite loop");
+          if (hintTL == NULL ||
+              hintTL == curTL /* Should not happen but protect against it */ ) {
+            // No useful hint.  Set the hint to NULL and go on.
+            curTL->set_hint(0);
+            break;
+          }
+          assert(hintTL->size() > size, "hint is inconsistent");
+          if (hintTL->surplus() > 0) {
+            // The hint led to a list that has a surplus.  Use it.
+            // Set the hint for the candidate to an overpopulated
+            // size.
+            curTL->set_hint(hintTL->size());
+            // Change the candidate.
+            curTL = hintTL;
+            break;
+          }
+          // The evm code reset the hint of the candidate as
+          // at an interim point.  Why?  Seems like this leaves
+          // the hint pointing to a list that didn't work.
+          // curTL->set_hint(hintTL->size());
+        }
+      }
+    }
+    // don't waste time splaying if chunk's singleton
+    if (splay && curTL->head()->next() != NULL) {
+      semi_splay_step(curTL);
+    }
+    retTC = curTL->first_available();
+    assert((retTC != NULL) && (curTL->count() > 0),
+      "A list in the binary tree should not be NULL");
+    assert(retTC->size() >= size,
+      "A chunk of the wrong size was found");
+    remove_chunk_from_tree(retTC);
+    assert(retTC->is_free(), "Header is not marked correctly");
+  }
+
+  if (FLSVerifyDictionary) {
+    verify();
+  }
+  return retTC;
+}
+
+template <class Chunk>
+TreeList<Chunk>* BinaryTreeDictionary<Chunk>::find_list(size_t size) const {
+  TreeList<Chunk>* curTL;
+  for (curTL = root(); curTL != NULL;) {
+    if (curTL->size() == size) {        // exact match
+      break;
+    }
+
+    if (curTL->size() < size) {        // proceed to right sub-tree
+      curTL = curTL->right();
+    } else {                           // proceed to left sub-tree
+      assert(curTL->size() > size, "size inconsistency");
+      curTL = curTL->left();
+    }
+  }
+  return curTL;
+}
+
+
+template <class Chunk>
+bool BinaryTreeDictionary<Chunk>::verify_chunk_in_free_list(Chunk* tc) const {
+  size_t size = tc->size();
+  TreeList<Chunk>* tl = find_list(size);
+  if (tl == NULL) {
+    return false;
+  } else {
+    return tl->verify_chunk_in_free_list(tc);
+  }
+}
+
+template <class Chunk>
+Chunk* BinaryTreeDictionary<Chunk>::find_largest_dict() const {
+  TreeList<Chunk> *curTL = root();
+  if (curTL != NULL) {
+    while(curTL->right() != NULL) curTL = curTL->right();
+    return curTL->largest_address();
+  } else {
+    return NULL;
+  }
+}
+
+// Remove the current chunk from the tree.  If it is not the last
+// chunk in a list on a tree node, just unlink it.
+// If it is the last chunk in the list (the next link is NULL),
+// remove the node and repair the tree.
+template <class Chunk>
+TreeChunk<Chunk>*
+BinaryTreeDictionary<Chunk>::remove_chunk_from_tree(TreeChunk<Chunk>* tc) {
+  assert(tc != NULL, "Should not call with a NULL chunk");
+  assert(tc->is_free(), "Header is not marked correctly");
+
+  TreeList<Chunk> *newTL, *parentTL;
+  TreeChunk<Chunk>* retTC;
+  TreeList<Chunk>* tl = tc->list();
+  debug_only(
+    bool removing_only_chunk = false;
+    if (tl == _root) {
+      if ((_root->left() == NULL) && (_root->right() == NULL)) {
+        if (_root->count() == 1) {
+          assert(_root->head() == tc, "Should only be this one chunk");
+          removing_only_chunk = true;
+        }
+      }
+    }
+  )
+  assert(tl != NULL, "List should be set");
+  assert(tl->parent() == NULL || tl == tl->parent()->left() ||
+         tl == tl->parent()->right(), "list is inconsistent");
+
+  bool complicated_splice = false;
+
+  retTC = tc;
+  // Removing this chunk can have the side effect of changing the node
+  // (TreeList<Chunk>*) in the tree.  If the node is the root, update it.
+  TreeList<Chunk>* replacementTL = tl->remove_chunk_replace_if_needed(tc);
+  assert(tc->is_free(), "Chunk should still be free");
+  assert(replacementTL->parent() == NULL ||
+         replacementTL == replacementTL->parent()->left() ||
+         replacementTL == replacementTL->parent()->right(),
+         "list is inconsistent");
+  if (tl == root()) {
+    assert(replacementTL->parent() == NULL, "Incorrectly replacing root");
+    set_root(replacementTL);
+  }
+  debug_only(
+    if (tl != replacementTL) {
+      assert(replacementTL->head() != NULL,
+        "If the tree list was replaced, it should not be a NULL list");
+      TreeList<Chunk>* rhl = replacementTL->head_as_TreeChunk()->list();
+      TreeList<Chunk>* rtl = TreeChunk<Chunk>::as_TreeChunk(replacementTL->tail())->list();
+      assert(rhl == replacementTL, "Broken head");
+      assert(rtl == replacementTL, "Broken tail");
+      assert(replacementTL->size() == tc->size(),  "Broken size");
+    }
+  )
+
+  // Does the tree need to be repaired?
+  if (replacementTL->count() == 0) {
+    assert(replacementTL->head() == NULL &&
+           replacementTL->tail() == NULL, "list count is incorrect");
+    // Find the replacement node for the (soon to be empty) node being removed.
+    // if we have a single (or no) child, splice child in our stead
+    if (replacementTL->left() == NULL) {
+      // left is NULL so pick right.  right may also be NULL.
+      newTL = replacementTL->right();
+      debug_only(replacementTL->clear_right();)
+    } else if (replacementTL->right() == NULL) {
+      // right is NULL
+      newTL = replacementTL->left();
+      debug_only(replacementTL->clearLeft();)
+    } else {  // we have both children, so, by patriarchal convention,
+              // my replacement is least node in right sub-tree
+      complicated_splice = true;
+      newTL = remove_tree_minimum(replacementTL->right());
+      assert(newTL != NULL && newTL->left() == NULL &&
+             newTL->right() == NULL, "sub-tree minimum exists");
+    }
+    // newTL is the replacement for the (soon to be empty) node.
+    // newTL may be NULL.
+    // should verify; we just cleanly excised our replacement
+    if (FLSVerifyDictionary) {
+      verify_tree();
+    }
+    // first make newTL my parent's child
+    if ((parentTL = replacementTL->parent()) == NULL) {
+      // newTL should be root
+      assert(tl == root(), "Incorrectly replacing root");
+      set_root(newTL);
+      if (newTL != NULL) {
+        newTL->clear_parent();
+      }
+    } else if (parentTL->right() == replacementTL) {
+      // replacementTL is a right child
+      parentTL->set_right(newTL);
+    } else {                                // replacementTL is a left child
+      assert(parentTL->left() == replacementTL, "should be left child");
+      parentTL->set_left(newTL);
+    }
+    debug_only(replacementTL->clear_parent();)
+    if (complicated_splice) {  // we need newTL to get replacementTL's
+                              // two children
+      assert(newTL != NULL &&
+             newTL->left() == NULL && newTL->right() == NULL,
+            "newTL should not have encumbrances from the past");
+      // we'd like to assert as below:
+      // assert(replacementTL->left() != NULL && replacementTL->right() != NULL,
+      //       "else !complicated_splice");
+      // ... however, the above assertion is too strong because we aren't
+      // guaranteed that replacementTL->right() is still NULL.
+      // Recall that we removed
+      // the right sub-tree minimum from replacementTL.
+      // That may well have been its right
+      // child! So we'll just assert half of the above:
+      assert(replacementTL->left() != NULL, "else !complicated_splice");
+      newTL->set_left(replacementTL->left());
+      newTL->set_right(replacementTL->right());
+      debug_only(
+        replacementTL->clear_right();
+        replacementTL->clearLeft();
+      )
+    }
+    assert(replacementTL->right() == NULL &&
+           replacementTL->left() == NULL &&
+           replacementTL->parent() == NULL,
+        "delete without encumbrances");
+  }
+
+  assert(total_size() >= retTC->size(), "Incorrect total size");
+  dec_total_size(retTC->size());     // size book-keeping
+  assert(total_free_blocks() > 0, "Incorrect total count");
+  set_total_free_blocks(total_free_blocks() - 1);
+
+  assert(retTC != NULL, "null chunk?");
+  assert(retTC->prev() == NULL && retTC->next() == NULL,
+         "should return without encumbrances");
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+  assert(!removing_only_chunk || _root == NULL, "root should be NULL");
+  return TreeChunk<Chunk>::as_TreeChunk(retTC);
+}
+
+// Remove the leftmost node (lm) in the tree and return it.
+// If lm has a right child, link it to the left node of
+// the parent of lm.
+template <class Chunk>
+TreeList<Chunk>* BinaryTreeDictionary<Chunk>::remove_tree_minimum(TreeList<Chunk>* tl) {
+  assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
+  // locate the subtree minimum by walking down left branches
+  TreeList<Chunk>* curTL = tl;
+  for (; curTL->left() != NULL; curTL = curTL->left());
+  // obviously curTL now has at most one child, a right child
+  if (curTL != root()) {  // Should this test just be removed?
+    TreeList<Chunk>* parentTL = curTL->parent();
+    if (parentTL->left() == curTL) { // curTL is a left child
+      parentTL->set_left(curTL->right());
+    } else {
+      // If the list tl has no left child, then curTL may be
+      // the right child of parentTL.
+      assert(parentTL->right() == curTL, "should be a right child");
+      parentTL->set_right(curTL->right());
+    }
+  } else {
+    // The only use of this method would not pass the root of the
+    // tree (as indicated by the assertion above that the tree list
+    // has a parent) but the specification does not explicitly exclude the
+    // passing of the root so accomodate it.
+    set_root(NULL);
+  }
+  debug_only(
+    curTL->clear_parent();  // Test if this needs to be cleared
+    curTL->clear_right();    // recall, above, left child is already null
+  )
+  // we just excised a (non-root) node, we should still verify all tree invariants
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+  return curTL;
+}
+
+// Based on a simplification of the algorithm by Sleator and Tarjan (JACM 1985).
+// The simplifications are the following:
+// . we splay only when we delete (not when we insert)
+// . we apply a single spay step per deletion/access
+// By doing such partial splaying, we reduce the amount of restructuring,
+// while getting a reasonably efficient search tree (we think).
+// [Measurements will be needed to (in)validate this expectation.]
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::semi_splay_step(TreeList<Chunk>* tc) {
+  // apply a semi-splay step at the given node:
+  // . if root, norting needs to be done
+  // . if child of root, splay once
+  // . else zig-zig or sig-zag depending on path from grandparent
+  if (root() == tc) return;
+  warning("*** Splaying not yet implemented; "
+          "tree operations may be inefficient ***");
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::insert_chunk_in_tree(Chunk* fc) {
+  TreeList<Chunk> *curTL, *prevTL;
+  size_t size = fc->size();
+
+  assert(size >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "too small to be a TreeList<Chunk>");
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+
+  fc->clear_next();
+  fc->link_prev(NULL);
+
+  // work down from the _root, looking for insertion point
+  for (prevTL = curTL = root(); curTL != NULL;) {
+    if (curTL->size() == size)  // exact match
+      break;
+    prevTL = curTL;
+    if (curTL->size() > size) { // follow left branch
+      curTL = curTL->left();
+    } else {                    // follow right branch
+      assert(curTL->size() < size, "size inconsistency");
+      curTL = curTL->right();
+    }
+  }
+  TreeChunk<Chunk>* tc = TreeChunk<Chunk>::as_TreeChunk(fc);
+  // This chunk is being returned to the binary tree.  Its embedded
+  // TreeList<Chunk> should be unused at this point.
+  tc->initialize();
+  if (curTL != NULL) {          // exact match
+    tc->set_list(curTL);
+    curTL->return_chunk_at_tail(tc);
+  } else {                     // need a new node in tree
+    tc->clear_next();
+    tc->link_prev(NULL);
+    TreeList<Chunk>* newTL = TreeList<Chunk>::as_TreeList(tc);
+    assert(((TreeChunk<Chunk>*)tc)->list() == newTL,
+      "List was not initialized correctly");
+    if (prevTL == NULL) {      // we are the only tree node
+      assert(root() == NULL, "control point invariant");
+      set_root(newTL);
+    } else {                   // insert under prevTL ...
+      if (prevTL->size() < size) {   // am right child
+        assert(prevTL->right() == NULL, "control point invariant");
+        prevTL->set_right(newTL);
+      } else {                       // am left child
+        assert(prevTL->size() > size && prevTL->left() == NULL, "cpt pt inv");
+        prevTL->set_left(newTL);
+      }
+    }
+  }
+  assert(tc->list() != NULL, "Tree list should be set");
+
+  inc_total_size(size);
+  // Method 'total_size_in_tree' walks through the every block in the
+  // tree, so it can cause significant performance loss if there are
+  // many blocks in the tree
+  assert(!FLSVerifyDictionary || total_size_in_tree(root()) == total_size(), "_total_size inconsistency");
+  set_total_free_blocks(total_free_blocks() + 1);
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::max_chunk_size() const {
+  FreeBlockDictionary<Chunk>::verify_par_locked();
+  TreeList<Chunk>* tc = root();
+  if (tc == NULL) return 0;
+  for (; tc->right() != NULL; tc = tc->right());
+  return tc->size();
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_list_length(TreeList<Chunk>* tl) const {
+  size_t res;
+  res = tl->count();
+#ifdef ASSERT
+  size_t cnt;
+  Chunk* tc = tl->head();
+  for (cnt = 0; tc != NULL; tc = tc->next(), cnt++);
+  assert(res == cnt, "The count is not being maintained correctly");
+#endif
+  return res;
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_size_in_tree(TreeList<Chunk>* tl) const {
+  if (tl == NULL)
+    return 0;
+  return (tl->size() * total_list_length(tl)) +
+         total_size_in_tree(tl->left())    +
+         total_size_in_tree(tl->right());
+}
+
+template <class Chunk>
+double BinaryTreeDictionary<Chunk>::sum_of_squared_block_sizes(TreeList<Chunk>* const tl) const {
+  if (tl == NULL) {
+    return 0.0;
+  }
+  double size = (double)(tl->size());
+  double curr = size * size * total_list_length(tl);
+  curr += sum_of_squared_block_sizes(tl->left());
+  curr += sum_of_squared_block_sizes(tl->right());
+  return curr;
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_free_blocks_in_tree(TreeList<Chunk>* tl) const {
+  if (tl == NULL)
+    return 0;
+  return total_list_length(tl) +
+         total_free_blocks_in_tree(tl->left()) +
+         total_free_blocks_in_tree(tl->right());
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::num_free_blocks() const {
+  assert(total_free_blocks_in_tree(root()) == total_free_blocks(),
+         "_total_free_blocks inconsistency");
+  return total_free_blocks();
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::tree_height_helper(TreeList<Chunk>* tl) const {
+  if (tl == NULL)
+    return 0;
+  return 1 + MAX2(tree_height_helper(tl->left()),
+                  tree_height_helper(tl->right()));
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::treeHeight() const {
+  return tree_height_helper(root());
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_nodes_helper(TreeList<Chunk>* tl) const {
+  if (tl == NULL) {
+    return 0;
+  }
+  return 1 + total_nodes_helper(tl->left()) +
+    total_nodes_helper(tl->right());
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_nodes_in_tree(TreeList<Chunk>* tl) const {
+  return total_nodes_helper(root());
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::dict_census_udpate(size_t size, bool split, bool birth){
+  TreeList<Chunk>* nd = find_list(size);
+  if (nd) {
+    if (split) {
+      if (birth) {
+        nd->increment_split_births();
+        nd->increment_surplus();
+      }  else {
+        nd->increment_split_deaths();
+        nd->decrement_surplus();
+      }
+    } else {
+      if (birth) {
+        nd->increment_coal_births();
+        nd->increment_surplus();
+      } else {
+        nd->increment_coal_deaths();
+        nd->decrement_surplus();
+      }
+    }
+  }
+  // A list for this size may not be found (nd == 0) if
+  //   This is a death where the appropriate list is now
+  //     empty and has been removed from the list.
+  //   This is a birth associated with a LinAB.  The chunk
+  //     for the LinAB is not in the dictionary.
+}
+
+template <class Chunk>
+bool BinaryTreeDictionary<Chunk>::coal_dict_over_populated(size_t size) {
+  if (FLSAlwaysCoalesceLarge) return true;
+
+  TreeList<Chunk>* list_of_size = find_list(size);
+  // None of requested size implies overpopulated.
+  return list_of_size == NULL || list_of_size->coal_desired() <= 0 ||
+         list_of_size->count() > list_of_size->coal_desired();
+}
+
+// Closures for walking the binary tree.
+//   do_list() walks the free list in a node applying the closure
+//     to each free chunk in the list
+//   do_tree() walks the nodes in the binary tree applying do_list()
+//     to each list at each node.
+
+template <class Chunk>
+class TreeCensusClosure : public StackObj {
+ protected:
+  virtual void do_list(FreeList<Chunk>* fl) = 0;
+ public:
+  virtual void do_tree(TreeList<Chunk>* tl) = 0;
+};
+
+template <class Chunk>
+class AscendTreeCensusClosure : public TreeCensusClosure<Chunk> {
+ public:
+  void do_tree(TreeList<Chunk>* tl) {
+    if (tl != NULL) {
+      do_tree(tl->left());
+      do_list(tl);
+      do_tree(tl->right());
+    }
+  }
+};
+
+template <class Chunk>
+class DescendTreeCensusClosure : public TreeCensusClosure<Chunk> {
+ public:
+  void do_tree(TreeList<Chunk>* tl) {
+    if (tl != NULL) {
+      do_tree(tl->right());
+      do_list(tl);
+      do_tree(tl->left());
+    }
+  }
+};
+
+// For each list in the tree, calculate the desired, desired
+// coalesce, count before sweep, and surplus before sweep.
+template <class Chunk>
+class BeginSweepClosure : public AscendTreeCensusClosure<Chunk> {
+  double _percentage;
+  float _inter_sweep_current;
+  float _inter_sweep_estimate;
+  float _intra_sweep_estimate;
+
+ public:
+  BeginSweepClosure(double p, float inter_sweep_current,
+                              float inter_sweep_estimate,
+                              float intra_sweep_estimate) :
+   _percentage(p),
+   _inter_sweep_current(inter_sweep_current),
+   _inter_sweep_estimate(inter_sweep_estimate),
+   _intra_sweep_estimate(intra_sweep_estimate) { }
+
+  void do_list(FreeList<Chunk>* fl) {
+    double coalSurplusPercent = _percentage;
+    fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
+    fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent));
+    fl->set_before_sweep(fl->count());
+    fl->set_bfr_surp(fl->surplus());
+  }
+};
+
+// Used to search the tree until a condition is met.
+// Similar to TreeCensusClosure but searches the
+// tree and returns promptly when found.
+
+template <class Chunk>
+class TreeSearchClosure : public StackObj {
+ protected:
+  virtual bool do_list(FreeList<Chunk>* fl) = 0;
+ public:
+  virtual bool do_tree(TreeList<Chunk>* tl) = 0;
+};
+
+#if 0 //  Don't need this yet but here for symmetry.
+template <class Chunk>
+class AscendTreeSearchClosure : public TreeSearchClosure {
+ public:
+  bool do_tree(TreeList<Chunk>* tl) {
+    if (tl != NULL) {
+      if (do_tree(tl->left())) return true;
+      if (do_list(tl)) return true;
+      if (do_tree(tl->right())) return true;
+    }
+    return false;
+  }
+};
+#endif
+
+template <class Chunk>
+class DescendTreeSearchClosure : public TreeSearchClosure<Chunk> {
+ public:
+  bool do_tree(TreeList<Chunk>* tl) {
+    if (tl != NULL) {
+      if (do_tree(tl->right())) return true;
+      if (do_list(tl)) return true;
+      if (do_tree(tl->left())) return true;
+    }
+    return false;
+  }
+};
+
+// Searches the tree for a chunk that ends at the
+// specified address.
+template <class Chunk>
+class EndTreeSearchClosure : public DescendTreeSearchClosure<Chunk> {
+  HeapWord* _target;
+  Chunk* _found;
+
+ public:
+  EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {}
+  bool do_list(FreeList<Chunk>* fl) {
+    Chunk* item = fl->head();
+    while (item != NULL) {
+      if (item->end() == _target) {
+        _found = item;
+        return true;
+      }
+      item = item->next();
+    }
+    return false;
+  }
+  Chunk* found() { return _found; }
+};
+
+template <class Chunk>
+Chunk* BinaryTreeDictionary<Chunk>::find_chunk_ends_at(HeapWord* target) const {
+  EndTreeSearchClosure<Chunk> etsc(target);
+  bool found_target = etsc.do_tree(root());
+  assert(found_target || etsc.found() == NULL, "Consistency check");
+  assert(!found_target || etsc.found() != NULL, "Consistency check");
+  return etsc.found();
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::begin_sweep_dict_census(double coalSurplusPercent,
+  float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
+  BeginSweepClosure<Chunk> bsc(coalSurplusPercent, inter_sweep_current,
+                                            inter_sweep_estimate,
+                                            intra_sweep_estimate);
+  bsc.do_tree(root());
+}
+
+// Closures and methods for calculating total bytes returned to the
+// free lists in the tree.
+#ifndef PRODUCT
+template <class Chunk>
+class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure<Chunk> {
+   public:
+  void do_list(FreeList<Chunk>* fl) {
+    fl->set_returned_bytes(0);
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::initialize_dict_returned_bytes() {
+  InitializeDictReturnedBytesClosure<Chunk> idrb;
+  idrb.do_tree(root());
+}
+
+template <class Chunk>
+class ReturnedBytesClosure : public AscendTreeCensusClosure<Chunk> {
+  size_t _dict_returned_bytes;
+ public:
+  ReturnedBytesClosure() { _dict_returned_bytes = 0; }
+  void do_list(FreeList<Chunk>* fl) {
+    _dict_returned_bytes += fl->returned_bytes();
+  }
+  size_t dict_returned_bytes() { return _dict_returned_bytes; }
+};
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::sum_dict_returned_bytes() {
+  ReturnedBytesClosure<Chunk> rbc;
+  rbc.do_tree(root());
+
+  return rbc.dict_returned_bytes();
+}
+
+// Count the number of entries in the tree.
+template <class Chunk>
+class treeCountClosure : public DescendTreeCensusClosure<Chunk> {
+ public:
+  uint count;
+  treeCountClosure(uint c) { count = c; }
+  void do_list(FreeList<Chunk>* fl) {
+    count++;
+  }
+};
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::total_count() {
+  treeCountClosure<Chunk> ctc(0);
+  ctc.do_tree(root());
+  return ctc.count;
+}
+#endif // PRODUCT
+
+// Calculate surpluses for the lists in the tree.
+template <class Chunk>
+class setTreeSurplusClosure : public AscendTreeCensusClosure<Chunk> {
+  double percentage;
+ public:
+  setTreeSurplusClosure(double v) { percentage = v; }
+  void do_list(FreeList<Chunk>* fl) {
+    double splitSurplusPercent = percentage;
+    fl->set_surplus(fl->count() -
+                   (ssize_t)((double)fl->desired() * splitSurplusPercent));
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::set_tree_surplus(double splitSurplusPercent) {
+  setTreeSurplusClosure<Chunk> sts(splitSurplusPercent);
+  sts.do_tree(root());
+}
+
+// Set hints for the lists in the tree.
+template <class Chunk>
+class setTreeHintsClosure : public DescendTreeCensusClosure<Chunk> {
+  size_t hint;
+ public:
+  setTreeHintsClosure(size_t v) { hint = v; }
+  void do_list(FreeList<Chunk>* fl) {
+    fl->set_hint(hint);
+    assert(fl->hint() == 0 || fl->hint() > fl->size(),
+      "Current hint is inconsistent");
+    if (fl->surplus() > 0) {
+      hint = fl->size();
+    }
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::set_tree_hints(void) {
+  setTreeHintsClosure<Chunk> sth(0);
+  sth.do_tree(root());
+}
+
+// Save count before previous sweep and splits and coalesces.
+template <class Chunk>
+class clearTreeCensusClosure : public AscendTreeCensusClosure<Chunk> {
+  void do_list(FreeList<Chunk>* fl) {
+    fl->set_prev_sweep(fl->count());
+    fl->set_coal_births(0);
+    fl->set_coal_deaths(0);
+    fl->set_split_births(0);
+    fl->set_split_deaths(0);
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::clear_tree_census(void) {
+  clearTreeCensusClosure<Chunk> ctc;
+  ctc.do_tree(root());
+}
+
+// Do reporting and post sweep clean up.
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::end_sweep_dict_census(double splitSurplusPercent) {
+  // Does walking the tree 3 times hurt?
+  set_tree_surplus(splitSurplusPercent);
+  set_tree_hints();
+  if (PrintGC && Verbose) {
+    report_statistics();
+  }
+  clear_tree_census();
+}
+
+// Print summary statistics
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::report_statistics() const {
+  FreeBlockDictionary<Chunk>::verify_par_locked();
+  gclog_or_tty->print("Statistics for BinaryTreeDictionary:\n"
+         "------------------------------------\n");
+  size_t total_size = total_chunk_size(debug_only(NULL));
+  size_t    free_blocks = num_free_blocks();
+  gclog_or_tty->print("Total Free Space: %d\n", total_size);
+  gclog_or_tty->print("Max   Chunk Size: %d\n", max_chunk_size());
+  gclog_or_tty->print("Number of Blocks: %d\n", free_blocks);
+  if (free_blocks > 0) {
+    gclog_or_tty->print("Av.  Block  Size: %d\n", total_size/free_blocks);
+  }
+  gclog_or_tty->print("Tree      Height: %d\n", treeHeight());
+}
+
+// Print census information - counts, births, deaths, etc.
+// for each list in the tree.  Also print some summary
+// information.
+template <class Chunk>
+class PrintTreeCensusClosure : public AscendTreeCensusClosure<Chunk> {
+  int _print_line;
+  size_t _total_free;
+  FreeList<Chunk> _total;
+
+ public:
+  PrintTreeCensusClosure() {
+    _print_line = 0;
+    _total_free = 0;
+  }
+  FreeList<Chunk>* total() { return &_total; }
+  size_t total_free() { return _total_free; }
+  void do_list(FreeList<Chunk>* fl) {
+    if (++_print_line >= 40) {
+      FreeList<Chunk>::print_labels_on(gclog_or_tty, "size");
+      _print_line = 0;
+    }
+    fl->print_on(gclog_or_tty);
+    _total_free +=            fl->count()            * fl->size()        ;
+    total()->set_count(      total()->count()       + fl->count()      );
+    total()->set_bfr_surp(    total()->bfr_surp()     + fl->bfr_surp()    );
+    total()->set_surplus(    total()->split_deaths() + fl->surplus()    );
+    total()->set_desired(    total()->desired()     + fl->desired()    );
+    total()->set_prev_sweep(  total()->prev_sweep()   + fl->prev_sweep()  );
+    total()->set_before_sweep(total()->before_sweep() + fl->before_sweep());
+    total()->set_coal_births( total()->coal_births()  + fl->coal_births() );
+    total()->set_coal_deaths( total()->coal_deaths()  + fl->coal_deaths() );
+    total()->set_split_births(total()->split_births() + fl->split_births());
+    total()->set_split_deaths(total()->split_deaths() + fl->split_deaths());
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::print_dict_census(void) const {
+
+  gclog_or_tty->print("\nBinaryTree\n");
+  FreeList<Chunk>::print_labels_on(gclog_or_tty, "size");
+  PrintTreeCensusClosure<Chunk> ptc;
+  ptc.do_tree(root());
+
+  FreeList<Chunk>* total = ptc.total();
+  FreeList<Chunk>::print_labels_on(gclog_or_tty, " ");
+  total->print_on(gclog_or_tty, "TOTAL\t");
+  gclog_or_tty->print(
+              "total_free(words): " SIZE_FORMAT_W(16)
+              " growth: %8.5f  deficit: %8.5f\n",
+              ptc.total_free(),
+              (double)(total->split_births() + total->coal_births()
+                     - total->split_deaths() - total->coal_deaths())
+              /(total->prev_sweep() != 0 ? (double)total->prev_sweep() : 1.0),
+             (double)(total->desired() - total->count())
+             /(total->desired() != 0 ? (double)total->desired() : 1.0));
+}
+
+template <class Chunk>
+class PrintFreeListsClosure : public AscendTreeCensusClosure<Chunk> {
+  outputStream* _st;
+  int _print_line;
+
+ public:
+  PrintFreeListsClosure(outputStream* st) {
+    _st = st;
+    _print_line = 0;
+  }
+  void do_list(FreeList<Chunk>* fl) {
+    if (++_print_line >= 40) {
+      FreeList<Chunk>::print_labels_on(_st, "size");
+      _print_line = 0;
+    }
+    fl->print_on(gclog_or_tty);
+    size_t sz = fl->size();
+    for (Chunk* fc = fl->head(); fc != NULL;
+         fc = fc->next()) {
+      _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ")  %s",
+                    fc, (HeapWord*)fc + sz,
+                    fc->cantCoalesce() ? "\t CC" : "");
+    }
+  }
+};
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::print_free_lists(outputStream* st) const {
+
+  FreeList<Chunk>::print_labels_on(st, "size");
+  PrintFreeListsClosure<Chunk> pflc(st);
+  pflc.do_tree(root());
+}
+
+// Verify the following tree invariants:
+// . _root has no parent
+// . parent and child point to each other
+// . each node's key correctly related to that of its child(ren)
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::verify_tree() const {
+  guarantee(root() == NULL || total_free_blocks() == 0 ||
+    total_size() != 0, "_total_size should't be 0?");
+  guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
+  verify_tree_helper(root());
+}
+
+template <class Chunk>
+size_t BinaryTreeDictionary<Chunk>::verify_prev_free_ptrs(TreeList<Chunk>* tl) {
+  size_t ct = 0;
+  for (Chunk* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
+    ct++;
+    assert(curFC->prev() == NULL || curFC->prev()->is_free(),
+      "Chunk should be free");
+  }
+  return ct;
+}
+
+// Note: this helper is recursive rather than iterative, so use with
+// caution on very deep trees; and watch out for stack overflow errors;
+// In general, to be used only for debugging.
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::verify_tree_helper(TreeList<Chunk>* tl) const {
+  if (tl == NULL)
+    return;
+  guarantee(tl->size() != 0, "A list must has a size");
+  guarantee(tl->left()  == NULL || tl->left()->parent()  == tl,
+         "parent<-/->left");
+  guarantee(tl->right() == NULL || tl->right()->parent() == tl,
+         "parent<-/->right");;
+  guarantee(tl->left() == NULL  || tl->left()->size()    <  tl->size(),
+         "parent !> left");
+  guarantee(tl->right() == NULL || tl->right()->size()   >  tl->size(),
+         "parent !< left");
+  guarantee(tl->head() == NULL || tl->head()->is_free(), "!Free");
+  guarantee(tl->head() == NULL || tl->head_as_TreeChunk()->list() == tl,
+    "list inconsistency");
+  guarantee(tl->count() > 0 || (tl->head() == NULL && tl->tail() == NULL),
+    "list count is inconsistent");
+  guarantee(tl->count() > 1 || tl->head() == tl->tail(),
+    "list is incorrectly constructed");
+  size_t count = verify_prev_free_ptrs(tl);
+  guarantee(count == (size_t)tl->count(), "Node count is incorrect");
+  if (tl->head() != NULL) {
+    tl->head_as_TreeChunk()->verify_tree_chunk_list();
+  }
+  verify_tree_helper(tl->left());
+  verify_tree_helper(tl->right());
+}
+
+template <class Chunk>
+void BinaryTreeDictionary<Chunk>::verify() const {
+  verify_tree();
+  guarantee(total_size() == total_size_in_tree(root()), "Total Size inconsistency");
+}
+
+#ifndef SERIALGC
+// Explicitly instantiate these types for FreeChunk.
+template class BinaryTreeDictionary<FreeChunk>;
+template class TreeChunk<FreeChunk>;
+template class TreeList<FreeChunk>;
+#endif // SERIALGC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/binaryTreeDictionary.hpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
+#define SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
+
+#include "memory/freeBlockDictionary.hpp"
+#include "memory/freeList.hpp"
+
+/*
+ * A binary tree based search structure for free blocks.
+ * This is currently used in the Concurrent Mark&Sweep implementation, but
+ * will be used for free block management for metadata.
+ */
+
+// A TreeList is a FreeList which can be used to maintain a
+// binary tree of free lists.
+
+template <class Chunk> class TreeChunk;
+template <class Chunk> class BinaryTreeDictionary;
+template <class Chunk> class AscendTreeCensusClosure;
+template <class Chunk> class DescendTreeCensusClosure;
+template <class Chunk> class DescendTreeSearchClosure;
+
+template <class Chunk>
+class TreeList: public FreeList<Chunk> {
+  friend class TreeChunk<Chunk>;
+  friend class BinaryTreeDictionary<Chunk>;
+  friend class AscendTreeCensusClosure<Chunk>;
+  friend class DescendTreeCensusClosure<Chunk>;
+  friend class DescendTreeSearchClosure<Chunk>;
+
+  TreeList<Chunk>* _parent;
+  TreeList<Chunk>* _left;
+  TreeList<Chunk>* _right;
+
+ protected:
+  TreeList<Chunk>* parent() const { return _parent; }
+  TreeList<Chunk>* left()   const { return _left;   }
+  TreeList<Chunk>* right()  const { return _right;  }
+
+  // Wrapper on call to base class, to get the template to compile.
+  Chunk* head() const { return FreeList<Chunk>::head(); }
+  Chunk* tail() const { return FreeList<Chunk>::tail(); }
+  void set_head(Chunk* head) { FreeList<Chunk>::set_head(head); }
+  void set_tail(Chunk* tail) { FreeList<Chunk>::set_tail(tail); }
+
+  size_t size() const { return FreeList<Chunk>::size(); }
+
+  // Accessors for links in tree.
+
+  void set_left(TreeList<Chunk>* tl) {
+    _left   = tl;
+    if (tl != NULL)
+      tl->set_parent(this);
+  }
+  void set_right(TreeList<Chunk>* tl) {
+    _right  = tl;
+    if (tl != NULL)
+      tl->set_parent(this);
+  }
+  void set_parent(TreeList<Chunk>* tl)  { _parent = tl;   }
+
+  void clearLeft()               { _left = NULL;   }
+  void clear_right()              { _right = NULL;  }
+  void clear_parent()             { _parent = NULL; }
+  void initialize()              { clearLeft(); clear_right(), clear_parent(); }
+
+  // For constructing a TreeList from a Tree chunk or
+  // address and size.
+  static TreeList<Chunk>* as_TreeList(TreeChunk<Chunk>* tc);
+  static TreeList<Chunk>* as_TreeList(HeapWord* addr, size_t size);
+
+  // Returns the head of the free list as a pointer to a TreeChunk.
+  TreeChunk<Chunk>* head_as_TreeChunk();
+
+  // Returns the first available chunk in the free list as a pointer
+  // to a TreeChunk.
+  TreeChunk<Chunk>* first_available();
+
+  // Returns the block with the largest heap address amongst
+  // those in the list for this size; potentially slow and expensive,
+  // use with caution!
+  TreeChunk<Chunk>* largest_address();
+
+  // remove_chunk_replace_if_needed() removes the given "tc" from the TreeList.
+  // If "tc" is the first chunk in the list, it is also the
+  // TreeList that is the node in the tree.  remove_chunk_replace_if_needed()
+  // returns the possibly replaced TreeList* for the node in
+  // the tree.  It also updates the parent of the original
+  // node to point to the new node.
+  TreeList<Chunk>* remove_chunk_replace_if_needed(TreeChunk<Chunk>* tc);
+  // See FreeList.
+  void return_chunk_at_head(TreeChunk<Chunk>* tc);
+  void return_chunk_at_tail(TreeChunk<Chunk>* tc);
+};
+
+// A TreeChunk is a subclass of a Chunk that additionally
+// maintains a pointer to the free list on which it is currently
+// linked.
+// A TreeChunk is also used as a node in the binary tree.  This
+// allows the binary tree to be maintained without any additional
+// storage (the free chunks are used).  In a binary tree the first
+// chunk in the free list is also the tree node.  Note that the
+// TreeChunk has an embedded TreeList for this purpose.  Because
+// the first chunk in the list is distinguished in this fashion
+// (also is the node in the tree), it is the last chunk to be found
+// on the free list for a node in the tree and is only removed if
+// it is the last chunk on the free list.
+
+template <class Chunk>
+class TreeChunk : public Chunk {
+  friend class TreeList<Chunk>;
+  TreeList<Chunk>* _list;
+  TreeList<Chunk> _embedded_list;  // if non-null, this chunk is on _list
+ protected:
+  TreeList<Chunk>* embedded_list() const { return (TreeList<Chunk>*) &_embedded_list; }
+  void set_embedded_list(TreeList<Chunk>* v) { _embedded_list = *v; }
+ public:
+  TreeList<Chunk>* list() { return _list; }
+  void set_list(TreeList<Chunk>* v) { _list = v; }
+  static TreeChunk<Chunk>* as_TreeChunk(Chunk* fc);
+  // Initialize fields in a TreeChunk that should be
+  // initialized when the TreeChunk is being added to
+  // a free list in the tree.
+  void initialize() { embedded_list()->initialize(); }
+
+  Chunk* next() const { return Chunk::next(); }
+  Chunk* prev() const { return Chunk::prev(); }
+  size_t size() const volatile { return Chunk::size(); }
+
+  // debugging
+  void verify_tree_chunk_list() const;
+};
+
+
+template <class Chunk>
+class BinaryTreeDictionary: public FreeBlockDictionary<Chunk> {
+  friend class VMStructs;
+  bool       _splay;
+  size_t     _total_size;
+  size_t     _total_free_blocks;
+  TreeList<Chunk>* _root;
+  bool       _adaptive_freelists;
+
+  // private accessors
+  bool splay() const { return _splay; }
+  void set_splay(bool v) { _splay = v; }
+  void set_total_size(size_t v) { _total_size = v; }
+  virtual void inc_total_size(size_t v);
+  virtual void dec_total_size(size_t v);
+  size_t total_free_blocks() const { return _total_free_blocks; }
+  void set_total_free_blocks(size_t v) { _total_free_blocks = v; }
+  TreeList<Chunk>* root() const { return _root; }
+  void set_root(TreeList<Chunk>* v) { _root = v; }
+  bool adaptive_freelists() { return _adaptive_freelists; }
+
+  // This field is added and can be set to point to the
+  // the Mutex used to synchronize access to the
+  // dictionary so that assertion checking can be done.
+  // For example it is set to point to _parDictionaryAllocLock.
+  NOT_PRODUCT(Mutex* _lock;)
+
+  // Remove a chunk of size "size" or larger from the tree and
+  // return it.  If the chunk
+  // is the last chunk of that size, remove the node for that size
+  // from the tree.
+  TreeChunk<Chunk>* get_chunk_from_tree(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither, bool splay);
+  // Return a list of the specified size or NULL from the tree.
+  // The list is not removed from the tree.
+  TreeList<Chunk>* find_list (size_t size) const;
+  // Remove this chunk from the tree.  If the removal results
+  // in an empty list in the tree, remove the empty list.
+  TreeChunk<Chunk>* remove_chunk_from_tree(TreeChunk<Chunk>* tc);
+  // Remove the node in the trees starting at tl that has the
+  // minimum value and return it.  Repair the tree as needed.
+  TreeList<Chunk>* remove_tree_minimum(TreeList<Chunk>* tl);
+  void       semi_splay_step(TreeList<Chunk>* tl);
+  // Add this free chunk to the tree.
+  void       insert_chunk_in_tree(Chunk* freeChunk);
+ public:
+
+  static const size_t min_tree_chunk_size  = sizeof(TreeChunk<Chunk>)/HeapWordSize;
+
+  void       verify_tree() const;
+  // verify that the given chunk is in the tree.
+  bool       verify_chunk_in_free_list(Chunk* tc) const;
+ private:
+  void          verify_tree_helper(TreeList<Chunk>* tl) const;
+  static size_t verify_prev_free_ptrs(TreeList<Chunk>* tl);
+
+  // Returns the total number of chunks in the list.
+  size_t     total_list_length(TreeList<Chunk>* tl) const;
+  // Returns the total number of words in the chunks in the tree
+  // starting at "tl".
+  size_t     total_size_in_tree(TreeList<Chunk>* tl) const;
+  // Returns the sum of the square of the size of each block
+  // in the tree starting at "tl".
+  double     sum_of_squared_block_sizes(TreeList<Chunk>* const tl) const;
+  // Returns the total number of free blocks in the tree starting
+  // at "tl".
+  size_t     total_free_blocks_in_tree(TreeList<Chunk>* tl) const;
+  size_t     num_free_blocks() const;
+  size_t     treeHeight() const;
+  size_t     tree_height_helper(TreeList<Chunk>* tl) const;
+  size_t     total_nodes_in_tree(TreeList<Chunk>* tl) const;
+  size_t     total_nodes_helper(TreeList<Chunk>* tl) const;
+
+ public:
+  // Constructor
+  BinaryTreeDictionary(bool adaptive_freelists, bool splay = false);
+  BinaryTreeDictionary(MemRegion mr, bool adaptive_freelists, bool splay = false);
+
+  // Public accessors
+  size_t total_size() const { return _total_size; }
+
+  // Reset the dictionary to the initial conditions with
+  // a single free chunk.
+  void       reset(MemRegion mr);
+  void       reset(HeapWord* addr, size_t size);
+  // Reset the dictionary to be empty.
+  void       reset();
+
+  // Return a chunk of size "size" or greater from
+  // the tree.
+  // want a better dynamic splay strategy for the future.
+  Chunk* get_chunk(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither) {
+    FreeBlockDictionary<Chunk>::verify_par_locked();
+    Chunk* res = get_chunk_from_tree(size, dither, splay());
+    assert(res == NULL || res->is_free(),
+           "Should be returning a free chunk");
+    return res;
+  }
+
+  void return_chunk(Chunk* chunk) {
+    FreeBlockDictionary<Chunk>::verify_par_locked();
+    insert_chunk_in_tree(chunk);
+  }
+
+  void remove_chunk(Chunk* chunk) {
+    FreeBlockDictionary<Chunk>::verify_par_locked();
+    remove_chunk_from_tree((TreeChunk<Chunk>*)chunk);
+    assert(chunk->is_free(), "Should still be a free chunk");
+  }
+
+  size_t     max_chunk_size() const;
+  size_t     total_chunk_size(debug_only(const Mutex* lock)) const {
+    debug_only(
+      if (lock != NULL && lock->owned_by_self()) {
+        assert(total_size_in_tree(root()) == total_size(),
+               "_total_size inconsistency");
+      }
+    )
+    return total_size();
+  }
+
+  size_t     min_size() const {
+    return min_tree_chunk_size;
+  }
+
+  double     sum_of_squared_block_sizes() const {
+    return sum_of_squared_block_sizes(root());
+  }
+
+  Chunk* find_chunk_ends_at(HeapWord* target) const;
+
+  // Find the list with size "size" in the binary tree and update
+  // the statistics in the list according to "split" (chunk was
+  // split or coalesce) and "birth" (chunk was added or removed).
+  void       dict_census_udpate(size_t size, bool split, bool birth);
+  // Return true if the dictionary is overpopulated (more chunks of
+  // this size than desired) for size "size".
+  bool       coal_dict_over_populated(size_t size);
+  // Methods called at the beginning of a sweep to prepare the
+  // statistics for the sweep.
+  void       begin_sweep_dict_census(double coalSurplusPercent,
+                                  float inter_sweep_current,
+                                  float inter_sweep_estimate,
+                                  float intra_sweep_estimate);
+  // Methods called after the end of a sweep to modify the
+  // statistics for the sweep.
+  void       end_sweep_dict_census(double splitSurplusPercent);
+  // Return the largest free chunk in the tree.
+  Chunk* find_largest_dict() const;
+  // Accessors for statistics
+  void       set_tree_surplus(double splitSurplusPercent);
+  void       set_tree_hints(void);
+  // Reset statistics for all the lists in the tree.
+  void       clear_tree_census(void);
+  // Print the statistcis for all the lists in the tree.  Also may
+  // print out summaries.
+  void       print_dict_census(void) const;
+  void       print_free_lists(outputStream* st) const;
+
+  // For debugging.  Returns the sum of the _returned_bytes for
+  // all lists in the tree.
+  size_t     sum_dict_returned_bytes()     PRODUCT_RETURN0;
+  // Sets the _returned_bytes for all the lists in the tree to zero.
+  void       initialize_dict_returned_bytes()      PRODUCT_RETURN;
+  // For debugging.  Return the total number of chunks in the dictionary.
+  size_t     total_count()       PRODUCT_RETURN0;
+
+  void       report_statistics() const;
+
+  void       verify() const;
+};
+
+#endif // SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
--- a/src/share/vm/memory/cardTableModRefBS.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/cardTableModRefBS.cpp	Tue May 15 11:27:24 2012 -0700
@@ -711,6 +711,11 @@
 }
 #endif
 
+void CardTableModRefBS::print_on(outputStream* st) const {
+  st->print_cr("Card table byte_map: [" INTPTR_FORMAT "," INTPTR_FORMAT "] byte_map_base: " INTPTR_FORMAT,
+               _byte_map, _byte_map + _byte_map_size, byte_map_base);
+}
+
 bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) {
   return
     CardTableModRefBS::card_will_be_scanned(cv) ||
--- a/src/share/vm/memory/cardTableModRefBS.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/cardTableModRefBS.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -72,6 +72,9 @@
     CT_MR_BS_last_reserved      = 16
   };
 
+  // a word's worth (row) of clean card values
+  static const intptr_t clean_card_row = (intptr_t)(-1);
+
   // dirty and precleaned are equivalent wrt younger_refs_iter.
   static bool card_is_dirty_wrt_gen_iter(jbyte cv) {
     return cv == dirty_card || cv == precleaned_card;
@@ -469,6 +472,9 @@
     return _byte_map + card_index;
   }
 
+  // Print a description of the memory for the barrier set
+  virtual void print_on(outputStream* st) const;
+
   void verify();
   void verify_guard();
 
--- a/src/share/vm/memory/cardTableRS.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/cardTableRS.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -173,6 +173,10 @@
             SharedHeap::heap()->workers()->active_workers()), "Mismatch");
 }
 
+bool ClearNoncleanCardWrapper::is_word_aligned(jbyte* entry) {
+  return (((intptr_t)entry) & (BytesPerWord-1)) == 0;
+}
+
 void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) {
   assert(mr.word_size() > 0, "Error");
   assert(_ct->is_aligned(mr.start()), "mr.start() should be card aligned");
@@ -194,6 +198,17 @@
         const MemRegion mrd(start_of_non_clean, end_of_non_clean);
         _dirty_card_closure->do_MemRegion(mrd);
       }
+
+      // fast forward through potential continuous whole-word range of clean cards beginning at a word-boundary
+      if (is_word_aligned(cur_entry)) {
+        jbyte* cur_row = cur_entry - BytesPerWord;
+        while (cur_row >= limit && *((intptr_t*)cur_row) ==  CardTableRS::clean_card_row()) {
+          cur_row -= BytesPerWord;
+        }
+        cur_entry = cur_row + BytesPerWord;
+        cur_hw = _ct->addr_for(cur_entry);
+      }
+
       // Reset the dirty window, while continuing to look
       // for the next dirty card that will start a
       // new dirty window.
--- a/src/share/vm/memory/cardTableRS.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/cardTableRS.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,10 @@
     return CardTableModRefBS::clean_card;
   }
 
+  static intptr_t clean_card_row() {
+    return CardTableModRefBS::clean_card_row;
+  }
+
   static bool
   card_is_dirty_wrt_gen_iter(jbyte cv) {
     return CardTableModRefBS::card_is_dirty_wrt_gen_iter(cv);
@@ -176,6 +180,8 @@
   // Work methods called by the clear_card()
   inline bool clear_card_serial(jbyte* entry);
   inline bool clear_card_parallel(jbyte* entry);
+  // check alignment of pointer
+  bool is_word_aligned(jbyte* entry);
 
 public:
   ClearNoncleanCardWrapper(DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct);
--- a/src/share/vm/memory/compactingPermGenGen.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/compactingPermGenGen.cpp	Tue May 15 11:27:24 2012 -0700
@@ -444,11 +444,11 @@
 }
 
 
-void CompactingPermGenGen::verify(bool allow_dirty) {
-  the_space()->verify(allow_dirty);
+void CompactingPermGenGen::verify() {
+  the_space()->verify();
   if (!SharedSkipVerify && spec()->enable_shared_spaces()) {
-    ro_space()->verify(allow_dirty);
-    rw_space()->verify(allow_dirty);
+    ro_space()->verify();
+    rw_space()->verify();
   }
 }
 
--- a/src/share/vm/memory/compactingPermGenGen.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/compactingPermGenGen.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -230,7 +230,7 @@
                                       void* new_vtable_start,
                                       void* obj);
 
-  void verify(bool allow_dirty);
+  void verify();
 
   // Serialization
   static void initialize_oops() KERNEL_RETURN;
--- a/src/share/vm/memory/defNewGeneration.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/defNewGeneration.cpp	Tue May 15 11:27:24 2012 -0700
@@ -939,10 +939,10 @@
   }
 }
 
-void DefNewGeneration::verify(bool allow_dirty) {
-  eden()->verify(allow_dirty);
-  from()->verify(allow_dirty);
-    to()->verify(allow_dirty);
+void DefNewGeneration::verify() {
+  eden()->verify();
+  from()->verify();
+    to()->verify();
 }
 
 void DefNewGeneration::print_on(outputStream* st) const {
--- a/src/share/vm/memory/defNewGeneration.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/defNewGeneration.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -340,7 +340,7 @@
   // PrintHeapAtGC support.
   void print_on(outputStream* st) const;
 
-  void verify(bool allow_dirty);
+  void verify();
 
   bool promo_failure_scan_is_complete() const {
     return _promo_failure_scan_stack.is_empty();
--- a/src/share/vm/memory/dump.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/dump.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -297,16 +297,14 @@
 
       if (obj->blueprint()->oop_is_instanceKlass()) {
         instanceKlass* ik = instanceKlass::cast((klassOop)obj);
-        typeArrayOop inner_classes = ik->inner_classes();
-        if (inner_classes != NULL) {
-          constantPoolOop constants = ik->constants();
-          int n = inner_classes->length();
-          for (int i = 0; i < n; i += instanceKlass::inner_class_next_offset) {
-            int ioff = i + instanceKlass::inner_class_inner_name_offset;
-            int index = inner_classes->ushort_at(ioff);
-            if (index != 0) {
-              _closure->do_symbol(constants->symbol_at_addr(index));
-            }
+        instanceKlassHandle ik_h((klassOop)obj);
+        InnerClassesIterator iter(ik_h);
+        constantPoolOop constants = ik->constants();
+        for (; !iter.done(); iter.next()) {
+          int index = iter.inner_name_index();
+
+          if (index != 0) {
+            _closure->do_symbol(constants->symbol_at_addr(index));
           }
         }
       }
@@ -1490,12 +1488,11 @@
 
     // sun.io.Converters
     static const char obj_array_sig[] = "[[Ljava/lang/Object;";
-    SymbolTable::lookup(obj_array_sig, (int)strlen(obj_array_sig), THREAD);
+    (void)SymbolTable::new_permanent_symbol(obj_array_sig, THREAD);
 
     // java.util.HashMap
     static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
-    SymbolTable::lookup(map_entry_array_sig, (int)strlen(map_entry_array_sig),
-                        THREAD);
+    (void)SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
 
     tty->print("Loading classes to share ... ");
     while ((fgets(class_name, sizeof class_name, file)) != NULL) {
@@ -1514,7 +1511,7 @@
       computed_jsum = jsum(computed_jsum, class_name, (const int)name_len - 1);
 
       // Got a class name - load it.
-      TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name, THREAD);
+      Symbol* class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD);
       guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
       klassOop klass = SystemDictionary::resolve_or_null(class_name_symbol,
                                                          THREAD);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/freeBlockDictionary.cpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#ifndef SERIALGC
+#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
+#endif // SERIALGC
+#include "memory/freeBlockDictionary.hpp"
+#ifdef TARGET_OS_FAMILY_linux
+# include "thread_linux.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_solaris
+# include "thread_solaris.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_windows
+# include "thread_windows.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "thread_bsd.inline.hpp"
+#endif
+
+#ifndef PRODUCT
+template <class Chunk> Mutex* FreeBlockDictionary<Chunk>::par_lock() const {
+  return _lock;
+}
+
+template <class Chunk> void FreeBlockDictionary<Chunk>::set_par_lock(Mutex* lock) {
+  _lock = lock;
+}
+
+template <class Chunk> void FreeBlockDictionary<Chunk>::verify_par_locked() const {
+#ifdef ASSERT
+  if (ParallelGCThreads > 0) {
+    Thread* my_thread = Thread::current();
+    if (my_thread->is_GC_task_thread()) {
+      assert(par_lock() != NULL, "Should be using locking?");
+      assert_lock_strong(par_lock());
+    }
+  }
+#endif // ASSERT
+}
+#endif
+
+#ifndef SERIALGC
+// Explicitly instantiate for FreeChunk
+template class FreeBlockDictionary<FreeChunk>;
+#endif // SERIALGC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/freeBlockDictionary.hpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_FREEBLOCKDICTIONARY_HPP
+#define SHARE_VM_MEMORY_FREEBLOCKDICTIONARY_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/mutex.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/ostream.hpp"
+
+// A FreeBlockDictionary is an abstract superclass that will allow
+// a number of alternative implementations in the future.
+template <class Chunk>
+class FreeBlockDictionary: public CHeapObj {
+ public:
+  enum Dither {
+    atLeast,
+    exactly,
+    roughly
+  };
+  enum DictionaryChoice {
+    dictionaryBinaryTree = 0,
+    dictionarySplayTree  = 1,
+    dictionarySkipList   = 2
+  };
+
+ private:
+  NOT_PRODUCT(Mutex* _lock;)
+
+ public:
+  virtual void       remove_chunk(Chunk* fc) = 0;
+  virtual Chunk*     get_chunk(size_t size, Dither dither = atLeast) = 0;
+  virtual void       return_chunk(Chunk* chunk) = 0;
+  virtual size_t     total_chunk_size(debug_only(const Mutex* lock)) const = 0;
+  virtual size_t     max_chunk_size()   const = 0;
+  virtual size_t     min_size()        const = 0;
+  // Reset the dictionary to the initial conditions for a single
+  // block.
+  virtual void       reset(HeapWord* addr, size_t size) = 0;
+  virtual void       reset() = 0;
+
+  virtual void       dict_census_udpate(size_t size, bool split, bool birth) = 0;
+  virtual bool       coal_dict_over_populated(size_t size) = 0;
+  virtual void       begin_sweep_dict_census(double coalSurplusPercent,
+                       float inter_sweep_current, float inter_sweep_estimate,
+                       float intra__sweep_current) = 0;
+  virtual void       end_sweep_dict_census(double splitSurplusPercent) = 0;
+  virtual Chunk*     find_largest_dict() const = 0;
+  // verify that the given chunk is in the dictionary.
+  virtual bool verify_chunk_in_free_list(Chunk* tc) const = 0;
+
+  // Sigma_{all_free_blocks} (block_size^2)
+  virtual double sum_of_squared_block_sizes() const = 0;
+
+  virtual Chunk* find_chunk_ends_at(HeapWord* target) const = 0;
+  virtual void inc_total_size(size_t v) = 0;
+  virtual void dec_total_size(size_t v) = 0;
+
+  NOT_PRODUCT (
+    virtual size_t   sum_dict_returned_bytes() = 0;
+    virtual void     initialize_dict_returned_bytes() = 0;
+    virtual size_t   total_count() = 0;
+  )
+
+  virtual void       report_statistics() const {
+    gclog_or_tty->print("No statistics available");
+  }
+
+  virtual void       print_dict_census() const = 0;
+  virtual void       print_free_lists(outputStream* st) const = 0;
+
+  virtual void       verify()         const = 0;
+
+  Mutex* par_lock()                const PRODUCT_RETURN0;
+  void   set_par_lock(Mutex* lock)       PRODUCT_RETURN;
+  void   verify_par_locked()       const PRODUCT_RETURN;
+};
+
+#endif // SHARE_VM_MEMORY_FREEBLOCKDICTIONARY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/freeList.cpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "memory/freeBlockDictionary.hpp"
+#include "memory/freeList.hpp"
+#include "memory/sharedHeap.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/vmThread.hpp"
+
+#ifndef SERIALGC
+#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
+#endif // SERIALGC
+
+// Free list.  A FreeList is used to access a linked list of chunks
+// of space in the heap.  The head and tail are maintained so that
+// items can be (as in the current implementation) added at the
+// at the tail of the list and removed from the head of the list to
+// maintain a FIFO queue.
+
+template <class Chunk>
+FreeList<Chunk>::FreeList() :
+  _head(NULL), _tail(NULL)
+#ifdef ASSERT
+  , _protecting_lock(NULL)
+#endif
+{
+  _size         = 0;
+  _count        = 0;
+  _hint         = 0;
+  init_statistics();
+}
+
+template <class Chunk>
+FreeList<Chunk>::FreeList(Chunk* fc) :
+  _head(fc), _tail(fc)
+#ifdef ASSERT
+  , _protecting_lock(NULL)
+#endif
+{
+  _size         = fc->size();
+  _count        = 1;
+  _hint         = 0;
+  init_statistics();
+#ifndef PRODUCT
+  _allocation_stats.set_returned_bytes(size() * HeapWordSize);
+#endif
+}
+
+template <class Chunk>
+void FreeList<Chunk>::reset(size_t hint) {
+  set_count(0);
+  set_head(NULL);
+  set_tail(NULL);
+  set_hint(hint);
+}
+
+template <class Chunk>
+void FreeList<Chunk>::init_statistics(bool split_birth) {
+  _allocation_stats.initialize(split_birth);
+}
+
+template <class Chunk>
+Chunk* FreeList<Chunk>::get_chunk_at_head() {
+  assert_proper_lock_protection();
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  Chunk* fc = head();
+  if (fc != NULL) {
+    Chunk* nextFC = fc->next();
+    if (nextFC != NULL) {
+      // The chunk fc being removed has a "next".  Set the "next" to the
+      // "prev" of fc.
+      nextFC->link_prev(NULL);
+    } else { // removed tail of list
+      link_tail(NULL);
+    }
+    link_head(nextFC);
+    decrement_count();
+  }
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  return fc;
+}
+
+
+template <class Chunk>
+void FreeList<Chunk>::getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl) {
+  assert_proper_lock_protection();
+  assert(fl->count() == 0, "Precondition");
+  if (count() > 0) {
+    int k = 1;
+    fl->set_head(head()); n--;
+    Chunk* tl = head();
+    while (tl->next() != NULL && n > 0) {
+      tl = tl->next(); n--; k++;
+    }
+    assert(tl != NULL, "Loop Inv.");
+
+    // First, fix up the list we took from.
+    Chunk* new_head = tl->next();
+    set_head(new_head);
+    set_count(count() - k);
+    if (new_head == NULL) {
+      set_tail(NULL);
+    } else {
+      new_head->link_prev(NULL);
+    }
+    // Now we can fix up the tail.
+    tl->link_next(NULL);
+    // And return the result.
+    fl->set_tail(tl);
+    fl->set_count(k);
+  }
+}
+
+// Remove this chunk from the list
+template <class Chunk>
+void FreeList<Chunk>::remove_chunk(Chunk*fc) {
+   assert_proper_lock_protection();
+   assert(head() != NULL, "Remove from empty list");
+   assert(fc != NULL, "Remove a NULL chunk");
+   assert(size() == fc->size(), "Wrong list");
+   assert(head() == NULL || head()->prev() == NULL, "list invariant");
+   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+   Chunk* prevFC = fc->prev();
+   Chunk* nextFC = fc->next();
+   if (nextFC != NULL) {
+     // The chunk fc being removed has a "next".  Set the "next" to the
+     // "prev" of fc.
+     nextFC->link_prev(prevFC);
+   } else { // removed tail of list
+     link_tail(prevFC);
+   }
+   if (prevFC == NULL) { // removed head of list
+     link_head(nextFC);
+     assert(nextFC == NULL || nextFC->prev() == NULL,
+       "Prev of head should be NULL");
+   } else {
+     prevFC->link_next(nextFC);
+     assert(tail() != prevFC || prevFC->next() == NULL,
+       "Next of tail should be NULL");
+   }
+   decrement_count();
+   assert(((head() == NULL) + (tail() == NULL) + (count() == 0)) % 3 == 0,
+          "H/T/C Inconsistency");
+   // clear next and prev fields of fc, debug only
+   NOT_PRODUCT(
+     fc->link_prev(NULL);
+     fc->link_next(NULL);
+   )
+   assert(fc->is_free(), "Should still be a free chunk");
+   assert(head() == NULL || head()->prev() == NULL, "list invariant");
+   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+   assert(head() == NULL || head()->size() == size(), "wrong item on list");
+   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
+}
+
+// Add this chunk at the head of the list.
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk, bool record_return) {
+  assert_proper_lock_protection();
+  assert(chunk != NULL, "insert a NULL chunk");
+  assert(size() == chunk->size(), "Wrong size");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk* oldHead = head();
+  assert(chunk != oldHead, "double insertion");
+  chunk->link_after(oldHead);
+  link_head(chunk);
+  if (oldHead == NULL) { // only chunk in list
+    assert(tail() == NULL, "inconsistent FreeList");
+    link_tail(chunk);
+  }
+  increment_count(); // of # of chunks in list
+  DEBUG_ONLY(
+    if (record_return) {
+      increment_returned_bytes_by(size()*HeapWordSize);
+    }
+  )
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  assert(head() == NULL || head()->size() == size(), "wrong item on list");
+  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
+}
+
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk) {
+  assert_proper_lock_protection();
+  return_chunk_at_head(chunk, true);
+}
+
+// Add this chunk at the tail of the list.
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk, bool record_return) {
+  assert_proper_lock_protection();
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  assert(chunk != NULL, "insert a NULL chunk");
+  assert(size() == chunk->size(), "wrong size");
+
+  Chunk* oldTail = tail();
+  assert(chunk != oldTail, "double insertion");
+  if (oldTail != NULL) {
+    oldTail->link_after(chunk);
+  } else { // only chunk in list
+    assert(head() == NULL, "inconsistent FreeList");
+    link_head(chunk);
+  }
+  link_tail(chunk);
+  increment_count();  // of # of chunks in list
+  DEBUG_ONLY(
+    if (record_return) {
+      increment_returned_bytes_by(size()*HeapWordSize);
+    }
+  )
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  assert(head() == NULL || head()->size() == size(), "wrong item on list");
+  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
+}
+
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk) {
+  return_chunk_at_tail(chunk, true);
+}
+
+template <class Chunk>
+void FreeList<Chunk>::prepend(FreeList<Chunk>* fl) {
+  assert_proper_lock_protection();
+  if (fl->count() > 0) {
+    if (count() == 0) {
+      set_head(fl->head());
+      set_tail(fl->tail());
+      set_count(fl->count());
+    } else {
+      // Both are non-empty.
+      Chunk* fl_tail = fl->tail();
+      Chunk* this_head = head();
+      assert(fl_tail->next() == NULL, "Well-formedness of fl");
+      fl_tail->link_next(this_head);
+      this_head->link_prev(fl_tail);
+      set_head(fl->head());
+      set_count(count() + fl->count());
+    }
+    fl->set_head(NULL);
+    fl->set_tail(NULL);
+    fl->set_count(0);
+  }
+}
+
+// verify_chunk_in_free_list() is used to verify that an item is in this free list.
+// It is used as a debugging aid.
+template <class Chunk>
+bool FreeList<Chunk>::verify_chunk_in_free_list(Chunk* fc) const {
+  // This is an internal consistency check, not part of the check that the
+  // chunk is in the free lists.
+  guarantee(fc->size() == size(), "Wrong list is being searched");
+  Chunk* curFC = head();
+  while (curFC) {
+    // This is an internal consistency check.
+    guarantee(size() == curFC->size(), "Chunk is in wrong list.");
+    if (fc == curFC) {
+      return true;
+    }
+    curFC = curFC->next();
+  }
+  return false;
+}
+
+#ifndef PRODUCT
+template <class Chunk>
+void FreeList<Chunk>::verify_stats() const {
+  // The +1 of the LH comparand is to allow some "looseness" in
+  // checking: we usually call this interface when adding a block
+  // and we'll subsequently update the stats; we cannot update the
+  // stats beforehand because in the case of the large-block BT
+  // dictionary for example, this might be the first block and
+  // in that case there would be no place that we could record
+  // the stats (which are kept in the block itself).
+  assert((_allocation_stats.prev_sweep() + _allocation_stats.split_births()
+          + _allocation_stats.coal_births() + 1)   // Total Production Stock + 1
+         >= (_allocation_stats.split_deaths() + _allocation_stats.coal_deaths()
+             + (ssize_t)count()),                // Total Current Stock + depletion
+         err_msg("FreeList " PTR_FORMAT " of size " SIZE_FORMAT
+                 " violates Conservation Principle: "
+                 "prev_sweep(" SIZE_FORMAT ")"
+                 " + split_births(" SIZE_FORMAT ")"
+                 " + coal_births(" SIZE_FORMAT ") + 1 >= "
+                 " split_deaths(" SIZE_FORMAT ")"
+                 " coal_deaths(" SIZE_FORMAT ")"
+                 " + count(" SSIZE_FORMAT ")",
+                 this, _size, _allocation_stats.prev_sweep(), _allocation_stats.split_births(),
+                 _allocation_stats.split_births(), _allocation_stats.split_deaths(),
+                 _allocation_stats.coal_deaths(), count()));
+}
+
+template <class Chunk>
+void FreeList<Chunk>::assert_proper_lock_protection_work() const {
+  assert(_protecting_lock != NULL, "Don't call this directly");
+  assert(ParallelGCThreads > 0, "Don't call this directly");
+  Thread* thr = Thread::current();
+  if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
+    // assert that we are holding the freelist lock
+  } else if (thr->is_GC_task_thread()) {
+    assert(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED");
+  } else if (thr->is_Java_thread()) {
+    assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
+  } else {
+    ShouldNotReachHere();  // unaccounted thread type?
+  }
+}
+#endif
+
+// Print the "label line" for free list stats.
+template <class Chunk>
+void FreeList<Chunk>::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.
+template <class Chunk>
+void FreeList<Chunk>::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",
+           bfr_surp(),             surplus(),             desired(),             prev_sweep(),           before_sweep(),
+           count(),               coal_births(),          coal_deaths(),          split_births(),         split_deaths());
+}
+
+#ifndef SERIALGC
+// Needs to be after the definitions have been seen.
+template class FreeList<FreeChunk>;
+#endif // SERIALGC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/memory/freeList.hpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_FREELIST_HPP
+#define SHARE_VM_MEMORY_FREELIST_HPP
+
+#include "gc_implementation/shared/allocationStats.hpp"
+
+class CompactibleFreeListSpace;
+
+// A class for maintaining a free list of Chunk's.  The FreeList
+// maintains a the structure of the list (head, tail, etc.) plus
+// statistics for allocations from the list.  The links between items
+// are not part of FreeList.  The statistics are
+// used to make decisions about coalescing Chunk's when they
+// are swept during collection.
+//
+// See the corresponding .cpp file for a description of the specifics
+// for that implementation.
+
+class Mutex;
+template <class Chunk> class TreeList;
+template <class Chunk> class PrintTreeCensusClosure;
+
+template <class Chunk>
+class FreeList VALUE_OBJ_CLASS_SPEC {
+  friend class CompactibleFreeListSpace;
+  friend class VMStructs;
+  friend class PrintTreeCensusClosure<Chunk>;
+
+ private:
+  Chunk*        _head;          // Head of list of free chunks
+  Chunk*        _tail;          // Tail of list of free chunks
+  size_t        _size;          // Size in Heap words of each chunk
+  ssize_t       _count;         // Number of entries in list
+  size_t        _hint;          // next larger size list with a positive surplus
+
+  AllocationStats _allocation_stats; // allocation-related statistics
+
+#ifdef ASSERT
+  Mutex*        _protecting_lock;
+#endif
+
+  // Asserts false if the protecting lock (if any) is not held.
+  void assert_proper_lock_protection_work() const PRODUCT_RETURN;
+  void assert_proper_lock_protection() const {
+#ifdef ASSERT
+    if (_protecting_lock != NULL)
+      assert_proper_lock_protection_work();
+#endif
+  }
+
+  // Initialize the allocation statistics.
+ protected:
+  void init_statistics(bool split_birth = false);
+  void set_count(ssize_t v) { _count = v;}
+  void increment_count()    {
+    _count++;
+  }
+
+  void decrement_count() {
+    _count--;
+    assert(_count >= 0, "Count should not be negative");
+  }
+
+ public:
+  // Constructor
+  // Construct a list without any entries.
+  FreeList();
+  // Construct a list with "fc" as the first (and lone) entry in the list.
+  FreeList(Chunk* fc);
+
+  // Reset the head, tail, hint, and count of a free list.
+  void reset(size_t hint);
+
+  // Declare the current free list to be protected by the given lock.
+#ifdef ASSERT
+  void set_protecting_lock(Mutex* protecting_lock) {
+    _protecting_lock = protecting_lock;
+  }
+#endif
+
+  // Accessors.
+  Chunk* head() const {
+    assert_proper_lock_protection();
+    return _head;
+  }
+  void set_head(Chunk* v) {
+    assert_proper_lock_protection();
+    _head = v;
+    assert(!_head || _head->size() == _size, "bad chunk size");
+  }
+  // Set the head of the list and set the prev field of non-null
+  // values to NULL.
+  void link_head(Chunk* v) {
+    assert_proper_lock_protection();
+    set_head(v);
+    // If this method is not used (just set the head instead),
+    // this check can be avoided.
+    if (v != NULL) {
+      v->link_prev(NULL);
+    }
+  }
+
+  Chunk* tail() const {
+    assert_proper_lock_protection();
+    return _tail;
+  }
+  void set_tail(Chunk* v) {
+    assert_proper_lock_protection();
+    _tail = v;
+    assert(!_tail || _tail->size() == _size, "bad chunk size");
+  }
+  // Set the tail of the list and set the next field of non-null
+  // values to NULL.
+  void link_tail(Chunk* v) {
+    assert_proper_lock_protection();
+    set_tail(v);
+    if (v != NULL) {
+      v->clear_next();
+    }
+  }
+
+  // No locking checks in read-accessors: lock-free reads (only) are benign.
+  // Readers are expected to have the lock if they are doing work that
+  // requires atomicity guarantees in sections of code.
+  size_t size() const {
+    return _size;
+  }
+  void set_size(size_t v) {
+    assert_proper_lock_protection();
+    _size = v;
+  }
+  ssize_t count() const {
+    return _count;
+  }
+  size_t hint() const {
+    return _hint;
+  }
+  void set_hint(size_t v) {
+    assert_proper_lock_protection();
+    assert(v == 0 || _size < v, "Bad hint"); _hint = v;
+  }
+
+  // Accessors for statistics
+  AllocationStats* allocation_stats() {
+    assert_proper_lock_protection();
+    return &_allocation_stats;
+  }
+
+  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,
+                       float intra_sweep_estimate) {
+    assert_proper_lock_protection();
+    _allocation_stats.compute_desired(_count,
+                                      inter_sweep_current,
+                                      inter_sweep_estimate,
+                                      intra_sweep_estimate);
+  }
+  ssize_t coal_desired() const {
+    return _allocation_stats.coal_desired();
+  }
+  void set_coal_desired(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_coal_desired(v);
+  }
+
+  ssize_t surplus() const {
+    return _allocation_stats.surplus();
+  }
+  void set_surplus(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_surplus(v);
+  }
+  void increment_surplus() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_surplus();
+  }
+  void decrement_surplus() {
+    assert_proper_lock_protection();
+    _allocation_stats.decrement_surplus();
+  }
+
+  ssize_t bfr_surp() const {
+    return _allocation_stats.bfr_surp();
+  }
+  void set_bfr_surp(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_bfr_surp(v);
+  }
+  ssize_t prev_sweep() const {
+    return _allocation_stats.prev_sweep();
+  }
+  void set_prev_sweep(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_prev_sweep(v);
+  }
+  ssize_t before_sweep() const {
+    return _allocation_stats.before_sweep();
+  }
+  void set_before_sweep(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_before_sweep(v);
+  }
+
+  ssize_t coal_births() const {
+    return _allocation_stats.coal_births();
+  }
+  void set_coal_births(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_coal_births(v);
+  }
+  void increment_coal_births() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_coal_births();
+  }
+
+  ssize_t coal_deaths() const {
+    return _allocation_stats.coal_deaths();
+  }
+  void set_coal_deaths(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_coal_deaths(v);
+  }
+  void increment_coal_deaths() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_coal_deaths();
+  }
+
+  ssize_t split_births() const {
+    return _allocation_stats.split_births();
+  }
+  void set_split_births(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_split_births(v);
+  }
+  void increment_split_births() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_split_births();
+  }
+
+  ssize_t split_deaths() const {
+    return _allocation_stats.split_deaths();
+  }
+  void set_split_deaths(ssize_t v) {
+    assert_proper_lock_protection();
+    _allocation_stats.set_split_deaths(v);
+  }
+  void increment_split_deaths() {
+    assert_proper_lock_protection();
+    _allocation_stats.increment_split_deaths();
+  }
+
+  NOT_PRODUCT(
+    // For debugging.  The "_returned_bytes" in all the lists are summed
+    // and compared with the total number of bytes swept during a
+    // collection.
+    size_t returned_bytes() const { return _allocation_stats.returned_bytes(); }
+    void set_returned_bytes(size_t v) { _allocation_stats.set_returned_bytes(v); }
+    void increment_returned_bytes_by(size_t v) {
+      _allocation_stats.set_returned_bytes(_allocation_stats.returned_bytes() + v);
+    }
+  )
+
+  // Unlink head of list and return it.  Returns NULL if
+  // the list is empty.
+  Chunk* get_chunk_at_head();
+
+  // Remove the first "n" or "count", whichever is smaller, chunks from the
+  // list, setting "fl", which is required to be empty, to point to them.
+  void getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl);
+
+  // Unlink this chunk from it's free list
+  void remove_chunk(Chunk* fc);
+
+  // Add this chunk to this free list.
+  void return_chunk_at_head(Chunk* fc);
+  void return_chunk_at_tail(Chunk* fc);
+
+  // Similar to returnChunk* but also records some diagnostic
+  // information.
+  void return_chunk_at_head(Chunk* fc, bool record_return);
+  void return_chunk_at_tail(Chunk* fc, bool record_return);
+
+  // Prepend "fl" (whose size is required to be the same as that of "this")
+  // to the front of "this" list.
+  void prepend(FreeList<Chunk>* fl);
+
+  // Verify that the chunk is in the list.
+  // found.  Return NULL if "fc" is not found.
+  bool verify_chunk_in_free_list(Chunk* fc) const;
+
+  // Stats verification
+  void verify_stats() const PRODUCT_RETURN;
+
+  // Printing support
+  static void print_labels_on(outputStream* st, const char* c);
+  void print_on(outputStream* st, const char* c = NULL) const;
+};
+
+#endif // SHARE_VM_MEMORY_FREELIST_HPP
--- a/src/share/vm/memory/genCollectedHeap.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/genCollectedHeap.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1247,18 +1247,18 @@
   return _gens[level]->gc_stats();
 }
 
-void GenCollectedHeap::verify(bool allow_dirty, bool silent, VerifyOption option /* ignored */) {
+void GenCollectedHeap::verify(bool silent, VerifyOption option /* ignored */) {
   if (!silent) {
     gclog_or_tty->print("permgen ");
   }
-  perm_gen()->verify(allow_dirty);
+  perm_gen()->verify();
   for (int i = _n_gens-1; i >= 0; i--) {
     Generation* g = _gens[i];
     if (!silent) {
       gclog_or_tty->print(g->name());
       gclog_or_tty->print(" ");
     }
-    g->verify(allow_dirty);
+    g->verify();
   }
   if (!silent) {
     gclog_or_tty->print("remset ");
--- a/src/share/vm/memory/genCollectedHeap.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/genCollectedHeap.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -357,7 +357,7 @@
   void prepare_for_verify();
 
   // Override.
-  void verify(bool allow_dirty, bool silent, VerifyOption option);
+  void verify(bool silent, VerifyOption option);
 
   // Override.
   virtual void print_on(outputStream* st) const;
--- a/src/share/vm/memory/generation.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/generation.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -696,8 +696,8 @@
   the_space()->set_top_for_allocations();
 }
 
-void OneContigSpaceCardGeneration::verify(bool allow_dirty) {
-  the_space()->verify(allow_dirty);
+void OneContigSpaceCardGeneration::verify() {
+  the_space()->verify();
 }
 
 void OneContigSpaceCardGeneration::print_on(outputStream* st)  const {
--- a/src/share/vm/memory/generation.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/generation.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -599,7 +599,7 @@
   virtual void print() const;
   virtual void print_on(outputStream* st) const;
 
-  virtual void verify(bool allow_dirty) = 0;
+  virtual void verify() = 0;
 
   struct StatRecord {
     int invocations;
@@ -753,7 +753,7 @@
 
   virtual void record_spaces_top();
 
-  virtual void verify(bool allow_dirty);
+  virtual void verify();
   virtual void print_on(outputStream* st) const;
 };
 
--- a/src/share/vm/memory/generationSpec.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/generationSpec.cpp	Tue May 15 11:27:24 2012 -0700
@@ -68,7 +68,7 @@
       ConcurrentMarkSweepGeneration* g = NULL;
       g = new ConcurrentMarkSweepGeneration(rs,
                  init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
-                 (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
+                 (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
 
       g->initialize_performance_counters();
 
@@ -88,7 +88,7 @@
       ASConcurrentMarkSweepGeneration* g = NULL;
       g = new ASConcurrentMarkSweepGeneration(rs,
                  init_size(), level, ctrs, UseCMSAdaptiveFreeLists,
-                 (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
+                 (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
 
       g->initialize_performance_counters();
 
@@ -175,7 +175,7 @@
       }
       // XXXPERM
       return new CMSPermGen(perm_rs, init_size, ctrs,
-                   (FreeBlockDictionary::DictionaryChoice)CMSDictionaryChoice);
+                   (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
     }
 #endif // SERIALGC
     default:
--- a/src/share/vm/memory/oopFactory.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/oopFactory.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -127,9 +127,13 @@
 klassOop oopFactory::new_instanceKlass(Symbol* name, int vtable_len, int itable_len,
                                        int static_field_size,
                                        unsigned int nonstatic_oop_map_count,
-                                       ReferenceType rt, TRAPS) {
+                                       AccessFlags access_flags,
+                                       ReferenceType rt,
+                                       KlassHandle host_klass, TRAPS) {
   instanceKlassKlass* ikk = instanceKlassKlass::cast(Universe::instanceKlassKlassObj());
-  return ikk->allocate_instance_klass(name, vtable_len, itable_len, static_field_size, nonstatic_oop_map_count, rt, CHECK_NULL);
+  return ikk->allocate_instance_klass(name, vtable_len, itable_len,
+                                      static_field_size, nonstatic_oop_map_count,
+                                      access_flags, rt, host_klass, CHECK_NULL);
 }
 
 
--- a/src/share/vm/memory/oopFactory.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/oopFactory.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,9 @@
                                            int vtable_len, int itable_len,
                                            int static_field_size,
                                            unsigned int nonstatic_oop_map_count,
-                                           ReferenceType rt, TRAPS);
+                                           AccessFlags access_flags,
+                                           ReferenceType rt,
+                                           KlassHandle host_klass, TRAPS);
 
   // Methods
 private:
--- a/src/share/vm/memory/space.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/space.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -531,7 +531,7 @@
               bottom(), top(), _offsets.threshold(), end());
 }
 
-void ContiguousSpace::verify(bool allow_dirty) const {
+void ContiguousSpace::verify() const {
   HeapWord* p = bottom();
   HeapWord* t = top();
   HeapWord* prev_p = NULL;
@@ -965,27 +965,12 @@
   initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle);
 }
 
-
-class VerifyOldOopClosure : public OopClosure {
- public:
-  oop  _the_obj;
-  bool _allow_dirty;
-  void do_oop(oop* p) {
-    _the_obj->verify_old_oop(p, _allow_dirty);
-  }
-  void do_oop(narrowOop* p) {
-    _the_obj->verify_old_oop(p, _allow_dirty);
-  }
-};
-
 #define OBJ_SAMPLE_INTERVAL 0
 #define BLOCK_SAMPLE_INTERVAL 100
 
-void OffsetTableContigSpace::verify(bool allow_dirty) const {
+void OffsetTableContigSpace::verify() const {
   HeapWord* p = bottom();
   HeapWord* prev_p = NULL;
-  VerifyOldOopClosure blk;      // Does this do anything?
-  blk._allow_dirty = allow_dirty;
   int objs = 0;
   int blocks = 0;
 
@@ -1007,8 +992,6 @@
 
     if (objs == OBJ_SAMPLE_INTERVAL) {
       oop(p)->verify();
-      blk._the_obj = oop(p);
-      oop(p)->oop_iterate(&blk);
       objs = 0;
     } else {
       objs++;
--- a/src/share/vm/memory/space.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/space.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -306,7 +306,7 @@
   }
 
   // Debugging
-  virtual void verify(bool allow_dirty) const = 0;
+  virtual void verify() const = 0;
 };
 
 // A MemRegionClosure (ResourceObj) whose "do_MemRegion" function applies an
@@ -948,7 +948,7 @@
   }
 
   // Debugging
-  virtual void verify(bool allow_dirty) const;
+  virtual void verify() const;
 
   // Used to increase collection frequency.  "factor" of 0 means entire
   // space.
@@ -1100,7 +1100,7 @@
   virtual void print_on(outputStream* st) const;
 
   // Debugging
-  void verify(bool allow_dirty) const;
+  void verify() const;
 
   // Shared space support
   void serialize_block_offset_array_offsets(SerializeOopClosure* soc);
--- a/src/share/vm/memory/universe.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/universe.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1326,7 +1326,7 @@
   st->print_cr("}");
 }
 
-void Universe::verify(bool allow_dirty, bool silent, VerifyOption option) {
+void Universe::verify(bool silent, VerifyOption option) {
   if (SharedSkipVerify) {
     return;
   }
@@ -1350,7 +1350,7 @@
   if (!silent) gclog_or_tty->print("[Verifying ");
   if (!silent) gclog_or_tty->print("threads ");
   Threads::verify();
-  heap()->verify(allow_dirty, silent, option);
+  heap()->verify(silent, option);
 
   if (!silent) gclog_or_tty->print("syms ");
   SymbolTable::verify();
--- a/src/share/vm/memory/universe.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/memory/universe.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -412,7 +412,7 @@
 
   // Debugging
   static bool verify_in_progress() { return _verify_in_progress; }
-  static void verify(bool allow_dirty = true, bool silent = false,
+  static void verify(bool silent = false,
                      VerifyOption option = VerifyOption_Default );
   static int  verify_count()       { return _verify_count; }
   // The default behavior is to call print_on() on gclog_or_tty.
--- a/src/share/vm/oops/arrayKlass.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/arrayKlass.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -153,6 +153,7 @@
   }
   if (length > arrayOopDesc::max_array_length(T_ARRAY)) {
     report_java_out_of_memory("Requested array size exceeds VM limit");
+    JvmtiExport::post_array_size_exhausted();
     THROW_OOP_0(Universe::out_of_memory_error_array_size());
   }
   int size = objArrayOopDesc::object_size(length);
--- a/src/share/vm/oops/cpCacheOop.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/cpCacheOop.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -504,17 +504,17 @@
 
 void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
   // print separator
-  if (index == 0) tty->print_cr("                 -------------");
+  if (index == 0) st->print_cr("                 -------------");
   // print entry
-  tty->print("%3d  ("PTR_FORMAT")  ", index, (intptr_t)this);
+  st->print("%3d  ("PTR_FORMAT")  ", index, (intptr_t)this);
   if (is_secondary_entry())
-    tty->print_cr("[%5d|secondary]", main_entry_index());
+    st->print_cr("[%5d|secondary]", main_entry_index());
   else
-    tty->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
-  tty->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)(oop)_f1);
-  tty->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_f2);
-  tty->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_flags);
-  tty->print_cr("                 -------------");
+    st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
+  st->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)(oop)_f1);
+  st->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_f2);
+  st->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_flags);
+  st->print_cr("                 -------------");
 }
 
 void ConstantPoolCacheEntry::verify(outputStream* st) const {
--- a/src/share/vm/oops/instanceKlass.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/instanceKlass.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -567,8 +567,18 @@
   ol.notify_all(CHECK);
 }
 
+// The embedded _implementor field can only record one implementor.
+// When there are more than one implementors, the _implementor field
+// is set to the interface klassOop itself. Following are the possible
+// values for the _implementor field:
+//   NULL                  - no implementor
+//   implementor klassOop  - one implementor
+//   self                  - more than one implementor
+//
+// The _implementor field only exists for interfaces.
 void instanceKlass::add_implementor(klassOop k) {
   assert(Compile_lock->owned_by_self(), "");
+  assert(is_interface(), "not interface");
   // Filter out my subinterfaces.
   // (Note: Interfaces are never on the subklass list.)
   if (instanceKlass::cast(k)->is_interface()) return;
@@ -583,17 +593,13 @@
     // Any supers of the super have the same (or fewer) transitive_interfaces.
     return;
 
-  // Update number of implementors
-  int i = _nof_implementors++;
-
-  // Record this implementor, if there are not too many already
-  if (i < implementors_limit) {
-    assert(_implementors[i] == NULL, "should be exactly one implementor");
-    oop_store_without_check((oop*)&_implementors[i], k);
-  } else if (i == implementors_limit) {
-    // clear out the list on first overflow
-    for (int i2 = 0; i2 < implementors_limit; i2++)
-      oop_store_without_check((oop*)&_implementors[i2], NULL);
+  klassOop ik = implementor();
+  if (ik == NULL) {
+    set_implementor(k);
+  } else if (ik != this->as_klassOop()) {
+    // There is already an implementor. Use itself as an indicator of
+    // more than one implementors.
+    set_implementor(this->as_klassOop());
   }
 
   // The implementor also implements the transitive_interfaces
@@ -603,9 +609,9 @@
 }
 
 void instanceKlass::init_implementor() {
-  for (int i = 0; i < implementors_limit; i++)
-    oop_store_without_check((oop*)&_implementors[i], NULL);
-  _nof_implementors = 0;
+  if (is_interface()) {
+    set_implementor(NULL);
+  }
 }
 
 
@@ -669,6 +675,7 @@
   if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
   if (length > arrayOopDesc::max_array_length(T_OBJECT)) {
     report_java_out_of_memory("Requested array size exceeds VM limit");
+    JvmtiExport::post_array_size_exhausted();
     THROW_OOP_0(Universe::out_of_memory_error_array_size());
   }
   int size = objArrayOopDesc::object_size(length);
@@ -1132,6 +1139,36 @@
   return probe;
 }
 
+u2 instanceKlass::enclosing_method_data(int offset) {
+  typeArrayOop inner_class_list = inner_classes();
+  if (inner_class_list == NULL) {
+    return 0;
+  }
+  int length = inner_class_list->length();
+  if (length % inner_class_next_offset == 0) {
+    return 0;
+  } else {
+    int index = length - enclosing_method_attribute_size;
+    typeArrayHandle inner_class_list_h(inner_class_list);
+    assert(offset < enclosing_method_attribute_size, "invalid offset");
+    return inner_class_list_h->ushort_at(index + offset);
+  }
+}
+
+void instanceKlass::set_enclosing_method_indices(u2 class_index,
+                                                 u2 method_index) {
+  typeArrayOop inner_class_list = inner_classes();
+  assert (inner_class_list != NULL, "_inner_classes list is not set up");
+  int length = inner_class_list->length();
+  if (length % inner_class_next_offset == enclosing_method_attribute_size) {
+    int index = length - enclosing_method_attribute_size;
+    typeArrayHandle inner_class_list_h(inner_class_list);
+    inner_class_list_h->ushort_at_put(
+      index + enclosing_method_class_index_offset, class_index);
+    inner_class_list_h->ushort_at_put(
+      index + enclosing_method_method_index_offset, method_index);
+  }
+}
 
 // Lookup or create a jmethodID.
 // This code is called by the VMThread and JavaThreads so the
@@ -1818,24 +1855,22 @@
 void instanceKlass::follow_weak_klass_links(
   BoolObjectClosure* is_alive, OopClosure* keep_alive) {
   assert(is_alive->do_object_b(as_klassOop()), "this oop should be live");
-  if (ClassUnloading) {
-    for (int i = 0; i < implementors_limit; i++) {
-      klassOop impl = _implementors[i];
-      if (impl == NULL)  break;  // no more in the list
-      if (!is_alive->do_object_b(impl)) {
-        // remove this guy from the list by overwriting him with the tail
-        int lasti = --_nof_implementors;
-        assert(lasti >= i && lasti < implementors_limit, "just checking");
-        _implementors[i] = _implementors[lasti];
-        _implementors[lasti] = NULL;
-        --i; // rerun the loop at this index
+
+  if (is_interface()) {
+    if (ClassUnloading) {
+      klassOop impl = implementor();
+      if (impl != NULL) {
+        if (!is_alive->do_object_b(impl)) {
+          // remove this guy
+          *adr_implementor() = NULL;
+        }
       }
-    }
-  } else {
-    for (int i = 0; i < implementors_limit; i++) {
-      keep_alive->do_oop(&adr_implementors()[i]);
+    } else {
+      assert(adr_implementor() != NULL, "just checking");
+      keep_alive->do_oop(adr_implementor());
     }
   }
+
   Klass::follow_weak_klass_links(is_alive, keep_alive);
 }
 
@@ -2106,28 +2141,21 @@
   jint access = access_flags().as_int();
 
   // But check if it happens to be member class.
-  typeArrayOop inner_class_list = inner_classes();
-  int length = (inner_class_list == NULL) ? 0 : inner_class_list->length();
-  assert (length % instanceKlass::inner_class_next_offset == 0, "just checking");
-  if (length > 0) {
-    typeArrayHandle inner_class_list_h(THREAD, inner_class_list);
-    instanceKlassHandle ik(THREAD, k);
-    for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) {
-      int ioff = inner_class_list_h->ushort_at(
-                      i + instanceKlass::inner_class_inner_class_info_offset);
-
-      // Inner class attribute can be zero, skip it.
-      // Strange but true:  JVM spec. allows null inner class refs.
-      if (ioff == 0) continue;
-
-      // only look at classes that are already loaded
-      // since we are looking for the flags for our self.
-      Symbol* inner_name = ik->constants()->klass_name_at(ioff);
-      if ((ik->name() == inner_name)) {
-        // This is really a member class.
-        access = inner_class_list_h->ushort_at(i + instanceKlass::inner_class_access_flags_offset);
-        break;
-      }
+  instanceKlassHandle ik(THREAD, k);
+  InnerClassesIterator iter(ik);
+  for (; !iter.done(); iter.next()) {
+    int ioff = iter.inner_class_info_index();
+    // Inner class attribute can be zero, skip it.
+    // Strange but true:  JVM spec. allows null inner class refs.
+    if (ioff == 0) continue;
+
+    // only look at classes that are already loaded
+    // since we are looking for the flags for our self.
+    Symbol* inner_name = ik->constants()->klass_name_at(ioff);
+    if ((ik->name() == inner_name)) {
+      // This is really a member class.
+      access = iter.inner_access_flags();
+      break;
     }
   }
   // Remember to strip ACC_SUPER bit
--- a/src/share/vm/oops/instanceKlass.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/instanceKlass.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,8 +56,6 @@
 //    [methods                    ]
 //    [local interfaces           ]
 //    [transitive interfaces      ]
-//    [number of implementors     ]
-//    [implementors               ] klassOop[2]
 //    [fields                     ]
 //    [constants                  ]
 //    [class loader               ]
@@ -77,9 +75,10 @@
 //    [oop map cache (stack maps) ]
 //    [EMBEDDED Java vtable             ] size in words = vtable_len
 //    [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size
-//
-//    The embedded nonstatic oop-map blocks are short pairs (offset, length) indicating
-//    where oops are located in instances of this klass.
+//      The embedded nonstatic oop-map blocks are short pairs (offset, length)
+//      indicating where oops are located in instances of this klass.
+//    [EMBEDDED implementor of the interface] only exist for interface
+//    [EMBEDDED host klass        ] only exist for an anonymous class (JSR 292 enabled)
 
 
 // forward declaration for class -- see below for definition
@@ -153,10 +152,6 @@
   oop* oop_block_beg() const { return adr_array_klasses(); }
   oop* oop_block_end() const { return adr_methods_default_annotations() + 1; }
 
-  enum {
-    implementors_limit = 2              // how many implems can we track?
-  };
-
  protected:
   //
   // The oop block.  See comment in klass.hpp before making changes.
@@ -182,16 +177,20 @@
   oop             _class_loader;
   // Protection domain.
   oop             _protection_domain;
-  // Host class, which grants its access privileges to this class also.
-  // This is only non-null for an anonymous class (JSR 292 enabled).
-  // The host class is either named, or a previously loaded anonymous class.
-  klassOop        _host_klass;
   // Class signers.
   objArrayOop     _signers;
-  // inner_classes attribute.
+  // The InnerClasses attribute and EnclosingMethod attribute. The
+  // _inner_classes is an array of shorts. If the class has InnerClasses
+  // attribute, then the _inner_classes array begins with 4-tuples of shorts
+  // [inner_class_info_index, outer_class_info_index,
+  // inner_name_index, inner_class_access_flags] for the InnerClasses
+  // attribute. If the EnclosingMethod attribute exists, it occupies the
+  // last two shorts [class_index, method_index] of the array. If only
+  // the InnerClasses attribute exists, the _inner_classes array length is
+  // number_of_inner_classes * 4. If the class has both InnerClasses
+  // and EnclosingMethod attributes the _inner_classes array length is
+  // number_of_inner_classes * 4 + enclosing_method_attribute_size.
   typeArrayOop    _inner_classes;
-  // Implementors of this interface (not valid if it overflows)
-  klassOop        _implementors[implementors_limit];
   // Annotations for this class, or null if none.
   typeArrayOop    _class_annotations;
   // Annotation objects (byte arrays) for fields, or null if no annotations.
@@ -232,9 +231,13 @@
   int             _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
 
   bool            _is_marked_dependent;  // used for marking during flushing and deoptimization
-  bool            _rewritten;            // methods rewritten.
-  bool            _has_nonstatic_fields; // for sizing with UseCompressedOops
-  bool            _should_verify_class;  // allow caching of preverification
+  enum {
+    _misc_rewritten            = 1 << 0, // methods rewritten.
+    _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops
+    _misc_should_verify_class  = 1 << 2, // allow caching of preverification
+    _misc_is_anonymous         = 1 << 3  // has embedded _inner_classes field
+  };
+  u2              _misc_flags;
   u2              _minor_version;        // minor version number of class file
   u2              _major_version;        // major version number of class file
   Thread*         _init_thread;          // Pointer to current thread doing initialization (to handle recusive initialization)
@@ -247,12 +250,9 @@
   nmethodBucket*  _dependencies;         // list of dependent nmethods
   nmethod*        _osr_nmethods_head;    // Head of list of on-stack replacement nmethods for this class
   BreakpointInfo* _breakpoints;          // bpt lists, managed by methodOop
-  int             _nof_implementors;     // No of implementors of this interface (zero if not an interface)
   // Array of interesting part(s) of the previous version(s) of this
   // instanceKlass. See PreviousVersionWalker below.
   GrowableArray<PreviousVersionNode *>* _previous_versions;
-  u2              _enclosing_method_class_index;  // Constant pool index for class of enclosing method, or 0 if none
-  u2              _enclosing_method_method_index; // Constant pool index for name and type of enclosing method, or 0 if none
   // JVMTI fields can be moved to their own structure - see 6315920
   unsigned char * _cached_class_file_bytes;       // JVMTI: cached class file, before retransformable agent modified it in CFLH
   jint            _cached_class_file_len;         // JVMTI: length of above
@@ -270,13 +270,36 @@
   // embedded Java itables follows here
   // embedded static fields follows here
   // embedded nonstatic oop-map blocks follows here
+  // embedded implementor of this interface follows here
+  //   The embedded implementor only exists if the current klass is an
+  //   iterface. The possible values of the implementor fall into following
+  //   three cases:
+  //     NULL: no implementor.
+  //     A klassOop that's not itself: one implementor.
+  //     Itsef: more than one implementors.
+  // embedded host klass follows here
+  //   The embedded host klass only exists in an anonymous class for
+  //   dynamic language support (JSR 292 enabled). The host class grants
+  //   its access privileges to this class also. The host class is either
+  //   named, or a previously loaded anonymous class. A non-anonymous class
+  //   or an anonymous class loaded through normal classloading does not
+  //   have this embedded field.
+  //
 
   friend class instanceKlassKlass;
   friend class SystemDictionary;
 
  public:
-  bool has_nonstatic_fields() const        { return _has_nonstatic_fields; }
-  void set_has_nonstatic_fields(bool b)    { _has_nonstatic_fields = b; }
+  bool has_nonstatic_fields() const        {
+    return (_misc_flags & _misc_has_nonstatic_fields) != 0;
+  }
+  void set_has_nonstatic_fields(bool b)    {
+    if (b) {
+      _misc_flags |= _misc_has_nonstatic_fields;
+    } else {
+      _misc_flags &= ~_misc_has_nonstatic_fields;
+    }
+  }
 
   // field sizes
   int nonstatic_field_size() const         { return _nonstatic_field_size; }
@@ -329,7 +352,7 @@
   int java_fields_count() const           { return (int)_java_fields_count; }
 
   // Number of fields including any injected fields
-  int all_fields_count() const            { return _fields->length() / sizeof(FieldInfo::field_slots); }
+  int all_fields_count() const            { return _fields->length() / FieldInfo::field_slots; }
 
   typeArrayOop fields() const              { return _fields; }
 
@@ -351,6 +374,12 @@
     inner_class_next_offset = 4
   };
 
+  enum EnclosingMethodAttributeOffset {
+    enclosing_method_class_index_offset = 0,
+    enclosing_method_method_index_offset = 1,
+    enclosing_method_attribute_size = 2
+  };
+
   // method override check
   bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
 
@@ -384,11 +413,19 @@
   bool is_in_error_state() const           { return _init_state == initialization_error; }
   bool is_reentrant_initialization(Thread *thread)  { return thread == _init_thread; }
   ClassState  init_state()                 { return (ClassState)_init_state; }
-  bool is_rewritten() const                { return _rewritten; }
+  bool is_rewritten() const                { return (_misc_flags & _misc_rewritten) != 0; }
 
   // defineClass specified verification
-  bool should_verify_class() const         { return _should_verify_class; }
-  void set_should_verify_class(bool value) { _should_verify_class = value; }
+  bool should_verify_class() const         {
+    return (_misc_flags & _misc_should_verify_class) != 0;
+  }
+  void set_should_verify_class(bool value) {
+    if (value) {
+      _misc_flags |= _misc_should_verify_class;
+    } else {
+      _misc_flags &= ~_misc_should_verify_class;
+    }
+  }
 
   // marking
   bool is_marked_dependent() const         { return _is_marked_dependent; }
@@ -457,9 +494,30 @@
   void set_protection_domain(oop pd)       { oop_store((oop*) &_protection_domain, pd); }
 
   // host class
-  oop host_klass() const                   { return _host_klass; }
-  void set_host_klass(oop host)            { oop_store((oop*) &_host_klass, host); }
-  bool is_anonymous() const                { return _host_klass != NULL; }
+  oop host_klass() const                   {
+    oop* hk = adr_host_klass();
+    if (hk == NULL) {
+      return NULL;
+    } else {
+      return *hk;
+    }
+  }
+  void set_host_klass(oop host)            {
+    assert(is_anonymous(), "not anonymous");
+    oop* addr = adr_host_klass();
+    assert(addr != NULL, "no reversed space");
+    oop_store(addr, host);
+  }
+  bool is_anonymous() const                {
+    return (_misc_flags & _misc_is_anonymous) != 0;
+  }
+  void set_is_anonymous(bool value)        {
+    if (value) {
+      _misc_flags |= _misc_is_anonymous;
+    } else {
+      _misc_flags &= ~_misc_is_anonymous;
+    }
+  }
 
   // signers
   objArrayOop signers() const              { return _signers; }
@@ -533,11 +591,15 @@
   Symbol* generic_signature() const                   { return _generic_signature; }
   void set_generic_signature(Symbol* sig)             { _generic_signature = sig; }
 
-  u2 enclosing_method_class_index() const             { return _enclosing_method_class_index; }
-  u2 enclosing_method_method_index() const            { return _enclosing_method_method_index; }
+  u2 enclosing_method_data(int offset);
+  u2 enclosing_method_class_index() {
+    return enclosing_method_data(enclosing_method_class_index_offset);
+  }
+  u2 enclosing_method_method_index() {
+    return enclosing_method_data(enclosing_method_method_index_offset);
+  }
   void set_enclosing_method_indices(u2 class_index,
-                                    u2 method_index)  { _enclosing_method_class_index  = class_index;
-                                                        _enclosing_method_method_index = method_index; }
+                                    u2 method_index);
 
   // jmethodID support
   static jmethodID get_jmethod_id(instanceKlassHandle ik_h,
@@ -626,19 +688,40 @@
 
   // support for stub routines
   static ByteSize init_state_offset()  { return in_ByteSize(sizeof(klassOopDesc) + offset_of(instanceKlass, _init_state)); }
+  TRACE_DEFINE_OFFSET;
   static ByteSize init_thread_offset() { return in_ByteSize(sizeof(klassOopDesc) + offset_of(instanceKlass, _init_thread)); }
 
   // subclass/subinterface checks
   bool implements_interface(klassOop k) const;
 
-  // Access to implementors of an interface. We only store the count
-  // of implementors, and in case, there are only a few
-  // implementors, we store them in a short list.
-  // This accessor returns NULL if we walk off the end of the list.
-  klassOop implementor(int i) const {
-    return (i < implementors_limit)? _implementors[i]: (klassOop) NULL;
+  // Access to the implementor of an interface.
+  klassOop implementor() const
+  {
+    klassOop* k = (klassOop*)adr_implementor();
+    if (k == NULL) {
+      return NULL;
+    } else {
+      return *k;
+    }
   }
-  int  nof_implementors() const       { return _nof_implementors; }
+
+  void set_implementor(klassOop k) {
+    assert(is_interface(), "not interface");
+    oop* addr = adr_implementor();
+    oop_store_without_check(addr, k);
+  }
+
+  int  nof_implementors() const       {
+    klassOop k = implementor();
+    if (k == NULL) {
+      return 0;
+    } else if (k != this->as_klassOop()) {
+      return 1;
+    } else {
+      return 2;
+    }
+  }
+
   void add_implementor(klassOop k);  // k is a new class that implements this interface
   void init_implementor();           // initialize
 
@@ -675,7 +758,17 @@
 
   // Sizing (in words)
   static int header_size()            { return align_object_offset(oopDesc::header_size() + sizeof(instanceKlass)/HeapWordSize); }
-  int object_size() const             { return object_size(align_object_offset(vtable_length()) + align_object_offset(itable_length()) + nonstatic_oop_map_size()); }
+
+  int object_size() const
+  {
+    return object_size(align_object_offset(vtable_length()) +
+                       align_object_offset(itable_length()) +
+                       ((is_interface() || is_anonymous()) ?
+                         align_object_offset(nonstatic_oop_map_size()) :
+                         nonstatic_oop_map_size()) +
+                       (is_interface() ? (int)sizeof(klassOop)/HeapWordSize : 0) +
+                       (is_anonymous() ? (int)sizeof(klassOop)/HeapWordSize : 0));
+  }
   static int vtable_start_offset()    { return header_size(); }
   static int vtable_length_offset()   { return oopDesc::header_size() + offset_of(instanceKlass, _vtable_len) / HeapWordSize; }
   static int object_size(int extra)   { return align_object_size(header_size() + extra); }
@@ -692,6 +785,29 @@
     return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
   }
 
+  oop* adr_implementor() const {
+    if (is_interface()) {
+      return (oop*)(start_of_nonstatic_oop_maps() +
+                    nonstatic_oop_map_count());
+    } else {
+      return NULL;
+    }
+  };
+
+  oop* adr_host_klass() const {
+    if (is_anonymous()) {
+      oop* adr_impl = adr_implementor();
+      if (adr_impl != NULL) {
+        return adr_impl + 1;
+      } else {
+        return (oop*)(start_of_nonstatic_oop_maps() +
+                      nonstatic_oop_map_count());
+      }
+    } else {
+      return NULL;
+    }
+  }
+
   // Allocation profiling support
   juint alloc_size() const            { return _alloc_count * size_helper(); }
   void set_alloc_size(juint n)        {}
@@ -765,7 +881,7 @@
 #else
   void set_init_state(ClassState state) { _init_state = (u1)state; }
 #endif
-  void set_rewritten()                  { _rewritten = true; }
+  void set_rewritten()                  { _misc_flags |= _misc_rewritten; }
   void set_init_thread(Thread *thread)  { _init_thread = thread; }
 
   u2 idnum_allocated_count() const      { return _idnum_allocated_count; }
@@ -798,10 +914,8 @@
   oop* adr_constants() const         { return (oop*)&this->_constants;}
   oop* adr_class_loader() const      { return (oop*)&this->_class_loader;}
   oop* adr_protection_domain() const { return (oop*)&this->_protection_domain;}
-  oop* adr_host_klass() const        { return (oop*)&this->_host_klass;}
   oop* adr_signers() const           { return (oop*)&this->_signers;}
   oop* adr_inner_classes() const     { return (oop*)&this->_inner_classes;}
-  oop* adr_implementors() const      { return (oop*)&this->_implementors[0];}
   oop* adr_methods_jmethod_ids() const             { return (oop*)&this->_methods_jmethod_ids;}
   oop* adr_methods_cached_itable_indices() const   { return (oop*)&this->_methods_cached_itable_indices;}
   oop* adr_class_annotations() const   { return (oop*)&this->_class_annotations;}
@@ -1053,4 +1167,83 @@
   nmethod* get_nmethod()                  { return _nmethod; }
 };
 
+// An iterator that's used to access the inner classes indices in the
+// instanceKlass::_inner_classes array.
+class InnerClassesIterator : public StackObj {
+ private:
+  typeArrayHandle _inner_classes;
+  int _length;
+  int _idx;
+ public:
+
+  InnerClassesIterator(instanceKlassHandle k) {
+    _inner_classes = k->inner_classes();
+    if (k->inner_classes() != NULL) {
+      _length = _inner_classes->length();
+      // The inner class array's length should be the multiple of
+      // inner_class_next_offset if it only contains the InnerClasses
+      // attribute data, or it should be
+      // n*inner_class_next_offset+enclosing_method_attribute_size
+      // if it also contains the EnclosingMethod data.
+      assert((_length % instanceKlass::inner_class_next_offset == 0 ||
+              _length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size),
+             "just checking");
+      // Remove the enclosing_method portion if exists.
+      if (_length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size) {
+        _length -= instanceKlass::enclosing_method_attribute_size;
+      }
+    } else {
+      _length = 0;
+    }
+    _idx = 0;
+  }
+
+  int length() const {
+    return _length;
+  }
+
+  void next() {
+    _idx += instanceKlass::inner_class_next_offset;
+  }
+
+  bool done() const {
+    return (_idx >= _length);
+  }
+
+  u2 inner_class_info_index() const {
+    return _inner_classes->ushort_at(
+               _idx + instanceKlass::inner_class_inner_class_info_offset);
+  }
+
+  void set_inner_class_info_index(u2 index) {
+    _inner_classes->ushort_at_put(
+               _idx + instanceKlass::inner_class_inner_class_info_offset, index);
+  }
+
+  u2 outer_class_info_index() const {
+    return _inner_classes->ushort_at(
+               _idx + instanceKlass::inner_class_outer_class_info_offset);
+  }
+
+  void set_outer_class_info_index(u2 index) {
+    _inner_classes->ushort_at_put(
+               _idx + instanceKlass::inner_class_outer_class_info_offset, index);
+  }
+
+  u2 inner_name_index() const {
+    return _inner_classes->ushort_at(
+               _idx + instanceKlass::inner_class_inner_name_offset);
+  }
+
+  void set_inner_name_index(u2 index) {
+    _inner_classes->ushort_at_put(
+               _idx + instanceKlass::inner_class_inner_name_offset, index);
+  }
+
+  u2 inner_access_flags() const {
+    return _inner_classes->ushort_at(
+               _idx + instanceKlass::inner_class_access_flags_offset);
+  }
+};
+
 #endif // SHARE_VM_OOPS_INSTANCEKLASS_HPP
--- a/src/share/vm/oops/instanceKlassKlass.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/instanceKlassKlass.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,7 +103,9 @@
   MarkSweep::mark_and_push(ik->adr_class_loader());
   MarkSweep::mark_and_push(ik->adr_inner_classes());
   MarkSweep::mark_and_push(ik->adr_protection_domain());
-  MarkSweep::mark_and_push(ik->adr_host_klass());
+  if (ik->adr_host_klass() != NULL) {
+    MarkSweep::mark_and_push(ik->adr_host_klass());
+  }
   MarkSweep::mark_and_push(ik->adr_signers());
   MarkSweep::mark_and_push(ik->adr_class_annotations());
   MarkSweep::mark_and_push(ik->adr_fields_annotations());
@@ -111,7 +113,7 @@
   MarkSweep::mark_and_push(ik->adr_methods_parameter_annotations());
   MarkSweep::mark_and_push(ik->adr_methods_default_annotations());
 
-  // We do not follow adr_implementors() here. It is followed later
+  // We do not follow adr_implementor() here. It is followed later
   // in instanceKlass::follow_weak_klass_links()
 
   klassKlass::oop_follow_contents(obj);
@@ -139,7 +141,9 @@
   PSParallelCompact::mark_and_push(cm, ik->adr_class_loader());
   PSParallelCompact::mark_and_push(cm, ik->adr_inner_classes());
   PSParallelCompact::mark_and_push(cm, ik->adr_protection_domain());
-  PSParallelCompact::mark_and_push(cm, ik->adr_host_klass());
+  if (ik->adr_host_klass() != NULL) {
+    PSParallelCompact::mark_and_push(cm, ik->adr_host_klass());
+  }
   PSParallelCompact::mark_and_push(cm, ik->adr_signers());
   PSParallelCompact::mark_and_push(cm, ik->adr_class_annotations());
   PSParallelCompact::mark_and_push(cm, ik->adr_fields_annotations());
@@ -177,11 +181,13 @@
   blk->do_oop(ik->adr_constants());
   blk->do_oop(ik->adr_class_loader());
   blk->do_oop(ik->adr_protection_domain());
-  blk->do_oop(ik->adr_host_klass());
+  if (ik->adr_host_klass() != NULL) {
+    blk->do_oop(ik->adr_host_klass());
+  }
   blk->do_oop(ik->adr_signers());
   blk->do_oop(ik->adr_inner_classes());
-  for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-    blk->do_oop(&ik->adr_implementors()[i]);
+  if (ik->adr_implementor() != NULL) {
+    blk->do_oop(ik->adr_implementor());
   }
   blk->do_oop(ik->adr_class_annotations());
   blk->do_oop(ik->adr_fields_annotations());
@@ -227,15 +233,13 @@
   adr = ik->adr_protection_domain();
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_host_klass();
-  if (mr.contains(adr)) blk->do_oop(adr);
+  if (adr != NULL && mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_signers();
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_inner_classes();
   if (mr.contains(adr)) blk->do_oop(adr);
-  adr = ik->adr_implementors();
-  for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-    if (mr.contains(&adr[i])) blk->do_oop(&adr[i]);
-  }
+  adr = ik->adr_implementor();
+  if (adr != NULL && mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_class_annotations();
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_fields_annotations();
@@ -270,11 +274,13 @@
   MarkSweep::adjust_pointer(ik->adr_constants());
   MarkSweep::adjust_pointer(ik->adr_class_loader());
   MarkSweep::adjust_pointer(ik->adr_protection_domain());
-  MarkSweep::adjust_pointer(ik->adr_host_klass());
+  if (ik->adr_host_klass() != NULL) {
+    MarkSweep::adjust_pointer(ik->adr_host_klass());
+  }
   MarkSweep::adjust_pointer(ik->adr_signers());
   MarkSweep::adjust_pointer(ik->adr_inner_classes());
-  for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-    MarkSweep::adjust_pointer(&ik->adr_implementors()[i]);
+  if (ik->adr_implementor() != NULL) {
+    MarkSweep::adjust_pointer(ik->adr_implementor());
   }
   MarkSweep::adjust_pointer(ik->adr_class_annotations());
   MarkSweep::adjust_pointer(ik->adr_fields_annotations());
@@ -302,7 +308,7 @@
   }
 
   oop* hk_addr = ik->adr_host_klass();
-  if (PSScavenge::should_scavenge(hk_addr)) {
+  if (hk_addr != NULL && PSScavenge::should_scavenge(hk_addr)) {
     pm->claim_or_forward_depth(hk_addr);
   }
 
@@ -328,6 +334,13 @@
   for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) {
     PSParallelCompact::adjust_pointer(cur_oop);
   }
+  // embedded oops
+  if (ik->adr_implementor() != NULL) {
+    PSParallelCompact::adjust_pointer(ik->adr_implementor());
+  }
+  if (ik->adr_host_klass() != NULL) {
+    PSParallelCompact::adjust_pointer(ik->adr_host_klass());
+  }
 
   OopClosure* closure = PSParallelCompact::adjust_root_pointer_closure();
   iterate_c_heap_oops(ik, closure);
@@ -342,11 +355,25 @@
 instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int itable_len,
                                             int static_field_size,
                                             unsigned nonstatic_oop_map_count,
-                                            ReferenceType rt, TRAPS) {
+                                            AccessFlags access_flags,
+                                            ReferenceType rt,
+                                            KlassHandle host_klass, TRAPS) {
 
   const int nonstatic_oop_map_size =
     instanceKlass::nonstatic_oop_map_size(nonstatic_oop_map_count);
-  int size = instanceKlass::object_size(align_object_offset(vtable_len) + align_object_offset(itable_len) + nonstatic_oop_map_size);
+  int size = align_object_offset(vtable_len) + align_object_offset(itable_len);
+  if (access_flags.is_interface() || !host_klass.is_null()) {
+    size += align_object_offset(nonstatic_oop_map_size);
+  } else {
+    size += nonstatic_oop_map_size;
+  }
+  if (access_flags.is_interface()) {
+    size += (int)sizeof(klassOop)/HeapWordSize;
+  }
+  if (!host_klass.is_null()) {
+    size += (int)sizeof(klassOop)/HeapWordSize;
+  }
+  size = instanceKlass::object_size(size);
 
   // Allocation
   KlassHandle h_this_klass(THREAD, as_klassOop());
@@ -378,6 +405,8 @@
     ik->set_itable_length(itable_len);
     ik->set_static_field_size(static_field_size);
     ik->set_nonstatic_oop_map_size(nonstatic_oop_map_size);
+    ik->set_access_flags(access_flags);
+    ik->set_is_anonymous(!host_klass.is_null());
     assert(k()->size() == size, "wrong size for object");
 
     ik->set_array_klasses(NULL);
@@ -390,7 +419,6 @@
     ik->set_constants(NULL);
     ik->set_class_loader(NULL);
     ik->set_protection_domain(NULL);
-    ik->set_host_klass(NULL);
     ik->set_signers(NULL);
     ik->set_source_file_name(NULL);
     ik->set_source_debug_extension(NULL);
@@ -416,7 +444,6 @@
     ik->set_methods_annotations(NULL);
     ik->set_methods_parameter_annotations(NULL);
     ik->set_methods_default_annotations(NULL);
-    ik->set_enclosing_method_indices(0, 0);
     ik->set_jvmti_cached_class_field_map(NULL);
     ik->set_initial_method_idnum(0);
     assert(k()->is_parsable(), "should be parsable here.");
@@ -471,16 +498,12 @@
 
   if (ik->is_interface()) {
     st->print_cr(BULLET"nof implementors:  %d", ik->nof_implementors());
-    int print_impl = 0;
-    for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-      if (ik->implementor(i) != NULL) {
-        if (++print_impl == 1)
-          st->print_cr(BULLET"implementor:    ");
-        st->print("   ");
-        ik->implementor(i)->print_value_on(st);
-      }
+    if (ik->nof_implementors() == 1) {
+      st->print_cr(BULLET"implementor:    ");
+      st->print("   ");
+      ik->implementor()->print_value_on(st);
+      st->cr();
     }
-    if (print_impl > 0)  st->cr();
   }
 
   st->print(BULLET"arrays:            "); ik->array_klasses()->print_value_on(st);     st->cr();
@@ -497,7 +520,9 @@
   st->print(BULLET"constants:         "); ik->constants()->print_value_on(st);         st->cr();
   st->print(BULLET"class loader:      "); ik->class_loader()->print_value_on(st);      st->cr();
   st->print(BULLET"protection domain: "); ik->protection_domain()->print_value_on(st); st->cr();
-  st->print(BULLET"host class:        "); ik->host_klass()->print_value_on(st);        st->cr();
+  if (ik->host_klass() != NULL) {
+    st->print(BULLET"host class:        "); ik->host_klass()->print_value_on(st);        st->cr();
+  }
   st->print(BULLET"signers:           "); ik->signers()->print_value_on(st);           st->cr();
   if (ik->source_file_name() != NULL) {
     st->print(BULLET"source file:       ");
@@ -641,16 +666,12 @@
     }
 
     // Verify implementor fields
-    bool saw_null_impl = false;
-    for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-      klassOop im = ik->implementor(i);
-      if (im == NULL) { saw_null_impl = true; continue; }
-      guarantee(!saw_null_impl, "non-nulls must preceded all nulls");
+    klassOop im = ik->implementor();
+    if (im != NULL) {
       guarantee(ik->is_interface(), "only interfaces should have implementor set");
-      guarantee(i < ik->nof_implementors(), "should only have one implementor");
       guarantee(im->is_perm(),  "should be in permspace");
       guarantee(im->is_klass(), "should be klass");
-      guarantee(!Klass::cast(klassOop(im))->is_interface(), "implementors cannot be interfaces");
+      guarantee(!Klass::cast(klassOop(im))->is_interface() || im == ik->as_klassOop(), "implementors cannot be interfaces");
     }
 
     // Verify local interfaces
--- a/src/share/vm/oops/instanceKlassKlass.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/instanceKlassKlass.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,9 @@
                                    int itable_len,
                                    int static_field_size,
                                    unsigned int nonstatic_oop_map_count,
+                                   AccessFlags access_flags,
                                    ReferenceType rt,
+                                   KlassHandle host_klass,
                                    TRAPS);
 
   // Casting from klassOop
--- a/src/share/vm/oops/instanceRefKlass.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/instanceRefKlass.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -497,36 +497,12 @@
 
   if (referent != NULL) {
     guarantee(referent->is_oop(), "referent field heap failed");
-    if (gch != NULL && !gch->is_in_young(obj)) {
-      // We do a specific remembered set check here since the referent
-      // field is not part of the oop mask and therefore skipped by the
-      // regular verify code.
-      if (UseCompressedOops) {
-        narrowOop* referent_addr = (narrowOop*)java_lang_ref_Reference::referent_addr(obj);
-        obj->verify_old_oop(referent_addr, true);
-      } else {
-        oop* referent_addr = (oop*)java_lang_ref_Reference::referent_addr(obj);
-        obj->verify_old_oop(referent_addr, true);
-      }
-    }
   }
   // Verify next field
   oop next = java_lang_ref_Reference::next(obj);
   if (next != NULL) {
     guarantee(next->is_oop(), "next field verify failed");
     guarantee(next->is_instanceRef(), "next field verify failed");
-    if (gch != NULL && !gch->is_in_young(obj)) {
-      // We do a specific remembered set check here since the next field is
-      // not part of the oop mask and therefore skipped by the regular
-      // verify code.
-      if (UseCompressedOops) {
-        narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj);
-        obj->verify_old_oop(next_addr, true);
-      } else {
-        oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj);
-        obj->verify_old_oop(next_addr, true);
-      }
-    }
   }
 }
 
--- a/src/share/vm/oops/klass.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/klass.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -174,10 +174,9 @@
 }
 
 void Klass_vtbl::post_new_init_klass(KlassHandle& klass,
-                                     klassOop new_klass,
-                                     int size) const {
+                                     klassOop new_klass) const {
   assert(!new_klass->klass_part()->null_vtbl(), "Not a complete klass");
-  CollectedHeap::post_allocation_install_obj_klass(klass, new_klass, size);
+  CollectedHeap::post_allocation_install_obj_klass(klass, new_klass);
 }
 
 void* Klass_vtbl::operator new(size_t ignored, KlassHandle& klass,
@@ -582,14 +581,6 @@
   guarantee(obj->klass()->is_klass(), "klass field is not a klass");
 }
 
-
-void Klass::oop_verify_old_oop(oop obj, oop* p, bool allow_dirty) {
-  /* $$$ I think this functionality should be handled by verification of
-  RememberedSet::verify_old_oop(obj, p, allow_dirty, false);
-  the card table. */
-}
-void Klass::oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty) { }
-
 #ifndef PRODUCT
 
 void Klass::verify_vtable_index(int i) {
--- a/src/share/vm/oops/klass.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/klass.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -149,7 +149,7 @@
   // by the shared "base_create" subroutines.
   //
   virtual void* allocate_permanent(KlassHandle& klass, int size, TRAPS) const = 0;
-  void post_new_init_klass(KlassHandle& klass, klassOop obj, int size) const;
+  void post_new_init_klass(KlassHandle& klass, klassOop obj) const;
 
   // Every subclass on which vtbl_value is called must include this macro.
   // Delay the installation of the klassKlass pointer until after the
@@ -160,7 +160,7 @@
     if (HAS_PENDING_EXCEPTION) return NULL;                                   \
     klassOop new_klass = ((Klass*) result)->as_klassOop();                    \
     OrderAccess::storestore();                                                \
-    post_new_init_klass(klass_klass, new_klass, size);                        \
+    post_new_init_klass(klass_klass, new_klass);                              \
     return result;                                                            \
   }
 
@@ -805,8 +805,6 @@
   // Verification
   virtual const char* internal_name() const = 0;
   virtual void oop_verify_on(oop obj, outputStream* st);
-  virtual void oop_verify_old_oop(oop obj, oop* p, bool allow_dirty);
-  virtual void oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty);
   // tells whether obj is partially constructed (gc during class loading)
   virtual bool oop_partially_loaded(oop obj) const { return false; }
   virtual void oop_set_partially_loaded(oop obj) {};
--- a/src/share/vm/oops/objArrayKlass.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/objArrayKlass.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,6 +68,7 @@
       return a;
     } else {
       report_java_out_of_memory("Requested array size exceeds VM limit");
+      JvmtiExport::post_array_size_exhausted();
       THROW_OOP_0(Universe::out_of_memory_error_array_size());
     }
   } else {
@@ -544,10 +545,3 @@
     guarantee(oa->obj_at(index)->is_oop_or_null(), "should be oop");
   }
 }
-
-void objArrayKlass::oop_verify_old_oop(oop obj, oop* p, bool allow_dirty) {
-  /* $$$ move into remembered set verification?
-  RememberedSet::verify_old_oop(obj, p, allow_dirty, true);
-  */
-}
-void objArrayKlass::oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty) {}
--- a/src/share/vm/oops/objArrayKlass.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/objArrayKlass.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -144,8 +144,6 @@
   // Verification
   const char* internal_name() const;
   void oop_verify_on(oop obj, outputStream* st);
-  void oop_verify_old_oop(oop obj, oop* p, bool allow_dirty);
-  void oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty);
 };
 
 #endif // SHARE_VM_OOPS_OBJARRAYKLASS_HPP
--- a/src/share/vm/oops/objArrayKlassKlass.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/objArrayKlassKlass.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -137,7 +137,7 @@
       new_str[idx++] = ';';
     }
     new_str[idx++] = '\0';
-    name = SymbolTable::new_symbol(new_str, CHECK_0);
+    name = SymbolTable::new_permanent_symbol(new_str, CHECK_0);
     if (element_klass->oop_is_instance()) {
       instanceKlass* ik = instanceKlass::cast(element_klass());
       ik->set_array_name(name);
--- a/src/share/vm/oops/oop.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/oop.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -107,16 +107,6 @@
   verify_on(tty);
 }
 
-
-// XXX verify_old_oop doesn't do anything (should we remove?)
-void oopDesc::verify_old_oop(oop* p, bool allow_dirty) {
-  blueprint()->oop_verify_old_oop(this, p, allow_dirty);
-}
-
-void oopDesc::verify_old_oop(narrowOop* p, bool allow_dirty) {
-  blueprint()->oop_verify_old_oop(this, p, allow_dirty);
-}
-
 bool oopDesc::partially_loaded() {
   return blueprint()->oop_partially_loaded(this);
 }
--- a/src/share/vm/oops/oop.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/oop.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -293,8 +293,6 @@
   // verification operations
   void verify_on(outputStream* st);
   void verify();
-  void verify_old_oop(oop* p, bool allow_dirty);
-  void verify_old_oop(narrowOop* p, bool allow_dirty);
 
   // tells whether this oop is partially constructed (gc during class loading)
   bool partially_loaded();
--- a/src/share/vm/oops/symbol.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/symbol.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,15 +29,25 @@
 #include "runtime/os.hpp"
 #include "memory/allocation.inline.hpp"
 
-Symbol::Symbol(const u1* name, int length) : _refcount(0), _length(length) {
+Symbol::Symbol(const u1* name, int length, int refcount) : _refcount(refcount), _length(length) {
   _identity_hash = os::random();
   for (int i = 0; i < _length; i++) {
     byte_at_put(i, name[i]);
   }
 }
 
-void* Symbol::operator new(size_t size, int len) {
-  return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol");
+void* Symbol::operator new(size_t sz, int len, TRAPS) {
+  int alloc_size = object_size(len)*HeapWordSize;
+  address res = (address) AllocateHeap(alloc_size, "symbol");
+  DEBUG_ONLY(set_allocation_type(res, ResourceObj::C_HEAP);)
+  return res;
+}
+
+void* Symbol::operator new(size_t sz, int len, Arena* arena, TRAPS) {
+  int alloc_size = object_size(len)*HeapWordSize;
+  address res = (address)arena->Amalloc(alloc_size);
+  DEBUG_ONLY(set_allocation_type(res, ResourceObj::ARENA);)
+  return res;
 }
 
 // ------------------------------------------------------------------
@@ -206,26 +216,5 @@
   }
 }
 
-void Symbol::increment_refcount() {
-  // Only increment the refcount if positive.  If negative either
-  // overflow has occurred or it is a permanent symbol in a read only
-  // shared archive.
-  if (_refcount >= 0) {
-    Atomic::inc(&_refcount);
-    NOT_PRODUCT(Atomic::inc(&_total_count);)
-  }
-}
-
-void Symbol::decrement_refcount() {
-  if (_refcount >= 0) {
-    Atomic::dec(&_refcount);
-#ifdef ASSERT
-    if (_refcount < 0) {
-      print();
-      assert(false, "reference count underflow for symbol");
-    }
-#endif
-  }
-}
-
+// SymbolTable prints this in its statistics
 NOT_PRODUCT(int Symbol::_total_count = 0;)
--- a/src/share/vm/oops/symbol.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/symbol.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 
 #include "utilities/utf8.hpp"
 #include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
 
 // A Symbol is a canonicalized string.
 // All Symbols reside in global SymbolTable and are reference counted.
@@ -95,7 +96,7 @@
 // TempNewSymbol (passed in as a parameter) so the reference count on its symbol
 // will be decremented when it goes out of scope.
 
-class Symbol : public CHeapObj {
+class Symbol : public ResourceObj {
   friend class VMStructs;
   friend class SymbolTable;
   friend class MoveSymbols;
@@ -111,7 +112,7 @@
   };
 
   static int object_size(int length) {
-    size_t size = heap_word_size(sizeof(Symbol) + length);
+    size_t size = heap_word_size(sizeof(Symbol) + (length > 0 ? length - 1 : 0));
     return align_object_size(size);
   }
 
@@ -120,28 +121,25 @@
     _body[index] = value;
   }
 
-  Symbol(const u1* name, int length);
-  void* operator new(size_t size, int len);
+  Symbol(const u1* name, int length, int refcount);
+  void* operator new(size_t size, int len, TRAPS);
+  void* operator new(size_t size, int len, Arena* arena, TRAPS);
 
  public:
   // Low-level access (used with care, since not GC-safe)
   const jbyte* base() const { return &_body[0]; }
 
-  int object_size() { return object_size(utf8_length()); }
+  int object_size()         { return object_size(utf8_length()); }
 
   // Returns the largest size symbol we can safely hold.
-  static int max_length() {
-    return max_symbol_length;
-  }
+  static int max_length()   { return max_symbol_length; }
 
-  int identity_hash() {
-    return _identity_hash;
-  }
+  int identity_hash()       { return _identity_hash; }
 
   // Reference counting.  See comments above this class for when to use.
-  int refcount() const { return _refcount; }
-  void increment_refcount();
-  void decrement_refcount();
+  int refcount() const      { return _refcount; }
+  inline void increment_refcount();
+  inline void decrement_refcount();
 
   int byte_at(int index) const {
     assert(index >=0 && index < _length, "symbol index overflow");
@@ -220,4 +218,26 @@
  return (((uintptr_t)this < (uintptr_t)other) ? -1
    : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1);
 }
+
+inline void Symbol::increment_refcount() {
+  // Only increment the refcount if positive.  If negative either
+  // overflow has occurred or it is a permanent symbol in a read only
+  // shared archive.
+  if (_refcount >= 0) {
+    Atomic::inc(&_refcount);
+    NOT_PRODUCT(Atomic::inc(&_total_count);)
+  }
+}
+
+inline void Symbol::decrement_refcount() {
+  if (_refcount >= 0) {
+    Atomic::dec(&_refcount);
+#ifdef ASSERT
+    if (_refcount < 0) {
+      print();
+      assert(false, "reference count underflow for symbol");
+    }
+#endif
+  }
+}
 #endif // SHARE_VM_OOPS_SYMBOL_HPP
--- a/src/share/vm/oops/typeArrayKlass.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/oops/typeArrayKlass.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,7 +55,7 @@
 
   Symbol* sym = NULL;
   if (name_str != NULL) {
-    sym = SymbolTable::new_symbol(name_str, CHECK_NULL);
+    sym = SymbolTable::new_permanent_symbol(name_str, CHECK_NULL);
   }
   KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj());
 
@@ -93,6 +93,7 @@
       return t;
     } else {
       report_java_out_of_memory("Requested array size exceeds VM limit");
+      JvmtiExport::post_array_size_exhausted();
       THROW_OOP_0(Universe::out_of_memory_error_array_size());
     }
   } else {
--- a/src/share/vm/opto/bytecodeInfo.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/bytecodeInfo.cpp	Tue May 15 11:27:24 2012 -0700
@@ -257,6 +257,18 @@
       return "exception method";
   }
 
+  if (callee_method->should_not_inline()) {
+    return "disallowed by CompilerOracle";
+  }
+
+  if (UseStringCache) {
+    // Do not inline StringCache::profile() method used only at the beginning.
+    if (callee_method->name() == ciSymbol::profile_name() &&
+        callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) {
+      return "profiling method";
+    }
+  }
+
   // use frequency-based objections only for non-trivial methods
   if (callee_method->code_size_for_inlining() <= MaxTrivialSize) return NULL;
 
@@ -278,18 +290,6 @@
     }
   }
 
-  if (callee_method->should_not_inline()) {
-    return "disallowed by CompilerOracle";
-  }
-
-  if (UseStringCache) {
-    // Do not inline StringCache::profile() method used only at the beginning.
-    if (callee_method->name() == ciSymbol::profile_name() &&
-        callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) {
-      return "profiling method";
-    }
-  }
-
   return NULL;
 }
 
--- a/src/share/vm/opto/c2_globals.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/c2_globals.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -465,6 +465,9 @@
   notproduct(bool, PrintOptimizePtrCompare, false,                          \
           "Print information about optimized pointers compare")             \
                                                                             \
+  notproduct(bool, VerifyConnectionGraph , true,                            \
+          "Verify Connection Graph construction in Escape Analysis")        \
+                                                                            \
   product(bool, UseOptoBiasInlining, true,                                  \
           "Generate biased locking code in C2 ideal graph")                 \
                                                                             \
--- a/src/share/vm/opto/callGenerator.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/callGenerator.cpp	Tue May 15 11:27:24 2012 -0700
@@ -137,6 +137,7 @@
   }
 
   CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), target, method(), kit.bci());
+  _call_node = call;  // Save the call node in case we need it later
   if (!is_static) {
     // Make an explicit receiver null_check as part of this call.
     // Since we share a map with the caller, his JVMS gets adjusted.
@@ -155,7 +156,6 @@
   kit.set_edges_for_java_call(call, false, _separate_io_proj);
   Node* ret = kit.set_results_for_java_call(call, _separate_io_proj);
   kit.push_node(method()->return_type()->basic_type(), ret);
-  _call_node = call;  // Save the call node in case we need it later
   return kit.transfer_exceptions_into_jvms();
 }
 
--- a/src/share/vm/opto/callnode.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/callnode.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1538,10 +1538,7 @@
     // If we are locking an unescaped object, the lock/unlock is unnecessary
     //
     ConnectionGraph *cgr = phase->C->congraph();
-    PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
-    if (cgr != NULL)
-      es = cgr->escape_state(obj_node());
-    if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
+    if (cgr != NULL && cgr->not_global_escape(obj_node())) {
       assert(!is_eliminated() || is_coarsened(), "sanity");
       // The lock could be marked eliminated by lock coarsening
       // code during first IGVN before EA. Replace coarsened flag
@@ -1680,10 +1677,7 @@
     // If we are unlocking an unescaped object, the lock/unlock is unnecessary.
     //
     ConnectionGraph *cgr = phase->C->congraph();
-    PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
-    if (cgr != NULL)
-      es = cgr->escape_state(obj_node());
-    if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
+    if (cgr != NULL && cgr->not_global_escape(obj_node())) {
       assert(!is_eliminated() || is_coarsened(), "sanity");
       // The lock could be marked eliminated by lock coarsening
       // code during first IGVN before EA. Replace coarsened flag
--- a/src/share/vm/opto/callnode.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/callnode.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -546,6 +546,12 @@
   // or result projection is there are several CheckCastPP
   // or returns NULL if there is no one.
   Node *result_cast();
+  // Does this node returns pointer?
+  bool returns_pointer() const {
+    const TypeTuple *r = tf()->range();
+    return (r->cnt() > TypeFunc::Parms &&
+            r->field_at(TypeFunc::Parms)->isa_ptr());
+  }
 
   // Collect all the interesting edges from a call for use in
   // replacing the call by something else.  Used by macro expansion
--- a/src/share/vm/opto/compile.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/compile.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1707,7 +1707,6 @@
       if (major_progress()) print_method("PhaseIdealLoop before EA", 2);
       if (failing())  return;
     }
-    TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
     ConnectionGraph::do_analysis(this, &igvn);
 
     if (failing())  return;
@@ -1719,6 +1718,7 @@
     if (failing())  return;
 
     if (congraph() != NULL && macro_count() > 0) {
+      NOT_PRODUCT( TracePhase t2("macroEliminate", &_t_macroEliminate, TimeCompiler); )
       PhaseMacroExpand mexp(igvn);
       mexp.eliminate_macro_nodes();
       igvn.set_delay_transform(false);
@@ -1875,10 +1875,10 @@
 
     cfg.Estimate_Block_Frequency();
     cfg.GlobalCodeMotion(m,unique(),proj_list);
+    if (failing())  return;
 
     print_method("Global code motion", 2);
 
-    if (failing())  return;
     NOT_PRODUCT( verify_graph_edges(); )
 
     debug_only( cfg.verify(); )
--- a/src/share/vm/opto/compile.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/compile.hpp	Tue May 15 11:27:24 2012 -0700
@@ -631,7 +631,7 @@
 
   // Decide how to build a call.
   // The profile factor is a discount to apply to this site's interp. profile.
-  CallGenerator*    call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual, JVMState* jvms, bool allow_inline, float profile_factor);
+  CallGenerator*    call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual, JVMState* jvms, bool allow_inline, float profile_factor, bool allow_intrinsics = true);
   bool should_delay_inlining(ciMethod* call_method, JVMState* jvms);
 
   // Report if there were too many traps at a current method and bci.
--- a/src/share/vm/opto/connode.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/connode.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1051,6 +1051,7 @@
 //------------------------------Value------------------------------------------
 const Type *CastX2PNode::Value( PhaseTransform *phase ) const {
   const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
   if (t->base() == Type_X && t->singleton()) {
     uintptr_t bits = (uintptr_t) t->is_intptr_t()->get_con();
     if (bits == 0)   return TypePtr::NULL_PTR;
@@ -1121,6 +1122,7 @@
 //------------------------------Value------------------------------------------
 const Type *CastP2XNode::Value( PhaseTransform *phase ) const {
   const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
   if (t->base() == Type::RawPtr && t->singleton()) {
     uintptr_t bits = (uintptr_t) t->is_rawptr()->get_con();
     return TypeX::make(bits);
--- a/src/share/vm/opto/doCall.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/doCall.cpp	Tue May 15 11:27:24 2012 -0700
@@ -61,7 +61,7 @@
 
 CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual,
                                        JVMState* jvms, bool allow_inline,
-                                       float prof_factor) {
+                                       float prof_factor, bool allow_intrinsics) {
   ciMethod*       caller   = jvms->method();
   int             bci      = jvms->bci();
   Bytecodes::Code bytecode = caller->java_code_at_bci(bci);
@@ -108,7 +108,7 @@
   // then we return it as the inlined version of the call.
   // We do this before the strict f.p. check below because the
   // intrinsics handle strict f.p. correctly.
-  if (allow_inline) {
+  if (allow_inline && allow_intrinsics) {
     CallGenerator* cg = find_intrinsic(call_method, call_is_virtual);
     if (cg != NULL)  return cg;
   }
@@ -455,21 +455,12 @@
     // cg->generate(), we are committed.  If it fails, the whole
     // compilation task is compromised.
     if (failing())  return;
-#ifndef PRODUCT
-    if (PrintOpto || PrintOptoInlining || PrintInlining) {
-      // Only one fall-back, so if an intrinsic fails, ignore any bytecodes.
-      if (cg->is_intrinsic() && call_method->code_size() > 0) {
-        tty->print("Bailed out of intrinsic, will not inline: ");
-        call_method->print_name(); tty->cr();
-      }
-    }
-#endif
+
     // This can happen if a library intrinsic is available, but refuses
     // the call site, perhaps because it did not match a pattern the
-    // intrinsic was expecting to optimize.  The fallback position is
-    // to call out-of-line.
-    try_inline = false;  // Inline tactic bailed out.
-    cg = C->call_generator(call_method, vtable_index, call_is_virtual, jvms, try_inline, prof_factor());
+    // intrinsic was expecting to optimize. Should always be possible to
+    // get a normal java call that may inline in that case
+    cg = C->call_generator(call_method, vtable_index, call_is_virtual, jvms, try_inline, prof_factor(), /* allow_intrinsics= */ false);
     if ((new_jvms = cg->generate(jvms)) == NULL) {
       guarantee(failing(), "call failed to generate:  calls should work");
       return;
--- a/src/share/vm/opto/escape.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/escape.cpp	Tue May 15 11:27:24 2012 -0700
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "ci/bcEscapeAnalyzer.hpp"
+#include "compiler/compileLog.hpp"
 #include "libadt/vectset.hpp"
 #include "memory/allocation.hpp"
 #include "opto/c2compiler.hpp"
@@ -34,125 +35,1935 @@
 #include "opto/phaseX.hpp"
 #include "opto/rootnode.hpp"
 
-void PointsToNode::add_edge(uint targIdx, PointsToNode::EdgeType et) {
-  uint v = (targIdx << EdgeShift) + ((uint) et);
-  if (_edges == NULL) {
-     Arena *a = Compile::current()->comp_arena();
-    _edges = new(a) GrowableArray<uint>(a, INITIAL_EDGE_COUNT, 0, 0);
-  }
-  _edges->append_if_missing(v);
-}
-
-void PointsToNode::remove_edge(uint targIdx, PointsToNode::EdgeType et) {
-  uint v = (targIdx << EdgeShift) + ((uint) et);
-
-  _edges->remove(v);
-}
-
-#ifndef PRODUCT
-static const char *node_type_names[] = {
-  "UnknownType",
-  "JavaObject",
-  "LocalVar",
-  "Field"
-};
-
-static const char *esc_names[] = {
-  "UnknownEscape",
-  "NoEscape",
-  "ArgEscape",
-  "GlobalEscape"
-};
-
-static const char *edge_type_suffix[] = {
- "?", // UnknownEdge
- "P", // PointsToEdge
- "D", // DeferredEdge
- "F"  // FieldEdge
-};
-
-void PointsToNode::dump(bool print_state) const {
-  NodeType nt = node_type();
-  tty->print("%s ", node_type_names[(int) nt]);
-  if (print_state) {
-    EscapeState es = escape_state();
-    tty->print("%s %s ", esc_names[(int) es], _scalar_replaceable ? "":"NSR");
-  }
-  tty->print("[[");
-  for (uint i = 0; i < edge_count(); i++) {
-    tty->print(" %d%s", edge_target(i), edge_type_suffix[(int) edge_type(i)]);
-  }
-  tty->print("]]  ");
-  if (_node == NULL)
-    tty->print_cr("<null>");
-  else
-    _node->dump();
-}
-#endif
-
 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
-  _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
-  _processed(C->comp_arena()),
-  pt_ptset(C->comp_arena()),
-  pt_visited(C->comp_arena()),
-  pt_worklist(C->comp_arena(), 4, 0, 0),
+  _nodes(C->comp_arena(), C->unique(), C->unique(), NULL),
   _collecting(true),
-  _progress(false),
+  _verify(false),
   _compile(C),
   _igvn(igvn),
   _node_map(C->comp_arena()) {
-
-  _phantom_object = C->top()->_idx,
-  add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true);
-
+  // Add unknown java object.
+  add_java_object(C->top(), PointsToNode::GlobalEscape);
+  phantom_obj = ptnode_adr(C->top()->_idx)->as_JavaObject();
   // Add ConP(#NULL) and ConN(#NULL) nodes.
   Node* oop_null = igvn->zerocon(T_OBJECT);
-  _oop_null = oop_null->_idx;
-  assert(_oop_null < nodes_size(), "should be created already");
-  add_node(oop_null, PointsToNode::JavaObject, PointsToNode::NoEscape, true);
-
+  assert(oop_null->_idx < nodes_size(), "should be created already");
+  add_java_object(oop_null, PointsToNode::NoEscape);
+  null_obj = ptnode_adr(oop_null->_idx)->as_JavaObject();
   if (UseCompressedOops) {
     Node* noop_null = igvn->zerocon(T_NARROWOOP);
-    _noop_null = noop_null->_idx;
-    assert(_noop_null < nodes_size(), "should be created already");
-    add_node(noop_null, PointsToNode::JavaObject, PointsToNode::NoEscape, true);
-  } else {
-    _noop_null = _oop_null; // Should be initialized
+    assert(noop_null->_idx < nodes_size(), "should be created already");
+    map_ideal_node(noop_null, null_obj);
   }
   _pcmp_neq = NULL; // Should be initialized
   _pcmp_eq  = NULL;
 }
 
-void ConnectionGraph::add_pointsto_edge(uint from_i, uint to_i) {
-  PointsToNode *f = ptnode_adr(from_i);
-  PointsToNode *t = ptnode_adr(to_i);
+bool ConnectionGraph::has_candidates(Compile *C) {
+  // EA brings benefits only when the code has allocations and/or locks which
+  // are represented by ideal Macro nodes.
+  int cnt = C->macro_count();
+  for( int i=0; i < cnt; i++ ) {
+    Node *n = C->macro_node(i);
+    if ( n->is_Allocate() )
+      return true;
+    if( n->is_Lock() ) {
+      Node* obj = n->as_Lock()->obj_node()->uncast();
+      if( !(obj->is_Parm() || obj->is_Con()) )
+        return true;
+    }
+  }
+  return false;
+}
+
+void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
+  Compile::TracePhase t2("escapeAnalysis", &Phase::_t_escapeAnalysis, true);
+  ResourceMark rm;
+
+  // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction
+  // to create space for them in ConnectionGraph::_nodes[].
+  Node* oop_null = igvn->zerocon(T_OBJECT);
+  Node* noop_null = igvn->zerocon(T_NARROWOOP);
+  ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
+  // Perform escape analysis
+  if (congraph->compute_escape()) {
+    // There are non escaping objects.
+    C->set_congraph(congraph);
+  }
+  // Cleanup.
+  if (oop_null->outcnt() == 0)
+    igvn->hash_delete(oop_null);
+  if (noop_null->outcnt() == 0)
+    igvn->hash_delete(noop_null);
+}
+
+bool ConnectionGraph::compute_escape() {
+  Compile* C = _compile;
+  PhaseGVN* igvn = _igvn;
+
+  // Worklists used by EA.
+  Unique_Node_List delayed_worklist;
+  GrowableArray<Node*> alloc_worklist;
+  GrowableArray<Node*> ptr_cmp_worklist;
+  GrowableArray<Node*> storestore_worklist;
+  GrowableArray<PointsToNode*>   ptnodes_worklist;
+  GrowableArray<JavaObjectNode*> java_objects_worklist;
+  GrowableArray<JavaObjectNode*> non_escaped_worklist;
+  GrowableArray<FieldNode*>      oop_fields_worklist;
+  DEBUG_ONLY( GrowableArray<Node*> addp_worklist; )
+
+  { Compile::TracePhase t3("connectionGraph", &Phase::_t_connectionGraph, true);
+
+  // 1. Populate Connection Graph (CG) with PointsTo nodes.
+  ideal_nodes.map(C->unique(), NULL);  // preallocate space
+  // Initialize worklist
+  if (C->root() != NULL) {
+    ideal_nodes.push(C->root());
+  }
+  for( uint next = 0; next < ideal_nodes.size(); ++next ) {
+    Node* n = ideal_nodes.at(next);
+    // Create PointsTo nodes and add them to Connection Graph. Called
+    // only once per ideal node since ideal_nodes is Unique_Node list.
+    add_node_to_connection_graph(n, &delayed_worklist);
+    PointsToNode* ptn = ptnode_adr(n->_idx);
+    if (ptn != NULL) {
+      ptnodes_worklist.append(ptn);
+      if (ptn->is_JavaObject()) {
+        java_objects_worklist.append(ptn->as_JavaObject());
+        if ((n->is_Allocate() || n->is_CallStaticJava()) &&
+            (ptn->escape_state() < PointsToNode::GlobalEscape)) {
+          // Only allocations and java static calls results are interesting.
+          non_escaped_worklist.append(ptn->as_JavaObject());
+        }
+      } else if (ptn->is_Field() && ptn->as_Field()->is_oop()) {
+        oop_fields_worklist.append(ptn->as_Field());
+      }
+    }
+    if (n->is_MergeMem()) {
+      // Collect all MergeMem nodes to add memory slices for
+      // scalar replaceable objects in split_unique_types().
+      _mergemem_worklist.append(n->as_MergeMem());
+    } else if (OptimizePtrCompare && n->is_Cmp() &&
+               (n->Opcode() == Op_CmpP || n->Opcode() == Op_CmpN)) {
+      // Collect compare pointers nodes.
+      ptr_cmp_worklist.append(n);
+    } else if (n->is_MemBarStoreStore()) {
+      // Collect all MemBarStoreStore nodes so that depending on the
+      // escape status of the associated Allocate node some of them
+      // may be eliminated.
+      storestore_worklist.append(n);
+#ifdef ASSERT
+    } else if(n->is_AddP()) {
+      // Collect address nodes for graph verification.
+      addp_worklist.append(n);
+#endif
+    }
+    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+      Node* m = n->fast_out(i);   // Get user
+      ideal_nodes.push(m);
+    }
+  }
+  if (non_escaped_worklist.length() == 0) {
+    _collecting = false;
+    return false; // Nothing to do.
+  }
+  // Add final simple edges to graph.
+  while(delayed_worklist.size() > 0) {
+    Node* n = delayed_worklist.pop();
+    add_final_edges(n);
+  }
+  int ptnodes_length = ptnodes_worklist.length();
+
+#ifdef ASSERT
+  if (VerifyConnectionGraph) {
+    // Verify that no new simple edges could be created and all
+    // local vars has edges.
+    _verify = true;
+    for (int next = 0; next < ptnodes_length; ++next) {
+      PointsToNode* ptn = ptnodes_worklist.at(next);
+      add_final_edges(ptn->ideal_node());
+      if (ptn->is_LocalVar() && ptn->edge_count() == 0) {
+        ptn->dump();
+        assert(ptn->as_LocalVar()->edge_count() > 0, "sanity");
+      }
+    }
+    _verify = false;
+  }
+#endif
+
+  // 2. Finish Graph construction by propagating references to all
+  //    java objects through graph.
+  if (!complete_connection_graph(ptnodes_worklist, non_escaped_worklist,
+                                 java_objects_worklist, oop_fields_worklist)) {
+    // All objects escaped or hit time or iterations limits.
+    _collecting = false;
+    return false;
+  }
+
+  // 3. Adjust scalar_replaceable state of nonescaping objects and push
+  //    scalar replaceable allocations on alloc_worklist for processing
+  //    in split_unique_types().
+  int non_escaped_length = non_escaped_worklist.length();
+  for (int next = 0; next < non_escaped_length; next++) {
+    JavaObjectNode* ptn = non_escaped_worklist.at(next);
+    if (ptn->escape_state() == PointsToNode::NoEscape &&
+        ptn->scalar_replaceable()) {
+      adjust_scalar_replaceable_state(ptn);
+      if (ptn->scalar_replaceable()) {
+        alloc_worklist.append(ptn->ideal_node());
+      }
+    }
+  }
+
+#ifdef ASSERT
+  if (VerifyConnectionGraph) {
+    // Verify that graph is complete - no new edges could be added or needed.
+    verify_connection_graph(ptnodes_worklist, non_escaped_worklist,
+                            java_objects_worklist, addp_worklist);
+  }
+  assert(C->unique() == nodes_size(), "no new ideal nodes should be added during ConnectionGraph build");
+  assert(null_obj->escape_state() == PointsToNode::NoEscape &&
+         null_obj->edge_count() == 0 &&
+         !null_obj->arraycopy_src() &&
+         !null_obj->arraycopy_dst(), "sanity");
+#endif
+
+  _collecting = false;
+
+  } // TracePhase t3("connectionGraph")
+
+  // 4. Optimize ideal graph based on EA information.
+  bool has_non_escaping_obj = (non_escaped_worklist.length() > 0);
+  if (has_non_escaping_obj) {
+    optimize_ideal_graph(ptr_cmp_worklist, storestore_worklist);
+  }
+
+#ifndef PRODUCT
+  if (PrintEscapeAnalysis) {
+    dump(ptnodes_worklist); // Dump ConnectionGraph
+  }
+#endif
+
+  bool has_scalar_replaceable_candidates = (alloc_worklist.length() > 0);
+#ifdef ASSERT
+  if (VerifyConnectionGraph) {
+    int alloc_length = alloc_worklist.length();
+    for (int next = 0; next < alloc_length; ++next) {
+      Node* n = alloc_worklist.at(next);
+      PointsToNode* ptn = ptnode_adr(n->_idx);
+      assert(ptn->escape_state() == PointsToNode::NoEscape && ptn->scalar_replaceable(), "sanity");
+    }
+  }
+#endif
+
+  // 5. Separate memory graph for scalar replaceable allcations.
+  if (has_scalar_replaceable_candidates &&
+      C->AliasLevel() >= 3 && EliminateAllocations) {
+    // Now use the escape information to create unique types for
+    // scalar replaceable objects.
+    split_unique_types(alloc_worklist);
+    if (C->failing())  return false;
+    C->print_method("After Escape Analysis", 2);
+
+#ifdef ASSERT
+  } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) {
+    tty->print("=== No allocations eliminated for ");
+    C->method()->print_short_name();
+    if(!EliminateAllocations) {
+      tty->print(" since EliminateAllocations is off ===");
+    } else if(!has_scalar_replaceable_candidates) {
+      tty->print(" since there are no scalar replaceable candidates ===");
+    } else if(C->AliasLevel() < 3) {
+      tty->print(" since AliasLevel < 3 ===");
+    }
+    tty->cr();
+#endif
+  }
+  return has_non_escaping_obj;
+}
+
+// Populate Connection Graph with PointsTo nodes and create simple
+// connection graph edges.
+void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
+  assert(!_verify, "this method sould not be called for verification");
+  PhaseGVN* igvn = _igvn;
+  uint n_idx = n->_idx;
+  PointsToNode* n_ptn = ptnode_adr(n_idx);
+  if (n_ptn != NULL)
+    return; // No need to redefine PointsTo node during first iteration.
+
+  if (n->is_Call()) {
+    // Arguments to allocation and locking don't escape.
+    if (n->is_AbstractLock()) {
+      // Put Lock and Unlock nodes on IGVN worklist to process them during
+      // first IGVN optimization when escape information is still available.
+      record_for_optimizer(n);
+    } else if (n->is_Allocate()) {
+      add_call_node(n->as_Call());
+      record_for_optimizer(n);
+    } else {
+      if (n->is_CallStaticJava()) {
+        const char* name = n->as_CallStaticJava()->_name;
+        if (name != NULL && strcmp(name, "uncommon_trap") == 0)
+          return; // Skip uncommon traps
+      }
+      // Don't mark as processed since call's arguments have to be processed.
+      delayed_worklist->push(n);
+      // Check if a call returns an object.
+      if (n->as_Call()->returns_pointer() &&
+          n->as_Call()->proj_out(TypeFunc::Parms) != NULL) {
+        add_call_node(n->as_Call());
+      }
+    }
+    return;
+  }
+  // Put this check here to process call arguments since some call nodes
+  // point to phantom_obj.
+  if (n_ptn == phantom_obj || n_ptn == null_obj)
+    return; // Skip predefined nodes.
 
-  assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
-  assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of PointsTo edge");
-  assert(t->node_type() == PointsToNode::JavaObject, "invalid destination of PointsTo edge");
-  if (to_i == _phantom_object) { // Quick test for most common object
-    if (f->has_unknown_ptr()) {
-      return;
+  int opcode = n->Opcode();
+  switch (opcode) {
+    case Op_AddP: {
+      Node* base = get_addp_base(n);
+      PointsToNode* ptn_base = ptnode_adr(base->_idx);
+      // Field nodes are created for all field types. They are used in
+      // adjust_scalar_replaceable_state() and split_unique_types().
+      // Note, non-oop fields will have only base edges in Connection
+      // Graph because such fields are not used for oop loads and stores.
+      int offset = address_offset(n, igvn);
+      add_field(n, PointsToNode::NoEscape, offset);
+      if (ptn_base == NULL) {
+        delayed_worklist->push(n); // Process it later.
+      } else {
+        n_ptn = ptnode_adr(n_idx);
+        add_base(n_ptn->as_Field(), ptn_base);
+      }
+      break;
+    }
+    case Op_CastX2P: {
+      map_ideal_node(n, phantom_obj);
+      break;
+    }
+    case Op_CastPP:
+    case Op_CheckCastPP:
+    case Op_EncodeP:
+    case Op_DecodeN: {
+      add_local_var_and_edge(n, PointsToNode::NoEscape,
+                             n->in(1), delayed_worklist);
+      break;
+    }
+    case Op_CMoveP: {
+      add_local_var(n, PointsToNode::NoEscape);
+      // Do not add edges during first iteration because some could be
+      // not defined yet.
+      delayed_worklist->push(n);
+      break;
+    }
+    case Op_ConP:
+    case Op_ConN: {
+      // assume all oop constants globally escape except for null
+      PointsToNode::EscapeState es;
+      if (igvn->type(n) == TypePtr::NULL_PTR ||
+          igvn->type(n) == TypeNarrowOop::NULL_PTR) {
+        es = PointsToNode::NoEscape;
+      } else {
+        es = PointsToNode::GlobalEscape;
+      }
+      add_java_object(n, es);
+      break;
+    }
+    case Op_CreateEx: {
+      // assume that all exception objects globally escape
+      add_java_object(n, PointsToNode::GlobalEscape);
+      break;
+    }
+    case Op_LoadKlass:
+    case Op_LoadNKlass: {
+      // Unknown class is loaded
+      map_ideal_node(n, phantom_obj);
+      break;
+    }
+    case Op_LoadP:
+    case Op_LoadN:
+    case Op_LoadPLocked: {
+      // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
+      // ThreadLocal has RawPrt type.
+      const Type* t = igvn->type(n);
+      if (t->make_ptr() != NULL) {
+        Node* adr = n->in(MemNode::Address);
+#ifdef ASSERT
+        if (!adr->is_AddP()) {
+          assert(igvn->type(adr)->isa_rawptr(), "sanity");
+        } else {
+          assert((ptnode_adr(adr->_idx) == NULL ||
+                  ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
+        }
+#endif
+        add_local_var_and_edge(n, PointsToNode::NoEscape,
+                               adr, delayed_worklist);
+      }
+      break;
+    }
+    case Op_Parm: {
+      map_ideal_node(n, phantom_obj);
+      break;
+    }
+    case Op_PartialSubtypeCheck: {
+      // Produces Null or notNull and is used in only in CmpP so
+      // phantom_obj could be used.
+      map_ideal_node(n, phantom_obj); // Result is unknown
+      break;
+    }
+    case Op_Phi: {
+      // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
+      // ThreadLocal has RawPrt type.
+      const Type* t = n->as_Phi()->type();
+      if (t->make_ptr() != NULL) {
+        add_local_var(n, PointsToNode::NoEscape);
+        // Do not add edges during first iteration because some could be
+        // not defined yet.
+        delayed_worklist->push(n);
+      }
+      break;
+    }
+    case Op_Proj: {
+      // we are only interested in the oop result projection from a call
+      if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() &&
+          n->in(0)->as_Call()->returns_pointer()) {
+        add_local_var_and_edge(n, PointsToNode::NoEscape,
+                               n->in(0), delayed_worklist);
+      }
+      break;
+    }
+    case Op_Rethrow: // Exception object escapes
+    case Op_Return: {
+      if (n->req() > TypeFunc::Parms &&
+          igvn->type(n->in(TypeFunc::Parms))->isa_oopptr()) {
+        // Treat Return value as LocalVar with GlobalEscape escape state.
+        add_local_var_and_edge(n, PointsToNode::GlobalEscape,
+                               n->in(TypeFunc::Parms), delayed_worklist);
+      }
+      break;
+    }
+    case Op_StoreP:
+    case Op_StoreN:
+    case Op_StorePConditional:
+    case Op_CompareAndSwapP:
+    case Op_CompareAndSwapN: {
+      Node* adr = n->in(MemNode::Address);
+      const Type *adr_type = igvn->type(adr);
+      adr_type = adr_type->make_ptr();
+      if (adr_type->isa_oopptr() ||
+          (opcode == Op_StoreP || opcode == Op_StoreN) &&
+                        (adr_type == TypeRawPtr::NOTNULL &&
+                         adr->in(AddPNode::Address)->is_Proj() &&
+                         adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
+        delayed_worklist->push(n); // Process it later.
+#ifdef ASSERT
+        assert(adr->is_AddP(), "expecting an AddP");
+        if (adr_type == TypeRawPtr::NOTNULL) {
+          // Verify a raw address for a store captured by Initialize node.
+          int offs = (int)igvn->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
+          assert(offs != Type::OffsetBot, "offset must be a constant");
+        }
+#endif
+      } else {
+        // Ignore copy the displaced header to the BoxNode (OSR compilation).
+        if (adr->is_BoxLock())
+          break;
+        // Stored value escapes in unsafe access.
+        if ((opcode == Op_StoreP) && (adr_type == TypeRawPtr::BOTTOM)) {
+          // Pointer stores in G1 barriers looks like unsafe access.
+          // Ignore such stores to be able scalar replace non-escaping
+          // allocations.
+          if (UseG1GC && adr->is_AddP()) {
+            Node* base = get_addp_base(adr);
+            if (base->Opcode() == Op_LoadP &&
+                base->in(MemNode::Address)->is_AddP()) {
+              adr = base->in(MemNode::Address);
+              Node* tls = get_addp_base(adr);
+              if (tls->Opcode() == Op_ThreadLocal) {
+                int offs = (int)igvn->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
+                if (offs == in_bytes(JavaThread::satb_mark_queue_offset() +
+                                     PtrQueue::byte_offset_of_buf())) {
+                  break; // G1 pre barier previous oop value store.
+                }
+                if (offs == in_bytes(JavaThread::dirty_card_queue_offset() +
+                                     PtrQueue::byte_offset_of_buf())) {
+                  break; // G1 post barier card address store.
+                }
+              }
+            }
+          }
+          delayed_worklist->push(n); // Process unsafe access later.
+          break;
+        }
+#ifdef ASSERT
+        n->dump(1);
+        assert(false, "not unsafe or G1 barrier raw StoreP");
+#endif
+      }
+      break;
+    }
+    case Op_AryEq:
+    case Op_StrComp:
+    case Op_StrEquals:
+    case Op_StrIndexOf: {
+      add_local_var(n, PointsToNode::ArgEscape);
+      delayed_worklist->push(n); // Process it later.
+      break;
+    }
+    case Op_ThreadLocal: {
+      add_java_object(n, PointsToNode::ArgEscape);
+      break;
+    }
+    default:
+      ; // Do nothing for nodes not related to EA.
+  }
+  return;
+}
+
+#ifdef ASSERT
+#define ELSE_FAIL(name)                               \
+      /* Should not be called for not pointer type. */  \
+      n->dump(1);                                       \
+      assert(false, name);                              \
+      break;
+#else
+#define ELSE_FAIL(name) \
+      break;
+#endif
+
+// Add final simple edges to graph.
+void ConnectionGraph::add_final_edges(Node *n) {
+  PointsToNode* n_ptn = ptnode_adr(n->_idx);
+#ifdef ASSERT
+  if (_verify && n_ptn->is_JavaObject())
+    return; // This method does not change graph for JavaObject.
+#endif
+
+  if (n->is_Call()) {
+    process_call_arguments(n->as_Call());
+    return;
+  }
+  assert(n->is_Store() || n->is_LoadStore() ||
+         (n_ptn != NULL) && (n_ptn->ideal_node() != NULL),
+         "node should be registered already");
+  int opcode = n->Opcode();
+  switch (opcode) {
+    case Op_AddP: {
+      Node* base = get_addp_base(n);
+      PointsToNode* ptn_base = ptnode_adr(base->_idx);
+      assert(ptn_base != NULL, "field's base should be registered");
+      add_base(n_ptn->as_Field(), ptn_base);
+      break;
+    }
+    case Op_CastPP:
+    case Op_CheckCastPP:
+    case Op_EncodeP:
+    case Op_DecodeN: {
+      add_local_var_and_edge(n, PointsToNode::NoEscape,
+                             n->in(1), NULL);
+      break;
+    }
+    case Op_CMoveP: {
+      for (uint i = CMoveNode::IfFalse; i < n->req(); i++) {
+        Node* in = n->in(i);
+        if (in == NULL)
+          continue;  // ignore NULL
+        Node* uncast_in = in->uncast();
+        if (uncast_in->is_top() || uncast_in == n)
+          continue;  // ignore top or inputs which go back this node
+        PointsToNode* ptn = ptnode_adr(in->_idx);
+        assert(ptn != NULL, "node should be registered");
+        add_edge(n_ptn, ptn);
+      }
+      break;
+    }
+    case Op_LoadP:
+    case Op_LoadN:
+    case Op_LoadPLocked: {
+      // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
+      // ThreadLocal has RawPrt type.
+      const Type* t = _igvn->type(n);
+      if (t->make_ptr() != NULL) {
+        Node* adr = n->in(MemNode::Address);
+        add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL);
+        break;
+      }
+      ELSE_FAIL("Op_LoadP");
+    }
+    case Op_Phi: {
+      // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
+      // ThreadLocal has RawPrt type.
+      const Type* t = n->as_Phi()->type();
+      if (t->make_ptr() != NULL) {
+        for (uint i = 1; i < n->req(); i++) {
+          Node* in = n->in(i);
+          if (in == NULL)
+            continue;  // ignore NULL
+          Node* uncast_in = in->uncast();
+          if (uncast_in->is_top() || uncast_in == n)
+            continue;  // ignore top or inputs which go back this node
+          PointsToNode* ptn = ptnode_adr(in->_idx);
+          assert(ptn != NULL, "node should be registered");
+          add_edge(n_ptn, ptn);
+        }
+        break;
+      }
+      ELSE_FAIL("Op_Phi");
+    }
+    case Op_Proj: {
+      // we are only interested in the oop result projection from a call
+      if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() &&
+          n->in(0)->as_Call()->returns_pointer()) {
+        add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(0), NULL);
+        break;
+      }
+      ELSE_FAIL("Op_Proj");
+    }
+    case Op_Rethrow: // Exception object escapes
+    case Op_Return: {
+      if (n->req() > TypeFunc::Parms &&
+          _igvn->type(n->in(TypeFunc::Parms))->isa_oopptr()) {
+        // Treat Return value as LocalVar with GlobalEscape escape state.
+        add_local_var_and_edge(n, PointsToNode::GlobalEscape,
+                               n->in(TypeFunc::Parms), NULL);
+        break;
+      }
+      ELSE_FAIL("Op_Return");
+    }
+    case Op_StoreP:
+    case Op_StoreN:
+    case Op_StorePConditional:
+    case Op_CompareAndSwapP:
+    case Op_CompareAndSwapN: {
+      Node* adr = n->in(MemNode::Address);
+      const Type *adr_type = _igvn->type(adr);
+      adr_type = adr_type->make_ptr();
+      if (adr_type->isa_oopptr() ||
+          (opcode == Op_StoreP || opcode == Op_StoreN) &&
+                        (adr_type == TypeRawPtr::NOTNULL &&
+                         adr->in(AddPNode::Address)->is_Proj() &&
+                         adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
+        // Point Address to Value
+        PointsToNode* adr_ptn = ptnode_adr(adr->_idx);
+        assert(adr_ptn != NULL &&
+               adr_ptn->as_Field()->is_oop(), "node should be registered");
+        Node *val = n->in(MemNode::ValueIn);
+        PointsToNode* ptn = ptnode_adr(val->_idx);
+        assert(ptn != NULL, "node should be registered");
+        add_edge(adr_ptn, ptn);
+        break;
+      } else if ((opcode == Op_StoreP) && (adr_type == TypeRawPtr::BOTTOM)) {
+        // Stored value escapes in unsafe access.
+        Node *val = n->in(MemNode::ValueIn);
+        PointsToNode* ptn = ptnode_adr(val->_idx);
+        assert(ptn != NULL, "node should be registered");
+        ptn->set_escape_state(PointsToNode::GlobalEscape);
+        // Add edge to object for unsafe access with offset.
+        PointsToNode* adr_ptn = ptnode_adr(adr->_idx);
+        assert(adr_ptn != NULL, "node should be registered");
+        if (adr_ptn->is_Field()) {
+          assert(adr_ptn->as_Field()->is_oop(), "should be oop field");
+          add_edge(adr_ptn, ptn);
+        }
+        break;
+      }
+      ELSE_FAIL("Op_StoreP");
+    }
+    case Op_AryEq:
+    case Op_StrComp:
+    case Op_StrEquals:
+    case Op_StrIndexOf: {
+      // char[] arrays passed to string intrinsic do not escape but
+      // they are not scalar replaceable. Adjust escape state for them.
+      // Start from in(2) edge since in(1) is memory edge.
+      for (uint i = 2; i < n->req(); i++) {
+        Node* adr = n->in(i);
+        const Type* at = _igvn->type(adr);
+        if (!adr->is_top() && at->isa_ptr()) {
+          assert(at == Type::TOP || at == TypePtr::NULL_PTR ||
+                 at->isa_ptr() != NULL, "expecting a pointer");
+          if (adr->is_AddP()) {
+            adr = get_addp_base(adr);
+          }
+          PointsToNode* ptn = ptnode_adr(adr->_idx);
+          assert(ptn != NULL, "node should be registered");
+          add_edge(n_ptn, ptn);
+        }
+      }
+      break;
+    }
+    default: {
+      // This method should be called only for EA specific nodes which may
+      // miss some edges when they were created.
+#ifdef ASSERT
+      n->dump(1);
+#endif
+      guarantee(false, "unknown node");
+    }
+  }
+  return;
+}
+
+void ConnectionGraph::add_call_node(CallNode* call) {
+  assert(call->returns_pointer(), "only for call which returns pointer");
+  uint call_idx = call->_idx;
+  if (call->is_Allocate()) {
+    Node* k = call->in(AllocateNode::KlassNode);
+    const TypeKlassPtr* kt = k->bottom_type()->isa_klassptr();
+    assert(kt != NULL, "TypeKlassPtr  required.");
+    ciKlass* cik = kt->klass();
+    PointsToNode::EscapeState es = PointsToNode::NoEscape;
+    bool scalar_replaceable = true;
+    if (call->is_AllocateArray()) {
+      if (!cik->is_array_klass()) { // StressReflectiveCode
+        es = PointsToNode::GlobalEscape;
+      } else {
+        int length = call->in(AllocateNode::ALength)->find_int_con(-1);
+        if (length < 0 || length > EliminateAllocationArraySizeLimit) {
+          // Not scalar replaceable if the length is not constant or too big.
+          scalar_replaceable = false;
+        }
+      }
+    } else {  // Allocate instance
+      if (cik->is_subclass_of(_compile->env()->Thread_klass()) ||
+         !cik->is_instance_klass() || // StressReflectiveCode
+          cik->as_instance_klass()->has_finalizer()) {
+        es = PointsToNode::GlobalEscape;
+      }
+    }
+    add_java_object(call, es);
+    PointsToNode* ptn = ptnode_adr(call_idx);
+    if (!scalar_replaceable && ptn->scalar_replaceable()) {
+      ptn->set_scalar_replaceable(false);
+    }
+  } else if (call->is_CallStaticJava()) {
+    // Call nodes could be different types:
+    //
+    // 1. CallDynamicJavaNode (what happened during call is unknown):
+    //
+    //    - mapped to GlobalEscape JavaObject node if oop is returned;
+    //
+    //    - all oop arguments are escaping globally;
+    //
+    // 2. CallStaticJavaNode (execute bytecode analysis if possible):
+    //
+    //    - the same as CallDynamicJavaNode if can't do bytecode analysis;
+    //
+    //    - mapped to GlobalEscape JavaObject node if unknown oop is returned;
+    //    - mapped to NoEscape JavaObject node if non-escaping object allocated
+    //      during call is returned;
+    //    - mapped to ArgEscape LocalVar node pointed to object arguments
+    //      which are returned and does not escape during call;
+    //
+    //    - oop arguments escaping status is defined by bytecode analysis;
+    //
+    // For a static call, we know exactly what method is being called.
+    // Use bytecode estimator to record whether the call's return value escapes.
+    ciMethod* meth = call->as_CallJava()->method();
+    if (meth == NULL) {
+      const char* name = call->as_CallStaticJava()->_name;
+      assert(strncmp(name, "_multianewarray", 15) == 0, "TODO: add failed case check");
+      // Returns a newly allocated unescaped object.
+      add_java_object(call, PointsToNode::NoEscape);
+      ptnode_adr(call_idx)->set_scalar_replaceable(false);
     } else {
-      f->set_has_unknown_ptr();
+      BCEscapeAnalyzer* call_analyzer = meth->get_bcea();
+      call_analyzer->copy_dependencies(_compile->dependencies());
+      if (call_analyzer->is_return_allocated()) {
+        // Returns a newly allocated unescaped object, simply
+        // update dependency information.
+        // Mark it as NoEscape so that objects referenced by
+        // it's fields will be marked as NoEscape at least.
+        add_java_object(call, PointsToNode::NoEscape);
+        ptnode_adr(call_idx)->set_scalar_replaceable(false);
+      } else {
+        // Determine whether any arguments are returned.
+        const TypeTuple* d = call->tf()->domain();
+        bool ret_arg = false;
+        for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
+          if (d->field_at(i)->isa_ptr() != NULL &&
+              call_analyzer->is_arg_returned(i - TypeFunc::Parms)) {
+            ret_arg = true;
+            break;
+          }
+        }
+        if (ret_arg) {
+          add_local_var(call, PointsToNode::ArgEscape);
+        } else {
+          // Returns unknown object.
+          map_ideal_node(call, phantom_obj);
+        }
+      }
+    }
+  } else {
+    // An other type of call, assume the worst case:
+    // returned value is unknown and globally escapes.
+    assert(call->Opcode() == Op_CallDynamicJava, "add failed case check");
+    map_ideal_node(call, phantom_obj);
+  }
+}
+
+void ConnectionGraph::process_call_arguments(CallNode *call) {
+    bool is_arraycopy = false;
+    switch (call->Opcode()) {
+#ifdef ASSERT
+    case Op_Allocate:
+    case Op_AllocateArray:
+    case Op_Lock:
+    case Op_Unlock:
+      assert(false, "should be done already");
+      break;
+#endif
+    case Op_CallLeafNoFP:
+      is_arraycopy = (call->as_CallLeaf()->_name != NULL &&
+                      strstr(call->as_CallLeaf()->_name, "arraycopy") != 0);
+      // fall through
+    case Op_CallLeaf: {
+      // Stub calls, objects do not escape but they are not scale replaceable.
+      // Adjust escape state for outgoing arguments.
+      const TypeTuple * d = call->tf()->domain();
+      bool src_has_oops = false;
+      for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
+        const Type* at = d->field_at(i);
+        Node *arg = call->in(i);
+        const Type *aat = _igvn->type(arg);
+        if (arg->is_top() || !at->isa_ptr() || !aat->isa_ptr())
+          continue;
+        if (arg->is_AddP()) {
+          //
+          // The inline_native_clone() case when the arraycopy stub is called
+          // after the allocation before Initialize and CheckCastPP nodes.
+          // Or normal arraycopy for object arrays case.
+          //
+          // Set AddP's base (Allocate) as not scalar replaceable since
+          // pointer to the base (with offset) is passed as argument.
+          //
+          arg = get_addp_base(arg);
+        }
+        PointsToNode* arg_ptn = ptnode_adr(arg->_idx);
+        assert(arg_ptn != NULL, "should be registered");
+        PointsToNode::EscapeState arg_esc = arg_ptn->escape_state();
+        if (is_arraycopy || arg_esc < PointsToNode::ArgEscape) {
+          assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
+                 aat->isa_ptr() != NULL, "expecting an Ptr");
+          bool arg_has_oops = aat->isa_oopptr() &&
+                              (aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
+                               (aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
+          if (i == TypeFunc::Parms) {
+            src_has_oops = arg_has_oops;
+          }
+          //
+          // src or dst could be j.l.Object when other is basic type array:
+          //
+          //   arraycopy(char[],0,Object*,0,size);
+          //   arraycopy(Object*,0,char[],0,size);
+          //
+          // Don't add edges in such cases.
+          //
+          bool arg_is_arraycopy_dest = src_has_oops && is_arraycopy &&
+                                       arg_has_oops && (i > TypeFunc::Parms);
+#ifdef ASSERT
+          if (!(is_arraycopy ||
+                call->as_CallLeaf()->_name != NULL &&
+                (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre")  == 0 ||
+                 strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ))
+          ) {
+            call->dump();
+            assert(false, "EA: unexpected CallLeaf");
+          }
+#endif
+          // Always process arraycopy's destination object since
+          // we need to add all possible edges to references in
+          // source object.
+          if (arg_esc >= PointsToNode::ArgEscape &&
+              !arg_is_arraycopy_dest) {
+            continue;
+          }
+          set_escape_state(arg_ptn, PointsToNode::ArgEscape);
+          if (arg_is_arraycopy_dest) {
+            Node* src = call->in(TypeFunc::Parms);
+            if (src->is_AddP()) {
+              src = get_addp_base(src);
+            }
+            PointsToNode* src_ptn = ptnode_adr(src->_idx);
+            assert(src_ptn != NULL, "should be registered");
+            if (arg_ptn != src_ptn) {
+              // Special arraycopy edge:
+              // A destination object's field can't have the source object
+              // as base since objects escape states are not related.
+              // Only escape state of destination object's fields affects
+              // escape state of fields in source object.
+              add_arraycopy(call, PointsToNode::ArgEscape, src_ptn, arg_ptn);
+            }
+          }
+        }
+      }
+      break;
+    }
+    case Op_CallStaticJava: {
+      // For a static call, we know exactly what method is being called.
+      // Use bytecode estimator to record the call's escape affects
+#ifdef ASSERT
+      const char* name = call->as_CallStaticJava()->_name;
+      assert((name == NULL || strcmp(name, "uncommon_trap") != 0), "normal calls only");
+#endif
+      ciMethod* meth = call->as_CallJava()->method();
+      BCEscapeAnalyzer* call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL;
+      // fall-through if not a Java method or no analyzer information
+      if (call_analyzer != NULL) {
+        PointsToNode* call_ptn = ptnode_adr(call->_idx);
+        const TypeTuple* d = call->tf()->domain();
+        for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
+          const Type* at = d->field_at(i);
+          int k = i - TypeFunc::Parms;
+          Node* arg = call->in(i);
+          PointsToNode* arg_ptn = ptnode_adr(arg->_idx);
+          if (at->isa_ptr() != NULL &&
+              call_analyzer->is_arg_returned(k)) {
+            // The call returns arguments.
+            if (call_ptn != NULL) { // Is call's result used?
+              assert(call_ptn->is_LocalVar(), "node should be registered");
+              assert(arg_ptn != NULL, "node should be registered");
+              add_edge(call_ptn, arg_ptn);
+            }
+          }
+          if (at->isa_oopptr() != NULL &&
+              arg_ptn->escape_state() < PointsToNode::GlobalEscape) {
+            if (!call_analyzer->is_arg_stack(k)) {
+              // The argument global escapes
+              set_escape_state(arg_ptn, PointsToNode::GlobalEscape);
+            } else {
+              set_escape_state(arg_ptn, PointsToNode::ArgEscape);
+              if (!call_analyzer->is_arg_local(k)) {
+                // The argument itself doesn't escape, but any fields might
+                set_fields_escape_state(arg_ptn, PointsToNode::GlobalEscape);
+              }
+            }
+          }
+        }
+        if (call_ptn != NULL && call_ptn->is_LocalVar()) {
+          // The call returns arguments.
+          assert(call_ptn->edge_count() > 0, "sanity");
+          if (!call_analyzer->is_return_local()) {
+            // Returns also unknown object.
+            add_edge(call_ptn, phantom_obj);
+          }
+        }
+        break;
+      }
+    }
+    default: {
+      // Fall-through here if not a Java method or no analyzer information
+      // or some other type of call, assume the worst case: all arguments
+      // globally escape.
+      const TypeTuple* d = call->tf()->domain();
+      for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
+        const Type* at = d->field_at(i);
+        if (at->isa_oopptr() != NULL) {
+          Node* arg = call->in(i);
+          if (arg->is_AddP()) {
+            arg = get_addp_base(arg);
+          }
+          assert(ptnode_adr(arg->_idx) != NULL, "should be defined already");
+          set_escape_state(ptnode_adr(arg->_idx), PointsToNode::GlobalEscape);
+        }
+      }
     }
   }
-  add_edge(f, to_i, PointsToNode::PointsToEdge);
+}
+
+
+// Finish Graph construction.
+bool ConnectionGraph::complete_connection_graph(
+                         GrowableArray<PointsToNode*>&   ptnodes_worklist,
+                         GrowableArray<JavaObjectNode*>& non_escaped_worklist,
+                         GrowableArray<JavaObjectNode*>& java_objects_worklist,
+                         GrowableArray<FieldNode*>&      oop_fields_worklist) {
+  // Normally only 1-3 passes needed to build Connection Graph depending
+  // on graph complexity. Observed 8 passes in jvm2008 compiler.compiler.
+  // Set limit to 20 to catch situation when something did go wrong and
+  // bailout Escape Analysis.
+  // Also limit build time to 30 sec (60 in debug VM).
+#define CG_BUILD_ITER_LIMIT 20
+#ifdef ASSERT
+#define CG_BUILD_TIME_LIMIT 60.0
+#else
+#define CG_BUILD_TIME_LIMIT 30.0
+#endif
+
+  // Propagate GlobalEscape and ArgEscape escape states and check that
+  // we still have non-escaping objects. The method pushs on _worklist
+  // Field nodes which reference phantom_object.
+  if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) {
+    return false; // Nothing to do.
+  }
+  // Now propagate references to all JavaObject nodes.
+  int java_objects_length = java_objects_worklist.length();
+  elapsedTimer time;
+  int new_edges = 1;
+  int iterations = 0;
+  do {
+    while ((new_edges > 0) &&
+          (iterations++   < CG_BUILD_ITER_LIMIT) &&
+          (time.seconds() < CG_BUILD_TIME_LIMIT)) {
+      time.start();
+      new_edges = 0;
+      // Propagate references to phantom_object for nodes pushed on _worklist
+      // by find_non_escaped_objects() and find_field_value().
+      new_edges += add_java_object_edges(phantom_obj, false);
+      for (int next = 0; next < java_objects_length; ++next) {
+        JavaObjectNode* ptn = java_objects_worklist.at(next);
+        new_edges += add_java_object_edges(ptn, true);
+      }
+      if (new_edges > 0) {
+        // Update escape states on each iteration if graph was updated.
+        if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) {
+          return false; // Nothing to do.
+        }
+      }
+      time.stop();
+    }
+    if ((iterations     < CG_BUILD_ITER_LIMIT) &&
+        (time.seconds() < CG_BUILD_TIME_LIMIT)) {
+      time.start();
+      // Find fields which have unknown value.
+      int fields_length = oop_fields_worklist.length();
+      for (int next = 0; next < fields_length; next++) {
+        FieldNode* field = oop_fields_worklist.at(next);
+        if (field->edge_count() == 0) {
+          new_edges += find_field_value(field);
+          // This code may added new edges to phantom_object.
+          // Need an other cycle to propagate references to phantom_object.
+        }
+      }
+      time.stop();
+    } else {
+      new_edges = 0; // Bailout
+    }
+  } while (new_edges > 0);
+
+  // Bailout if passed limits.
+  if ((iterations     >= CG_BUILD_ITER_LIMIT) ||
+      (time.seconds() >= CG_BUILD_TIME_LIMIT)) {
+    Compile* C = _compile;
+    if (C->log() != NULL) {
+      C->log()->begin_elem("connectionGraph_bailout reason='reached ");
+      C->log()->text("%s", (iterations >= CG_BUILD_ITER_LIMIT) ? "iterations" : "time");
+      C->log()->end_elem(" limit'");
+    }
+    assert(false, err_msg("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
+           time.seconds(), iterations, nodes_size(), ptnodes_worklist.length()));
+    // Possible infinite build_connection_graph loop,
+    // bailout (no changes to ideal graph were made).
+    return false;
+  }
+#ifdef ASSERT
+  if (Verbose && PrintEscapeAnalysis) {
+    tty->print_cr("EA: %d iterations to build connection graph with %d nodes and worklist size %d",
+                  iterations, nodes_size(), ptnodes_worklist.length());
+  }
+#endif
+
+#undef CG_BUILD_ITER_LIMIT
+#undef CG_BUILD_TIME_LIMIT
+
+  // Find fields initialized by NULL for non-escaping Allocations.
+  int non_escaped_length = non_escaped_worklist.length();
+  for (int next = 0; next < non_escaped_length; next++) {
+    JavaObjectNode* ptn = non_escaped_worklist.at(next);
+    PointsToNode::EscapeState es = ptn->escape_state();
+    assert(es <= PointsToNode::ArgEscape, "sanity");
+    if (es == PointsToNode::NoEscape) {
+      if (find_init_values(ptn, null_obj, _igvn) > 0) {
+        // Adding references to NULL object does not change escape states
+        // since it does not escape. Also no fields are added to NULL object.
+        add_java_object_edges(null_obj, false);
+      }
+    }
+    Node* n = ptn->ideal_node();
+    if (n->is_Allocate()) {
+      // The object allocated by this Allocate node will never be
+      // seen by an other thread. Mark it so that when it is
+      // expanded no MemBarStoreStore is added.
+      InitializeNode* ini = n->as_Allocate()->initialization();
+      if (ini != NULL)
+        ini->set_does_not_escape();
+    }
+  }
+  return true; // Finished graph construction.
+}
+
+// Propagate GlobalEscape and ArgEscape escape states to all nodes
+// and check that we still have non-escaping java objects.
+bool ConnectionGraph::find_non_escaped_objects(GrowableArray<PointsToNode*>& ptnodes_worklist,
+                                               GrowableArray<JavaObjectNode*>& non_escaped_worklist) {
+  GrowableArray<PointsToNode*> escape_worklist;
+  // First, put all nodes with GlobalEscape and ArgEscape states on worklist.
+  int ptnodes_length = ptnodes_worklist.length();
+  for (int next = 0; next < ptnodes_length; ++next) {
+    PointsToNode* ptn = ptnodes_worklist.at(next);
+    if (ptn->escape_state() >= PointsToNode::ArgEscape ||
+        ptn->fields_escape_state() >= PointsToNode::ArgEscape) {
+      escape_worklist.push(ptn);
+    }
+  }
+  // Set escape states to referenced nodes (edges list).
+  while (escape_worklist.length() > 0) {
+    PointsToNode* ptn = escape_worklist.pop();
+    PointsToNode::EscapeState es  = ptn->escape_state();
+    PointsToNode::EscapeState field_es = ptn->fields_escape_state();
+    if (ptn->is_Field() && ptn->as_Field()->is_oop() &&
+        es >= PointsToNode::ArgEscape) {
+      // GlobalEscape or ArgEscape state of field means it has unknown value.
+      if (add_edge(ptn, phantom_obj)) {
+        // New edge was added
+        add_field_uses_to_worklist(ptn->as_Field());
+      }
+    }
+    for (EdgeIterator i(ptn); i.has_next(); i.next()) {
+      PointsToNode* e = i.get();
+      if (e->is_Arraycopy()) {
+        assert(ptn->arraycopy_dst(), "sanity");
+        // Propagate only fields escape state through arraycopy edge.
+        if (e->fields_escape_state() < field_es) {
+          set_fields_escape_state(e, field_es);
+          escape_worklist.push(e);
+        }
+      } else if (es >= field_es) {
+        // fields_escape_state is also set to 'es' if it is less than 'es'.
+        if (e->escape_state() < es) {
+          set_escape_state(e, es);
+          escape_worklist.push(e);
+        }
+      } else {
+        // Propagate field escape state.
+        bool es_changed = false;
+        if (e->fields_escape_state() < field_es) {
+          set_fields_escape_state(e, field_es);
+          es_changed = true;
+        }
+        if ((e->escape_state() < field_es) &&
+            e->is_Field() && ptn->is_JavaObject() &&
+            e->as_Field()->is_oop()) {
+          // Change escape state of referenced fileds.
+          set_escape_state(e, field_es);
+          es_changed = true;;
+        } else if (e->escape_state() < es) {
+          set_escape_state(e, es);
+          es_changed = true;;
+        }
+        if (es_changed) {
+          escape_worklist.push(e);
+        }
+      }
+    }
+  }
+  // Remove escaped objects from non_escaped list.
+  for (int next = non_escaped_worklist.length()-1; next >= 0 ; --next) {
+    JavaObjectNode* ptn = non_escaped_worklist.at(next);
+    if (ptn->escape_state() >= PointsToNode::GlobalEscape) {
+      non_escaped_worklist.delete_at(next);
+    }
+    if (ptn->escape_state() == PointsToNode::NoEscape) {
+      // Find fields in non-escaped allocations which have unknown value.
+      find_init_values(ptn, phantom_obj, NULL);
+    }
+  }
+  return (non_escaped_worklist.length() > 0);
+}
+
+// Add all references to JavaObject node by walking over all uses.
+int ConnectionGraph::add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist) {
+  int new_edges = 0;
+  if (populate_worklist) {
+    // Populate _worklist by uses of jobj's uses.
+    for (UseIterator i(jobj); i.has_next(); i.next()) {
+      PointsToNode* use = i.get();
+      if (use->is_Arraycopy())
+        continue;
+      add_uses_to_worklist(use);
+      if (use->is_Field() && use->as_Field()->is_oop()) {
+        // Put on worklist all field's uses (loads) and
+        // related field nodes (same base and offset).
+        add_field_uses_to_worklist(use->as_Field());
+      }
+    }
+  }
+  while(_worklist.length() > 0) {
+    PointsToNode* use = _worklist.pop();
+    if (PointsToNode::is_base_use(use)) {
+      // Add reference from jobj to field and from field to jobj (field's base).
+      use = PointsToNode::get_use_node(use)->as_Field();
+      if (add_base(use->as_Field(), jobj)) {
+        new_edges++;
+      }
+      continue;
+    }
+    assert(!use->is_JavaObject(), "sanity");
+    if (use->is_Arraycopy()) {
+      if (jobj == null_obj) // NULL object does not have field edges
+        continue;
+      // Added edge from Arraycopy node to arraycopy's source java object
+      if (add_edge(use, jobj)) {
+        jobj->set_arraycopy_src();
+        new_edges++;
+      }
+      // and stop here.
+      continue;
+    }
+    if (!add_edge(use, jobj))
+      continue; // No new edge added, there was such edge already.
+    new_edges++;
+    if (use->is_LocalVar()) {
+      add_uses_to_worklist(use);
+      if (use->arraycopy_dst()) {
+        for (EdgeIterator i(use); i.has_next(); i.next()) {
+          PointsToNode* e = i.get();
+          if (e->is_Arraycopy()) {
+            if (jobj == null_obj) // NULL object does not have field edges
+              continue;
+            // Add edge from arraycopy's destination java object to Arraycopy node.
+            if (add_edge(jobj, e)) {
+              new_edges++;
+              jobj->set_arraycopy_dst();
+            }
+          }
+        }
+      }
+    } else {
+      // Added new edge to stored in field values.
+      // Put on worklist all field's uses (loads) and
+      // related field nodes (same base and offset).
+      add_field_uses_to_worklist(use->as_Field());
+    }
+  }
+  return new_edges;
+}
+
+// Put on worklist all related field nodes.
+void ConnectionGraph::add_field_uses_to_worklist(FieldNode* field) {
+  assert(field->is_oop(), "sanity");
+  int offset = field->offset();
+  add_uses_to_worklist(field);
+  // Loop over all bases of this field and push on worklist Field nodes
+  // with the same offset and base (since they may reference the same field).
+  for (BaseIterator i(field); i.has_next(); i.next()) {
+    PointsToNode* base = i.get();
+    add_fields_to_worklist(field, base);
+    // Check if the base was source object of arraycopy and go over arraycopy's
+    // destination objects since values stored to a field of source object are
+    // accessable by uses (loads) of fields of destination objects.
+    if (base->arraycopy_src()) {
+      for (UseIterator j(base); j.has_next(); j.next()) {
+        PointsToNode* arycp = j.get();
+        if (arycp->is_Arraycopy()) {
+          for (UseIterator k(arycp); k.has_next(); k.next()) {
+            PointsToNode* abase = k.get();
+            if (abase->arraycopy_dst() && abase != base) {
+              // Look for the same arracopy reference.
+              add_fields_to_worklist(field, abase);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+// Put on worklist all related field nodes.
+void ConnectionGraph::add_fields_to_worklist(FieldNode* field, PointsToNode* base) {
+  int offset = field->offset();
+  if (base->is_LocalVar()) {
+    for (UseIterator j(base); j.has_next(); j.next()) {
+      PointsToNode* f = j.get();
+      if (PointsToNode::is_base_use(f)) { // Field
+        f = PointsToNode::get_use_node(f);
+        if (f == field || !f->as_Field()->is_oop())
+          continue;
+        int offs = f->as_Field()->offset();
+        if (offs == offset || offset == Type::OffsetBot || offs == Type::OffsetBot) {
+          add_to_worklist(f);
+        }
+      }
+    }
+  } else {
+    assert(base->is_JavaObject(), "sanity");
+    if (// Skip phantom_object since it is only used to indicate that
+        // this field's content globally escapes.
+        (base != phantom_obj) &&
+        // NULL object node does not have fields.
+        (base != null_obj)) {
+      for (EdgeIterator i(base); i.has_next(); i.next()) {
+        PointsToNode* f = i.get();
+        // Skip arraycopy edge since store to destination object field
+        // does not update value in source object field.
+        if (f->is_Arraycopy()) {
+          assert(base->arraycopy_dst(), "sanity");
+          continue;
+        }
+        if (f == field || !f->as_Field()->is_oop())
+          continue;
+        int offs = f->as_Field()->offset();
+        if (offs == offset || offset == Type::OffsetBot || offs == Type::OffsetBot) {
+          add_to_worklist(f);
+        }
+      }
+    }
+  }
+}
+
+// Find fields which have unknown value.
+int ConnectionGraph::find_field_value(FieldNode* field) {
+  // Escaped fields should have init value already.
+  assert(field->escape_state() == PointsToNode::NoEscape, "sanity");
+  int new_edges = 0;
+  for (BaseIterator i(field); i.has_next(); i.next()) {
+    PointsToNode* base = i.get();
+    if (base->is_JavaObject()) {
+      // Skip Allocate's fields which will be processed later.
+      if (base->ideal_node()->is_Allocate())
+        return 0;
+      assert(base == null_obj, "only NULL ptr base expected here");
+    }
+  }
+  if (add_edge(field, phantom_obj)) {
+    // New edge was added
+    new_edges++;
+    add_field_uses_to_worklist(field);
+  }
+  return new_edges;
+}
+
+// Find fields initializing values for allocations.
+int ConnectionGraph::find_init_values(JavaObjectNode* pta, PointsToNode* init_val, PhaseTransform* phase) {
+  assert(pta->escape_state() == PointsToNode::NoEscape, "Not escaped Allocate nodes only");
+  int new_edges = 0;
+  Node* alloc = pta->ideal_node();
+  if (init_val == phantom_obj) {
+    // Do nothing for Allocate nodes since its fields values are "known".
+    if (alloc->is_Allocate())
+      return 0;
+    assert(alloc->as_CallStaticJava(), "sanity");
+#ifdef ASSERT
+    if (alloc->as_CallStaticJava()->method() == NULL) {
+      const char* name = alloc->as_CallStaticJava()->_name;
+      assert(strncmp(name, "_multianewarray", 15) == 0, "sanity");
+    }
+#endif
+    // Non-escaped allocation returned from Java or runtime call have
+    // unknown values in fields.
+    for (EdgeIterator i(pta); i.has_next(); i.next()) {
+      PointsToNode* ptn = i.get();
+      if (ptn->is_Field() && ptn->as_Field()->is_oop()) {
+        if (add_edge(ptn, phantom_obj)) {
+          // New edge was added
+          new_edges++;
+          add_field_uses_to_worklist(ptn->as_Field());
+        }
+      }
+    }
+    return new_edges;
+  }
+  assert(init_val == null_obj, "sanity");
+  // Do nothing for Call nodes since its fields values are unknown.
+  if (!alloc->is_Allocate())
+    return 0;
+
+  InitializeNode* ini = alloc->as_Allocate()->initialization();
+  Compile* C = _compile;
+  bool visited_bottom_offset = false;
+  GrowableArray<int> offsets_worklist;
+
+  // Check if an oop field's initializing value is recorded and add
+  // a corresponding NULL if field's value if it is not recorded.
+  // Connection Graph does not record a default initialization by NULL
+  // captured by Initialize node.
+  //
+  for (EdgeIterator i(pta); i.has_next(); i.next()) {
+    PointsToNode* ptn = i.get(); // Field (AddP)
+    if (!ptn->is_Field() || !ptn->as_Field()->is_oop())
+      continue; // Not oop field
+    int offset = ptn->as_Field()->offset();
+    if (offset == Type::OffsetBot) {
+      if (!visited_bottom_offset) {
+        // OffsetBot is used to reference array's element,
+        // always add reference to NULL to all Field nodes since we don't
+        // known which element is referenced.
+        if (add_edge(ptn, null_obj)) {
+          // New edge was added
+          new_edges++;
+          add_field_uses_to_worklist(ptn->as_Field());
+          visited_bottom_offset = true;
+        }
+      }
+    } else {
+      // Check only oop fields.
+      const Type* adr_type = ptn->ideal_node()->as_AddP()->bottom_type();
+      if (adr_type->isa_rawptr()) {
+#ifdef ASSERT
+        // Raw pointers are used for initializing stores so skip it
+        // since it should be recorded already
+        Node* base = get_addp_base(ptn->ideal_node());
+        assert(adr_type->isa_rawptr() && base->is_Proj() &&
+               (base->in(0) == alloc),"unexpected pointer type");
+#endif
+        continue;
+      }
+      if (!offsets_worklist.contains(offset)) {
+        offsets_worklist.append(offset);
+        Node* value = NULL;
+        if (ini != NULL) {
+          BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT;
+          Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase);
+          if (store != NULL && store->is_Store()) {
+            value = store->in(MemNode::ValueIn);
+          } else {
+            // There could be initializing stores which follow allocation.
+            // For example, a volatile field store is not collected
+            // by Initialize node.
+            //
+            // Need to check for dependent loads to separate such stores from
+            // stores which follow loads. For now, add initial value NULL so
+            // that compare pointers optimization works correctly.
+          }
+        }
+        if (value == NULL) {
+          // A field's initializing value was not recorded. Add NULL.
+          if (add_edge(ptn, null_obj)) {
+            // New edge was added
+            new_edges++;
+            add_field_uses_to_worklist(ptn->as_Field());
+          }
+        }
+      }
+    }
+  }
+  return new_edges;
 }
 
-void ConnectionGraph::add_deferred_edge(uint from_i, uint to_i) {
-  PointsToNode *f = ptnode_adr(from_i);
-  PointsToNode *t = ptnode_adr(to_i);
+// Adjust scalar_replaceable state after Connection Graph is built.
+void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
+  // Search for non-escaping objects which are not scalar replaceable
+  // and mark them to propagate the state to referenced objects.
+
+  // 1. An object is not scalar replaceable if the field into which it is
+  // stored has unknown offset (stored into unknown element of an array).
+  //
+  for (UseIterator i(jobj); i.has_next(); i.next()) {
+    PointsToNode* use = i.get();
+    assert(!use->is_Arraycopy(), "sanity");
+    if (use->is_Field()) {
+      FieldNode* field = use->as_Field();
+      assert(field->is_oop() && field->scalar_replaceable() &&
+             field->fields_escape_state() == PointsToNode::NoEscape, "sanity");
+      if (field->offset() == Type::OffsetBot) {
+        jobj->set_scalar_replaceable(false);
+        return;
+      }
+    }
+    assert(use->is_Field() || use->is_LocalVar(), "sanity");
+    // 2. An object is not scalar replaceable if it is merged with other objects.
+    for (EdgeIterator j(use); j.has_next(); j.next()) {
+      PointsToNode* ptn = j.get();
+      if (ptn->is_JavaObject() && ptn != jobj) {
+        // Mark all objects.
+        jobj->set_scalar_replaceable(false);
+         ptn->set_scalar_replaceable(false);
+      }
+    }
+    if (!jobj->scalar_replaceable()) {
+      return;
+    }
+  }
+
+  for (EdgeIterator j(jobj); j.has_next(); j.next()) {
+    // Non-escaping object node should point only to field nodes.
+    FieldNode* field = j.get()->as_Field();
+    int offset = field->as_Field()->offset();
+
+    // 3. An object is not scalar replaceable if it has a field with unknown
+    // offset (array's element is accessed in loop).
+    if (offset == Type::OffsetBot) {
+      jobj->set_scalar_replaceable(false);
+      return;
+    }
+    // 4. Currently an object is not scalar replaceable if a LoadStore node
+    // access its field since the field value is unknown after it.
+    //
+    Node* n = field->ideal_node();
+    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+      if (n->fast_out(i)->is_LoadStore()) {
+        jobj->set_scalar_replaceable(false);
+        return;
+      }
+    }
+
+    // 5. Or the address may point to more then one object. This may produce
+    // the false positive result (set not scalar replaceable)
+    // since the flow-insensitive escape analysis can't separate
+    // the case when stores overwrite the field's value from the case
+    // when stores happened on different control branches.
+    //
+    // Note: it will disable scalar replacement in some cases:
+    //
+    //    Point p[] = new Point[1];
+    //    p[0] = new Point(); // Will be not scalar replaced
+    //
+    // but it will save us from incorrect optimizations in next cases:
+    //
+    //    Point p[] = new Point[1];
+    //    if ( x ) p[0] = new Point(); // Will be not scalar replaced
+    //
+    if (field->base_count() > 1) {
+      for (BaseIterator i(field); i.has_next(); i.next()) {
+        PointsToNode* base = i.get();
+        // Don't take into account LocalVar nodes which
+        // may point to only one object which should be also
+        // this field's base by now.
+        if (base->is_JavaObject() && base != jobj) {
+          // Mark all bases.
+          jobj->set_scalar_replaceable(false);
+          base->set_scalar_replaceable(false);
+        }
+      }
+    }
+  }
+}
+
+#ifdef ASSERT
+void ConnectionGraph::verify_connection_graph(
+                         GrowableArray<PointsToNode*>&   ptnodes_worklist,
+                         GrowableArray<JavaObjectNode*>& non_escaped_worklist,
+                         GrowableArray<JavaObjectNode*>& java_objects_worklist,
+                         GrowableArray<Node*>& addp_worklist) {
+  // Verify that graph is complete - no new edges could be added.
+  int java_objects_length = java_objects_worklist.length();
+  int non_escaped_length  = non_escaped_worklist.length();
+  int new_edges = 0;
+  for (int next = 0; next < java_objects_length; ++next) {
+    JavaObjectNode* ptn = java_objects_worklist.at(next);
+    new_edges += add_java_object_edges(ptn, true);
+  }
+  assert(new_edges == 0, "graph was not complete");
+  // Verify that escape state is final.
+  int length = non_escaped_worklist.length();
+  find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist);
+  assert((non_escaped_length == non_escaped_worklist.length()) &&
+         (non_escaped_length == length) &&
+         (_worklist.length() == 0), "escape state was not final");
+
+  // Verify fields information.
+  int addp_length = addp_worklist.length();
+  for (int next = 0; next < addp_length; ++next ) {
+    Node* n = addp_worklist.at(next);
+    FieldNode* field = ptnode_adr(n->_idx)->as_Field();
+    if (field->is_oop()) {
+      // Verify that field has all bases
+      Node* base = get_addp_base(n);
+      PointsToNode* ptn = ptnode_adr(base->_idx);
+      if (ptn->is_JavaObject()) {
+        assert(field->has_base(ptn->as_JavaObject()), "sanity");
+      } else {
+        assert(ptn->is_LocalVar(), "sanity");
+        for (EdgeIterator i(ptn); i.has_next(); i.next()) {
+          PointsToNode* e = i.get();
+          if (e->is_JavaObject()) {
+            assert(field->has_base(e->as_JavaObject()), "sanity");
+          }
+        }
+      }
+      // Verify that all fields have initializing values.
+      if (field->edge_count() == 0) {
+        field->dump();
+        assert(field->edge_count() > 0, "sanity");
+      }
+    }
+  }
+}
+#endif
+
+// Optimize ideal graph.
+void ConnectionGraph::optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
+                                           GrowableArray<Node*>& storestore_worklist) {
+  Compile* C = _compile;
+  PhaseIterGVN* igvn = _igvn;
+  if (EliminateLocks) {
+    // Mark locks before changing ideal graph.
+    int cnt = C->macro_count();
+    for( int i=0; i < cnt; i++ ) {
+      Node *n = C->macro_node(i);
+      if (n->is_AbstractLock()) { // Lock and Unlock nodes
+        AbstractLockNode* alock = n->as_AbstractLock();
+        if (!alock->is_non_esc_obj()) {
+          if (not_global_escape(alock->obj_node())) {
+            assert(!alock->is_eliminated() || alock->is_coarsened(), "sanity");
+            // The lock could be marked eliminated by lock coarsening
+            // code during first IGVN before EA. Replace coarsened flag
+            // to eliminate all associated locks/unlocks.
+            alock->set_non_esc_obj();
+          }
+        }
+      }
+    }
+  }
+
+  if (OptimizePtrCompare) {
+    // Add ConI(#CC_GT) and ConI(#CC_EQ).
+    _pcmp_neq = igvn->makecon(TypeInt::CC_GT);
+    _pcmp_eq = igvn->makecon(TypeInt::CC_EQ);
+    // Optimize objects compare.
+    while (ptr_cmp_worklist.length() != 0) {
+      Node *n = ptr_cmp_worklist.pop();
+      Node *res = optimize_ptr_compare(n);
+      if (res != NULL) {
+#ifndef PRODUCT
+        if (PrintOptimizePtrCompare) {
+          tty->print_cr("++++ Replaced: %d %s(%d,%d) --> %s", n->_idx, (n->Opcode() == Op_CmpP ? "CmpP" : "CmpN"), n->in(1)->_idx, n->in(2)->_idx, (res == _pcmp_eq ? "EQ" : "NotEQ"));
+          if (Verbose) {
+            n->dump(1);
+          }
+        }
+#endif
+        igvn->replace_node(n, res);
+      }
+    }
+    // cleanup
+    if (_pcmp_neq->outcnt() == 0)
+      igvn->hash_delete(_pcmp_neq);
+    if (_pcmp_eq->outcnt()  == 0)
+      igvn->hash_delete(_pcmp_eq);
+  }
+
+  // For MemBarStoreStore nodes added in library_call.cpp, check
+  // escape status of associated AllocateNode and optimize out
+  // MemBarStoreStore node if the allocated object never escapes.
+  while (storestore_worklist.length() != 0) {
+    Node *n = storestore_worklist.pop();
+    MemBarStoreStoreNode *storestore = n ->as_MemBarStoreStore();
+    Node *alloc = storestore->in(MemBarNode::Precedent)->in(0);
+    assert (alloc->is_Allocate(), "storestore should point to AllocateNode");
+    if (not_global_escape(alloc)) {
+      MemBarNode* mb = MemBarNode::make(C, Op_MemBarCPUOrder, Compile::AliasIdxBot);
+      mb->init_req(TypeFunc::Memory, storestore->in(TypeFunc::Memory));
+      mb->init_req(TypeFunc::Control, storestore->in(TypeFunc::Control));
+      igvn->register_new_node_with_optimizer(mb);
+      igvn->replace_node(storestore, mb);
+    }
+  }
+}
+
+// Optimize objects compare.
+Node* ConnectionGraph::optimize_ptr_compare(Node* n) {
+  assert(OptimizePtrCompare, "sanity");
+  PointsToNode* ptn1 = ptnode_adr(n->in(1)->_idx);
+  PointsToNode* ptn2 = ptnode_adr(n->in(2)->_idx);
+  JavaObjectNode* jobj1 = unique_java_object(n->in(1));
+  JavaObjectNode* jobj2 = unique_java_object(n->in(2));
+  assert(ptn1->is_JavaObject() || ptn1->is_LocalVar(), "sanity");
+  assert(ptn2->is_JavaObject() || ptn2->is_LocalVar(), "sanity");
 
-  assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
-  assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of Deferred edge");
-  assert(t->node_type() == PointsToNode::LocalVar || t->node_type() == PointsToNode::Field, "invalid destination of Deferred edge");
-  // don't add a self-referential edge, this can occur during removal of
-  // deferred edges
-  if (from_i != to_i)
-    add_edge(f, to_i, PointsToNode::DeferredEdge);
+  // Check simple cases first.
+  if (jobj1 != NULL) {
+    if (jobj1->escape_state() == PointsToNode::NoEscape) {
+      if (jobj1 == jobj2) {
+        // Comparing the same not escaping object.
+        return _pcmp_eq;
+      }
+      Node* obj = jobj1->ideal_node();
+      // Comparing not escaping allocation.
+      if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
+          !ptn2->points_to(jobj1)) {
+        return _pcmp_neq; // This includes nullness check.
+      }
+    }
+  }
+  if (jobj2 != NULL) {
+    if (jobj2->escape_state() == PointsToNode::NoEscape) {
+      Node* obj = jobj2->ideal_node();
+      // Comparing not escaping allocation.
+      if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
+          !ptn1->points_to(jobj2)) {
+        return _pcmp_neq; // This includes nullness check.
+      }
+    }
+  }
+  if (jobj1 != NULL && jobj1 != phantom_obj &&
+      jobj2 != NULL && jobj2 != phantom_obj &&
+      jobj1->ideal_node()->is_Con() &&
+      jobj2->ideal_node()->is_Con()) {
+    // Klass or String constants compare. Need to be careful with
+    // compressed pointers - compare types of ConN and ConP instead of nodes.
+    const Type* t1 = jobj1->ideal_node()->bottom_type()->make_ptr();
+    const Type* t2 = jobj2->ideal_node()->bottom_type()->make_ptr();
+    assert(t1 != NULL && t2 != NULL, "sanity");
+    if (t1->make_ptr() == t2->make_ptr()) {
+      return _pcmp_eq;
+    } else {
+      return _pcmp_neq;
+    }
+  }
+  if (ptn1->meet(ptn2)) {
+    return NULL; // Sets are not disjoint
+  }
+
+  // Sets are disjoint.
+  bool set1_has_unknown_ptr = ptn1->points_to(phantom_obj);
+  bool set2_has_unknown_ptr = ptn2->points_to(phantom_obj);
+  bool set1_has_null_ptr    = ptn1->points_to(null_obj);
+  bool set2_has_null_ptr    = ptn2->points_to(null_obj);
+  if (set1_has_unknown_ptr && set2_has_null_ptr ||
+      set2_has_unknown_ptr && set1_has_null_ptr) {
+    // Check nullness of unknown object.
+    return NULL;
+  }
+
+  // Disjointness by itself is not sufficient since
+  // alias analysis is not complete for escaped objects.
+  // Disjoint sets are definitely unrelated only when
+  // at least one set has only not escaping allocations.
+  if (!set1_has_unknown_ptr && !set1_has_null_ptr) {
+    if (ptn1->non_escaping_allocation()) {
+      return _pcmp_neq;
+    }
+  }
+  if (!set2_has_unknown_ptr && !set2_has_null_ptr) {
+    if (ptn2->non_escaping_allocation()) {
+      return _pcmp_neq;
+    }
+  }
+  return NULL;
+}
+
+// Connection Graph constuction functions.
+
+void ConnectionGraph::add_local_var(Node *n, PointsToNode::EscapeState es) {
+  PointsToNode* ptadr = _nodes.at(n->_idx);
+  if (ptadr != NULL) {
+    assert(ptadr->is_LocalVar() && ptadr->ideal_node() == n, "sanity");
+    return;
+  }
+  Compile* C = _compile;
+  ptadr = new (C->comp_arena()) LocalVarNode(C, n, es);
+  _nodes.at_put(n->_idx, ptadr);
+}
+
+void ConnectionGraph::add_java_object(Node *n, PointsToNode::EscapeState es) {
+  PointsToNode* ptadr = _nodes.at(n->_idx);
+  if (ptadr != NULL) {
+    assert(ptadr->is_JavaObject() && ptadr->ideal_node() == n, "sanity");
+    return;
+  }
+  Compile* C = _compile;
+  ptadr = new (C->comp_arena()) JavaObjectNode(C, n, es);
+  _nodes.at_put(n->_idx, ptadr);
+}
+
+void ConnectionGraph::add_field(Node *n, PointsToNode::EscapeState es, int offset) {
+  PointsToNode* ptadr = _nodes.at(n->_idx);
+  if (ptadr != NULL) {
+    assert(ptadr->is_Field() && ptadr->ideal_node() == n, "sanity");
+    return;
+  }
+  Compile* C = _compile;
+  bool is_oop = is_oop_field(n, offset);
+  FieldNode* field = new (C->comp_arena()) FieldNode(C, n, es, offset, is_oop);
+  _nodes.at_put(n->_idx, field);
+}
+
+void ConnectionGraph::add_arraycopy(Node *n, PointsToNode::EscapeState es,
+                                    PointsToNode* src, PointsToNode* dst) {
+  assert(!src->is_Field() && !dst->is_Field(), "only for JavaObject and LocalVar");
+  assert((src != null_obj) && (dst != null_obj), "not for ConP NULL");
+  PointsToNode* ptadr = _nodes.at(n->_idx);
+  if (ptadr != NULL) {
+    assert(ptadr->is_Arraycopy() && ptadr->ideal_node() == n, "sanity");
+    return;
+  }
+  Compile* C = _compile;
+  ptadr = new (C->comp_arena()) ArraycopyNode(C, n, es);
+  _nodes.at_put(n->_idx, ptadr);
+  // Add edge from arraycopy node to source object.
+  (void)add_edge(ptadr, src);
+  src->set_arraycopy_src();
+  // Add edge from destination object to arraycopy node.
+  (void)add_edge(dst, ptadr);
+  dst->set_arraycopy_dst();
 }
 
+bool ConnectionGraph::is_oop_field(Node* n, int offset) {
+  const Type* adr_type = n->as_AddP()->bottom_type();
+  BasicType bt = T_INT;
+  if (offset == Type::OffsetBot) {
+    // Check only oop fields.
+    if (!adr_type->isa_aryptr() ||
+        (adr_type->isa_aryptr()->klass() == NULL) ||
+         adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
+      // OffsetBot is used to reference array's element. Ignore first AddP.
+      if (find_second_addp(n, n->in(AddPNode::Base)) == NULL) {
+        bt = T_OBJECT;
+      }
+    }
+  } else if (offset != oopDesc::klass_offset_in_bytes()) {
+    if (adr_type->isa_instptr()) {
+      ciField* field = _compile->alias_type(adr_type->isa_instptr())->field();
+      if (field != NULL) {
+        bt = field->layout_type();
+      } else {
+        // Ignore non field load (for example, klass load)
+      }
+    } else if (adr_type->isa_aryptr()) {
+      if (offset == arrayOopDesc::length_offset_in_bytes()) {
+        // Ignore array length load.
+      } else if (find_second_addp(n, n->in(AddPNode::Base)) != NULL) {
+        // Ignore first AddP.
+      } else {
+        const Type* elemtype = adr_type->isa_aryptr()->elem();
+        bt = elemtype->array_element_basic_type();
+      }
+    } else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
+      // Allocation initialization, ThreadLocal field access, unsafe access
+      for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+        int opcode = n->fast_out(i)->Opcode();
+        if (opcode == Op_StoreP || opcode == Op_LoadP ||
+            opcode == Op_StoreN || opcode == Op_LoadN) {
+          bt = T_OBJECT;
+        }
+      }
+    }
+  }
+  return (bt == T_OBJECT || bt == T_NARROWOOP || bt == T_ARRAY);
+}
+
+// Returns unique pointed java object or NULL.
+JavaObjectNode* ConnectionGraph::unique_java_object(Node *n) {
+  assert(!_collecting, "should not call when contructed graph");
+  // If the node was created after the escape computation we can't answer.
+  uint idx = n->_idx;
+  if (idx >= nodes_size()) {
+    return NULL;
+  }
+  PointsToNode* ptn = ptnode_adr(idx);
+  if (ptn->is_JavaObject()) {
+    return ptn->as_JavaObject();
+  }
+  assert(ptn->is_LocalVar(), "sanity");
+  // Check all java objects it points to.
+  JavaObjectNode* jobj = NULL;
+  for (EdgeIterator i(ptn); i.has_next(); i.next()) {
+    PointsToNode* e = i.get();
+    if (e->is_JavaObject()) {
+      if (jobj == NULL) {
+        jobj = e->as_JavaObject();
+      } else if (jobj != e) {
+        return NULL;
+      }
+    }
+  }
+  return jobj;
+}
+
+// Return true if this node points only to non-escaping allocations.
+bool PointsToNode::non_escaping_allocation() {
+  if (is_JavaObject()) {
+    Node* n = ideal_node();
+    if (n->is_Allocate() || n->is_CallStaticJava()) {
+      return (escape_state() == PointsToNode::NoEscape);
+    } else {
+      return false;
+    }
+  }
+  assert(is_LocalVar(), "sanity");
+  // Check all java objects it points to.
+  for (EdgeIterator i(this); i.has_next(); i.next()) {
+    PointsToNode* e = i.get();
+    if (e->is_JavaObject()) {
+      Node* n = e->ideal_node();
+      if ((e->escape_state() != PointsToNode::NoEscape) ||
+          !(n->is_Allocate() || n->is_CallStaticJava())) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+// Return true if we know the node does not escape globally.
+bool ConnectionGraph::not_global_escape(Node *n) {
+  assert(!_collecting, "should not call during graph construction");
+  // If the node was created after the escape computation we can't answer.
+  uint idx = n->_idx;
+  if (idx >= nodes_size()) {
+    return false;
+  }
+  PointsToNode* ptn = ptnode_adr(idx);
+  PointsToNode::EscapeState es = ptn->escape_state();
+  // If we have already computed a value, return it.
+  if (es >= PointsToNode::GlobalEscape)
+    return false;
+  if (ptn->is_JavaObject()) {
+    return true; // (es < PointsToNode::GlobalEscape);
+  }
+  assert(ptn->is_LocalVar(), "sanity");
+  // Check all java objects it points to.
+  for (EdgeIterator i(ptn); i.has_next(); i.next()) {
+    if (i.get()->escape_state() >= PointsToNode::GlobalEscape)
+      return false;
+  }
+  return true;
+}
+
+
+// Helper functions
+
+// Return true if this node points to specified node or nodes it points to.
+bool PointsToNode::points_to(JavaObjectNode* ptn) const {
+  if (is_JavaObject()) {
+    return (this == ptn);
+  }
+  assert(is_LocalVar(), "sanity");
+  for (EdgeIterator i(this); i.has_next(); i.next()) {
+    if (i.get() == ptn)
+      return true;
+  }
+  return false;
+}
+
+// Return true if one node points to an other.
+bool PointsToNode::meet(PointsToNode* ptn) {
+  if (this == ptn) {
+    return true;
+  } else if (ptn->is_JavaObject()) {
+    return this->points_to(ptn->as_JavaObject());
+  } else if (this->is_JavaObject()) {
+    return ptn->points_to(this->as_JavaObject());
+  }
+  assert(this->is_LocalVar() && ptn->is_LocalVar(), "sanity");
+  int ptn_count =  ptn->edge_count();
+  for (EdgeIterator i(this); i.has_next(); i.next()) {
+    PointsToNode* this_e = i.get();
+    for (int j = 0; j < ptn_count; j++) {
+      if (this_e == ptn->edge(j))
+        return true;
+    }
+  }
+  return false;
+}
+
+#ifdef ASSERT
+// Return true if bases point to this java object.
+bool FieldNode::has_base(JavaObjectNode* jobj) const {
+  for (BaseIterator i(this); i.has_next(); i.next()) {
+    if (i.get() == jobj)
+      return true;
+  }
+  return false;
+}
+#endif
+
 int ConnectionGraph::address_offset(Node* adr, PhaseTransform *phase) {
   const Type *adr_type = phase->type(adr);
   if (adr->is_AddP() && adr_type->isa_oopptr() == NULL &&
@@ -171,286 +1982,7 @@
   return t_ptr->offset();
 }
 
-void ConnectionGraph::add_field_edge(uint from_i, uint to_i, int offset) {
-  // Don't add fields to NULL pointer.
-  if (is_null_ptr(from_i))
-    return;
-  PointsToNode *f = ptnode_adr(from_i);
-  PointsToNode *t = ptnode_adr(to_i);
-
-  assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
-  assert(f->node_type() == PointsToNode::JavaObject, "invalid destination of Field edge");
-  assert(t->node_type() == PointsToNode::Field, "invalid destination of Field edge");
-  assert (t->offset() == -1 || t->offset() == offset, "conflicting field offsets");
-  t->set_offset(offset);
-
-  add_edge(f, to_i, PointsToNode::FieldEdge);
-}
-
-void ConnectionGraph::set_escape_state(uint ni, PointsToNode::EscapeState es) {
-  // Don't change non-escaping state of NULL pointer.
-  if (is_null_ptr(ni))
-    return;
-  PointsToNode *npt = ptnode_adr(ni);
-  PointsToNode::EscapeState old_es = npt->escape_state();
-  if (es > old_es)
-    npt->set_escape_state(es);
-}
-
-void ConnectionGraph::add_node(Node *n, PointsToNode::NodeType nt,
-                               PointsToNode::EscapeState es, bool done) {
-  PointsToNode* ptadr = ptnode_adr(n->_idx);
-  ptadr->_node = n;
-  ptadr->set_node_type(nt);
-
-  // inline set_escape_state(idx, es);
-  PointsToNode::EscapeState old_es = ptadr->escape_state();
-  if (es > old_es)
-    ptadr->set_escape_state(es);
-
-  if (done)
-    _processed.set(n->_idx);
-}
-
-PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) {
-  uint idx = n->_idx;
-  PointsToNode::EscapeState es;
-
-  // If we are still collecting or there were no non-escaping allocations
-  // we don't know the answer yet
-  if (_collecting)
-    return PointsToNode::UnknownEscape;
-
-  // if the node was created after the escape computation, return
-  // UnknownEscape
-  if (idx >= nodes_size())
-    return PointsToNode::UnknownEscape;
-
-  es = ptnode_adr(idx)->escape_state();
-
-  // if we have already computed a value, return it
-  if (es != PointsToNode::UnknownEscape &&
-      ptnode_adr(idx)->node_type() == PointsToNode::JavaObject)
-    return es;
-
-  // PointsTo() calls n->uncast() which can return a new ideal node.
-  if (n->uncast()->_idx >= nodes_size())
-    return PointsToNode::UnknownEscape;
-
-  PointsToNode::EscapeState orig_es = es;
-
-  // compute max escape state of anything this node could point to
-  for(VectorSetI i(PointsTo(n)); i.test() && es != PointsToNode::GlobalEscape; ++i) {
-    uint pt = i.elem;
-    PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
-    if (pes > es)
-      es = pes;
-  }
-  if (orig_es != es) {
-    // cache the computed escape state
-    assert(es > orig_es, "should have computed an escape state");
-    set_escape_state(idx, es);
-  } // orig_es could be PointsToNode::UnknownEscape
-  return es;
-}
-
-VectorSet* ConnectionGraph::PointsTo(Node * n) {
-  pt_ptset.Reset();
-  pt_visited.Reset();
-  pt_worklist.clear();
-
-#ifdef ASSERT
-  Node *orig_n = n;
-#endif
-
-  n = n->uncast();
-  PointsToNode* npt = ptnode_adr(n->_idx);
-
-  // If we have a JavaObject, return just that object
-  if (npt->node_type() == PointsToNode::JavaObject) {
-    pt_ptset.set(n->_idx);
-    return &pt_ptset;
-  }
-#ifdef ASSERT
-  if (npt->_node == NULL) {
-    if (orig_n != n)
-      orig_n->dump();
-    n->dump();
-    assert(npt->_node != NULL, "unregistered node");
-  }
-#endif
-  pt_worklist.push(n->_idx);
-  while(pt_worklist.length() > 0) {
-    int ni = pt_worklist.pop();
-    if (pt_visited.test_set(ni))
-      continue;
-
-    PointsToNode* pn = ptnode_adr(ni);
-    // ensure that all inputs of a Phi have been processed
-    assert(!_collecting || !pn->_node->is_Phi() || _processed.test(ni),"");
-
-    int edges_processed = 0;
-    uint e_cnt = pn->edge_count();
-    for (uint e = 0; e < e_cnt; e++) {
-      uint etgt = pn->edge_target(e);
-      PointsToNode::EdgeType et = pn->edge_type(e);
-      if (et == PointsToNode::PointsToEdge) {
-        pt_ptset.set(etgt);
-        edges_processed++;
-      } else if (et == PointsToNode::DeferredEdge) {
-        pt_worklist.push(etgt);
-        edges_processed++;
-      } else {
-        assert(false,"neither PointsToEdge or DeferredEdge");
-      }
-    }
-    if (edges_processed == 0) {
-      // no deferred or pointsto edges found.  Assume the value was set
-      // outside this method.  Add the phantom object to the pointsto set.
-      pt_ptset.set(_phantom_object);
-    }
-  }
-  return &pt_ptset;
-}
-
-void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) {
-  // This method is most expensive during ConnectionGraph construction.
-  // Reuse vectorSet and an additional growable array for deferred edges.
-  deferred_edges->clear();
-  visited->Reset();
-
-  visited->set(ni);
-  PointsToNode *ptn = ptnode_adr(ni);
-  assert(ptn->node_type() == PointsToNode::LocalVar ||
-         ptn->node_type() == PointsToNode::Field, "sanity");
-  assert(ptn->edge_count() != 0, "should have at least phantom_object");
-
-  // Mark current edges as visited and move deferred edges to separate array.
-  for (uint i = 0; i < ptn->edge_count(); ) {
-    uint t = ptn->edge_target(i);
-#ifdef ASSERT
-    assert(!visited->test_set(t), "expecting no duplications");
-#else
-    visited->set(t);
-#endif
-    if (ptn->edge_type(i) == PointsToNode::DeferredEdge) {
-      ptn->remove_edge(t, PointsToNode::DeferredEdge);
-      deferred_edges->append(t);
-    } else {
-      i++;
-    }
-  }
-  for (int next = 0; next < deferred_edges->length(); ++next) {
-    uint t = deferred_edges->at(next);
-    PointsToNode *ptt = ptnode_adr(t);
-    uint e_cnt = ptt->edge_count();
-    assert(e_cnt != 0, "should have at least phantom_object");
-    for (uint e = 0; e < e_cnt; e++) {
-      uint etgt = ptt->edge_target(e);
-      if (visited->test_set(etgt))
-        continue;
-
-      PointsToNode::EdgeType et = ptt->edge_type(e);
-      if (et == PointsToNode::PointsToEdge) {
-        add_pointsto_edge(ni, etgt);
-      } else if (et == PointsToNode::DeferredEdge) {
-        deferred_edges->append(etgt);
-      } else {
-        assert(false,"invalid connection graph");
-      }
-    }
-  }
-  if (ptn->edge_count() == 0) {
-    // No pointsto edges found after deferred edges are removed.
-    // For example, in the next case where call is replaced
-    // with uncommon trap and as result array's load references
-    // itself through deferred edges:
-    //
-    // A a = b[i];
-    // if (c!=null) a = c.foo();
-    // b[i] = a;
-    //
-    // Assume the value was set outside this method and
-    // add edge to phantom object.
-    add_pointsto_edge(ni, _phantom_object);
-  }
-}
-
-
-//  Add an edge to node given by "to_i" from any field of adr_i whose offset
-//  matches "offset"  A deferred edge is added if to_i is a LocalVar, and
-//  a pointsto edge is added if it is a JavaObject
-
-void ConnectionGraph::add_edge_from_fields(uint adr_i, uint to_i, int offs) {
-  // No fields for NULL pointer.
-  if (is_null_ptr(adr_i)) {
-    return;
-  }
-  PointsToNode* an = ptnode_adr(adr_i);
-  PointsToNode* to = ptnode_adr(to_i);
-  bool deferred = (to->node_type() == PointsToNode::LocalVar);
-  bool escaped  = (to_i == _phantom_object) && (offs == Type::OffsetTop);
-  if (escaped) {
-    // Values in fields escaped during call.
-    assert(an->escape_state() >= PointsToNode::ArgEscape, "sanity");
-    offs = Type::OffsetBot;
-  }
-  for (uint fe = 0; fe < an->edge_count(); fe++) {
-    assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge");
-    int fi = an->edge_target(fe);
-    if (escaped) {
-      set_escape_state(fi, PointsToNode::GlobalEscape);
-    }
-    PointsToNode* pf = ptnode_adr(fi);
-    int po = pf->offset();
-    if (po == offs || po == Type::OffsetBot || offs == Type::OffsetBot) {
-      if (deferred)
-        add_deferred_edge(fi, to_i);
-      else
-        add_pointsto_edge(fi, to_i);
-    }
-  }
-}
-
-// Add a deferred  edge from node given by "from_i" to any field of adr_i
-// whose offset matches "offset".
-void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) {
-  // No fields for NULL pointer.
-  if (is_null_ptr(adr_i)) {
-    return;
-  }
-  if (adr_i == _phantom_object) {
-    // Add only one edge for unknown object.
-    add_pointsto_edge(from_i, _phantom_object);
-    return;
-  }
-  PointsToNode* an = ptnode_adr(adr_i);
-  bool is_alloc = an->_node->is_Allocate();
-  for (uint fe = 0; fe < an->edge_count(); fe++) {
-    assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge");
-    int fi = an->edge_target(fe);
-    PointsToNode* pf = ptnode_adr(fi);
-    int offset = pf->offset();
-    if (!is_alloc) {
-      // Assume the field was set outside this method if it is not Allocation
-      add_pointsto_edge(fi, _phantom_object);
-    }
-    if (offset == offs || offset == Type::OffsetBot || offs == Type::OffsetBot) {
-      add_deferred_edge(from_i, fi);
-    }
-  }
-  // Some fields references (AddP) may still be missing
-  // until Connection Graph construction is complete.
-  // For example, loads from RAW pointers with offset 0
-  // which don't have AddP.
-  // A reference to phantom_object will be added if
-  // a field reference is still missing after completing
-  // Connection Graph (see remove_deferred()).
-}
-
-// Helper functions
-
-static Node* get_addp_base(Node *addp) {
+Node* ConnectionGraph::get_addp_base(Node *addp) {
   assert(addp->is_AddP(), "must be AddP");
   //
   // AddP cases for Base and Address inputs:
@@ -513,30 +2045,30 @@
   //       | |
   //       AddP  ( base == address )
   //
-  Node *base = addp->in(AddPNode::Base)->uncast();
-  if (base->is_top()) { // The AddP case #3 and #6.
-    base = addp->in(AddPNode::Address)->uncast();
+  Node *base = addp->in(AddPNode::Base);
+  if (base->uncast()->is_top()) { // The AddP case #3 and #6.
+    base = addp->in(AddPNode::Address);
     while (base->is_AddP()) {
       // Case #6 (unsafe access) may have several chained AddP nodes.
-      assert(base->in(AddPNode::Base)->is_top(), "expected unsafe access address only");
-      base = base->in(AddPNode::Address)->uncast();
+      assert(base->in(AddPNode::Base)->uncast()->is_top(), "expected unsafe access address only");
+      base = base->in(AddPNode::Address);
     }
-    assert(base->Opcode() == Op_ConP || base->Opcode() == Op_ThreadLocal ||
-           base->Opcode() == Op_CastX2P || base->is_DecodeN() ||
-           (base->is_Mem() && base->bottom_type() == TypeRawPtr::NOTNULL) ||
-           (base->is_Proj() && base->in(0)->is_Allocate()), "sanity");
+    Node* uncast_base = base->uncast();
+    int opcode = uncast_base->Opcode();
+    assert(opcode == Op_ConP || opcode == Op_ThreadLocal ||
+           opcode == Op_CastX2P || uncast_base->is_DecodeN() ||
+           (uncast_base->is_Mem() && uncast_base->bottom_type() == TypeRawPtr::NOTNULL) ||
+           (uncast_base->is_Proj() && uncast_base->in(0)->is_Allocate()), "sanity");
   }
   return base;
 }
 
-static Node* find_second_addp(Node* addp, Node* n) {
+Node* ConnectionGraph::find_second_addp(Node* addp, Node* n) {
   assert(addp->is_AddP() && addp->outcnt() > 0, "Don't process dead nodes");
-
   Node* addp2 = addp->raw_out(0);
   if (addp->outcnt() == 1 && addp2->is_AddP() &&
       addp2->in(AddPNode::Base) == n &&
       addp2->in(AddPNode::Address) == addp) {
-
     assert(addp->in(AddPNode::Base) == n, "expecting the same base");
     //
     // Find array's offset to push it on worklist first and
@@ -575,7 +2107,8 @@
 // Adjust the type and inputs of an AddP which computes the
 // address of a field of an instance
 //
-bool ConnectionGraph::split_AddP(Node *addp, Node *base,  PhaseGVN  *igvn) {
+bool ConnectionGraph::split_AddP(Node *addp, Node *base) {
+  PhaseGVN* igvn = _igvn;
   const TypeOopPtr *base_t = igvn->type(base)->isa_oopptr();
   assert(base_t != NULL && base_t->is_known_instance(), "expecting instance oopptr");
   const TypeOopPtr *t = igvn->type(addp)->isa_oopptr();
@@ -612,7 +2145,6 @@
       !base_t->klass()->is_subtype_of(t->klass())) {
      return false; // bail out
   }
-
   const TypeOopPtr *tinst = base_t->add_offset(t->offset())->is_oopptr();
   // Do NOT remove the next line: ensure a new alias index is allocated
   // for the instance type. Note: C++ will not remove it since the call
@@ -620,9 +2152,7 @@
   int alias_idx = _compile->get_alias_index(tinst);
   igvn->set_type(addp, tinst);
   // record the allocation in the node map
-  assert(ptnode_adr(addp->_idx)->_node != NULL, "should be registered");
-  set_map(addp->_idx, get_map(base->_idx));
-
+  set_map(addp, get_map(base->_idx));
   // Set addp's Base and Address to 'base'.
   Node *abase = addp->in(AddPNode::Base);
   Node *adr   = addp->in(AddPNode::Address);
@@ -657,8 +2187,9 @@
 // created phi or an existing phi.  Sets create_new to indicate whether a new
 // phi was created.  Cache the last newly created phi in the node map.
 //
-PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn, bool &new_created) {
+PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, bool &new_created) {
   Compile *C = _compile;
+  PhaseGVN* igvn = _igvn;
   new_created = false;
   int phi_alias_idx = C->get_alias_index(orig_phi->adr_type());
   // nothing to do if orig_phi is bottom memory or matches alias_idx
@@ -698,12 +2229,7 @@
   C->copy_node_notes_to(result, orig_phi);
   igvn->set_type(result, result->bottom_type());
   record_for_optimizer(result);
-
-  debug_only(Node* pn = ptnode_adr(orig_phi->_idx)->_node;)
-  assert(pn == NULL || pn == orig_phi, "wrong node");
-  set_map(orig_phi->_idx, result);
-  ptnode_adr(orig_phi->_idx)->_node = orig_phi;
-
+  set_map(orig_phi, result);
   new_created = true;
   return result;
 }
@@ -712,27 +2238,25 @@
 // Return a new version of Memory Phi "orig_phi" with the inputs having the
 // specified alias index.
 //
-PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn) {
-
+PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist) {
   assert(alias_idx != Compile::AliasIdxBot, "can't split out bottom memory");
   Compile *C = _compile;
+  PhaseGVN* igvn = _igvn;
   bool new_phi_created;
-  PhiNode *result = create_split_phi(orig_phi, alias_idx, orig_phi_worklist, igvn, new_phi_created);
+  PhiNode *result = create_split_phi(orig_phi, alias_idx, orig_phi_worklist, new_phi_created);
   if (!new_phi_created) {
     return result;
   }
-
   GrowableArray<PhiNode *>  phi_list;
   GrowableArray<uint>  cur_input;
-
   PhiNode *phi = orig_phi;
   uint idx = 1;
   bool finished = false;
   while(!finished) {
     while (idx < phi->req()) {
-      Node *mem = find_inst_mem(phi->in(idx), alias_idx, orig_phi_worklist, igvn);
+      Node *mem = find_inst_mem(phi->in(idx), alias_idx, orig_phi_worklist);
       if (mem != NULL && mem->is_Phi()) {
-        PhiNode *newphi = create_split_phi(mem->as_Phi(), alias_idx, orig_phi_worklist, igvn, new_phi_created);
+        PhiNode *newphi = create_split_phi(mem->as_Phi(), alias_idx, orig_phi_worklist, new_phi_created);
         if (new_phi_created) {
           // found an phi for which we created a new split, push current one on worklist and begin
           // processing new one
@@ -775,19 +2299,18 @@
   return result;
 }
 
-
 //
 // The next methods are derived from methods in MemNode.
 //
-static Node *step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop) {
+Node* ConnectionGraph::step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop) {
   Node *mem = mmem;
   // TypeOopPtr::NOTNULL+any is an OOP with unknown offset - generally
   // means an array I have not precisely typed yet.  Do not do any
   // alias stuff with it any time soon.
-  if( toop->base() != Type::AnyPtr &&
+  if (toop->base() != Type::AnyPtr &&
       !(toop->klass() != NULL &&
         toop->klass()->is_java_lang_Object() &&
-        toop->offset() == Type::OffsetBot) ) {
+        toop->offset() == Type::OffsetBot)) {
     mem = mmem->memory_at(alias_idx);
     // Update input if it is progress over what we have now
   }
@@ -797,9 +2320,9 @@
 //
 // Move memory users to their memory slices.
 //
-void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis, PhaseGVN *igvn) {
+void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis) {
   Compile* C = _compile;
-
+  PhaseGVN* igvn = _igvn;
   const TypePtr* tp = igvn->type(n->in(MemNode::Address))->isa_ptr();
   assert(tp != NULL, "ptr type");
   int alias_idx = C->get_alias_index(tp);
@@ -816,7 +2339,7 @@
       }
       // Replace previous general reference to mem node.
       uint orig_uniq = C->unique();
-      Node* m = find_inst_mem(n, general_idx, orig_phis, igvn);
+      Node* m = find_inst_mem(n, general_idx, orig_phis);
       assert(orig_uniq == C->unique(), "no new nodes");
       mmem->set_memory_at(general_idx, m);
       --imax;
@@ -836,7 +2359,7 @@
       }
       // Move to general memory slice.
       uint orig_uniq = C->unique();
-      Node* m = find_inst_mem(n, general_idx, orig_phis, igvn);
+      Node* m = find_inst_mem(n, general_idx, orig_phis);
       assert(orig_uniq == C->unique(), "no new nodes");
       igvn->hash_delete(use);
       imax -= use->replace_edge(n, m);
@@ -873,10 +2396,11 @@
 // Search memory chain of "mem" to find a MemNode whose address
 // is the specified alias index.
 //
-Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArray<PhiNode *>  &orig_phis, PhaseGVN *phase) {
+Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArray<PhiNode *>  &orig_phis) {
   if (orig_mem == NULL)
     return orig_mem;
-  Compile* C = phase->C;
+  Compile* C = _compile;
+  PhaseGVN* igvn = _igvn;
   const TypeOopPtr *toop = C->get_adr_type(alias_idx)->isa_oopptr();
   bool is_instance = (toop != NULL) && toop->is_known_instance();
   Node *start_mem = C->start()->proj_out(TypeFunc::Memory);
@@ -887,7 +2411,7 @@
     if (result == start_mem)
       break;  // hit one of our sentinels
     if (result->is_Mem()) {
-      const Type *at = phase->type(result->in(MemNode::Address));
+      const Type *at = igvn->type(result->in(MemNode::Address));
       if (at == Type::TOP)
         break; // Dead
       assert (at->isa_ptr() != NULL, "pointer type required.");
@@ -909,7 +2433,7 @@
         break;  // hit one of our sentinels
       } else if (proj_in->is_Call()) {
         CallNode *call = proj_in->as_Call();
-        if (!call->may_modify(toop, phase)) {
+        if (!call->may_modify(toop, igvn)) {
           result = call->in(TypeFunc::Memory);
         }
       } else if (proj_in->is_Initialize()) {
@@ -928,7 +2452,7 @@
       if (result == mmem->base_memory()) {
         // Didn't find instance memory, search through general slice recursively.
         result = mmem->memory_at(C->get_general_index(alias_idx));
-        result = find_inst_mem(result, alias_idx, orig_phis, phase);
+        result = find_inst_mem(result, alias_idx, orig_phis);
         if (C->failing()) {
           return NULL;
         }
@@ -936,7 +2460,7 @@
       }
     } else if (result->is_Phi() &&
                C->get_alias_index(result->as_Phi()->adr_type()) != alias_idx) {
-      Node *un = result->as_Phi()->unique_input(phase);
+      Node *un = result->as_Phi()->unique_input(igvn);
       if (un != NULL) {
         orig_phis.append_if_missing(result->as_Phi());
         result = un;
@@ -944,7 +2468,7 @@
         break;
       }
     } else if (result->is_ClearArray()) {
-      if (!ClearArrayNode::step_through(&result, (uint)toop->instance_id(), phase)) {
+      if (!ClearArrayNode::step_through(&result, (uint)toop->instance_id(), igvn)) {
         // Can not bypass initialization of the instance
         // we are looking for.
         break;
@@ -952,7 +2476,7 @@
       // Otherwise skip it (the call updated 'result' value).
     } else if (result->Opcode() == Op_SCMemProj) {
       assert(result->in(0)->is_LoadStore(), "sanity");
-      const Type *at = phase->type(result->in(0)->in(MemNode::Address));
+      const Type *at = igvn->type(result->in(0)->in(MemNode::Address));
       if (at != Type::TOP) {
         assert (at->isa_ptr() != NULL, "pointer type required.");
         int idx = C->get_alias_index(at->is_ptr());
@@ -972,7 +2496,7 @@
       orig_phis.append_if_missing(mphi);
     } else if (C->get_alias_index(t) != alias_idx) {
       // Create a new Phi with the specified alias index type.
-      result = split_memory_phi(mphi, alias_idx, orig_phis, phase);
+      result = split_memory_phi(mphi, alias_idx, orig_phis);
     }
   }
   // the result is either MemNode, PhiNode, InitializeNode.
@@ -1071,12 +2595,12 @@
 void ConnectionGraph::split_unique_types(GrowableArray<Node *>  &alloc_worklist) {
   GrowableArray<Node *>  memnode_worklist;
   GrowableArray<PhiNode *>  orig_phis;
-
   PhaseIterGVN  *igvn = _igvn;
   uint new_index_start = (uint) _compile->num_alias_types();
   Arena* arena = Thread::current()->resource_area();
   VectorSet visited(arena);
-
+  ideal_nodes.clear(); // Reset for use with set_map/get_map.
+  uint unique_old = _compile->unique();
 
   //  Phase 1:  Process possible allocations from alloc_worklist.
   //  Create instance types for the CheckCastPP for allocations where possible.
@@ -1088,17 +2612,15 @@
   while (alloc_worklist.length() != 0) {
     Node *n = alloc_worklist.pop();
     uint ni = n->_idx;
-    const TypeOopPtr* tinst = NULL;
     if (n->is_Call()) {
       CallNode *alloc = n->as_Call();
       // copy escape information to call node
       PointsToNode* ptn = ptnode_adr(alloc->_idx);
-      PointsToNode::EscapeState es = escape_state(alloc);
+      PointsToNode::EscapeState es = ptn->escape_state();
       // We have an allocation or call which returns a Java object,
       // see if it is unescaped.
       if (es != PointsToNode::NoEscape || !ptn->scalar_replaceable())
         continue;
-
       // Find CheckCastPP for the allocate or for the return value of a call
       n = alloc->result_cast();
       if (n == NULL) {            // No uses except Initialize node
@@ -1145,20 +2667,18 @@
         // so it could be eliminated.
         alloc->as_Allocate()->_is_scalar_replaceable = true;
       }
-      set_escape_state(n->_idx, es); // CheckCastPP escape state
+      set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state
       // in order for an object to be scalar-replaceable, it must be:
       //   - a direct allocation (not a call returning an object)
       //   - non-escaping
       //   - eligible to be a unique type
       //   - not determined to be ineligible by escape analysis
-      assert(ptnode_adr(alloc->_idx)->_node != NULL &&
-             ptnode_adr(n->_idx)->_node != NULL, "should be registered");
-      set_map(alloc->_idx, n);
-      set_map(n->_idx, alloc);
+      set_map(alloc, n);
+      set_map(n, alloc);
       const TypeOopPtr *t = igvn->type(n)->isa_oopptr();
       if (t == NULL)
         continue;  // not a TypeOopPtr
-      tinst = t->cast_to_exactness(true)->is_oopptr()->cast_to_instance_id(ni);
+      const TypeOopPtr* tinst = t->cast_to_exactness(true)->is_oopptr()->cast_to_instance_id(ni);
       igvn->hash_delete(n);
       igvn->set_type(n,  tinst);
       n->raise_bottom_type(tinst);
@@ -1168,9 +2688,10 @@
 
         // First, put on the worklist all Field edges from Connection Graph
         // which is more accurate then putting immediate users from Ideal Graph.
-        for (uint e = 0; e < ptn->edge_count(); e++) {
-          Node *use = ptnode_adr(ptn->edge_target(e))->_node;
-          assert(ptn->edge_type(e) == PointsToNode::FieldEdge && use->is_AddP(),
+        for (EdgeIterator e(ptn); e.has_next(); e.next()) {
+          PointsToNode* tgt = e.get();
+          Node* use = tgt->ideal_node();
+          assert(tgt->is_Field() && use->is_AddP(),
                  "only AddP nodes are Field edges in CG");
           if (use->outcnt() > 0) { // Don't process dead nodes
             Node* addp2 = find_second_addp(use, use->in(AddPNode::Base));
@@ -1202,16 +2723,18 @@
         }
       }
     } else if (n->is_AddP()) {
-      VectorSet* ptset = PointsTo(get_addp_base(n));
-      assert(ptset->Size() == 1, "AddP address is unique");
-      uint elem = ptset->getelem(); // Allocation node's index
-      if (elem == _phantom_object) {
-        assert(false, "escaped allocation");
-        continue; // Assume the value was set outside this method.
+      JavaObjectNode* jobj = unique_java_object(get_addp_base(n));
+      if (jobj == NULL || jobj == phantom_obj) {
+#ifdef ASSERT
+        ptnode_adr(get_addp_base(n)->_idx)->dump();
+        ptnode_adr(n->_idx)->dump();
+        assert(jobj != NULL && jobj != phantom_obj, "escaped allocation");
+#endif
+        _compile->record_failure(C2Compiler::retry_no_escape_analysis());
+        return;
       }
-      Node *base = get_map(elem);  // CheckCastPP node
-      if (!split_AddP(n, base, igvn)) continue; // wrong type from dead path
-      tinst = igvn->type(base)->isa_oopptr();
+      Node *base = get_map(jobj->idx());  // CheckCastPP node
+      if (!split_AddP(n, base)) continue; // wrong type from dead path
     } else if (n->is_Phi() ||
                n->is_CheckCastPP() ||
                n->is_EncodeP() ||
@@ -1221,18 +2744,20 @@
         assert(n->is_Phi(), "loops only through Phi's");
         continue;  // already processed
       }
-      VectorSet* ptset = PointsTo(n);
-      if (ptset->Size() == 1) {
-        uint elem = ptset->getelem(); // Allocation node's index
-        if (elem == _phantom_object) {
-          assert(false, "escaped allocation");
-          continue; // Assume the value was set outside this method.
-        }
-        Node *val = get_map(elem);   // CheckCastPP node
+      JavaObjectNode* jobj = unique_java_object(n);
+      if (jobj == NULL || jobj == phantom_obj) {
+#ifdef ASSERT
+        ptnode_adr(n->_idx)->dump();
+        assert(jobj != NULL && jobj != phantom_obj, "escaped allocation");
+#endif
+        _compile->record_failure(C2Compiler::retry_no_escape_analysis());
+        return;
+      } else {
+        Node *val = get_map(jobj->idx());   // CheckCastPP node
         TypeNode *tn = n->as_Type();
-        tinst = igvn->type(val)->isa_oopptr();
+        const TypeOopPtr* tinst = igvn->type(val)->isa_oopptr();
         assert(tinst != NULL && tinst->is_known_instance() &&
-               (uint)tinst->instance_id() == elem , "instance type expected.");
+               tinst->instance_id() == jobj->idx() , "instance type expected.");
 
         const Type *tn_type = igvn->type(tn);
         const TypeOopPtr *tn_t;
@@ -1241,7 +2766,6 @@
         } else {
           tn_t = tn_type->isa_oopptr();
         }
-
         if (tn_t != NULL && tinst->klass()->is_subtype_of(tn_t->klass())) {
           if (tn_type->isa_narrowoop()) {
             tn_type = tinst->make_narrowoop();
@@ -1314,13 +2838,13 @@
   }
   // New alias types were created in split_AddP().
   uint new_index_end = (uint) _compile->num_alias_types();
+  assert(unique_old == _compile->unique(), "there should be no new ideal nodes after Phase 1");
 
   //  Phase 2:  Process MemNode's from memnode_worklist. compute new address type and
   //            compute new values for Memory inputs  (the Memory inputs are not
   //            actually updated until phase 4.)
   if (memnode_worklist.length() == 0)
     return;  // nothing to do
-
   while (memnode_worklist.length() != 0) {
     Node *n = memnode_worklist.pop();
     if (visited.test_set(n->_idx))
@@ -1341,17 +2865,14 @@
       assert (addr_t->isa_ptr() != NULL, "pointer type required.");
       int alias_idx = _compile->get_alias_index(addr_t->is_ptr());
       assert ((uint)alias_idx < new_index_end, "wrong alias index");
-      Node *mem = find_inst_mem(n->in(MemNode::Memory), alias_idx, orig_phis, igvn);
+      Node *mem = find_inst_mem(n->in(MemNode::Memory), alias_idx, orig_phis);
       if (_compile->failing()) {
         return;
       }
       if (mem != n->in(MemNode::Memory)) {
         // We delay the memory edge update since we need old one in
         // MergeMem code below when instances memory slices are separated.
-        debug_only(Node* pn = ptnode_adr(n->_idx)->_node;)
-        assert(pn == NULL || pn == n, "wrong node");
-        set_map(n->_idx, mem);
-        ptnode_adr(n->_idx)->_node = n;
+        set_map(n, mem);
       }
       if (n->is_Load()) {
         continue;  // don't push users
@@ -1442,7 +2963,7 @@
         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)) {
-            Node* result = find_inst_mem(mem, ni, orig_phis, igvn);
+            Node* result = find_inst_mem(mem, ni, orig_phis);
             if (_compile->failing()) {
               return;
             }
@@ -1458,7 +2979,7 @@
       if (result == nmm->base_memory()) {
         // Didn't find instance memory, search through general slice recursively.
         result = nmm->memory_at(_compile->get_general_index(ni));
-        result = find_inst_mem(result, ni, orig_phis, igvn);
+        result = find_inst_mem(result, ni, orig_phis);
         if (_compile->failing()) {
           return;
         }
@@ -1482,7 +3003,7 @@
     igvn->hash_delete(phi);
     for (uint i = 1; i < phi->req(); i++) {
       Node *mem = phi->in(i);
-      Node *new_mem = find_inst_mem(mem, alias_idx, orig_phis, igvn);
+      Node *new_mem = find_inst_mem(mem, alias_idx, orig_phis);
       if (_compile->failing()) {
         return;
       }
@@ -1496,39 +3017,36 @@
 
   // Update the memory inputs of MemNodes with the value we computed
   // in Phase 2 and move stores memory users to corresponding memory slices.
-
   // Disable memory split verification code until the fix for 6984348.
   // Currently it produces false negative results since it does not cover all cases.
 #if 0 // ifdef ASSERT
   visited.Reset();
   Node_Stack old_mems(arena, _compile->unique() >> 2);
 #endif
-  for (uint i = 0; i < nodes_size(); i++) {
-    Node *nmem = get_map(i);
-    if (nmem != NULL) {
-      Node *n = ptnode_adr(i)->_node;
-      assert(n != NULL, "sanity");
-      if (n->is_Mem()) {
+  for (uint i = 0; i < ideal_nodes.size(); i++) {
+    Node*    n = ideal_nodes.at(i);
+    Node* nmem = get_map(n->_idx);
+    assert(nmem != NULL, "sanity");
+    if (n->is_Mem()) {
 #if 0 // ifdef ASSERT
-        Node* old_mem = n->in(MemNode::Memory);
-        if (!visited.test_set(old_mem->_idx)) {
-          old_mems.push(old_mem, old_mem->outcnt());
-        }
+      Node* old_mem = n->in(MemNode::Memory);
+      if (!visited.test_set(old_mem->_idx)) {
+        old_mems.push(old_mem, old_mem->outcnt());
+      }
 #endif
-        assert(n->in(MemNode::Memory) != nmem, "sanity");
-        if (!n->is_Load()) {
-          // Move memory users of a store first.
-          move_inst_mem(n, orig_phis, igvn);
-        }
-        // Now update memory input
-        igvn->hash_delete(n);
-        n->set_req(MemNode::Memory, nmem);
-        igvn->hash_insert(n);
-        record_for_optimizer(n);
-      } else {
-        assert(n->is_Allocate() || n->is_CheckCastPP() ||
-               n->is_AddP() || n->is_Phi(), "unknown node used for set_map()");
+      assert(n->in(MemNode::Memory) != nmem, "sanity");
+      if (!n->is_Load()) {
+        // Move memory users of a store first.
+        move_inst_mem(n, orig_phis);
       }
+      // Now update memory input
+      igvn->hash_delete(n);
+      n->set_req(MemNode::Memory, nmem);
+      igvn->hash_insert(n);
+      record_for_optimizer(n);
+    } else {
+      assert(n->is_Allocate() || n->is_CheckCastPP() ||
+             n->is_AddP() || n->is_Phi(), "unknown node used for set_map()");
     }
   }
 #if 0 // ifdef ASSERT
@@ -1542,1597 +3060,72 @@
 #endif
 }
 
-bool ConnectionGraph::has_candidates(Compile *C) {
-  // EA brings benefits only when the code has allocations and/or locks which
-  // are represented by ideal Macro nodes.
-  int cnt = C->macro_count();
-  for( int i=0; i < cnt; i++ ) {
-    Node *n = C->macro_node(i);
-    if ( n->is_Allocate() )
-      return true;
-    if( n->is_Lock() ) {
-      Node* obj = n->as_Lock()->obj_node()->uncast();
-      if( !(obj->is_Parm() || obj->is_Con()) )
-        return true;
-    }
-  }
-  return false;
-}
-
-void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
-  // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction
-  // to create space for them in ConnectionGraph::_nodes[].
-  Node* oop_null = igvn->zerocon(T_OBJECT);
-  Node* noop_null = igvn->zerocon(T_NARROWOOP);
-
-  ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
-  // Perform escape analysis
-  if (congraph->compute_escape()) {
-    // There are non escaping objects.
-    C->set_congraph(congraph);
-  }
-
-  // Cleanup.
-  if (oop_null->outcnt() == 0)
-    igvn->hash_delete(oop_null);
-  if (noop_null->outcnt() == 0)
-    igvn->hash_delete(noop_null);
-}
-
-bool ConnectionGraph::compute_escape() {
-  Compile* C = _compile;
-
-  // 1. Populate Connection Graph (CG) with Ideal nodes.
-
-  Unique_Node_List worklist_init;
-  worklist_init.map(C->unique(), NULL);  // preallocate space
-
-  // Initialize worklist
-  if (C->root() != NULL) {
-    worklist_init.push(C->root());
-  }
-
-  GrowableArray<Node*> alloc_worklist;
-  GrowableArray<Node*> addp_worklist;
-  GrowableArray<Node*> ptr_cmp_worklist;
-  GrowableArray<Node*> storestore_worklist;
-  PhaseGVN* igvn = _igvn;
-
-  // Push all useful nodes onto CG list and set their type.
-  for( uint next = 0; next < worklist_init.size(); ++next ) {
-    Node* n = worklist_init.at(next);
-    record_for_escape_analysis(n, igvn);
-    // Only allocations and java static calls results are checked
-    // for an escape status. See process_call_result() below.
-    if (n->is_Allocate() || n->is_CallStaticJava() &&
-        ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) {
-      alloc_worklist.append(n);
-    } else if(n->is_AddP()) {
-      // Collect address nodes. Use them during stage 3 below
-      // to build initial connection graph field edges.
-      addp_worklist.append(n);
-    } else if (n->is_MergeMem()) {
-      // Collect all MergeMem nodes to add memory slices for
-      // scalar replaceable objects in split_unique_types().
-      _mergemem_worklist.append(n->as_MergeMem());
-    } else if (OptimizePtrCompare && n->is_Cmp() &&
-               (n->Opcode() == Op_CmpP || n->Opcode() == Op_CmpN)) {
-      // Compare pointers nodes
-      ptr_cmp_worklist.append(n);
-    } else if (n->is_MemBarStoreStore()) {
-      // Collect all MemBarStoreStore nodes so that depending on the
-      // escape status of the associated Allocate node some of them
-      // may be eliminated.
-      storestore_worklist.append(n);
-    }
-    for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
-      Node* m = n->fast_out(i);   // Get user
-      worklist_init.push(m);
-    }
-  }
-
-  if (alloc_worklist.length() == 0) {
-    _collecting = false;
-    return false; // Nothing to do.
-  }
-
-  // 2. First pass to create simple CG edges (doesn't require to walk CG).
-  uint delayed_size = _delayed_worklist.size();
-  for( uint next = 0; next < delayed_size; ++next ) {
-    Node* n = _delayed_worklist.at(next);
-    build_connection_graph(n, igvn);
-  }
-
-  // 3. Pass to create initial fields edges (JavaObject -F-> AddP)
-  //    to reduce number of iterations during stage 4 below.
-  uint addp_length = addp_worklist.length();
-  for( uint next = 0; next < addp_length; ++next ) {
-    Node* n = addp_worklist.at(next);
-    Node* base = get_addp_base(n);
-    if (base->is_Proj() && base->in(0)->is_Call())
-      base = base->in(0);
-    PointsToNode::NodeType nt = ptnode_adr(base->_idx)->node_type();
-    if (nt == PointsToNode::JavaObject) {
-      build_connection_graph(n, igvn);
-    }
-  }
-
-  GrowableArray<int> cg_worklist;
-  cg_worklist.append(_phantom_object);
-  GrowableArray<uint>  worklist;
-
-  // 4. Build Connection Graph which need
-  //    to walk the connection graph.
-  _progress = false;
-  for (uint ni = 0; ni < nodes_size(); ni++) {
-    PointsToNode* ptn = ptnode_adr(ni);
-    Node *n = ptn->_node;
-    if (n != NULL) { // Call, AddP, LoadP, StoreP
-      build_connection_graph(n, igvn);
-      if (ptn->node_type() != PointsToNode::UnknownType)
-        cg_worklist.append(n->_idx); // Collect CG nodes
-      if (!_processed.test(n->_idx))
-        worklist.append(n->_idx); // Collect C/A/L/S nodes
-    }
-  }
-
-  // After IGVN user nodes may have smaller _idx than
-  // their inputs so they will be processed first in
-  // previous loop. Because of that not all Graph
-  // edges will be created. Walk over interesting
-  // nodes again until no new edges are created.
-  //
-  // Normally only 1-3 passes needed to build
-  // Connection Graph depending on graph complexity.
-  // Observed 8 passes in jvm2008 compiler.compiler.
-  // Set limit to 20 to catch situation when something
-  // did go wrong and recompile the method without EA.
-  // Also limit build time to 30 sec (60 in debug VM).
-
-#define CG_BUILD_ITER_LIMIT 20
-
-#ifdef ASSERT
-#define CG_BUILD_TIME_LIMIT 60.0
-#else
-#define CG_BUILD_TIME_LIMIT 30.0
-#endif
+#ifndef PRODUCT
+static const char *node_type_names[] = {
+  "UnknownType",
+  "JavaObject",
+  "LocalVar",
+  "Field",
+  "Arraycopy"
+};
 
-  uint length = worklist.length();
-  int iterations = 0;
-  elapsedTimer time;
-  while(_progress &&
-        (iterations++   < CG_BUILD_ITER_LIMIT) &&
-        (time.seconds() < CG_BUILD_TIME_LIMIT)) {
-    time.start();
-    _progress = false;
-    for( uint next = 0; next < length; ++next ) {
-      int ni = worklist.at(next);
-      PointsToNode* ptn = ptnode_adr(ni);
-      Node* n = ptn->_node;
-      assert(n != NULL, "should be known node");
-      build_connection_graph(n, igvn);
-    }
-    time.stop();
-  }
-  if ((iterations     >= CG_BUILD_ITER_LIMIT) ||
-      (time.seconds() >= CG_BUILD_TIME_LIMIT)) {
-    assert(false, err_msg("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
-           time.seconds(), iterations, nodes_size(), length));
-    // Possible infinite build_connection_graph loop,
-    // bailout (no changes to ideal graph were made).
-    _collecting = false;
-    return false;
-  }
-#undef CG_BUILD_ITER_LIMIT
-#undef CG_BUILD_TIME_LIMIT
-
-  // 5. Propagate escaped states.
-  worklist.clear();
-
-  // mark all nodes reachable from GlobalEscape nodes
-  (void)propagate_escape_state(&cg_worklist, &worklist, PointsToNode::GlobalEscape);
-
-  // mark all nodes reachable from ArgEscape nodes
-  bool has_non_escaping_obj = propagate_escape_state(&cg_worklist, &worklist, PointsToNode::ArgEscape);
-
-  Arena* arena = Thread::current()->resource_area();
-  VectorSet visited(arena);
-
-  // 6. Find fields initializing values for not escaped allocations
-  uint alloc_length = alloc_worklist.length();
-  for (uint next = 0; next < alloc_length; ++next) {
-    Node* n = alloc_worklist.at(next);
-    PointsToNode::EscapeState es = ptnode_adr(n->_idx)->escape_state();
-    if (es == PointsToNode::NoEscape) {
-      has_non_escaping_obj = true;
-      if (n->is_Allocate()) {
-        find_init_values(n, &visited, igvn);
-        // The object allocated by this Allocate node will never be
-        // seen by an other thread. Mark it so that when it is
-        // expanded no MemBarStoreStore is added.
-        n->as_Allocate()->initialization()->set_does_not_escape();
-      }
-    } else if ((es == PointsToNode::ArgEscape) && n->is_Allocate()) {
-      // Same as above. Mark this Allocate node so that when it is
-      // expanded no MemBarStoreStore is added.
-      n->as_Allocate()->initialization()->set_does_not_escape();
-    }
-  }
-
-  uint cg_length = cg_worklist.length();
-
-  // Skip the rest of code if all objects escaped.
-  if (!has_non_escaping_obj) {
-    cg_length = 0;
-    addp_length = 0;
-  }
-
-  for (uint next = 0; next < cg_length; ++next) {
-    int ni = cg_worklist.at(next);
-    PointsToNode* ptn = ptnode_adr(ni);
-    PointsToNode::NodeType nt = ptn->node_type();
-    if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
-      if (ptn->edge_count() == 0) {
-        // No values were found. Assume the value was set
-        // outside this method - add edge to phantom object.
-        add_pointsto_edge(ni, _phantom_object);
-      }
-    }
-  }
-
-  // 7. Remove deferred edges from the graph.
-  for (uint next = 0; next < cg_length; ++next) {
-    int ni = cg_worklist.at(next);
-    PointsToNode* ptn = ptnode_adr(ni);
-    PointsToNode::NodeType nt = ptn->node_type();
-    if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
-      remove_deferred(ni, &worklist, &visited);
-    }
-  }
-
-  // 8. Adjust escape state of nonescaping objects.
-  for (uint next = 0; next < addp_length; ++next) {
-    Node* n = addp_worklist.at(next);
-    adjust_escape_state(n);
-  }
-
-  // push all NoEscape nodes on the worklist
-  worklist.clear();
-  for( uint next = 0; next < cg_length; ++next ) {
-    int nk = cg_worklist.at(next);
-    if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape &&
-        !is_null_ptr(nk))
-      worklist.push(nk);
-  }
-
-  alloc_worklist.clear();
-  // Propagate scalar_replaceable value.
-  while(worklist.length() > 0) {
-    uint nk = worklist.pop();
-    PointsToNode* ptn = ptnode_adr(nk);
-    Node* n = ptn->_node;
-    bool scalar_replaceable = ptn->scalar_replaceable();
-    if (n->is_Allocate() && scalar_replaceable) {
-      // Push scalar replaceable allocations on alloc_worklist
-      // for processing in split_unique_types(). Note,
-      // following code may change scalar_replaceable value.
-      alloc_worklist.append(n);
-    }
-    uint e_cnt = ptn->edge_count();
-    for (uint ei = 0; ei < e_cnt; ei++) {
-      uint npi = ptn->edge_target(ei);
-      if (is_null_ptr(npi))
-        continue;
-      PointsToNode *np = ptnode_adr(npi);
-      if (np->escape_state() < PointsToNode::NoEscape) {
-        set_escape_state(npi, PointsToNode::NoEscape);
-        if (!scalar_replaceable) {
-          np->set_scalar_replaceable(false);
-        }
-        worklist.push(npi);
-      } else if (np->scalar_replaceable() && !scalar_replaceable) {
-        np->set_scalar_replaceable(false);
-        worklist.push(npi);
-      }
-    }
-  }
-
-  _collecting = false;
-  assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build");
-
-  assert(ptnode_adr(_oop_null)->escape_state() == PointsToNode::NoEscape &&
-         ptnode_adr(_oop_null)->edge_count() == 0, "sanity");
-  if (UseCompressedOops) {
-    assert(ptnode_adr(_noop_null)->escape_state() == PointsToNode::NoEscape &&
-           ptnode_adr(_noop_null)->edge_count() == 0, "sanity");
-  }
-
-  if (EliminateLocks && has_non_escaping_obj) {
-    // Mark locks before changing ideal graph.
-    int cnt = C->macro_count();
-    for( int i=0; i < cnt; i++ ) {
-      Node *n = C->macro_node(i);
-      if (n->is_AbstractLock()) { // Lock and Unlock nodes
-        AbstractLockNode* alock = n->as_AbstractLock();
-        if (!alock->is_non_esc_obj()) {
-          PointsToNode::EscapeState es = escape_state(alock->obj_node());
-          assert(es != PointsToNode::UnknownEscape, "should know");
-          if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
-            assert(!alock->is_eliminated() || alock->is_coarsened(), "sanity");
-            // The lock could be marked eliminated by lock coarsening
-            // code during first IGVN before EA. Replace coarsened flag
-            // to eliminate all associated locks/unlocks.
-            alock->set_non_esc_obj();
-          }
-        }
-      }
-    }
-  }
-
-  if (OptimizePtrCompare && has_non_escaping_obj) {
-    // Add ConI(#CC_GT) and ConI(#CC_EQ).
-    _pcmp_neq = igvn->makecon(TypeInt::CC_GT);
-    _pcmp_eq = igvn->makecon(TypeInt::CC_EQ);
-    // Optimize objects compare.
-    while (ptr_cmp_worklist.length() != 0) {
-      Node *n = ptr_cmp_worklist.pop();
-      Node *res = optimize_ptr_compare(n);
-      if (res != NULL) {
-#ifndef PRODUCT
-        if (PrintOptimizePtrCompare) {
-          tty->print_cr("++++ Replaced: %d %s(%d,%d) --> %s", n->_idx, (n->Opcode() == Op_CmpP ? "CmpP" : "CmpN"), n->in(1)->_idx, n->in(2)->_idx, (res == _pcmp_eq ? "EQ" : "NotEQ"));
-          if (Verbose) {
-            n->dump(1);
-          }
-        }
-#endif
-        _igvn->replace_node(n, res);
-      }
-    }
-    // cleanup
-    if (_pcmp_neq->outcnt() == 0)
-      igvn->hash_delete(_pcmp_neq);
-    if (_pcmp_eq->outcnt()  == 0)
-      igvn->hash_delete(_pcmp_eq);
-  }
+static const char *esc_names[] = {
+  "UnknownEscape",
+  "NoEscape",
+  "ArgEscape",
+  "GlobalEscape"
+};
 
-  // For MemBarStoreStore nodes added in library_call.cpp, check
-  // escape status of associated AllocateNode and optimize out
-  // MemBarStoreStore node if the allocated object never escapes.
-  while (storestore_worklist.length() != 0) {
-    Node *n = storestore_worklist.pop();
-    MemBarStoreStoreNode *storestore = n ->as_MemBarStoreStore();
-    Node *alloc = storestore->in(MemBarNode::Precedent)->in(0);
-    assert (alloc->is_Allocate(), "storestore should point to AllocateNode");
-    PointsToNode::EscapeState es = ptnode_adr(alloc->_idx)->escape_state();
-    if (es == PointsToNode::NoEscape || es == PointsToNode::ArgEscape) {
-      MemBarNode* mb = MemBarNode::make(C, Op_MemBarCPUOrder, Compile::AliasIdxBot);
-      mb->init_req(TypeFunc::Memory, storestore->in(TypeFunc::Memory));
-      mb->init_req(TypeFunc::Control, storestore->in(TypeFunc::Control));
-
-      _igvn->register_new_node_with_optimizer(mb);
-      _igvn->replace_node(storestore, mb);
-    }
-  }
-
-#ifndef PRODUCT
-  if (PrintEscapeAnalysis) {
-    dump(); // Dump ConnectionGraph
-  }
-#endif
-
-  bool has_scalar_replaceable_candidates = false;
-  alloc_length = alloc_worklist.length();
-  for (uint next = 0; next < alloc_length; ++next) {
-    Node* n = alloc_worklist.at(next);
-    PointsToNode* ptn = ptnode_adr(n->_idx);
-    assert(ptn->escape_state() == PointsToNode::NoEscape, "sanity");
-    if (ptn->scalar_replaceable()) {
-      has_scalar_replaceable_candidates = true;
-      break;
-    }
-  }
-
-  if ( has_scalar_replaceable_candidates &&
-       C->AliasLevel() >= 3 && EliminateAllocations ) {
-
-    // Now use the escape information to create unique types for
-    // scalar replaceable objects.
-    split_unique_types(alloc_worklist);
-
-    if (C->failing())  return false;
-
-    C->print_method("After Escape Analysis", 2);
-
-#ifdef ASSERT
-  } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) {
-    tty->print("=== No allocations eliminated for ");
-    C->method()->print_short_name();
-    if(!EliminateAllocations) {
-      tty->print(" since EliminateAllocations is off ===");
-    } else if(!has_scalar_replaceable_candidates) {
-      tty->print(" since there are no scalar replaceable candidates ===");
-    } else if(C->AliasLevel() < 3) {
-      tty->print(" since AliasLevel < 3 ===");
-    }
-    tty->cr();
-#endif
+void PointsToNode::dump(bool print_state) const {
+  NodeType nt = node_type();
+  tty->print("%s ", node_type_names[(int) nt]);
+  if (print_state) {
+    EscapeState es = escape_state();
+    EscapeState fields_es = fields_escape_state();
+    tty->print("%s(%s) ", esc_names[(int)es], esc_names[(int)fields_es]);
+    if (nt == PointsToNode::JavaObject && !this->scalar_replaceable())
+      tty->print("NSR");
   }
-  return has_non_escaping_obj;
-}
-
-// Find fields initializing values for allocations.
-void ConnectionGraph::find_init_values(Node* alloc, VectorSet* visited, PhaseTransform* phase) {
-  assert(alloc->is_Allocate(), "Should be called for Allocate nodes only");
-  PointsToNode* pta = ptnode_adr(alloc->_idx);
-  assert(pta->escape_state() == PointsToNode::NoEscape, "Not escaped Allocate nodes only");
-  InitializeNode* ini = alloc->as_Allocate()->initialization();
-
-  Compile* C = _compile;
-  visited->Reset();
-  // Check if a oop field's initializing value is recorded and add
-  // a corresponding NULL field's value if it is not recorded.
-  // Connection Graph does not record a default initialization by NULL
-  // captured by Initialize node.
-  //
-  uint null_idx = UseCompressedOops ? _noop_null : _oop_null;
-  uint ae_cnt = pta->edge_count();
-  bool visited_bottom_offset = false;
-  for (uint ei = 0; ei < ae_cnt; ei++) {
-    uint nidx = pta->edge_target(ei); // Field (AddP)
-    PointsToNode* ptn = ptnode_adr(nidx);
-    assert(ptn->_node->is_AddP(), "Should be AddP nodes only");
-    int offset = ptn->offset();
-    if (offset == Type::OffsetBot) {
-      if (!visited_bottom_offset) {
-        visited_bottom_offset = true;
-        // Check only oop fields.
-        const Type* adr_type = ptn->_node->as_AddP()->bottom_type();
-        if (!adr_type->isa_aryptr() ||
-            (adr_type->isa_aryptr()->klass() == NULL) ||
-             adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
-          // OffsetBot is used to reference array's element,
-          // always add reference to NULL since we don't
-          // known which element is referenced.
-          add_edge_from_fields(alloc->_idx, null_idx, offset);
-        }
-      }
-    } else if (offset != oopDesc::klass_offset_in_bytes() &&
-               !visited->test_set(offset)) {
-
-      // Check only oop fields.
-      const Type* adr_type = ptn->_node->as_AddP()->bottom_type();
-      BasicType basic_field_type = T_INT;
-      if (adr_type->isa_instptr()) {
-        ciField* field = C->alias_type(adr_type->isa_instptr())->field();
-        if (field != NULL) {
-          basic_field_type = field->layout_type();
-        } else {
-          // Ignore non field load (for example, klass load)
-        }
-      } else if (adr_type->isa_aryptr()) {
-        if (offset != arrayOopDesc::length_offset_in_bytes()) {
-          const Type* elemtype = adr_type->isa_aryptr()->elem();
-          basic_field_type = elemtype->array_element_basic_type();
-        } else {
-          // Ignore array length load
-        }
-#ifdef ASSERT
-      } else {
-        // Raw pointers are used for initializing stores so skip it
-        // since it should be recorded already
-        Node* base = get_addp_base(ptn->_node);
-        assert(adr_type->isa_rawptr() && base->is_Proj() &&
-               (base->in(0) == alloc),"unexpected pointer type");
-#endif
-      }
-      if (basic_field_type == T_OBJECT ||
-          basic_field_type == T_NARROWOOP ||
-          basic_field_type == T_ARRAY) {
-        Node* value = NULL;
-        if (ini != NULL) {
-          BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT;
-          Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase);
-          if (store != NULL && store->is_Store()) {
-            value = store->in(MemNode::ValueIn);
-          } else if (ptn->edge_count() > 0) { // Are there oop stores?
-            // Check for a store which follows allocation without branches.
-            // For example, a volatile field store is not collected
-            // by Initialize node. TODO: it would be nice to use idom() here.
-            //
-            // Search all references to the same field which use different
-            // AddP nodes, for example, in the next case:
-            //
-            //    Point p[] = new Point[1];
-            //    if ( x ) { p[0] = new Point(); p[0].x = x; }
-            //    if ( p[0] != null ) { y = p[0].x; } // has CastPP
-            //
-            for (uint next = ei; (next < ae_cnt) && (value == NULL); next++) {
-              uint fpi = pta->edge_target(next); // Field (AddP)
-              PointsToNode *ptf = ptnode_adr(fpi);
-              if (ptf->offset() == offset) {
-                Node* nf = ptf->_node;
-                for (DUIterator_Fast imax, i = nf->fast_outs(imax); i < imax; i++) {
-                  store = nf->fast_out(i);
-                  if (store->is_Store() && store->in(0) != NULL) {
-                    Node* ctrl = store->in(0);
-                    while(!(ctrl == ini || ctrl == alloc || ctrl == NULL ||
-                            ctrl == C->root() || ctrl == C->top() || ctrl->is_Region() ||
-                            ctrl->is_IfTrue() || ctrl->is_IfFalse())) {
-                       ctrl = ctrl->in(0);
-                    }
-                    if (ctrl == ini || ctrl == alloc) {
-                      value = store->in(MemNode::ValueIn);
-                      break;
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-        if (value == NULL || value != ptnode_adr(value->_idx)->_node) {
-          // A field's initializing value was not recorded. Add NULL.
-          add_edge_from_fields(alloc->_idx, null_idx, offset);
-        }
-      }
+  if (is_Field()) {
+    FieldNode* f = (FieldNode*)this;
+    tty->print("(");
+    for (BaseIterator i(f); i.has_next(); i.next()) {
+      PointsToNode* b = i.get();
+      tty->print(" %d%s", b->idx(),(b->is_JavaObject() ? "P" : ""));
     }
+    tty->print(" )");
   }
-}
-
-// Adjust escape state after Connection Graph is built.
-void ConnectionGraph::adjust_escape_state(Node* n) {
-  PointsToNode* ptn = ptnode_adr(n->_idx);
-  assert(n->is_AddP(), "Should be called for AddP nodes only");
-  // Search for objects which are not scalar replaceable
-  // and mark them to propagate the state to referenced objects.
-  //
-
-  int offset = ptn->offset();
-  Node* base = get_addp_base(n);
-  VectorSet* ptset = PointsTo(base);
-  int ptset_size = ptset->Size();
-
-  // An object is not scalar replaceable if the field which may point
-  // to it has unknown offset (unknown element of an array of objects).
-  //
-
-  if (offset == Type::OffsetBot) {
-    uint e_cnt = ptn->edge_count();
-    for (uint ei = 0; ei < e_cnt; ei++) {
-      uint npi = ptn->edge_target(ei);
-      ptnode_adr(npi)->set_scalar_replaceable(false);
-    }
-  }
-
-  // Currently an object is not scalar replaceable if a LoadStore node
-  // access its field since the field value is unknown after it.
-  //
-  bool has_LoadStore = false;
-  for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
-    Node *use = n->fast_out(i);
-    if (use->is_LoadStore()) {
-      has_LoadStore = true;
-      break;
-    }
+  tty->print("[");
+  for (EdgeIterator i(this); i.has_next(); i.next()) {
+    PointsToNode* e = i.get();
+    tty->print(" %d%s%s", e->idx(),(e->is_JavaObject() ? "P" : (e->is_Field() ? "F" : "")), e->is_Arraycopy() ? "cp" : "");
   }
-  // An object is not scalar replaceable if the address points
-  // to unknown field (unknown element for arrays, offset is OffsetBot).
-  //
-  // Or the address may point to more then one object. This may produce
-  // the false positive result (set not scalar replaceable)
-  // since the flow-insensitive escape analysis can't separate
-  // the case when stores overwrite the field's value from the case
-  // when stores happened on different control branches.
-  //
-  // Note: it will disable scalar replacement in some cases:
-  //
-  //    Point p[] = new Point[1];
-  //    p[0] = new Point(); // Will be not scalar replaced
-  //
-  // but it will save us from incorrect optimizations in next cases:
-  //
-  //    Point p[] = new Point[1];
-  //    if ( x ) p[0] = new Point(); // Will be not scalar replaced
-  //
-  if (ptset_size > 1 || ptset_size != 0 &&
-      (has_LoadStore || offset == Type::OffsetBot)) {
-    for( VectorSetI j(ptset); j.test(); ++j ) {
-      ptnode_adr(j.elem)->set_scalar_replaceable(false);
-    }
-  }
-}
-
-// Propagate escape states to referenced nodes.
-bool ConnectionGraph::propagate_escape_state(GrowableArray<int>* cg_worklist,
-                                             GrowableArray<uint>* worklist,
-                                             PointsToNode::EscapeState esc_state) {
-  bool has_java_obj = false;
-
-  // push all nodes with the same escape state on the worklist
-  uint cg_length = cg_worklist->length();
-  for (uint next = 0; next < cg_length; ++next) {
-    int nk = cg_worklist->at(next);
-    if (ptnode_adr(nk)->escape_state() == esc_state)
-      worklist->push(nk);
-  }
-  // mark all reachable nodes
-  while (worklist->length() > 0) {
-    int pt = worklist->pop();
-    PointsToNode* ptn = ptnode_adr(pt);
-    if (ptn->node_type() == PointsToNode::JavaObject &&
-        !is_null_ptr(pt)) {
-      has_java_obj = true;
-      if (esc_state > PointsToNode::NoEscape) {
-        // fields values are unknown if object escapes
-        add_edge_from_fields(pt, _phantom_object, Type::OffsetBot);
-      }
+  tty->print(" [");
+  for (UseIterator i(this); i.has_next(); i.next()) {
+    PointsToNode* u = i.get();
+    bool is_base = false;
+    if (PointsToNode::is_base_use(u)) {
+      is_base = true;
+      u = PointsToNode::get_use_node(u)->as_Field();
     }
-    uint e_cnt = ptn->edge_count();
-    for (uint ei = 0; ei < e_cnt; ei++) {
-      uint npi = ptn->edge_target(ei);
-      if (is_null_ptr(npi))
-        continue;
-      PointsToNode *np = ptnode_adr(npi);
-      if (np->escape_state() < esc_state) {
-        set_escape_state(npi, esc_state);
-        worklist->push(npi);
-      }
-    }
-  }
-  // Has not escaping java objects
-  return has_java_obj && (esc_state < PointsToNode::GlobalEscape);
-}
-
-// Optimize objects compare.
-Node* ConnectionGraph::optimize_ptr_compare(Node* n) {
-  assert(OptimizePtrCompare, "sanity");
-  // Clone returned Set since PointsTo() returns pointer
-  // to the same structure ConnectionGraph.pt_ptset.
-  VectorSet ptset1 = *PointsTo(n->in(1));
-  VectorSet ptset2 = *PointsTo(n->in(2));
-
-  // Check simple cases first.
-  if (ptset1.Size() == 1) {
-    uint pt1 = ptset1.getelem();
-    PointsToNode* ptn1 = ptnode_adr(pt1);
-    if (ptn1->escape_state() == PointsToNode::NoEscape) {
-      if (ptset2.Size() == 1 && ptset2.getelem() == pt1) {
-        // Comparing the same not escaping object.
-        return _pcmp_eq;
-      }
-      Node* obj = ptn1->_node;
-      // Comparing not escaping allocation.
-      if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
-          !ptset2.test(pt1)) {
-        return _pcmp_neq; // This includes nullness check.
-      }
-    }
-  } else if (ptset2.Size() == 1) {
-    uint pt2 = ptset2.getelem();
-    PointsToNode* ptn2 = ptnode_adr(pt2);
-    if (ptn2->escape_state() == PointsToNode::NoEscape) {
-      Node* obj = ptn2->_node;
-      // Comparing not escaping allocation.
-      if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
-          !ptset1.test(pt2)) {
-        return _pcmp_neq; // This includes nullness check.
-      }
-    }
+    tty->print(" %d%s%s", u->idx(), is_base ? "b" : "", u->is_Arraycopy() ? "cp" : "");
   }
-
-  if (!ptset1.disjoint(ptset2)) {
-    return NULL; // Sets are not disjoint
-  }
-
-  // Sets are disjoint.
-  bool set1_has_unknown_ptr = ptset1.test(_phantom_object) != 0;
-  bool set2_has_unknown_ptr = ptset2.test(_phantom_object) != 0;
-  bool set1_has_null_ptr   = (ptset1.test(_oop_null) | ptset1.test(_noop_null)) != 0;
-  bool set2_has_null_ptr   = (ptset2.test(_oop_null) | ptset2.test(_noop_null)) != 0;
-
-  if (set1_has_unknown_ptr && set2_has_null_ptr ||
-      set2_has_unknown_ptr && set1_has_null_ptr) {
-    // Check nullness of unknown object.
-    return NULL;
-  }
-
-  // Disjointness by itself is not sufficient since
-  // alias analysis is not complete for escaped objects.
-  // Disjoint sets are definitely unrelated only when
-  // at least one set has only not escaping objects.
-  if (!set1_has_unknown_ptr && !set1_has_null_ptr) {
-    bool has_only_non_escaping_alloc = true;
-    for (VectorSetI i(&ptset1); i.test(); ++i) {
-      uint pt = i.elem;
-      PointsToNode* ptn = ptnode_adr(pt);
-      Node* obj = ptn->_node;
-      if (ptn->escape_state() != PointsToNode::NoEscape ||
-          !(obj->is_Allocate() || obj->is_CallStaticJava())) {
-        has_only_non_escaping_alloc = false;
-        break;
-      }
-    }
-    if (has_only_non_escaping_alloc) {
-      return _pcmp_neq;
-    }
-  }
-  if (!set2_has_unknown_ptr && !set2_has_null_ptr) {
-    bool has_only_non_escaping_alloc = true;
-    for (VectorSetI i(&ptset2); i.test(); ++i) {
-      uint pt = i.elem;
-      PointsToNode* ptn = ptnode_adr(pt);
-      Node* obj = ptn->_node;
-      if (ptn->escape_state() != PointsToNode::NoEscape ||
-          !(obj->is_Allocate() || obj->is_CallStaticJava())) {
-        has_only_non_escaping_alloc = false;
-        break;
-      }
-    }
-    if (has_only_non_escaping_alloc) {
-      return _pcmp_neq;
-    }
-  }
-  return NULL;
+  tty->print(" ]]  ");
+  if (_node == NULL)
+    tty->print_cr("<null>");
+  else
+    _node->dump();
 }
 
-void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) {
-    bool is_arraycopy = false;
-    switch (call->Opcode()) {
-#ifdef ASSERT
-    case Op_Allocate:
-    case Op_AllocateArray:
-    case Op_Lock:
-    case Op_Unlock:
-      assert(false, "should be done already");
-      break;
-#endif
-    case Op_CallLeafNoFP:
-      is_arraycopy = (call->as_CallLeaf()->_name != NULL &&
-                      strstr(call->as_CallLeaf()->_name, "arraycopy") != 0);
-      // fall through
-    case Op_CallLeaf:
-    {
-      // Stub calls, objects do not escape but they are not scale replaceable.
-      // Adjust escape state for outgoing arguments.
-      const TypeTuple * d = call->tf()->domain();
-      bool src_has_oops = false;
-      for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
-        const Type* at = d->field_at(i);
-        Node *arg = call->in(i)->uncast();
-        const Type *aat = phase->type(arg);
-        PointsToNode::EscapeState arg_esc = ptnode_adr(arg->_idx)->escape_state();
-        if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() &&
-            (is_arraycopy || arg_esc < PointsToNode::ArgEscape)) {
-#ifdef ASSERT
-          assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
-                 aat->isa_ptr() != NULL, "expecting an Ptr");
-          if (!(is_arraycopy ||
-                call->as_CallLeaf()->_name != NULL &&
-                (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre")  == 0 ||
-                 strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ))
-          ) {
-            call->dump();
-            assert(false, "EA: unexpected CallLeaf");
-          }
-#endif
-          if (arg_esc < PointsToNode::ArgEscape) {
-            set_escape_state(arg->_idx, PointsToNode::ArgEscape);
-            Node* arg_base = arg;
-            if (arg->is_AddP()) {
-              //
-              // The inline_native_clone() case when the arraycopy stub is called
-              // after the allocation before Initialize and CheckCastPP nodes.
-              // Or normal arraycopy for object arrays case.
-              //
-              // Set AddP's base (Allocate) as not scalar replaceable since
-              // pointer to the base (with offset) is passed as argument.
-              //
-              arg_base = get_addp_base(arg);
-              set_escape_state(arg_base->_idx, PointsToNode::ArgEscape);
-            }
-          }
-
-          bool arg_has_oops = aat->isa_oopptr() &&
-                              (aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
-                               (aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
-          if (i == TypeFunc::Parms) {
-            src_has_oops = arg_has_oops;
-          }
-          //
-          // src or dst could be j.l.Object when other is basic type array:
-          //
-          //   arraycopy(char[],0,Object*,0,size);
-          //   arraycopy(Object*,0,char[],0,size);
-          //
-          // Do nothing special in such cases.
-          //
-          if (is_arraycopy && (i > TypeFunc::Parms) &&
-              src_has_oops && arg_has_oops) {
-            // Destination object's fields reference an unknown object.
-            Node* arg_base = arg;
-            if (arg->is_AddP()) {
-              arg_base = get_addp_base(arg);
-            }
-            for (VectorSetI s(PointsTo(arg_base)); s.test(); ++s) {
-              uint ps = s.elem;
-              set_escape_state(ps, PointsToNode::ArgEscape);
-              add_edge_from_fields(ps, _phantom_object, Type::OffsetBot);
-            }
-            // Conservatively all values in source object fields globally escape
-            // since we don't know if values in destination object fields
-            // escape (it could be traced but it is too expensive).
-            Node* src = call->in(TypeFunc::Parms)->uncast();
-            Node* src_base = src;
-            if (src->is_AddP()) {
-              src_base  = get_addp_base(src);
-            }
-            for (VectorSetI s(PointsTo(src_base)); s.test(); ++s) {
-              uint ps = s.elem;
-              set_escape_state(ps, PointsToNode::ArgEscape);
-              // Use OffsetTop to indicate fields global escape.
-              add_edge_from_fields(ps, _phantom_object, Type::OffsetTop);
-            }
-          }
-        }
-      }
-      break;
-    }
-
-    case Op_CallStaticJava:
-    // For a static call, we know exactly what method is being called.
-    // Use bytecode estimator to record the call's escape affects
-    {
-      ciMethod *meth = call->as_CallJava()->method();
-      BCEscapeAnalyzer *call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL;
-      // fall-through if not a Java method or no analyzer information
-      if (call_analyzer != NULL) {
-        const TypeTuple * d = call->tf()->domain();
-        bool copy_dependencies = false;
-        for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
-          const Type* at = d->field_at(i);
-          int k = i - TypeFunc::Parms;
-          Node *arg = call->in(i)->uncast();
-
-          if (at->isa_oopptr() != NULL &&
-              ptnode_adr(arg->_idx)->escape_state() < PointsToNode::GlobalEscape) {
-
-            bool global_escapes = false;
-            bool fields_escapes = false;
-            if (!call_analyzer->is_arg_stack(k)) {
-              // The argument global escapes, mark everything it could point to
-              set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
-              global_escapes = true;
-            } else {
-              if (!call_analyzer->is_arg_local(k)) {
-                // The argument itself doesn't escape, but any fields might
-                fields_escapes = true;
-              }
-              set_escape_state(arg->_idx, PointsToNode::ArgEscape);
-              copy_dependencies = true;
-            }
-
-            for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
-              uint pt = j.elem;
-              if (global_escapes) {
-                // The argument global escapes, mark everything it could point to
-                set_escape_state(pt, PointsToNode::GlobalEscape);
-                add_edge_from_fields(pt, _phantom_object, Type::OffsetBot);
-              } else {
-                set_escape_state(pt, PointsToNode::ArgEscape);
-                if (fields_escapes) {
-                  // The argument itself doesn't escape, but any fields might.
-                  // Use OffsetTop to indicate such case.
-                  add_edge_from_fields(pt, _phantom_object, Type::OffsetTop);
-                }
-              }
-            }
-          }
-        }
-        if (copy_dependencies)
-          call_analyzer->copy_dependencies(_compile->dependencies());
-        break;
-      }
-    }
-
-    default:
-    // Fall-through here if not a Java method or no analyzer information
-    // or some other type of call, assume the worst case: all arguments
-    // globally escape.
-    {
-      // adjust escape state for  outgoing arguments
-      const TypeTuple * d = call->tf()->domain();
-      for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
-        const Type* at = d->field_at(i);
-        if (at->isa_oopptr() != NULL) {
-          Node *arg = call->in(i)->uncast();
-          set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
-          for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
-            uint pt = j.elem;
-            set_escape_state(pt, PointsToNode::GlobalEscape);
-            add_edge_from_fields(pt, _phantom_object, Type::OffsetBot);
-          }
-        }
-      }
-    }
-  }
-}
-void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *phase) {
-  CallNode   *call = resproj->in(0)->as_Call();
-  uint    call_idx = call->_idx;
-  uint resproj_idx = resproj->_idx;
-
-  switch (call->Opcode()) {
-    case Op_Allocate:
-    {
-      Node *k = call->in(AllocateNode::KlassNode);
-      const TypeKlassPtr *kt = k->bottom_type()->isa_klassptr();
-      assert(kt != NULL, "TypeKlassPtr  required.");
-      ciKlass* cik = kt->klass();
-
-      PointsToNode::EscapeState es;
-      uint edge_to;
-      if (cik->is_subclass_of(_compile->env()->Thread_klass()) ||
-         !cik->is_instance_klass() || // StressReflectiveCode
-          cik->as_instance_klass()->has_finalizer()) {
-        es = PointsToNode::GlobalEscape;
-        edge_to = _phantom_object; // Could not be worse
-      } else {
-        es = PointsToNode::NoEscape;
-        edge_to = call_idx;
-        assert(ptnode_adr(call_idx)->scalar_replaceable(), "sanity");
-      }
-      set_escape_state(call_idx, es);
-      add_pointsto_edge(resproj_idx, edge_to);
-      _processed.set(resproj_idx);
-      break;
-    }
-
-    case Op_AllocateArray:
-    {
-
-      Node *k = call->in(AllocateNode::KlassNode);
-      const TypeKlassPtr *kt = k->bottom_type()->isa_klassptr();
-      assert(kt != NULL, "TypeKlassPtr  required.");
-      ciKlass* cik = kt->klass();
-
-      PointsToNode::EscapeState es;
-      uint edge_to;
-      if (!cik->is_array_klass()) { // StressReflectiveCode
-        es = PointsToNode::GlobalEscape;
-        edge_to = _phantom_object;
-      } else {
-        es = PointsToNode::NoEscape;
-        edge_to = call_idx;
-        assert(ptnode_adr(call_idx)->scalar_replaceable(), "sanity");
-        int length = call->in(AllocateNode::ALength)->find_int_con(-1);
-        if (length < 0 || length > EliminateAllocationArraySizeLimit) {
-          // Not scalar replaceable if the length is not constant or too big.
-          ptnode_adr(call_idx)->set_scalar_replaceable(false);
-        }
-      }
-      set_escape_state(call_idx, es);
-      add_pointsto_edge(resproj_idx, edge_to);
-      _processed.set(resproj_idx);
-      break;
-    }
-
-    case Op_CallStaticJava:
-    // For a static call, we know exactly what method is being called.
-    // Use bytecode estimator to record whether the call's return value escapes
-    {
-      bool done = true;
-      const TypeTuple *r = call->tf()->range();
-      const Type* ret_type = NULL;
-
-      if (r->cnt() > TypeFunc::Parms)
-        ret_type = r->field_at(TypeFunc::Parms);
-
-      // Note:  we use isa_ptr() instead of isa_oopptr()  here because the
-      //        _multianewarray functions return a TypeRawPtr.
-      if (ret_type == NULL || ret_type->isa_ptr() == NULL) {
-        _processed.set(resproj_idx);
-        break;  // doesn't return a pointer type
-      }
-      ciMethod *meth = call->as_CallJava()->method();
-      const TypeTuple * d = call->tf()->domain();
-      if (meth == NULL) {
-        // not a Java method, assume global escape
-        set_escape_state(call_idx, PointsToNode::GlobalEscape);
-        add_pointsto_edge(resproj_idx, _phantom_object);
-      } else {
-        BCEscapeAnalyzer *call_analyzer = meth->get_bcea();
-        bool copy_dependencies = false;
-
-        if (call_analyzer->is_return_allocated()) {
-          // Returns a newly allocated unescaped object, simply
-          // update dependency information.
-          // Mark it as NoEscape so that objects referenced by
-          // it's fields will be marked as NoEscape at least.
-          set_escape_state(call_idx, PointsToNode::NoEscape);
-          ptnode_adr(call_idx)->set_scalar_replaceable(false);
-          // Fields values are unknown
-          add_edge_from_fields(call_idx, _phantom_object, Type::OffsetBot);
-          add_pointsto_edge(resproj_idx, call_idx);
-          copy_dependencies = true;
-        } else {
-          // determine whether any arguments are returned
-          set_escape_state(call_idx, PointsToNode::ArgEscape);
-          bool ret_arg = false;
-          for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
-            const Type* at = d->field_at(i);
-            if (at->isa_oopptr() != NULL) {
-              Node *arg = call->in(i)->uncast();
-
-              if (call_analyzer->is_arg_returned(i - TypeFunc::Parms)) {
-                ret_arg = true;
-                PointsToNode *arg_esp = ptnode_adr(arg->_idx);
-                if (arg_esp->node_type() == PointsToNode::UnknownType)
-                  done = false;
-                else if (arg_esp->node_type() == PointsToNode::JavaObject)
-                  add_pointsto_edge(resproj_idx, arg->_idx);
-                else
-                  add_deferred_edge(resproj_idx, arg->_idx);
-              }
-            }
-          }
-          if (done) {
-            copy_dependencies = true;
-            // is_return_local() is true when only arguments are returned.
-            if (!ret_arg || !call_analyzer->is_return_local()) {
-              // Returns unknown object.
-              add_pointsto_edge(resproj_idx, _phantom_object);
-            }
-          }
-        }
-        if (copy_dependencies)
-          call_analyzer->copy_dependencies(_compile->dependencies());
-      }
-      if (done)
-        _processed.set(resproj_idx);
-      break;
-    }
-
-    default:
-    // Some other type of call, assume the worst case that the
-    // returned value, if any, globally escapes.
-    {
-      const TypeTuple *r = call->tf()->range();
-      if (r->cnt() > TypeFunc::Parms) {
-        const Type* ret_type = r->field_at(TypeFunc::Parms);
-
-        // Note:  we use isa_ptr() instead of isa_oopptr()  here because the
-        //        _multianewarray functions return a TypeRawPtr.
-        if (ret_type->isa_ptr() != NULL) {
-          set_escape_state(call_idx, PointsToNode::GlobalEscape);
-          add_pointsto_edge(resproj_idx, _phantom_object);
-        }
-      }
-      _processed.set(resproj_idx);
-    }
-  }
-}
-
-// Populate Connection Graph with Ideal nodes and create simple
-// connection graph edges (do not need to check the node_type of inputs
-// or to call PointsTo() to walk the connection graph).
-void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) {
-  if (_processed.test(n->_idx))
-    return; // No need to redefine node's state.
-
-  if (n->is_Call()) {
-    // Arguments to allocation and locking don't escape.
-    if (n->is_Allocate()) {
-      add_node(n, PointsToNode::JavaObject, PointsToNode::UnknownEscape, true);
-      record_for_optimizer(n);
-    } else if (n->is_Lock() || n->is_Unlock()) {
-      // Put Lock and Unlock nodes on IGVN worklist to process them during
-      // the first IGVN optimization when escape information is still available.
-      record_for_optimizer(n);
-      _processed.set(n->_idx);
-    } else {
-      // Don't mark as processed since call's arguments have to be processed.
-      PointsToNode::NodeType nt = PointsToNode::UnknownType;
-      PointsToNode::EscapeState es = PointsToNode::UnknownEscape;
-
-      // Check if a call returns an object.
-      const TypeTuple *r = n->as_Call()->tf()->range();
-      if (r->cnt() > TypeFunc::Parms &&
-          r->field_at(TypeFunc::Parms)->isa_ptr() &&
-          n->as_Call()->proj_out(TypeFunc::Parms) != NULL) {
-        nt = PointsToNode::JavaObject;
-        if (!n->is_CallStaticJava()) {
-          // Since the called mathod is statically unknown assume
-          // the worst case that the returned value globally escapes.
-          es = PointsToNode::GlobalEscape;
-        }
-      }
-      add_node(n, nt, es, false);
-    }
-    return;
-  }
-
-  // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
-  // ThreadLocal has RawPrt type.
-  switch (n->Opcode()) {
-    case Op_AddP:
-    {
-      add_node(n, PointsToNode::Field, PointsToNode::UnknownEscape, false);
-      break;
-    }
-    case Op_CastX2P:
-    { // "Unsafe" memory access.
-      add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
-      break;
-    }
-    case Op_CastPP:
-    case Op_CheckCastPP:
-    case Op_EncodeP:
-    case Op_DecodeN:
-    {
-      add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
-      int ti = n->in(1)->_idx;
-      PointsToNode::NodeType nt = ptnode_adr(ti)->node_type();
-      if (nt == PointsToNode::UnknownType) {
-        _delayed_worklist.push(n); // Process it later.
-        break;
-      } else if (nt == PointsToNode::JavaObject) {
-        add_pointsto_edge(n->_idx, ti);
-      } else {
-        add_deferred_edge(n->_idx, ti);
-      }
-      _processed.set(n->_idx);
-      break;
-    }
-    case Op_ConP:
-    {
-      // assume all pointer constants globally escape except for null
-      PointsToNode::EscapeState es;
-      if (phase->type(n) == TypePtr::NULL_PTR)
-        es = PointsToNode::NoEscape;
-      else
-        es = PointsToNode::GlobalEscape;
-
-      add_node(n, PointsToNode::JavaObject, es, true);
-      break;
-    }
-    case Op_ConN:
-    {
-      // assume all narrow oop constants globally escape except for null
-      PointsToNode::EscapeState es;
-      if (phase->type(n) == TypeNarrowOop::NULL_PTR)
-        es = PointsToNode::NoEscape;
-      else
-        es = PointsToNode::GlobalEscape;
-
-      add_node(n, PointsToNode::JavaObject, es, true);
-      break;
-    }
-    case Op_CreateEx:
-    {
-      // assume that all exception objects globally escape
-      add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
-      break;
-    }
-    case Op_LoadKlass:
-    case Op_LoadNKlass:
-    {
-      add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
-      break;
-    }
-    case Op_LoadP:
-    case Op_LoadN:
-    {
-      const Type *t = phase->type(n);
-      if (t->make_ptr() == NULL) {
-        _processed.set(n->_idx);
-        return;
-      }
-      add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
-      break;
-    }
-    case Op_Parm:
-    {
-      _processed.set(n->_idx); // No need to redefine it state.
-      uint con = n->as_Proj()->_con;
-      if (con < TypeFunc::Parms)
-        return;
-      const Type *t = n->in(0)->as_Start()->_domain->field_at(con);
-      if (t->isa_ptr() == NULL)
-        return;
-      // We have to assume all input parameters globally escape
-      // (Note: passing 'false' since _processed is already set).
-      add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, false);
-      break;
-    }
-    case Op_PartialSubtypeCheck:
-    { // Produces Null or notNull and is used in CmpP.
-      add_node(n, PointsToNode::JavaObject, PointsToNode::ArgEscape, true);
-      break;
-    }
-    case Op_Phi:
-    {
-      const Type *t = n->as_Phi()->type();
-      if (t->make_ptr() == NULL) {
-        // nothing to do if not an oop or narrow oop
-        _processed.set(n->_idx);
-        return;
-      }
-      add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
-      uint i;
-      for (i = 1; i < n->req() ; i++) {
-        Node* in = n->in(i);
-        if (in == NULL)
-          continue;  // ignore NULL
-        in = in->uncast();
-        if (in->is_top() || in == n)
-          continue;  // ignore top or inputs which go back this node
-        int ti = in->_idx;
-        PointsToNode::NodeType nt = ptnode_adr(ti)->node_type();
-        if (nt == PointsToNode::UnknownType) {
-          break;
-        } else if (nt == PointsToNode::JavaObject) {
-          add_pointsto_edge(n->_idx, ti);
-        } else {
-          add_deferred_edge(n->_idx, ti);
-        }
-      }
-      if (i >= n->req())
-        _processed.set(n->_idx);
-      else
-        _delayed_worklist.push(n);
-      break;
-    }
-    case Op_Proj:
-    {
-      // we are only interested in the oop result projection from a call
-      if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) {
-        const TypeTuple *r = n->in(0)->as_Call()->tf()->range();
-        assert(r->cnt() > TypeFunc::Parms, "sanity");
-        if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) {
-          add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
-          int ti = n->in(0)->_idx;
-          // The call may not be registered yet (since not all its inputs are registered)
-          // if this is the projection from backbranch edge of Phi.
-          if (ptnode_adr(ti)->node_type() != PointsToNode::UnknownType) {
-            process_call_result(n->as_Proj(), phase);
-          }
-          if (!_processed.test(n->_idx)) {
-            // The call's result may need to be processed later if the call
-            // returns it's argument and the argument is not processed yet.
-            _delayed_worklist.push(n);
-          }
-          break;
-        }
-      }
-      _processed.set(n->_idx);
-      break;
-    }
-    case Op_Return:
-    {
-      if( n->req() > TypeFunc::Parms &&
-          phase->type(n->in(TypeFunc::Parms))->isa_oopptr() ) {
-        // Treat Return value as LocalVar with GlobalEscape escape state.
-        add_node(n, PointsToNode::LocalVar, PointsToNode::GlobalEscape, false);
-        int ti = n->in(TypeFunc::Parms)->_idx;
-        PointsToNode::NodeType nt = ptnode_adr(ti)->node_type();
-        if (nt == PointsToNode::UnknownType) {
-          _delayed_worklist.push(n); // Process it later.
-          break;
-        } else if (nt == PointsToNode::JavaObject) {
-          add_pointsto_edge(n->_idx, ti);
-        } else {
-          add_deferred_edge(n->_idx, ti);
-        }
-      }
-      _processed.set(n->_idx);
-      break;
-    }
-    case Op_StoreP:
-    case Op_StoreN:
-    {
-      const Type *adr_type = phase->type(n->in(MemNode::Address));
-      adr_type = adr_type->make_ptr();
-      if (adr_type->isa_oopptr()) {
-        add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false);
-      } else {
-        Node* adr = n->in(MemNode::Address);
-        if (adr->is_AddP() && phase->type(adr) == TypeRawPtr::NOTNULL &&
-            adr->in(AddPNode::Address)->is_Proj() &&
-            adr->in(AddPNode::Address)->in(0)->is_Allocate()) {
-          add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false);
-          // We are computing a raw address for a store captured
-          // by an Initialize compute an appropriate address type.
-          int offs = (int)phase->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
-          assert(offs != Type::OffsetBot, "offset must be a constant");
-        } else {
-          _processed.set(n->_idx);
-          return;
-        }
-      }
-      break;
-    }
-    case Op_StorePConditional:
-    case Op_CompareAndSwapP:
-    case Op_CompareAndSwapN:
-    {
-      const Type *adr_type = phase->type(n->in(MemNode::Address));
-      adr_type = adr_type->make_ptr();
-      if (adr_type->isa_oopptr()) {
-        add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false);
-      } else {
-        _processed.set(n->_idx);
-        return;
-      }
-      break;
-    }
-    case Op_AryEq:
-    case Op_StrComp:
-    case Op_StrEquals:
-    case Op_StrIndexOf:
-    {
-      // char[] arrays passed to string intrinsics are not scalar replaceable.
-      add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false);
-      break;
-    }
-    case Op_ThreadLocal:
-    {
-      add_node(n, PointsToNode::JavaObject, PointsToNode::ArgEscape, true);
-      break;
-    }
-    default:
-      ;
-      // nothing to do
-  }
-  return;
-}
-
-void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
-  uint n_idx = n->_idx;
-  assert(ptnode_adr(n_idx)->_node != NULL, "node should be registered");
-
-  // Don't set processed bit for AddP, LoadP, StoreP since
-  // they may need more then one pass to process.
-  // Also don't mark as processed Call nodes since their
-  // arguments may need more then one pass to process.
-  if (_processed.test(n_idx))
-    return; // No need to redefine node's state.
-
-  if (n->is_Call()) {
-    CallNode *call = n->as_Call();
-    process_call_arguments(call, phase);
-    return;
-  }
-
-  switch (n->Opcode()) {
-    case Op_AddP:
-    {
-      Node *base = get_addp_base(n);
-      int offset = address_offset(n, phase);
-      // Create a field edge to this node from everything base could point to.
-      for( VectorSetI i(PointsTo(base)); i.test(); ++i ) {
-        uint pt = i.elem;
-        add_field_edge(pt, n_idx, offset);
-      }
-      break;
-    }
-    case Op_CastX2P:
-    {
-      assert(false, "Op_CastX2P");
-      break;
-    }
-    case Op_CastPP:
-    case Op_CheckCastPP:
-    case Op_EncodeP:
-    case Op_DecodeN:
-    {
-      int ti = n->in(1)->_idx;
-      assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "all nodes should be registered");
-      if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) {
-        add_pointsto_edge(n_idx, ti);
-      } else {
-        add_deferred_edge(n_idx, ti);
-      }
-      _processed.set(n_idx);
-      break;
-    }
-    case Op_ConP:
-    {
-      assert(false, "Op_ConP");
-      break;
-    }
-    case Op_ConN:
-    {
-      assert(false, "Op_ConN");
-      break;
-    }
-    case Op_CreateEx:
-    {
-      assert(false, "Op_CreateEx");
-      break;
-    }
-    case Op_LoadKlass:
-    case Op_LoadNKlass:
-    {
-      assert(false, "Op_LoadKlass");
-      break;
-    }
-    case Op_LoadP:
-    case Op_LoadN:
-    {
-      const Type *t = phase->type(n);
-#ifdef ASSERT
-      if (t->make_ptr() == NULL)
-        assert(false, "Op_LoadP");
-#endif
-
-      Node* adr = n->in(MemNode::Address)->uncast();
-      Node* adr_base;
-      if (adr->is_AddP()) {
-        adr_base = get_addp_base(adr);
-      } else {
-        adr_base = adr;
-      }
-
-      // For everything "adr_base" could point to, create a deferred edge from
-      // this node to each field with the same offset.
-      int offset = address_offset(adr, phase);
-      for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) {
-        uint pt = i.elem;
-        if (adr->is_AddP()) {
-          // Add field edge if it is missing.
-          add_field_edge(pt, adr->_idx, offset);
-        }
-        add_deferred_edge_to_fields(n_idx, pt, offset);
-      }
-      break;
-    }
-    case Op_Parm:
-    {
-      assert(false, "Op_Parm");
-      break;
-    }
-    case Op_PartialSubtypeCheck:
-    {
-      assert(false, "Op_PartialSubtypeCheck");
-      break;
-    }
-    case Op_Phi:
-    {
-#ifdef ASSERT
-      const Type *t = n->as_Phi()->type();
-      if (t->make_ptr() == NULL)
-        assert(false, "Op_Phi");
-#endif
-      for (uint i = 1; i < n->req() ; i++) {
-        Node* in = n->in(i);
-        if (in == NULL)
-          continue;  // ignore NULL
-        in = in->uncast();
-        if (in->is_top() || in == n)
-          continue;  // ignore top or inputs which go back this node
-        int ti = in->_idx;
-        PointsToNode::NodeType nt = ptnode_adr(ti)->node_type();
-        assert(nt != PointsToNode::UnknownType, "all nodes should be known");
-        if (nt == PointsToNode::JavaObject) {
-          add_pointsto_edge(n_idx, ti);
-        } else {
-          add_deferred_edge(n_idx, ti);
-        }
-      }
-      _processed.set(n_idx);
-      break;
-    }
-    case Op_Proj:
-    {
-      // we are only interested in the oop result projection from a call
-      if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) {
-        assert(ptnode_adr(n->in(0)->_idx)->node_type() != PointsToNode::UnknownType,
-               "all nodes should be registered");
-        const TypeTuple *r = n->in(0)->as_Call()->tf()->range();
-        assert(r->cnt() > TypeFunc::Parms, "sanity");
-        if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) {
-          process_call_result(n->as_Proj(), phase);
-          assert(_processed.test(n_idx), "all call results should be processed");
-          break;
-        }
-      }
-      assert(false, "Op_Proj");
-      break;
-    }
-    case Op_Return:
-    {
-#ifdef ASSERT
-      if( n->req() <= TypeFunc::Parms ||
-          !phase->type(n->in(TypeFunc::Parms))->isa_oopptr() ) {
-        assert(false, "Op_Return");
-      }
-#endif
-      int ti = n->in(TypeFunc::Parms)->_idx;
-      assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "node should be registered");
-      if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) {
-        add_pointsto_edge(n_idx, ti);
-      } else {
-        add_deferred_edge(n_idx, ti);
-      }
-      _processed.set(n_idx);
-      break;
-    }
-    case Op_StoreP:
-    case Op_StoreN:
-    case Op_StorePConditional:
-    case Op_CompareAndSwapP:
-    case Op_CompareAndSwapN:
-    {
-      Node *adr = n->in(MemNode::Address);
-      const Type *adr_type = phase->type(adr)->make_ptr();
-#ifdef ASSERT
-      if (!adr_type->isa_oopptr())
-        assert(phase->type(adr) == TypeRawPtr::NOTNULL, "Op_StoreP");
-#endif
-
-      assert(adr->is_AddP(), "expecting an AddP");
-      Node *adr_base = get_addp_base(adr);
-      Node *val = n->in(MemNode::ValueIn)->uncast();
-      int offset = address_offset(adr, phase);
-      // For everything "adr_base" could point to, create a deferred edge
-      // to "val" from each field with the same offset.
-      for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) {
-        uint pt = i.elem;
-        // Add field edge if it is missing.
-        add_field_edge(pt, adr->_idx, offset);
-        add_edge_from_fields(pt, val->_idx, offset);
-      }
-      break;
-    }
-    case Op_AryEq:
-    case Op_StrComp:
-    case Op_StrEquals:
-    case Op_StrIndexOf:
-    {
-      // char[] arrays passed to string intrinsic do not escape but
-      // they are not scalar replaceable. Adjust escape state for them.
-      // Start from in(2) edge since in(1) is memory edge.
-      for (uint i = 2; i < n->req(); i++) {
-        Node* adr = n->in(i)->uncast();
-        const Type *at = phase->type(adr);
-        if (!adr->is_top() && at->isa_ptr()) {
-          assert(at == Type::TOP || at == TypePtr::NULL_PTR ||
-                 at->isa_ptr() != NULL, "expecting an Ptr");
-          if (adr->is_AddP()) {
-            adr = get_addp_base(adr);
-          }
-          // Mark as ArgEscape everything "adr" could point to.
-          set_escape_state(adr->_idx, PointsToNode::ArgEscape);
-        }
-      }
-      _processed.set(n_idx);
-      break;
-    }
-    case Op_ThreadLocal:
-    {
-      assert(false, "Op_ThreadLocal");
-      break;
-    }
-    default:
-      // This method should be called only for EA specific nodes.
-      ShouldNotReachHere();
-  }
-}
-
-#ifndef PRODUCT
-void ConnectionGraph::dump() {
+void ConnectionGraph::dump(GrowableArray<PointsToNode*>& ptnodes_worklist) {
   bool first = true;
-
-  uint size = nodes_size();
-  for (uint ni = 0; ni < size; ni++) {
-    PointsToNode *ptn = ptnode_adr(ni);
-    PointsToNode::NodeType ptn_type = ptn->node_type();
-
-    if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL)
+  int ptnodes_length = ptnodes_worklist.length();
+  for (int i = 0; i < ptnodes_length; i++) {
+    PointsToNode *ptn = ptnodes_worklist.at(i);
+    if (ptn == NULL || !ptn->is_JavaObject())
       continue;
-    PointsToNode::EscapeState es = escape_state(ptn->_node);
-    if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
+    PointsToNode::EscapeState es = ptn->escape_state();
+    if (ptn->ideal_node()->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
       if (first) {
         tty->cr();
         tty->print("======== Connection graph for ");
@@ -3140,22 +3133,14 @@
         tty->cr();
         first = false;
       }
-      tty->print("%6d ", ni);
       ptn->dump();
-      // Print all locals which reference this allocation
-      for (uint li = ni; li < size; li++) {
-        PointsToNode *ptn_loc = ptnode_adr(li);
-        PointsToNode::NodeType ptn_loc_type = ptn_loc->node_type();
-        if ( ptn_loc_type == PointsToNode::LocalVar && ptn_loc->_node != NULL &&
-             ptn_loc->edge_count() == 1 && ptn_loc->edge_target(0) == ni ) {
-          ptnode_adr(li)->dump(false);
-        }
-      }
-      if (Verbose) {
-        // Print all fields which reference this allocation
-        for (uint i = 0; i < ptn->edge_count(); i++) {
-          uint ei = ptn->edge_target(i);
-          ptnode_adr(ei)->dump(false);
+      // Print all locals and fields which reference this allocation
+      for (UseIterator j(ptn); j.has_next(); j.next()) {
+        PointsToNode* use = j.get();
+        if (use->is_LocalVar()) {
+          use->dump(Verbose);
+        } else if (Verbose) {
+          use->dump();
         }
       }
       tty->cr();
--- a/src/share/vm/opto/escape.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/escape.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -115,18 +115,36 @@
 class  CallNode;
 class  PhiNode;
 class  PhaseTransform;
+class  PointsToNode;
 class  Type;
 class  TypePtr;
 class  VectorSet;
 
-class PointsToNode {
-friend class ConnectionGraph;
+class JavaObjectNode;
+class LocalVarNode;
+class FieldNode;
+class ArraycopyNode;
+
+// ConnectionGraph nodes
+class PointsToNode : public ResourceObj {
+  GrowableArray<PointsToNode*> _edges; // List of nodes this node points to
+  GrowableArray<PointsToNode*> _uses;  // List of nodes which point to this node
+
+  const u1           _type;  // NodeType
+  u1                _flags;  // NodeFlags
+  u1               _escape;  // EscapeState of object
+  u1        _fields_escape;  // EscapeState of object's fields
+
+  Node* const        _node;  // Ideal node corresponding to this PointsTo node.
+  const int           _idx;  // Cached ideal node's _idx
+
 public:
   typedef enum {
     UnknownType = 0,
     JavaObject  = 1,
     LocalVar    = 2,
-    Field       = 3
+    Field       = 3,
+    Arraycopy   = 4
   } NodeType;
 
   typedef enum {
@@ -140,178 +158,387 @@
   } EscapeState;
 
   typedef enum {
-    UnknownEdge   = 0,
-    PointsToEdge  = 1,
-    DeferredEdge  = 2,
-    FieldEdge     = 3
-  } EdgeType;
-
-private:
-  enum {
-    EdgeMask = 3,
-    EdgeShift = 2,
-
-    INITIAL_EDGE_COUNT = 4
-  };
-
-  NodeType             _type;
-  EscapeState          _escape;
-  GrowableArray<uint>* _edges; // outgoing edges
-  Node* _node;                 // Ideal node corresponding to this PointsTo node.
-  int   _offset;               // Object fields offsets.
-  bool  _scalar_replaceable;   // Not escaped object could be replaced with scalar
-  bool  _has_unknown_ptr;      // Has edge to phantom_object
-
-public:
-  PointsToNode():
-    _type(UnknownType),
-    _escape(UnknownEscape),
-    _edges(NULL),
-    _node(NULL),
-    _offset(-1),
-    _has_unknown_ptr(false),
-    _scalar_replaceable(true) {}
+    ScalarReplaceable = 1,  // Not escaped object could be replaced with scalar
+    PointsToUnknown   = 2,  // Has edge to phantom_object
+    ArraycopySrc      = 4,  // Has edge from Arraycopy node
+    ArraycopyDst      = 8   // Has edge to Arraycopy node
+  } NodeFlags;
 
 
-  EscapeState escape_state() const { return _escape; }
-  NodeType node_type() const { return _type;}
-  int offset() { return _offset;}
-  bool scalar_replaceable() { return _scalar_replaceable;}
-  bool has_unknown_ptr()    { return _has_unknown_ptr;}
-
-  void set_offset(int offs) { _offset = offs;}
-  void set_escape_state(EscapeState state) { _escape = state; }
-  void set_node_type(NodeType ntype) {
-    assert(_type == UnknownType || _type == ntype, "Can't change node type");
-    _type = ntype;
-  }
-  void set_scalar_replaceable(bool v) { _scalar_replaceable = v; }
-  void set_has_unknown_ptr()          { _has_unknown_ptr = true; }
-
-  // count of outgoing edges
-  uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); }
-
-  // node index of target of outgoing edge "e"
-  uint edge_target(uint e) const {
-    assert(_edges != NULL, "valid edge index");
-    return (_edges->at(e) >> EdgeShift);
-  }
-  // type of outgoing edge "e"
-  EdgeType edge_type(uint e) const {
-    assert(_edges != NULL, "valid edge index");
-    return (EdgeType) (_edges->at(e) & EdgeMask);
+  PointsToNode(Compile *C, Node* n, EscapeState es, NodeType type):
+    _edges(C->comp_arena(), 2, 0, NULL),
+    _uses (C->comp_arena(), 2, 0, NULL),
+    _node(n),
+    _idx(n->_idx),
+    _type((u1)type),
+    _escape((u1)es),
+    _fields_escape((u1)es),
+    _flags(ScalarReplaceable) {
+    assert(n != NULL && es != UnknownEscape, "sanity");
   }
 
-  // add a edge of the specified type pointing to the specified target
-  void add_edge(uint targIdx, EdgeType et);
+  Node* ideal_node()   const { return _node; }
+  int          idx()   const { return _idx; }
+
+  bool is_JavaObject() const { return _type == (u1)JavaObject; }
+  bool is_LocalVar()   const { return _type == (u1)LocalVar; }
+  bool is_Field()      const { return _type == (u1)Field; }
+  bool is_Arraycopy()  const { return _type == (u1)Arraycopy; }
+
+  JavaObjectNode* as_JavaObject() { assert(is_JavaObject(),""); return (JavaObjectNode*)this; }
+  LocalVarNode*   as_LocalVar()   { assert(is_LocalVar(),"");   return (LocalVarNode*)this; }
+  FieldNode*      as_Field()      { assert(is_Field(),"");      return (FieldNode*)this; }
+  ArraycopyNode*  as_Arraycopy()  { assert(is_Arraycopy(),"");  return (ArraycopyNode*)this; }
+
+  EscapeState escape_state() const { return (EscapeState)_escape; }
+  void    set_escape_state(EscapeState state) { _escape = (u1)state; }
+
+  EscapeState fields_escape_state() const { return (EscapeState)_fields_escape; }
+  void    set_fields_escape_state(EscapeState state) { _fields_escape = (u1)state; }
+
+  bool     has_unknown_ptr() const { return (_flags & PointsToUnknown) != 0; }
+  void set_has_unknown_ptr()       { _flags |= PointsToUnknown; }
+
+  bool     arraycopy_src() const { return (_flags & ArraycopySrc) != 0; }
+  void set_arraycopy_src()       { _flags |= ArraycopySrc; }
+  bool     arraycopy_dst() const { return (_flags & ArraycopyDst) != 0; }
+  void set_arraycopy_dst()       { _flags |= ArraycopyDst; }
 
-  // remove an edge of the specified type pointing to the specified target
-  void remove_edge(uint targIdx, EdgeType et);
+  bool     scalar_replaceable() const { return (_flags & ScalarReplaceable) != 0;}
+  void set_scalar_replaceable(bool v) {
+    if (v)
+      _flags |= ScalarReplaceable;
+    else
+      _flags &= ~ScalarReplaceable;
+  }
+
+  int edge_count()              const { return _edges.length(); }
+  PointsToNode* edge(int e)     const { return _edges.at(e); }
+  bool add_edge(PointsToNode* edge)    { return _edges.append_if_missing(edge); }
+
+  int use_count()             const { return _uses.length(); }
+  PointsToNode* use(int e)    const { return _uses.at(e); }
+  bool add_use(PointsToNode* use)    { return _uses.append_if_missing(use); }
+
+  // Mark base edge use to distinguish from stored value edge.
+  bool add_base_use(FieldNode* use) { return _uses.append_if_missing((PointsToNode*)((intptr_t)use + 1)); }
+  static bool is_base_use(PointsToNode* use) { return (((intptr_t)use) & 1); }
+  static PointsToNode* get_use_node(PointsToNode* use) { return (PointsToNode*)(((intptr_t)use) & ~1); }
+
+  // Return true if this node points to specified node or nodes it points to.
+  bool points_to(JavaObjectNode* ptn) const;
+
+  // Return true if this node points only to non-escaping allocations.
+  bool non_escaping_allocation();
+
+  // Return true if one node points to an other.
+  bool meet(PointsToNode* ptn);
 
 #ifndef PRODUCT
+  NodeType node_type() const { return (NodeType)_type;}
   void dump(bool print_state=true) const;
 #endif
 
 };
 
+class LocalVarNode: public PointsToNode {
+public:
+  LocalVarNode(Compile *C, Node* n, EscapeState es):
+    PointsToNode(C, n, es, LocalVar) {}
+};
+
+class JavaObjectNode: public PointsToNode {
+public:
+  JavaObjectNode(Compile *C, Node* n, EscapeState es):
+    PointsToNode(C, n, es, JavaObject) {
+      if (es > NoEscape)
+        set_scalar_replaceable(false);
+    }
+};
+
+class FieldNode: public PointsToNode {
+  GrowableArray<PointsToNode*> _bases; // List of JavaObject nodes which point to this node
+  const int   _offset; // Field's offset.
+  const bool  _is_oop; // Field points to object
+        bool  _has_unknown_base; // Has phantom_object base
+public:
+  FieldNode(Compile *C, Node* n, EscapeState es, int offs, bool is_oop):
+    PointsToNode(C, n, es, Field),
+    _offset(offs), _is_oop(is_oop),
+    _has_unknown_base(false) {}
+
+  int      offset()              const { return _offset;}
+  bool     is_oop()              const { return _is_oop;}
+  bool     has_unknown_base()    const { return _has_unknown_base; }
+  void set_has_unknown_base()          { _has_unknown_base = true; }
+
+  int base_count()              const { return _bases.length(); }
+  PointsToNode* base(int e)     const { return _bases.at(e); }
+  bool add_base(PointsToNode* base)    { return _bases.append_if_missing(base); }
+#ifdef ASSERT
+  // Return true if bases points to this java object.
+  bool has_base(JavaObjectNode* ptn) const;
+#endif
+
+};
+
+class ArraycopyNode: public PointsToNode {
+public:
+  ArraycopyNode(Compile *C, Node* n, EscapeState es):
+    PointsToNode(C, n, es, Arraycopy) {}
+};
+
+// Iterators for PointsTo node's edges:
+//   for (EdgeIterator i(n); i.has_next(); i.next()) {
+//     PointsToNode* u = i.get();
+class PointsToIterator: public StackObj {
+protected:
+  const PointsToNode* node;
+  const int cnt;
+  int i;
+public:
+  inline PointsToIterator(const PointsToNode* n, int cnt) : node(n), cnt(cnt), i(0) { }
+  inline bool has_next() const { return i < cnt; }
+  inline void next() { i++; }
+  PointsToNode* get() const { ShouldNotCallThis(); return NULL; }
+};
+
+class EdgeIterator: public PointsToIterator {
+public:
+  inline EdgeIterator(const PointsToNode* n) : PointsToIterator(n, n->edge_count()) { }
+  inline PointsToNode* get() const { return node->edge(i); }
+};
+
+class UseIterator: public PointsToIterator {
+public:
+  inline UseIterator(const PointsToNode* n) : PointsToIterator(n, n->use_count()) { }
+  inline PointsToNode* get() const { return node->use(i); }
+};
+
+class BaseIterator: public PointsToIterator {
+public:
+  inline BaseIterator(const FieldNode* n) : PointsToIterator(n, n->base_count()) { }
+  inline PointsToNode* get() const { return ((PointsToNode*)node)->as_Field()->base(i); }
+};
+
+
 class ConnectionGraph: public ResourceObj {
 private:
-  GrowableArray<PointsToNode>  _nodes; // Connection graph nodes indexed
-                                       // by ideal node index.
-
-  Unique_Node_List  _delayed_worklist; // Nodes to be processed before
-                                       // the call build_connection_graph().
+  GrowableArray<PointsToNode*>  _nodes; // Map from ideal nodes to
+                                        // ConnectionGraph nodes.
 
-  GrowableArray<MergeMemNode *>  _mergemem_worklist; // List of all MergeMem nodes
+  GrowableArray<PointsToNode*>  _worklist; // Nodes to be processed
 
-  VectorSet                _processed; // Records which nodes have been
-                                       // processed.
-
-  bool                    _collecting; // Indicates whether escape information
-                                       // is still being collected. If false,
-                                       // no new nodes will be processed.
+  bool            _collecting; // Indicates whether escape information
+                               // is still being collected. If false,
+                               // no new nodes will be processed.
 
-  bool                    _progress;   // Indicates whether new Graph's edges
-                                       // were created.
+  bool               _verify;  // verify graph
 
-  uint                _phantom_object; // Index of globally escaping object
-                                       // that pointer values loaded from
-                                       // a field which has not been set
-                                       // are assumed to point to.
-  uint                      _oop_null; // ConP(#NULL)->_idx
-  uint                     _noop_null; // ConN(#NULL)->_idx
-  Node*                     _pcmp_neq; // ConI(#CC_GT)
-  Node*                      _pcmp_eq; // ConI(#CC_EQ)
+  JavaObjectNode* phantom_obj; // Unknown object
+  JavaObjectNode*    null_obj;
+  Node*             _pcmp_neq; // ConI(#CC_GT)
+  Node*              _pcmp_eq; // ConI(#CC_EQ)
 
-  Compile *                  _compile; // Compile object for current compilation
-  PhaseIterGVN *                _igvn; // Value numbering
+  Compile*           _compile; // Compile object for current compilation
+  PhaseIterGVN*         _igvn; // Value numbering
+
+  Unique_Node_List ideal_nodes; // Used by CG construction and types splitting.
 
   // Address of an element in _nodes.  Used when the element is to be modified
-  PointsToNode *ptnode_adr(uint idx) const {
+  PointsToNode* ptnode_adr(int idx) const {
     // There should be no new ideal nodes during ConnectionGraph build,
-    // growableArray::adr_at() will throw assert otherwise.
-    return _nodes.adr_at(idx);
+    // growableArray::at() will throw assert otherwise.
+    return _nodes.at(idx);
   }
   uint nodes_size() const { return _nodes.length(); }
 
-  bool is_null_ptr(uint idx) const { return (idx == _noop_null || idx == _oop_null); }
+  // Add nodes to ConnectionGraph.
+  void add_local_var(Node* n, PointsToNode::EscapeState es);
+  void add_java_object(Node* n, PointsToNode::EscapeState es);
+  void add_field(Node* n, PointsToNode::EscapeState es, int offset);
+  void add_arraycopy(Node* n, PointsToNode::EscapeState es, PointsToNode* src, PointsToNode* dst);
+
+  // Compute the escape state for arguments to a call.
+  void process_call_arguments(CallNode *call);
+
+  // Add PointsToNode node corresponding to a call
+  void add_call_node(CallNode* call);
+
+  // Map ideal node to existing PointsTo node (usually phantom_object).
+  void map_ideal_node(Node *n, PointsToNode* ptn) {
+    assert(ptn != NULL, "only existing PointsTo node");
+    _nodes.at_put(n->_idx, ptn);
+  }
+
+  // Create PointsToNode node and add it to Connection Graph.
+  void add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist);
+
+  // Add final simple edges to graph.
+  void add_final_edges(Node *n);
+
+  // Finish Graph construction.
+  bool complete_connection_graph(GrowableArray<PointsToNode*>&   ptnodes_worklist,
+                                 GrowableArray<JavaObjectNode*>& non_escaped_worklist,
+                                 GrowableArray<JavaObjectNode*>& java_objects_worklist,
+                                 GrowableArray<FieldNode*>&      oop_fields_worklist);
+
+#ifdef ASSERT
+  void verify_connection_graph(GrowableArray<PointsToNode*>&   ptnodes_worklist,
+                               GrowableArray<JavaObjectNode*>& non_escaped_worklist,
+                               GrowableArray<JavaObjectNode*>& java_objects_worklist,
+                               GrowableArray<Node*>& addp_worklist);
+#endif
+
+  // Add all references to this JavaObject node.
+  int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist);
+
+  // Put node on worklist if it is (or was) not there.
+  void add_to_worklist(PointsToNode* pt) {
+    _worklist.push(pt);
+    return;
+  }
+
+  // Put on worklist all uses of this node.
+  void add_uses_to_worklist(PointsToNode* pt) {
+    for (UseIterator i(pt); i.has_next(); i.next())
+      _worklist.push(i.get());
+  }
+
+  // Put on worklist all field's uses and related field nodes.
+  void add_field_uses_to_worklist(FieldNode* field);
+
+  // Put on worklist all related field nodes.
+  void add_fields_to_worklist(FieldNode* field, PointsToNode* base);
+
+  // Find fields which have unknown value.
+  int find_field_value(FieldNode* field);
+
+  // Find fields initializing values for allocations.
+  int find_init_values(JavaObjectNode* ptn, PointsToNode* init_val, PhaseTransform* phase);
+
+  // Set the escape state of an object and its fields.
+  void set_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) {
+    // Don't change non-escaping state of NULL pointer.
+    if (ptn != null_obj) {
+      if (ptn->escape_state() < esc)
+        ptn->set_escape_state(esc);
+      if (ptn->fields_escape_state() < esc)
+        ptn->set_fields_escape_state(esc);
+    }
+  }
+  void set_fields_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) {
+    // Don't change non-escaping state of NULL pointer.
+    if (ptn != null_obj) {
+      if (ptn->fields_escape_state() < esc)
+        ptn->set_fields_escape_state(esc);
+    }
+  }
 
-  // Add node to ConnectionGraph.
-  void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done);
+  // Propagate GlobalEscape and ArgEscape escape states to all nodes
+  // and check that we still have non-escaping java objects.
+  bool find_non_escaped_objects(GrowableArray<PointsToNode*>& ptnodes_worklist,
+                                GrowableArray<JavaObjectNode*>& non_escaped_worklist);
+
+  // Adjust scalar_replaceable state after Connection Graph is built.
+  void adjust_scalar_replaceable_state(JavaObjectNode* jobj);
+
+  // Optimize ideal graph.
+  void optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
+                            GrowableArray<Node*>& storestore_worklist);
+  // Optimize objects compare.
+  Node* optimize_ptr_compare(Node* n);
+
+  // Returns unique corresponding java object or NULL.
+  JavaObjectNode* unique_java_object(Node *n);
+
+  // Add an edge of the specified type pointing to the specified target.
+  bool add_edge(PointsToNode* from, PointsToNode* to) {
+    assert(!from->is_Field() || from->as_Field()->is_oop(), "sanity");
+
+    if (to == phantom_obj) {
+      if (from->has_unknown_ptr()) {
+        return false; // already points to phantom_obj
+      }
+      from->set_has_unknown_ptr();
+    }
+
+    bool is_new = from->add_edge(to);
+    assert(to != phantom_obj || is_new, "sanity");
+    if (is_new) { // New edge?
+      assert(!_verify, "graph is incomplete");
+      is_new = to->add_use(from);
+      assert(is_new, "use should be also new");
+    }
+    return is_new;
+  }
+
+  // Add an edge from Field node to its base and back.
+  bool add_base(FieldNode* from, PointsToNode* to) {
+    assert(!to->is_Arraycopy(), "sanity");
+    if (to == phantom_obj) {
+      if (from->has_unknown_base()) {
+        return false; // already has phantom_obj base
+      }
+      from->set_has_unknown_base();
+    }
+    bool is_new = from->add_base(to);
+    assert(to != phantom_obj || is_new, "sanity");
+    if (is_new) {      // New edge?
+      assert(!_verify, "graph is incomplete");
+      if (to == null_obj)
+        return is_new; // Don't add fields to NULL pointer.
+      if (to->is_JavaObject()) {
+        is_new = to->add_edge(from);
+      } else {
+        is_new = to->add_base_use(from);
+      }
+      assert(is_new, "use should be also new");
+    }
+    return is_new;
+  }
+
+  // Add LocalVar node and edge if possible
+  void add_local_var_and_edge(Node* n, PointsToNode::EscapeState es, Node* to,
+                              Unique_Node_List *delayed_worklist) {
+    PointsToNode* ptn = ptnode_adr(to->_idx);
+    if (delayed_worklist != NULL) { // First iteration of CG construction
+      add_local_var(n, es);
+      if (ptn == NULL) {
+        delayed_worklist->push(n);
+        return; // Process it later.
+      }
+    } else {
+      assert(ptn != NULL, "node should be registered");
+    }
+    add_edge(ptnode_adr(n->_idx), ptn);
+  }
+
+  // Helper functions
+  bool   is_oop_field(Node* n, int offset);
+  static Node* get_addp_base(Node *addp);
+  static Node* find_second_addp(Node* addp, Node* n);
 
   // offset of a field reference
   int address_offset(Node* adr, PhaseTransform *phase);
 
-  // compute the escape state for arguments to a call
-  void process_call_arguments(CallNode *call, PhaseTransform *phase);
 
-  // compute the escape state for the return value of a call
-  void process_call_result(ProjNode *resproj, PhaseTransform *phase);
-
-  // Populate Connection Graph with Ideal nodes.
-  void record_for_escape_analysis(Node *n, PhaseTransform *phase);
-
-  // Build Connection Graph and set nodes escape state.
-  void build_connection_graph(Node *n, PhaseTransform *phase);
-
-  // walk the connection graph starting at the node corresponding to "n" and
-  // add the index of everything it could point to, to "ptset".  This may cause
-  // Phi's encountered to get (re)processed  (which requires "phase".)
-  VectorSet* PointsTo(Node * n);
-
-  // Reused structures for PointsTo().
-  VectorSet            pt_ptset;
-  VectorSet            pt_visited;
-  GrowableArray<uint>  pt_worklist;
+  // Propagate unique types created for unescaped allocated objects
+  // through the graph
+  void split_unique_types(GrowableArray<Node *>  &alloc_worklist);
 
-  //  Edge manipulation.  The "from_i" and "to_i" arguments are the
-  //  node indices of the source and destination of the edge
-  void add_pointsto_edge(uint from_i, uint to_i);
-  void add_deferred_edge(uint from_i, uint to_i);
-  void add_field_edge(uint from_i, uint to_i, int offs);
+  // Helper methods for unique types split.
+  bool split_AddP(Node *addp, Node *base);
 
-  // Add an edge of the specified type pointing to the specified target.
-  // Set _progress if new edge is added.
-  void add_edge(PointsToNode *f, uint to_i, PointsToNode::EdgeType et) {
-    uint e_cnt = f->edge_count();
-    f->add_edge(to_i, et);
-    _progress |= (f->edge_count() != e_cnt);
-  }
+  PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, bool &new_created);
+  PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist);
 
-  // Add an edge to node given by "to_i" from any field of adr_i whose offset
-  // matches "offset"  A deferred edge is added if to_i is a LocalVar, and
-  // a pointsto edge is added if it is a JavaObject
-  void add_edge_from_fields(uint adr, uint to_i, int offs);
-
-  // Add a deferred  edge from node given by "from_i" to any field
-  // of adr_i whose offset matches "offset"
-  void add_deferred_edge_to_fields(uint from_i, uint adr, int offs);
+  void  move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis);
+  Node* find_inst_mem(Node* mem, int alias_idx,GrowableArray<PhiNode *>  &orig_phi_worklist);
+  Node* step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop);
 
 
-  // Remove outgoing deferred edges from the node referenced by "ni".
-  // Any outgoing edges from the target of the deferred edge are copied
-  // to "ni".
-  void remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited);
+  GrowableArray<MergeMemNode*>  _mergemem_worklist; // List of all MergeMem nodes
 
   Node_Array _node_map; // used for bookeeping during type splitting
                         // Used for the following purposes:
@@ -320,21 +547,18 @@
                         // MemNode       - new memory input for this node
                         // ChecCastPP    - allocation that this is a cast of
                         // allocation    - CheckCastPP of the allocation
-  bool split_AddP(Node *addp, Node *base,  PhaseGVN  *igvn);
-  PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn, bool &new_created);
-  PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn);
-  void  move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis, PhaseGVN *igvn);
-  Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *>  &orig_phi_worklist,  PhaseGVN  *igvn);
-
-  // Propagate unique types created for unescaped allocated objects
-  // through the graph
-  void split_unique_types(GrowableArray<Node *>  &alloc_worklist);
 
   // manage entries in _node_map
-  void  set_map(int idx, Node *n)        { _node_map.map(idx, n); }
-  Node *get_map(int idx)                 { return _node_map[idx]; }
-  PhiNode *get_map_phi(int idx) {
-    Node *phi = _node_map[idx];
+
+  void  set_map(Node* from, Node* to)  {
+    ideal_nodes.push(from);
+    _node_map.map(from->_idx, to);
+  }
+
+  Node* get_map(int idx) { return _node_map[idx]; }
+
+  PhiNode* get_map_phi(int idx) {
+    Node* phi = _node_map[idx];
     return (phi == NULL) ? NULL : phi->as_Phi();
   }
 
@@ -344,23 +568,6 @@
     _igvn->add_users_to_worklist(n);
   }
 
-  // Set the escape state of a node
-  void set_escape_state(uint ni, PointsToNode::EscapeState es);
-
-  // Find fields initializing values for allocations.
-  void find_init_values(Node* n, VectorSet* visited, PhaseTransform* phase);
-
-  // Adjust escape state after Connection Graph is built.
-  void adjust_escape_state(Node* n);
-
-  // Propagate escape states to referenced nodes.
-  bool propagate_escape_state(GrowableArray<int>* cg_worklist,
-                              GrowableArray<uint>* worklist,
-                              PointsToNode::EscapeState esc_state);
-
-  // Optimize objects compare.
-  Node* optimize_ptr_compare(Node* n);
-
   // Compute the escape information
   bool compute_escape();
 
@@ -373,11 +580,10 @@
   // Perform escape analysis
   static void do_analysis(Compile *C, PhaseIterGVN *igvn);
 
-  // escape state of a node
-  PointsToNode::EscapeState escape_state(Node *n);
+  bool not_global_escape(Node *n);
 
 #ifndef PRODUCT
-  void dump();
+  void dump(GrowableArray<PointsToNode*>& ptnodes_worklist);
 #endif
 };
 
--- a/src/share/vm/opto/library_call.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/library_call.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -175,7 +175,11 @@
   bool inline_unsafe_allocate();
   bool inline_unsafe_copyMemory();
   bool inline_native_currentThread();
-  bool inline_native_time_funcs(bool isNano);
+#ifdef TRACE_HAVE_INTRINSICS
+  bool inline_native_classID();
+  bool inline_native_threadID();
+#endif
+  bool inline_native_time_funcs(address method, const char* funcName);
   bool inline_native_isInterrupted();
   bool inline_native_Class_query(vmIntrinsics::ID id);
   bool inline_native_subtype_check();
@@ -338,8 +342,27 @@
     break;
 
   case vmIntrinsics::_bitCount_i:
+    if (!Matcher::match_rule_supported(Op_PopCountI)) return NULL;
+    break;
+
   case vmIntrinsics::_bitCount_l:
-    if (!UsePopCountInstruction)  return NULL;
+    if (!Matcher::match_rule_supported(Op_PopCountL)) return NULL;
+    break;
+
+  case vmIntrinsics::_numberOfLeadingZeros_i:
+    if (!Matcher::match_rule_supported(Op_CountLeadingZerosI)) return NULL;
+    break;
+
+  case vmIntrinsics::_numberOfLeadingZeros_l:
+    if (!Matcher::match_rule_supported(Op_CountLeadingZerosL)) return NULL;
+    break;
+
+  case vmIntrinsics::_numberOfTrailingZeros_i:
+    if (!Matcher::match_rule_supported(Op_CountTrailingZerosI)) return NULL;
+    break;
+
+  case vmIntrinsics::_numberOfTrailingZeros_l:
+    if (!Matcher::match_rule_supported(Op_CountTrailingZerosL)) return NULL;
     break;
 
   case vmIntrinsics::_Reference_get:
@@ -416,14 +439,12 @@
     return kit.transfer_exceptions_into_jvms();
   }
 
-  if (PrintIntrinsics) {
+  // The intrinsic bailed out
+  if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
     if (jvms->has_method()) {
       // Not a root compile.
-      tty->print("Did not inline intrinsic %s%s at bci:%d in",
-                 vmIntrinsics::name_at(intrinsic_id()),
-                 (is_virtual() ? " (virtual)" : ""), kit.bci());
-      kit.caller()->print_short_name(tty);
-      tty->print_cr(" (%d bytes)", kit.caller()->code_size());
+      const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)";
+      CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), msg);
     } else {
       // Root compile
       tty->print("Did not generate intrinsic %s%s at bci:%d in",
@@ -621,10 +642,18 @@
   case vmIntrinsics::_isInterrupted:
     return inline_native_isInterrupted();
 
+#ifdef TRACE_HAVE_INTRINSICS
+  case vmIntrinsics::_classID:
+    return inline_native_classID();
+  case vmIntrinsics::_threadID:
+    return inline_native_threadID();
+  case vmIntrinsics::_counterTime:
+    return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime");
+#endif
   case vmIntrinsics::_currentTimeMillis:
-    return inline_native_time_funcs(false);
+    return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis");
   case vmIntrinsics::_nanoTime:
-    return inline_native_time_funcs(true);
+    return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime");
   case vmIntrinsics::_allocateInstance:
     return inline_unsafe_allocate();
   case vmIntrinsics::_copyMemory:
@@ -2823,14 +2852,63 @@
   return true;
 }
 
+#ifdef TRACE_HAVE_INTRINSICS
+/*
+ * oop -> myklass
+ * myklass->trace_id |= USED
+ * return myklass->trace_id & ~0x3
+ */
+bool LibraryCallKit::inline_native_classID() {
+  int nargs = 1 + 1;
+  null_check_receiver(callee());  // check then ignore argument(0)
+  _sp += nargs;
+  Node* cls = do_null_check(argument(1), T_OBJECT);
+  _sp -= nargs;
+  Node* kls = load_klass_from_mirror(cls, false, nargs, NULL, 0);
+  _sp += nargs;
+  kls = do_null_check(kls, T_OBJECT);
+  _sp -= nargs;
+  ByteSize offset = TRACE_ID_OFFSET;
+  Node* insp = basic_plus_adr(kls, in_bytes(offset));
+  Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG);
+  Node* bits = longcon(~0x03l); // ignore bit 0 & 1
+  Node* andl = _gvn.transform(new (C, 3) AndLNode(tvalue, bits));
+  Node* clsused = longcon(0x01l); // set the class bit
+  Node* orl = _gvn.transform(new (C, 3) OrLNode(tvalue, clsused));
+
+  const TypePtr *adr_type = _gvn.type(insp)->isa_ptr();
+  store_to_memory(control(), insp, orl, T_LONG, adr_type);
+  push_pair(andl);
+  return true;
+}
+
+bool LibraryCallKit::inline_native_threadID() {
+  Node* tls_ptr = NULL;
+  Node* cur_thr = generate_current_thread(tls_ptr);
+  Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset()));
+  Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS);
+  p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset()));
+
+  Node* threadid = NULL;
+  size_t thread_id_size = OSThread::thread_id_size();
+  if (thread_id_size == (size_t) BytesPerLong) {
+    threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG));
+    push(threadid);
+  } else if (thread_id_size == (size_t) BytesPerInt) {
+    threadid = make_load(control(), p, TypeInt::INT, T_INT);
+    push(threadid);
+  } else {
+    ShouldNotReachHere();
+  }
+  return true;
+}
+#endif
+
 //------------------------inline_native_time_funcs--------------
 // inline code for System.currentTimeMillis() and System.nanoTime()
 // these have the same type and signature
-bool LibraryCallKit::inline_native_time_funcs(bool isNano) {
-  address funcAddr = isNano ? CAST_FROM_FN_PTR(address, os::javaTimeNanos) :
-                              CAST_FROM_FN_PTR(address, os::javaTimeMillis);
-  const char * funcName = isNano ? "nanoTime" : "currentTimeMillis";
-  const TypeFunc *tf = OptoRuntime::current_time_millis_Type();
+bool LibraryCallKit::inline_native_time_funcs(address funcAddr, const char* funcName) {
+  const TypeFunc *tf = OptoRuntime::void_long_Type();
   const TypePtr* no_memory_effects = NULL;
   Node* time = make_runtime_call(RC_LEAF, tf, funcAddr, funcName, no_memory_effects);
   Node* value = _gvn.transform(new (C, 1) ProjNode(time, TypeFunc::Parms+0));
@@ -5453,4 +5531,3 @@
   push(result);
   return true;
 }
-
--- a/src/share/vm/opto/phase.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/phase.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,8 +39,9 @@
 
 // The next timers used for LogCompilation
 elapsedTimer Phase::_t_parser;
-elapsedTimer Phase::_t_escapeAnalysis;
 elapsedTimer Phase::_t_optimizer;
+elapsedTimer   Phase::_t_escapeAnalysis;
+elapsedTimer     Phase::_t_connectionGraph;
 elapsedTimer   Phase::_t_idealLoop;
 elapsedTimer   Phase::_t_ccp;
 elapsedTimer Phase::_t_matcher;
@@ -51,6 +52,7 @@
 elapsedTimer Phase::_t_graphReshaping;
 elapsedTimer Phase::_t_scheduler;
 elapsedTimer Phase::_t_blockOrdering;
+elapsedTimer Phase::_t_macroEliminate;
 elapsedTimer Phase::_t_macroExpand;
 elapsedTimer Phase::_t_peephole;
 elapsedTimer Phase::_t_codeGeneration;
@@ -104,6 +106,8 @@
     if (DoEscapeAnalysis) {
       // EA is part of Optimizer.
       tty->print_cr ("      escape analysis: %3.3f sec", Phase::_t_escapeAnalysis.seconds());
+      tty->print_cr ("        connection graph: %3.3f sec", Phase::_t_connectionGraph.seconds());
+      tty->print_cr ("      macroEliminate : %3.3f sec", Phase::_t_macroEliminate.seconds());
     }
     tty->print_cr ("      iterGVN        : %3.3f sec", Phase::_t_iterGVN.seconds());
     tty->print_cr ("      idealLoop      : %3.3f sec", Phase::_t_idealLoop.seconds());
@@ -112,9 +116,10 @@
     tty->print_cr ("      iterGVN2       : %3.3f sec", Phase::_t_iterGVN2.seconds());
     tty->print_cr ("      macroExpand    : %3.3f sec", Phase::_t_macroExpand.seconds());
     tty->print_cr ("      graphReshape   : %3.3f sec", Phase::_t_graphReshaping.seconds());
-    double optimizer_subtotal = Phase::_t_iterGVN.seconds() +
+    double optimizer_subtotal = Phase::_t_iterGVN.seconds() + Phase::_t_iterGVN2.seconds() +
+      Phase::_t_escapeAnalysis.seconds() + Phase::_t_macroEliminate.seconds() +
       Phase::_t_idealLoop.seconds() + Phase::_t_ccp.seconds() +
-      Phase::_t_graphReshaping.seconds();
+      Phase::_t_macroExpand.seconds() + Phase::_t_graphReshaping.seconds();
     double percent_of_optimizer = ((optimizer_subtotal == 0.0) ? 0.0 : (optimizer_subtotal / Phase::_t_optimizer.seconds() * 100.0));
     tty->print_cr ("      subtotal       : %3.3f sec,  %3.2f %%", optimizer_subtotal, percent_of_optimizer);
   }
--- a/src/share/vm/opto/phase.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/phase.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -72,8 +72,12 @@
 
 // The next timers used for LogCompilation
   static elapsedTimer _t_parser;
-  static elapsedTimer _t_escapeAnalysis;
   static elapsedTimer _t_optimizer;
+public:
+  // ConnectionGraph can't be Phase since it is used after EA done.
+  static elapsedTimer   _t_escapeAnalysis;
+  static elapsedTimer     _t_connectionGraph;
+protected:
   static elapsedTimer   _t_idealLoop;
   static elapsedTimer   _t_ccp;
   static elapsedTimer _t_matcher;
@@ -84,6 +88,7 @@
   static elapsedTimer _t_graphReshaping;
   static elapsedTimer _t_scheduler;
   static elapsedTimer _t_blockOrdering;
+  static elapsedTimer _t_macroEliminate;
   static elapsedTimer _t_macroExpand;
   static elapsedTimer _t_peephole;
   static elapsedTimer _t_codeGeneration;
--- a/src/share/vm/opto/runtime.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/runtime.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -709,9 +709,9 @@
   return TypeFunc::make(domain, range);
 }
 
-//-------------- currentTimeMillis
+//-------------- currentTimeMillis, currentTimeNanos, etc
 
-const TypeFunc* OptoRuntime::current_time_millis_Type() {
+const TypeFunc* OptoRuntime::void_long_Type() {
   // create input type (domain)
   const Type **fields = TypeTuple::fields(0);
   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+0, fields);
--- a/src/share/vm/opto/runtime.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/runtime.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -268,7 +268,7 @@
   static const TypeFunc* Math_DD_D_Type(); // mod,pow & friends
   static const TypeFunc* modf_Type();
   static const TypeFunc* l2f_Type();
-  static const TypeFunc* current_time_millis_Type();
+  static const TypeFunc* void_long_Type();
 
   static const TypeFunc* flush_windows_Type();
 
--- a/src/share/vm/opto/stringopts.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/stringopts.cpp	Tue May 15 11:27:24 2012 -0700
@@ -897,8 +897,8 @@
 }
 
 Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) {
-  const TypeKlassPtr* klass_type = TypeKlassPtr::make(field->holder());
-  Node* klass_node = __ makecon(klass_type);
+  const TypeInstPtr* mirror_type = TypeInstPtr::make(field->holder()->java_mirror());
+  Node* klass_node = __ makecon(mirror_type);
   BasicType bt = field->layout_type();
   ciType* field_klass = field->type();
 
@@ -913,6 +913,7 @@
       // and may yield a vacuous result if the field is of interface type.
       type = TypeOopPtr::make_from_constant(con, true)->isa_oopptr();
       assert(type != NULL, "field singleton type must be consistent");
+      return __ makecon(type);
     } else {
       type = TypeOopPtr::make_from_klass(field_klass->as_klass());
     }
@@ -922,7 +923,7 @@
 
   return kit.make_load(NULL, kit.basic_plus_adr(klass_node, field->offset_in_bytes()),
                        type, T_OBJECT,
-                       C->get_alias_index(klass_type->add_offset(field->offset_in_bytes())));
+                       C->get_alias_index(mirror_type->add_offset(field->offset_in_bytes())));
 }
 
 Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) {
--- a/src/share/vm/opto/superword.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/opto/superword.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1221,12 +1221,11 @@
       return opd; // input is matching vector
     }
     assert(!opd->is_VectorStore(), "such vector is not expected here");
-    // Convert scalar input to vector. Use p0's type because it's container
-    // maybe smaller than the operand's container.
-    const Type* opd_t = velt_type(!in_bb(opd) ? p0 : opd);
-    const Type* p0_t  = velt_type(p0);
-    if (p0_t->higher_equal(opd_t)) opd_t = p0_t;
-    VectorNode* vn    = VectorNode::scalar2vector(_phase->C, opd, vlen, opd_t);
+    // Convert scalar input to vector with the same number of elements as
+    // p0's vector. Use p0's type because size of operand's container in
+    // vector should match p0's size regardless operand's size.
+    const Type* p0_t = velt_type(p0);
+    VectorNode* vn = VectorNode::scalar2vector(_phase->C, opd, vlen, p0_t);
 
     _phase->_igvn.register_new_node_with_optimizer(vn);
     _phase->set_ctrl(vn, _phase->get_ctrl(opd));
@@ -1234,14 +1233,15 @@
   }
 
   // Insert pack operation
-  const Type* opd_t = velt_type(!in_bb(opd) ? p0 : opd);
-  PackNode* pk = PackNode::make(_phase->C, opd, opd_t);
+  const Type* p0_t = velt_type(p0);
+  PackNode* pk = PackNode::make(_phase->C, opd, p0_t);
+  DEBUG_ONLY( const BasicType opd_bt = opd->bottom_type()->basic_type(); )
 
   for (uint i = 1; i < vlen; i++) {
     Node* pi = p->at(i);
     Node* in = pi->in(opd_idx);
     assert(my_pack(in) == NULL, "Should already have been unpacked");
-    assert(opd_t == velt_type(!in_bb(in) ? pi : in), "all same type");
+    assert(opd_bt == in->bottom_type()->basic_type(), "all same type");
     pk->add_opd(in);
   }
   _phase->_igvn.register_new_node_with_optimizer(pk);
--- a/src/share/vm/precompiled/precompiled.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/precompiled/precompiled.hpp	Tue May 15 11:27:24 2012 -0700
@@ -293,13 +293,10 @@
 # include "c1/c1_globals.hpp"
 #endif // COMPILER1
 #ifndef SERIALGC
-# include "gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp"
 # include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
 # include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
 # include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"
-# include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
 # include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
-# include "gc_implementation/concurrentMarkSweep/freeList.hpp"
 # include "gc_implementation/concurrentMarkSweep/promotionInfo.hpp"
 # include "gc_implementation/g1/dirtyCardQueue.hpp"
 # include "gc_implementation/g1/g1BlockOffsetTable.hpp"
--- a/src/share/vm/prims/jvm.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/prims/jvm.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1301,9 +1301,6 @@
 // Inner class reflection ///////////////////////////////////////////////////////////////////////////////
 
 JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass))
-  const int inner_class_info_index = 0;
-  const int outer_class_info_index = 1;
-
   JvmtiVMObjectAllocEventCollector oam;
   // ofClass is a reference to a java_lang_Class object. The mirror object
   // of an instanceKlass
@@ -1315,26 +1312,26 @@
   }
 
   instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
-
-  if (k->inner_classes()->length() == 0) {
+  InnerClassesIterator iter(k);
+
+  if (iter.length() == 0) {
     // Neither an inner nor outer class
     oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL);
     return (jobjectArray)JNIHandles::make_local(env, result);
   }
 
   // find inner class info
-  typeArrayHandle    icls(thread, k->inner_classes());
   constantPoolHandle cp(thread, k->constants());
-  int length = icls->length();
+  int length = iter.length();
 
   // Allocate temp. result array
   objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), length/4, CHECK_NULL);
   objArrayHandle result (THREAD, r);
   int members = 0;
 
-  for(int i = 0; i < length; i += 4) {
-    int ioff = icls->ushort_at(i + inner_class_info_index);
-    int ooff = icls->ushort_at(i + outer_class_info_index);
+  for (; !iter.done(); iter.next()) {
+    int ioff = iter.inner_class_info_index();
+    int ooff = iter.outer_class_info_index();
 
     if (ioff != 0 && ooff != 0) {
       // Check to see if the name matches the class we're looking for
@@ -1392,17 +1389,13 @@
                                                      bool* inner_is_member,
                                                      TRAPS) {
   Thread* thread = THREAD;
-  const int inner_class_info_index = inner_class_inner_class_info_offset;
-  const int outer_class_info_index = inner_class_outer_class_info_offset;
-
-  if (k->inner_classes()->length() == 0) {
+  InnerClassesIterator iter(k);
+  if (iter.length() == 0) {
     // No inner class info => no declaring class
     return NULL;
   }
 
-  typeArrayHandle i_icls(thread, k->inner_classes());
   constantPoolHandle i_cp(thread, k->constants());
-  int i_length = i_icls->length();
 
   bool found = false;
   klassOop ok;
@@ -1410,10 +1403,10 @@
   *inner_is_member = false;
 
   // Find inner_klass attribute
-  for (int i = 0; i < i_length && !found; i += inner_class_next_offset) {
-    int ioff = i_icls->ushort_at(i + inner_class_info_index);
-    int ooff = i_icls->ushort_at(i + outer_class_info_index);
-    int noff = i_icls->ushort_at(i + inner_class_inner_name_offset);
+  for (; !iter.done() && !found; iter.next()) {
+    int ioff = iter.inner_class_info_index();
+    int ooff = iter.outer_class_info_index();
+    int noff = iter.inner_name_index();
     if (ioff != 0) {
       // Check to see if the name matches the class we're looking for
       // before attempting to find the class.
--- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -292,8 +292,8 @@
 
 // Compute the number of entries in the InnerClasses attribute
 u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() {
-  typeArrayOop inner_class_list = ikh()->inner_classes();
-  return (inner_class_list == NULL) ? 0 : inner_class_list->length();
+  InnerClassesIterator iter(ikh());
+  return iter.length();
 }
 
 // Write an annotation attribute.  The VM stores them in raw form, so all we need
@@ -324,26 +324,20 @@
 // JVMSpec|     } classes[number_of_classes];
 // JVMSpec|   }
 void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) {
-  typeArrayOop inner_class_list = ikh()->inner_classes();
-  guarantee(inner_class_list != NULL && inner_class_list->length() == length,
+  InnerClassesIterator iter(ikh());
+  guarantee(iter.length() != 0 && iter.length() == length,
             "caller must check");
-  typeArrayHandle inner_class_list_h(thread(), inner_class_list);
-  assert (length % instanceKlass::inner_class_next_offset == 0, "just checking");
   u2 entry_count = length / instanceKlass::inner_class_next_offset;
   u4 size = 2 + entry_count * (2+2+2+2);
 
   write_attribute_name_index("InnerClasses");
   write_u4(size);
   write_u2(entry_count);
-  for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) {
-    write_u2(inner_class_list_h->ushort_at(
-                      i + instanceKlass::inner_class_inner_class_info_offset));
-    write_u2(inner_class_list_h->ushort_at(
-                      i + instanceKlass::inner_class_outer_class_info_offset));
-    write_u2(inner_class_list_h->ushort_at(
-                      i + instanceKlass::inner_class_inner_name_offset));
-    write_u2(inner_class_list_h->ushort_at(
-                      i + instanceKlass::inner_class_access_flags_offset));
+  for (; !iter.done(); iter.next()) {
+    write_u2(iter.inner_class_info_index());
+    write_u2(iter.outer_class_info_index());
+    write_u2(iter.inner_name_index());
+    write_u2(iter.inner_access_flags());
   }
 }
 
@@ -727,8 +721,11 @@
       case Bytecodes::_invokestatic    :  // fall through
       case Bytecodes::_invokedynamic   :  // fall through
       case Bytecodes::_invokeinterface :
-        assert(len == 3 || (code == Bytecodes::_invokeinterface && len ==5),
+        assert(len == 3 ||
+               (code == Bytecodes::_invokeinterface && len == 5) ||
+               (code == Bytecodes::_invokedynamic   && len == 5),
                "sanity check");
+
         int cpci = Bytes::get_native_u2(bcp+1);
         bool is_invokedynamic = (EnableInvokeDynamic && code == Bytecodes::_invokedynamic);
         if (is_invokedynamic)
--- a/src/share/vm/prims/jvmtiExport.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/prims/jvmtiExport.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -324,6 +324,12 @@
       record_vm_internal_object_allocation(object);
     }
   }
+  inline static void post_array_size_exhausted() {
+    if (should_post_resource_exhausted()) {
+      post_resource_exhausted(JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR,
+                              "Requested array size exceeds VM limit");
+    }
+  }
 
   static void cleanup_thread             (JavaThread* thread) KERNEL_RETURN;
 
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Tue May 15 11:27:24 2012 -0700
@@ -2400,44 +2400,33 @@
   // new constant indices as needed. The inner classes info is a
   // quadruple:
   // (inner_class_info, outer_class_info, inner_name, inner_access_flags)
-  typeArrayOop inner_class_list = scratch_class->inner_classes();
-  int icl_length = (inner_class_list == NULL) ? 0 : inner_class_list->length();
-  if (icl_length > 0) {
-    typeArrayHandle inner_class_list_h(THREAD, inner_class_list);
-    for (int i = 0; i < icl_length;
-         i += instanceKlass::inner_class_next_offset) {
-      int cur_index = inner_class_list_h->ushort_at(i
-                        + instanceKlass::inner_class_inner_class_info_offset);
-      if (cur_index == 0) {
-        continue;  // JVM spec. allows null inner class refs so skip it
-      }
-      int new_index = find_new_index(cur_index);
-      if (new_index != 0) {
-        RC_TRACE_WITH_THREAD(0x00080000, THREAD,
-          ("inner_class_info change: %d to %d", cur_index, new_index));
-        inner_class_list_h->ushort_at_put(i
-          + instanceKlass::inner_class_inner_class_info_offset, new_index);
-      }
-      cur_index = inner_class_list_h->ushort_at(i
-                    + instanceKlass::inner_class_outer_class_info_offset);
-      new_index = find_new_index(cur_index);
-      if (new_index != 0) {
-        RC_TRACE_WITH_THREAD(0x00080000, THREAD,
-          ("outer_class_info change: %d to %d", cur_index, new_index));
-        inner_class_list_h->ushort_at_put(i
-          + instanceKlass::inner_class_outer_class_info_offset, new_index);
-      }
-      cur_index = inner_class_list_h->ushort_at(i
-                    + instanceKlass::inner_class_inner_name_offset);
-      new_index = find_new_index(cur_index);
-      if (new_index != 0) {
-        RC_TRACE_WITH_THREAD(0x00080000, THREAD,
-          ("inner_name change: %d to %d", cur_index, new_index));
-        inner_class_list_h->ushort_at_put(i
-          + instanceKlass::inner_class_inner_name_offset, new_index);
-      }
-    } // end for each inner class
-  } // end if we have inner classes
+  InnerClassesIterator iter(scratch_class);
+  for (; !iter.done(); iter.next()) {
+    int cur_index = iter.inner_class_info_index();
+    if (cur_index == 0) {
+      continue;  // JVM spec. allows null inner class refs so skip it
+    }
+    int new_index = find_new_index(cur_index);
+    if (new_index != 0) {
+      RC_TRACE_WITH_THREAD(0x00080000, THREAD,
+        ("inner_class_info change: %d to %d", cur_index, new_index));
+      iter.set_inner_class_info_index(new_index);
+    }
+    cur_index = iter.outer_class_info_index();
+    new_index = find_new_index(cur_index);
+    if (new_index != 0) {
+      RC_TRACE_WITH_THREAD(0x00080000, THREAD,
+        ("outer_class_info change: %d to %d", cur_index, new_index));
+      iter.set_outer_class_info_index(new_index);
+    }
+    cur_index = iter.inner_name_index();
+    new_index = find_new_index(cur_index);
+    if (new_index != 0) {
+      RC_TRACE_WITH_THREAD(0x00080000, THREAD,
+        ("inner_name change: %d to %d", cur_index, new_index));
+      iter.set_inner_name_index(new_index);
+    }
+  } // end for each inner class
 
   // Attach each method in klass to the new constant pool and update
   // to use new constant pool indices as needed:
--- a/src/share/vm/prims/nativeLookup.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/prims/nativeLookup.cpp	Tue May 15 11:27:24 2012 -0700
@@ -121,6 +121,7 @@
   void JNICALL JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls);
   void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls);
   void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
+  void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
 }
 
 #define CC (char*)  /* cast a literal from (const char*) */
@@ -133,7 +134,8 @@
 
   { CC"Java_sun_misc_Unsafe_registerNatives",                      NULL, FN_PTR(JVM_RegisterUnsafeMethods)       },
   { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
-  { CC"Java_sun_misc_Perf_registerNatives",                        NULL, FN_PTR(JVM_RegisterPerfMethods)         }
+  { CC"Java_sun_misc_Perf_registerNatives",                        NULL, FN_PTR(JVM_RegisterPerfMethods)         },
+  { CC"Java_sun_hotspot_WhiteBox_registerNatives",                 NULL, FN_PTR(JVM_RegisterWhiteBoxMethods)     },
 };
 
 static address lookup_special_native(char* jni_name) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/prims/wbtestmethods/parserTests.cpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "classfile/symbolTable.hpp"
+
+#include "prims/jni.h"
+#include "prims/whitebox.hpp"
+#include "prims/wbtestmethods/parserTests.hpp"
+#include "runtime/interfaceSupport.hpp"
+
+#include "memory/oopFactory.hpp"
+
+#include "services/diagnosticArgument.hpp"
+#include "services/diagnosticFramework.hpp"
+
+//There's no way of beforeahnd knowing an upper size
+//Of the length of a string representation of
+//the value of an argument.
+#define VALUE_MAXLEN 256
+
+// DiagnosticFramework test utility methods
+
+/*
+ * The DiagnosticArgumentType class contains an enum that says which type
+ * this argument represents. (JLONG, BOOLEAN etc).
+ * This method Returns a char* representation of that enum value.
+ */
+static const char* lookup_diagnosticArgumentEnum(const char* field_name, oop object) {
+  Thread* THREAD = Thread::current();
+  const char* enum_sig = "Lsun/hotspot/parser/DiagnosticCommand$DiagnosticArgumentType;";
+  TempNewSymbol enumSigSymbol = SymbolTable::lookup(enum_sig, (int) strlen(enum_sig), THREAD);
+  int offset = WhiteBox::offset_for_field(field_name, object, enumSigSymbol);
+  oop enumOop = object->obj_field(offset);
+
+  const char* ret = WhiteBox::lookup_jstring("name", enumOop);
+  return ret;
+}
+
+/*
+ * Takes an oop to a DiagnosticArgumentType-instance and
+ * reads the fields from it. Fills an native DCmdParser with
+ * this info.
+ */
+static void fill_in_parser(DCmdParser* parser, oop argument)
+{
+  const char* name = WhiteBox::lookup_jstring("name", argument);
+  const char* desc = WhiteBox::lookup_jstring("desc", argument);
+  const char* default_value = WhiteBox::lookup_jstring("defaultValue", argument);
+  bool mandatory = WhiteBox::lookup_bool("mandatory", argument);
+  const char*  type = lookup_diagnosticArgumentEnum("type", argument);
+
+   if (strcmp(type, "STRING") == 0) {
+     DCmdArgument<char*>* argument = new DCmdArgument<char*>(
+     name, desc,
+     "STRING", mandatory, default_value);
+     parser->add_dcmd_option(argument);
+   } else if (strcmp(type, "NANOTIME") == 0) {
+     DCmdArgument<NanoTimeArgument>* argument = new DCmdArgument<NanoTimeArgument>(
+     name, desc,
+     "NANOTIME", mandatory, default_value);
+     parser->add_dcmd_option(argument);
+   } else if (strcmp(type, "JLONG") == 0) {
+     DCmdArgument<jlong>* argument = new DCmdArgument<jlong>(
+     name, desc,
+     "JLONG", mandatory, default_value);
+     parser->add_dcmd_option(argument);
+   } else if (strcmp(type, "BOOLEAN") == 0) {
+     DCmdArgument<bool>* argument = new DCmdArgument<bool>(
+     name, desc,
+     "BOOLEAN", mandatory, default_value);
+     parser->add_dcmd_option(argument);
+   } else if (strcmp(type, "MEMORYSIZE") == 0) {
+     DCmdArgument<MemorySizeArgument>* argument = new DCmdArgument<MemorySizeArgument>(
+     name, desc,
+     "MEMORY SIZE", mandatory, default_value);
+     parser->add_dcmd_option(argument);
+   } else if (strcmp(type, "STRINGARRAY") == 0) {
+     DCmdArgument<StringArrayArgument*>* argument = new DCmdArgument<StringArrayArgument*>(
+     name, desc,
+     "STRING SET", mandatory);
+     parser->add_dcmd_option(argument);
+   }
+}
+
+/*
+ * Will Fill in a java object array with alternating names of parsed command line options and
+ * the value that has been parsed for it:
+ * { name, value, name, value ... }
+ * This can then be checked from java.
+ */
+WB_ENTRY(jobjectArray, WB_ParseCommandLine(JNIEnv* env, jobject o, jstring j_cmdline, jobjectArray arguments))
+  ResourceMark rm;
+  DCmdParser parser;
+
+  const char* c_cmdline = java_lang_String::as_utf8_string(JNIHandles::resolve(j_cmdline));
+  objArrayOop argumentArray = objArrayOop(JNIHandles::resolve_non_null(arguments));
+
+  int length = argumentArray->length();
+
+  for (int i = 0; i < length; i++) {
+    oop argument_oop = argumentArray->obj_at(i);
+    fill_in_parser(&parser, argument_oop);
+  }
+
+  CmdLine cmdline(c_cmdline, strlen(c_cmdline), true);
+  parser.parse(&cmdline,',',CHECK_NULL);
+
+  klassOop k = SystemDictionary::Object_klass();
+  objArrayOop returnvalue_array = oopFactory::new_objArray(k, parser.num_arguments() * 2, CHECK_NULL);
+
+  GrowableArray<const char *>*parsedArgNames = parser.argument_name_array();
+
+  for (int i = 0; i < parser.num_arguments(); i++) {
+    oop parsedName = java_lang_String::create_oop_from_str(parsedArgNames->at(i), CHECK_NULL);
+    returnvalue_array->obj_at_put(i*2, parsedName);
+    GenDCmdArgument* arg = parser.lookup_dcmd_option(parsedArgNames->at(i), strlen(parsedArgNames->at(i)));
+    char buf[VALUE_MAXLEN];
+    arg->value_as_str(buf, sizeof(buf));
+    oop parsedValue = java_lang_String::create_oop_from_str(buf, CHECK_NULL);
+    returnvalue_array->obj_at_put(i*2+1, parsedValue);
+  }
+
+  return (jobjectArray) JNIHandles::make_local(returnvalue_array);
+
+WB_END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/prims/wbtestmethods/parserTests.hpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
+#define SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
+
+#include "prims/jni.h"
+#include "prims/whitebox.hpp"
+
+WB_METHOD_DECLARE WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments);
+
+#endif //SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/prims/whitebox.cpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "memory/universe.hpp"
+#include "oops/oop.inline.hpp"
+
+#include "classfile/symbolTable.hpp"
+
+#include "prims/whitebox.hpp"
+#include "prims/wbtestmethods/parserTests.hpp"
+
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/os.hpp"
+#include "utilities/debug.hpp"
+
+#ifndef SERIALGC
+#include "gc_implementation/g1/concurrentMark.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/heapRegionRemSet.hpp"
+#endif // !SERIALGC
+
+bool WhiteBox::_used = false;
+
+WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
+  return (jlong)(void*)JNIHandles::resolve(obj);
+WB_END
+
+WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
+  return heapOopSize;
+WB_END
+
+#ifndef SERIALGC
+WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
+  G1CollectedHeap* g1 = G1CollectedHeap::heap();
+  oop result = JNIHandles::resolve(obj);
+  const HeapRegion* hr = g1->heap_region_containing(result);
+  return hr->isHumongous();
+WB_END
+
+WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
+  G1CollectedHeap* g1 = G1CollectedHeap::heap();
+  size_t nr = g1->free_regions();
+  return (jlong)nr;
+WB_END
+
+WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
+  G1CollectedHeap* g1 = G1CollectedHeap::heap();
+  ConcurrentMark* cm = g1->concurrent_mark();
+  return cm->concurrent_marking_in_progress();
+WB_END
+
+WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
+  return (jint)HeapRegion::GrainBytes;
+WB_END
+#endif // !SERIALGC
+
+//Some convenience methods to deal with objects from java
+int WhiteBox::offset_for_field(const char* field_name, oop object,
+    Symbol* signature_symbol) {
+  assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
+  Thread* THREAD = Thread::current();
+
+  //Get the class of our object
+  klassOop arg_klass = object->klass();
+  //Turn it into an instance-klass
+  instanceKlass* ik = instanceKlass::cast(arg_klass);
+
+  //Create symbols to look for in the class
+  TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
+      THREAD);
+
+  //To be filled in with an offset of the field we're looking for
+  fieldDescriptor fd;
+
+  klassOop res = ik->find_field(name_symbol, signature_symbol, &fd);
+  if (res == NULL) {
+    tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
+        name_symbol->as_C_string());
+    fatal("Invalid layout of preloaded class");
+  }
+
+  //fetch the field at the offset we've found
+  int dest_offset = fd.offset();
+
+  return dest_offset;
+}
+
+
+const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
+  int offset = offset_for_field(field_name, object,
+      vmSymbols::string_signature());
+  oop string = object->obj_field(offset);
+  const char* ret = java_lang_String::as_utf8_string(string);
+  return ret;
+}
+
+bool WhiteBox::lookup_bool(const char* field_name, oop object) {
+  int offset =
+      offset_for_field(field_name, object, vmSymbols::bool_signature());
+  bool ret = (object->bool_field(offset) == JNI_TRUE);
+  return ret;
+}
+
+
+#define CC (char*)
+
+static JNINativeMethod methods[] = {
+  {CC"getObjectAddress",   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
+  {CC"getHeapOopSize",     CC"()I",                   (void*)&WB_GetHeapOopSize    },
+  {CC "parseCommandLine",
+      CC "(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
+      (void*) &WB_ParseCommandLine
+  },
+#ifndef SERIALGC
+  {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
+  {CC"g1IsHumongous",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
+  {CC"g1NumFreeRegions",   CC"()J",                   (void*)&WB_G1NumFreeRegions  },
+  {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
+#endif // !SERIALGC
+};
+
+#undef CC
+
+JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
+  {
+    if (WhiteBoxAPI) {
+      // Make sure that wbclass is loaded by the null classloader
+      instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
+      Handle loader(ikh->class_loader());
+      if (loader.is_null()) {
+        ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
+        jint result = env->RegisterNatives(wbclass, methods, sizeof(methods)/sizeof(methods[0]));
+        if (result == 0) {
+          WhiteBox::set_used();
+        }
+      }
+    }
+  }
+JVM_END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/prims/whitebox.hpp	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_PRIMS_WHITEBOX_HPP
+#define SHARE_VM_PRIMS_WHITEBOX_HPP
+
+#include "prims/jni.h"
+
+#include "memory/allocation.hpp"
+#include "oops/oopsHierarchy.hpp"
+
+// Entry macro to transition from JNI to VM state.
+
+#define WB_ENTRY(result_type, header) JNI_ENTRY(result_type, header)
+#define WB_END JNI_END
+#define WB_METHOD_DECLARE extern "C" jobjectArray JNICALL
+
+class WhiteBox : public AllStatic {
+ private:
+  static bool _used;
+ public:
+  static bool used()     { return _used; }
+  static void set_used() { _used = true; }
+  static int offset_for_field(const char* field_name, oop object,
+    Symbol* signature_symbol);
+  static const char* lookup_jstring(const char* field_name, oop object);
+  static bool lookup_bool(const char* field_name, oop object);
+};
+
+
+
+#endif // SHARE_VM_PRIMS_WHITEBOX_HPP
--- a/src/share/vm/runtime/arguments.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/arguments.cpp	Tue May 15 11:27:24 2012 -0700
@@ -816,8 +816,24 @@
     return true;
   }
 
-  jio_fprintf(defaultStream::error_stream(),
-              "Unrecognized VM option '%s'\n", argname);
+  // For locked flags, report a custom error message if available.
+  // Otherwise, report the standard unrecognized VM option.
+
+  Flag* locked_flag = Flag::find_flag((char*)argname, strlen(argname), true);
+  if (locked_flag != NULL) {
+    char locked_message_buf[BUFLEN];
+    locked_flag->get_locked_message(locked_message_buf, BUFLEN);
+    if (strlen(locked_message_buf) == 0) {
+      jio_fprintf(defaultStream::error_stream(),
+        "Unrecognized VM option '%s'\n", argname);
+    } else {
+      jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf);
+    }
+  } else {
+    jio_fprintf(defaultStream::error_stream(),
+                "Unrecognized VM option '%s'\n", argname);
+  }
+
   // allow for commandline "commenting out" options like -XX:#+Verbose
   return arg[0] == '#';
 }
@@ -2050,6 +2066,19 @@
     FREE_C_HEAP_ARRAY(char, altclasses_path);
   }
 
+  if (WhiteBoxAPI) {
+    // Append wb.jar to bootclasspath if enabled
+    const char* wb_jar = "wb.jar";
+    size_t wb_path_len = strlen(get_meta_index_dir()) + 1 +
+                         strlen(wb_jar);
+    char* wb_path = NEW_C_HEAP_ARRAY(char, wb_path_len);
+    strcpy(wb_path, get_meta_index_dir());
+    strcat(wb_path, wb_jar);
+    scp.add_suffix(wb_path);
+    scp_assembly_required = true;
+    FREE_C_HEAP_ARRAY(char, wb_path);
+  }
+
   // Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM)
   result = parse_java_options_environment_variable(&scp, &scp_assembly_required);
   if (result != JNI_OK) {
@@ -2510,15 +2539,6 @@
       // was arrived at by experimenting with specjbb.
       FLAG_SET_CMDLINE(uintx, OldPLABSize, 8*K);  // Note: this is in words
 
-      // CompilationPolicyChoice=0 causes the server compiler to adopt
-      // a more conservative which-method-do-I-compile policy when one
-      // of the counters maintained by the interpreter trips.  The
-      // result is reduced startup time and improved specjbb and
-      // alacrity performance.  Zero is the default, but we set it
-      // explicitly here in case the default changes.
-      // See runtime/compilationPolicy.*.
-      FLAG_SET_CMDLINE(intx, CompilationPolicyChoice, 0);
-
       // Enable parallel GC and adaptive generation sizing
       FLAG_SET_CMDLINE(bool, UseParallelGC, true);
       FLAG_SET_DEFAULT(ParallelGCThreads,
--- a/src/share/vm/runtime/globals.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/globals.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,12 @@
   }
 }
 
+// Get custom message for this locked flag, or return NULL if
+// none is available.
+void Flag::get_locked_message(char* buf, int buflen) const {
+  get_locked_message_ext(buf, buflen);
+}
+
 bool Flag::is_writeable() const {
   return strcmp(kind, "{manageable}") == 0 ||
          strcmp(kind, "{product rw}") == 0 ||
@@ -260,17 +266,22 @@
   return strncmp(s, q, len) == 0;
 }
 
-Flag* Flag::find_flag(char* name, size_t length) {
-  for (Flag* current = &flagTable[0]; current->name; current++) {
+// Search the flag table for a named flag
+Flag* Flag::find_flag(char* name, size_t length, bool allow_locked) {
+  for (Flag* current = &flagTable[0]; current->name != NULL; current++) {
     if (str_equal(current->name, name, length)) {
+      // Found a matching entry.  Report locked flags only if allowed.
       if (!(current->is_unlocked() || current->is_unlocker())) {
-        // disable use of diagnostic or experimental flags until they
-        // are explicitly unlocked
-        return NULL;
+        if (!allow_locked) {
+          // disable use of locked flags, e.g. diagnostic, experimental,
+          // commercial... until they are explicitly unlocked
+          return NULL;
+        }
       }
       return current;
     }
   }
+  // Flag name is not in the flag table
   return NULL;
 }
 
--- a/src/share/vm/runtime/globals.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/globals.hpp	Tue May 15 11:27:24 2012 -0700
@@ -222,7 +222,7 @@
   // number of flags
   static size_t numFlags;
 
-  static Flag* find_flag(char* name, size_t length);
+  static Flag* find_flag(char* name, size_t length, bool allow_locked = false);
 
   bool is_bool() const        { return strcmp(type, "bool") == 0; }
   bool get_bool() const       { return *((bool*) addr); }
@@ -259,6 +259,9 @@
   bool is_writeable_ext() const;
   bool is_external_ext() const;
 
+  void get_locked_message(char*, int) const;
+  void get_locked_message_ext(char*, int) const;
+
   void print_on(outputStream* st, bool withComments = false );
   void print_as_flag(outputStream* st);
 };
@@ -3804,7 +3807,7 @@
   product(uintx, SharedReadOnlySize,   10*M,                                \
           "Size of read-only space in permanent generation (in bytes)")     \
                                                                             \
-  product(uintx, SharedMiscDataSize,    NOT_LP64(4*M) LP64_ONLY(5*M),       \
+  product(uintx, SharedMiscDataSize, NOT_LP64(4*M) LP64_ONLY(5*M) NOT_PRODUCT(+1*M),       \
           "Size of the shared data area adjacent to the heap (in bytes)")   \
                                                                             \
   product(uintx, SharedMiscCodeSize,    4*M,                                \
@@ -3896,7 +3899,10 @@
   product(bool, UseVMInterruptibleIO, false,                                \
           "(Unstable, Solaris-specific) Thread interrupt before or with "   \
           "EINTR for I/O operations results in OS_INTRPT. The default value"\
-          " of this flag is true for JDK 6 and earlier")
+          " of this flag is true for JDK 6 and earlier")                    \
+                                                                            \
+  diagnostic(bool, WhiteBoxAPI, false,                                      \
+          "Enable internal testing APIs")
 
 /*
  *  Macros for factoring of globals
--- a/src/share/vm/runtime/globals_ext.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/globals_ext.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,4 +61,9 @@
   return false;
 }
 
+inline void Flag::get_locked_message_ext(char* buf, int buflen) const {
+  assert(buf != NULL, "Buffer cannot be NULL");
+  buf[0] = '\0';
+}
+
 #endif // SHARE_VM_RUNTIME_GLOBALS_EXT_HPP
--- a/src/share/vm/runtime/interfaceSupport.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/interfaceSupport.hpp	Tue May 15 11:27:24 2012 -0700
@@ -436,6 +436,7 @@
 #define VM_LEAF_BASE(result_type, header)                            \
   TRACE_CALL(result_type, header)                                    \
   debug_only(NoHandleMark __hm;)                                     \
+  os::verify_stack_alignment();                                      \
   /* begin of body */
 
 
@@ -445,6 +446,7 @@
   TRACE_CALL(result_type, header)                                    \
   HandleMarkCleaner __hm(thread);                                    \
   Thread* THREAD = thread;                                           \
+  os::verify_stack_alignment();                                      \
   /* begin of body */
 
 
@@ -454,6 +456,7 @@
   TRACE_CALL(result_type, header)                                    \
   debug_only(NoHandleMark __hm;)                                     \
   Thread* THREAD = thread;                                           \
+  os::verify_stack_alignment();                                      \
   /* begin of body */
 
 
--- a/src/share/vm/runtime/os.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/os.hpp	Tue May 15 11:27:24 2012 -0700
@@ -404,6 +404,8 @@
   static address current_stack_base();
   static size_t current_stack_size();
 
+  static void verify_stack_alignment() PRODUCT_RETURN;
+
   static int message_box(const char* title, const char* message);
   static char* do_you_want_to_debug(const char* message);
 
--- a/src/share/vm/runtime/osThread.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/osThread.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,6 +98,7 @@
 
   // For java intrinsics:
   static ByteSize interrupted_offset()            { return byte_offset_of(OSThread, _interrupted); }
+  static ByteSize thread_id_offset()              { return byte_offset_of(OSThread, _thread_id); }
 
   // Platform dependent stuff
 #ifdef TARGET_OS_FAMILY_linux
--- a/src/share/vm/runtime/reflection.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/reflection.cpp	Tue May 15 11:27:24 2012 -0700
@@ -591,14 +591,11 @@
 // Caller is responsible for figuring out in advance which case must be true.
 void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner,
                                        bool inner_is_member, TRAPS) {
-  const int inner_class_info_index = 0;
-  const int outer_class_info_index = 1;
-
-  typeArrayHandle    icls (THREAD, outer->inner_classes());
+  InnerClassesIterator iter(outer);
   constantPoolHandle cp   (THREAD, outer->constants());
-  for(int i = 0; i < icls->length(); i += 4) {
-     int ioff = icls->ushort_at(i + inner_class_info_index);
-     int ooff = icls->ushort_at(i + outer_class_info_index);
+  for (; !iter.done(); iter.next()) {
+     int ioff = iter.inner_class_info_index();
+     int ooff = iter.outer_class_info_index();
 
      if (inner_is_member && ioff != 0 && ooff != 0) {
         klassOop o = cp->klass_at(ooff, CHECK);
--- a/src/share/vm/runtime/safepoint.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/safepoint.cpp	Tue May 15 11:27:24 2012 -0700
@@ -219,6 +219,8 @@
 #ifdef ASSERT
   for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
     assert(cur->safepoint_state()->is_running(), "Illegal initial state");
+    // Clear the visited flag to ensure that the critical counts are collected properly.
+    cur->set_visited_for_critical_count(false);
   }
 #endif // ASSERT
 
@@ -378,6 +380,13 @@
 
   OrderAccess::fence();
 
+#ifdef ASSERT
+  for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
+    // make sure all the threads were visited
+    assert(cur->was_visited_for_critical_count(), "missed a thread");
+  }
+#endif // ASSERT
+
   // Update the count of active JNI critical regions
   GC_locker::set_jni_lock_count(_current_jni_active_count);
 
@@ -626,6 +635,7 @@
         _waiting_to_block--;
         thread->safepoint_state()->set_has_called_back(true);
 
+        DEBUG_ONLY(thread->set_visited_for_critical_count(true));
         if (thread->in_critical()) {
           // Notice that this thread is in a critical section
           increment_jni_active_count();
@@ -907,12 +917,8 @@
   // running, but are actually at a safepoint. We will happily
   // agree and update the safepoint state here.
   if (SafepointSynchronize::safepoint_safe(_thread, state)) {
+    SafepointSynchronize::check_for_lazy_critical_native(_thread, state);
     roll_forward(_at_safepoint);
-    SafepointSynchronize::check_for_lazy_critical_native(_thread, state);
-    if (_thread->in_critical()) {
-      // Notice that this thread is in a critical section
-      SafepointSynchronize::increment_jni_active_count();
-    }
     return;
   }
 
@@ -937,6 +943,11 @@
   switch(_type) {
     case _at_safepoint:
       SafepointSynchronize::signal_thread_at_safepoint();
+      DEBUG_ONLY(_thread->set_visited_for_critical_count(true));
+      if (_thread->in_critical()) {
+        // Notice that this thread is in a critical section
+        SafepointSynchronize::increment_jni_active_count();
+      }
       break;
 
     case _call_back:
--- a/src/share/vm/runtime/thread.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/thread.cpp	Tue May 15 11:27:24 2012 -0700
@@ -247,6 +247,10 @@
   omInUseList = NULL ;
   omInUseCount = 0 ;
 
+#ifdef ASSERT
+  _visited_for_critical_count = false;
+#endif
+
   _SR_lock = new Monitor(Mutex::suspend_resume, "SR_lock", true);
   _suspend_flags = 0;
 
@@ -3464,13 +3468,13 @@
     create_vm_init_libraries();
   }
 
+  // Notify JVMTI agents that VM initialization is complete - nop if no agents.
+  JvmtiExport::post_vm_initialized();
+
   if (!TRACE_START()) {
     vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
   }
 
-  // Notify JVMTI agents that VM initialization is complete - nop if no agents.
-  JvmtiExport::post_vm_initialized();
-
   if (CleanChunkPoolAsync) {
     Chunk::start_chunk_pool_cleaner_task();
   }
--- a/src/share/vm/runtime/thread.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/thread.hpp	Tue May 15 11:27:24 2012 -0700
@@ -268,6 +268,15 @@
   ObjectMonitor* omInUseList;                   // SLL to track monitors in circulation
   int omInUseCount;                             // length of omInUseList
 
+#ifdef ASSERT
+ private:
+  bool _visited_for_critical_count;
+
+ public:
+  void set_visited_for_critical_count(bool z) { _visited_for_critical_count = z; }
+  bool was_visited_for_critical_count() const   { return _visited_for_critical_count; }
+#endif
+
  public:
   enum {
     is_definitely_current_thread = true
--- a/src/share/vm/runtime/vmStructs.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/vmStructs.cpp	Tue May 15 11:27:24 2012 -0700
@@ -44,7 +44,6 @@
 #include "code/vmreg.hpp"
 #include "compiler/oopMap.hpp"
 #include "compiler/compileBroker.hpp"
-#include "gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp"
 #include "gc_implementation/shared/immutableSpace.hpp"
 #include "gc_implementation/shared/markSweep.hpp"
 #include "gc_implementation/shared/mutableSpace.hpp"
@@ -55,6 +54,7 @@
 #include "memory/cardTableRS.hpp"
 #include "memory/compactPermGen.hpp"
 #include "memory/defNewGeneration.hpp"
+#include "memory/freeBlockDictionary.hpp"
 #include "memory/genCollectedHeap.hpp"
 #include "memory/generation.hpp"
 #include "memory/generationSpec.hpp"
@@ -292,8 +292,6 @@
   nonstatic_field(instanceKlass,               _method_ordering,                              typeArrayOop)                          \
   nonstatic_field(instanceKlass,               _local_interfaces,                             objArrayOop)                           \
   nonstatic_field(instanceKlass,               _transitive_interfaces,                        objArrayOop)                           \
-  nonstatic_field(instanceKlass,               _nof_implementors,                             int)                                   \
-  nonstatic_field(instanceKlass,               _implementors[0],                              klassOop)                              \
   nonstatic_field(instanceKlass,               _fields,                                       typeArrayOop)                          \
   nonstatic_field(instanceKlass,               _java_fields_count,                            u2)                                    \
   nonstatic_field(instanceKlass,               _constants,                                    constantPoolOop)                       \
@@ -2343,7 +2341,6 @@
   /* instanceKlass enum                */                                 \
   /*************************************/                                 \
                                                                           \
-  declare_constant(instanceKlass::implementors_limit)                     \
                                                                           \
   /*************************************/                                 \
   /* FieldInfo FieldOffset enum        */                                 \
--- a/src/share/vm/runtime/vmThread.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/runtime/vmThread.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -304,7 +304,7 @@
     os::check_heap();
     // Silent verification so as not to pollute normal output,
     // unless we really asked for it.
-    Universe::verify(true, !(PrintGCDetails || Verbose));
+    Universe::verify(!(PrintGCDetails || Verbose));
   }
 
   CompileBroker::set_should_block();
--- a/src/share/vm/services/diagnosticArgument.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/services/diagnosticArgument.cpp	Tue May 15 11:27:24 2012 -0700
@@ -43,6 +43,47 @@
   set_is_set(true);
 }
 
+void GenDCmdArgument::to_string(jlong l, char* buf, size_t len) {
+  jio_snprintf(buf, len, INT64_FORMAT, l);
+}
+
+void GenDCmdArgument::to_string(bool b, char* buf, size_t len) {
+  jio_snprintf(buf, len, b ? "true" : "false");
+}
+
+void GenDCmdArgument::to_string(NanoTimeArgument n, char* buf, size_t len) {
+  jio_snprintf(buf, len, INT64_FORMAT, n._nanotime);
+}
+
+void GenDCmdArgument::to_string(MemorySizeArgument m, char* buf, size_t len) {
+  jio_snprintf(buf, len, INT64_FORMAT, m._size);
+}
+
+void GenDCmdArgument::to_string(char* c, char* buf, size_t len) {
+  jio_snprintf(buf, len, "%s", c);
+}
+
+void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) {
+  int length = f->array()->length();
+  size_t written = 0;
+  buf[0] = 0;
+  for (int i = 0; i < length; i++) {
+    char* next_str = f->array()->at(i);
+    size_t next_size = strlen(next_str);
+    //Check if there's room left to write next element
+    if (written + next_size > len) {
+      return;
+    }
+    //Actually write element
+    strcat(buf, next_str);
+    written += next_size;
+    //Check if there's room left for the comma
+    if (i < length-1 && len - written > 0) {
+      strcat(buf, ",");
+    }
+  }
+}
+
 template <> void DCmdArgument<jlong>::parse_value(const char* str,
                                                   size_t len, TRAPS) {
     if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) {
--- a/src/share/vm/services/diagnosticArgument.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/services/diagnosticArgument.hpp	Tue May 15 11:27:24 2012 -0700
@@ -110,12 +110,20 @@
   virtual void init_value(TRAPS) = 0;
   virtual void reset(TRAPS) = 0;
   virtual void cleanup() = 0;
+  virtual void value_as_str(char* buf, size_t len) = 0;
   void set_next(GenDCmdArgument* arg) {
     _next = arg;
   }
   GenDCmdArgument* next() {
     return _next;
   }
+
+  void to_string(jlong l, char* buf, size_t len);
+  void to_string(bool b, char* buf, size_t len);
+  void to_string(char* c, char* buf, size_t len);
+  void to_string(NanoTimeArgument n, char* buf, size_t len);
+  void to_string(MemorySizeArgument f, char* buf, size_t len);
+  void to_string(StringArrayArgument* s, char* buf, size_t len);
 };
 
 template <class ArgType> class DCmdArgument: public GenDCmdArgument {
@@ -143,6 +151,7 @@
   void parse_value(const char* str, size_t len, TRAPS);
   void init_value(TRAPS);
   void destroy_value();
+  void value_as_str(char *buf, size_t len) { return to_string(_value, buf, len);}
 };
 
 #endif  /* SHARE_VM_SERVICES_DIAGNOSTICARGUMENT_HPP */
--- a/src/share/vm/services/diagnosticCommand.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/services/diagnosticCommand.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,11 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(true, false));
 
+  //Enhanced JMX Agent Support
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(true,false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(true,false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(true,false));
+
 }
 
 #ifndef HAVE_EXTRA_DCMD
@@ -344,3 +349,185 @@
     return 0;
   }
 }
+
+// Enhanced JMX Agent support
+
+JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated) :
+
+  DCmdWithParser(output, heap_allocated),
+
+  _config_file
+  ("config.file",
+   "set com.sun.management.config.file", "STRING", false),
+
+  _jmxremote_port
+  ("jmxremote.port",
+   "set com.sun.management.jmxremote.port", "STRING", false),
+
+  _jmxremote_rmi_port
+  ("jmxremote.rmi.port",
+   "set com.sun.management.jmxremote.rmi.port", "STRING", false),
+
+  _jmxremote_ssl
+  ("jmxremote.ssl",
+   "set com.sun.management.jmxremote.ssl", "STRING", false),
+
+  _jmxremote_registry_ssl
+  ("jmxremote.registry.ssl",
+   "set com.sun.management.jmxremote.registry.ssl", "STRING", false),
+
+  _jmxremote_authenticate
+  ("jmxremote.authenticate",
+   "set com.sun.management.jmxremote.authenticate", "STRING", false),
+
+  _jmxremote_password_file
+  ("jmxremote.password.file",
+   "set com.sun.management.jmxremote.password.file", "STRING", false),
+
+  _jmxremote_access_file
+  ("jmxremote.access.file",
+   "set com.sun.management.jmxremote.access.file", "STRING", false),
+
+  _jmxremote_login_config
+  ("jmxremote.login.config",
+   "set com.sun.management.jmxremote.login.config", "STRING", false),
+
+  _jmxremote_ssl_enabled_cipher_suites
+  ("jmxremote.ssl.enabled.cipher.suites",
+   "set com.sun.management.jmxremote.ssl.enabled.cipher.suite", "STRING", false),
+
+  _jmxremote_ssl_enabled_protocols
+  ("jmxremote.ssl.enabled.protocols",
+   "set com.sun.management.jmxremote.ssl.enabled.protocols", "STRING", false),
+
+  _jmxremote_ssl_need_client_auth
+  ("jmxremote.ssl.need.client.auth",
+   "set com.sun.management.jmxremote.need.client.auth", "STRING", false),
+
+  _jmxremote_ssl_config_file
+  ("jmxremote.ssl.config.file",
+   "set com.sun.management.jmxremote.ssl_config_file", "STRING", false)
+
+  {
+    _dcmdparser.add_dcmd_option(&_config_file);
+    _dcmdparser.add_dcmd_option(&_jmxremote_port);
+    _dcmdparser.add_dcmd_option(&_jmxremote_rmi_port);
+    _dcmdparser.add_dcmd_option(&_jmxremote_ssl);
+    _dcmdparser.add_dcmd_option(&_jmxremote_registry_ssl);
+    _dcmdparser.add_dcmd_option(&_jmxremote_authenticate);
+    _dcmdparser.add_dcmd_option(&_jmxremote_password_file);
+    _dcmdparser.add_dcmd_option(&_jmxremote_access_file);
+    _dcmdparser.add_dcmd_option(&_jmxremote_login_config);
+    _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_cipher_suites);
+    _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols);
+    _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth);
+    _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file);
+}
+
+
+int JMXStartRemoteDCmd::num_arguments() {
+  ResourceMark rm;
+  JMXStartRemoteDCmd* dcmd = new JMXStartRemoteDCmd(NULL, false);
+  if (dcmd != NULL) {
+    DCmdMark mark(dcmd);
+    return dcmd->_dcmdparser.num_arguments();
+  } else {
+    return 0;
+  }
+}
+
+
+void JMXStartRemoteDCmd::execute(TRAPS) {
+    ResourceMark rm(THREAD);
+    HandleMark hm(THREAD);
+
+    // Load and initialize the sun.management.Agent class
+    // invoke startRemoteManagementAgent(string) method to start
+    // the remote management server.
+    // throw java.lang.NoSuchMethodError if the method doesn't exist
+
+    Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
+    klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+    instanceKlassHandle ik (THREAD, k);
+
+    JavaValue result(T_VOID);
+
+    // Pass all command line arguments to java as key=value,...
+    // All checks are done on java side
+
+    int len = 0;
+    stringStream options;
+    char comma[2] = {0,0};
+
+    // Leave default values on Agent.class side and pass only
+    // agruments explicitly set by user. All arguments passed
+    // to jcmd override properties with the same name set by
+    // command line with -D or by managmenent.properties
+    // file.
+#define PUT_OPTION(a) \
+    if ( (a).is_set() ){ \
+        options.print("%scom.sun.management.%s=%s", comma, (a).name(), (a).value()); \
+        comma[0] = ','; \
+    }
+
+    PUT_OPTION(_config_file);
+    PUT_OPTION(_jmxremote_port);
+    PUT_OPTION(_jmxremote_rmi_port);
+    PUT_OPTION(_jmxremote_ssl);
+    PUT_OPTION(_jmxremote_registry_ssl);
+    PUT_OPTION(_jmxremote_authenticate);
+    PUT_OPTION(_jmxremote_password_file);
+    PUT_OPTION(_jmxremote_access_file);
+    PUT_OPTION(_jmxremote_login_config);
+    PUT_OPTION(_jmxremote_ssl_enabled_cipher_suites);
+    PUT_OPTION(_jmxremote_ssl_enabled_protocols);
+    PUT_OPTION(_jmxremote_ssl_need_client_auth);
+    PUT_OPTION(_jmxremote_ssl_config_file);
+
+#undef PUT_OPTION
+
+    Handle str = java_lang_String::create_from_str(options.as_string(), CHECK);
+    JavaCalls::call_static(&result, ik, vmSymbols::startRemoteAgent_name(), vmSymbols::string_void_signature(), str, CHECK);
+}
+
+JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated) :
+  DCmd(output, heap_allocated)
+{
+  // do nothing
+}
+
+void JMXStartLocalDCmd::execute(TRAPS) {
+    ResourceMark rm(THREAD);
+    HandleMark hm(THREAD);
+
+    // Load and initialize the sun.management.Agent class
+    // invoke startLocalManagementAgent(void) method to start
+    // the local management server
+    // throw java.lang.NoSuchMethodError if method doesn't exist
+
+    Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
+    klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+    instanceKlassHandle ik (THREAD, k);
+
+    JavaValue result(T_VOID);
+    JavaCalls::call_static(&result, ik, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK);
+}
+
+
+void JMXStopRemoteDCmd::execute(TRAPS) {
+    ResourceMark rm(THREAD);
+    HandleMark hm(THREAD);
+
+    // Load and initialize the sun.management.Agent class
+    // invoke stopRemoteManagementAgent method to stop the
+    // management server
+    // throw java.lang.NoSuchMethodError if method doesn't exist
+
+    Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
+    klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+    instanceKlassHandle ik (THREAD, k);
+
+    JavaValue result(T_VOID);
+    JavaCalls::call_static(&result, ik, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK);
+}
+
--- a/src/share/vm/services/diagnosticCommand.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/services/diagnosticCommand.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -214,4 +214,82 @@
   virtual void execute(TRAPS);
 };
 
+// Enhanced JMX Agent support
+
+class JMXStartRemoteDCmd : public DCmdWithParser {
+
+  // Explicitly list all properties that could be
+  // passed to Agent.startRemoteManagementAgent()
+  // com.sun.management is omitted
+
+  DCmdArgument<char *> _config_file;
+  DCmdArgument<char *> _jmxremote_port;
+  DCmdArgument<char *> _jmxremote_rmi_port;
+  DCmdArgument<char *> _jmxremote_ssl;
+  DCmdArgument<char *> _jmxremote_registry_ssl;
+  DCmdArgument<char *> _jmxremote_authenticate;
+  DCmdArgument<char *> _jmxremote_password_file;
+  DCmdArgument<char *> _jmxremote_access_file;
+  DCmdArgument<char *> _jmxremote_login_config;
+  DCmdArgument<char *> _jmxremote_ssl_enabled_cipher_suites;
+  DCmdArgument<char *> _jmxremote_ssl_enabled_protocols;
+  DCmdArgument<char *> _jmxremote_ssl_need_client_auth;
+  DCmdArgument<char *> _jmxremote_ssl_config_file;
+
+public:
+  JMXStartRemoteDCmd(outputStream *output, bool heap_allocated);
+
+  static const char *name() {
+    return "ManagementAgent.start";
+  }
+
+  static const char *description() {
+    return "Start remote management agent.";
+  }
+
+  static int num_arguments();
+
+  virtual void execute(TRAPS);
+
+};
+
+class JMXStartLocalDCmd : public DCmd {
+
+  // Explicitly request start of local agent,
+  // it will not be started by start dcmd
+
+
+public:
+  JMXStartLocalDCmd(outputStream *output, bool heap_allocated);
+
+  static const char *name() {
+    return "ManagementAgent.start_local";
+  }
+
+  static const char *description() {
+    return "Start local management agent.";
+  }
+
+  virtual void execute(TRAPS);
+
+};
+
+class JMXStopRemoteDCmd : public DCmd {
+public:
+  JMXStopRemoteDCmd(outputStream *output, bool heap_allocated) :
+  DCmd(output, heap_allocated) {
+    // Do Nothing
+  }
+
+  static const char *name() {
+    return "ManagementAgent.stop";
+  }
+
+  static const char *description() {
+    return "Stop remote management agent.";
+  }
+
+  virtual void execute(TRAPS);
+};
+
 #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/src/share/vm/services/gcNotifier.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/services/gcNotifier.cpp	Tue May 15 11:27:24 2012 -0700
@@ -163,8 +163,8 @@
   constructor_args.push_oop(gcInfo_instance);
   constructor_args.push_oop(getGcInfoBuilder(gcManager,THREAD));
   constructor_args.push_long(gcStatInfo->gc_index());
-  constructor_args.push_long(gcStatInfo->start_time());
-  constructor_args.push_long(gcStatInfo->end_time());
+  constructor_args.push_long(Management::ticks_to_ms(gcStatInfo->start_time()));
+  constructor_args.push_long(Management::ticks_to_ms(gcStatInfo->end_time()));
   constructor_args.push_oop(usage_before_gc_ah);
   constructor_args.push_oop(usage_after_gc_ah);
   constructor_args.push_oop(extra_array);
--- a/src/share/vm/trace/traceMacros.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/trace/traceMacros.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,5 +43,9 @@
 #define TRACE_SET_KLASS_TRACE_ID(x1, x2) do { } while (0)
 #define TRACE_DEFINE_KLASS_METHODS typedef int ___IGNORED_hs_trace_type1
 #define TRACE_DEFINE_KLASS_TRACE_ID typedef int ___IGNORED_hs_trace_type2
+#define TRACE_DEFINE_OFFSET typedef int ___IGNORED_hs_trace_type3
+#define TRACE_ID_OFFSET in_ByteSize(0); ShouldNotReachHere()
+#define TRACE_TEMPLATES(template)
+#define TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias)
 
 #endif
--- a/src/share/vm/utilities/bitMap.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/utilities/bitMap.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -179,64 +179,6 @@
   clear_range_within_word(bit_index(end_full_word), end);
 }
 
-void BitMap::mostly_disjoint_range_union(BitMap* from_bitmap,
-                                         idx_t   from_start_index,
-                                         idx_t   to_start_index,
-                                         size_t  word_num) {
-  // Ensure that the parameters are correct.
-  // These shouldn't be that expensive to check, hence I left them as
-  // guarantees.
-  guarantee(from_bitmap->bit_in_word(from_start_index) == 0,
-            "it should be aligned on a word boundary");
-  guarantee(bit_in_word(to_start_index) == 0,
-            "it should be aligned on a word boundary");
-  guarantee(word_num >= 2, "word_num should be at least 2");
-
-  intptr_t* from = (intptr_t*) from_bitmap->word_addr(from_start_index);
-  intptr_t* to   = (intptr_t*) word_addr(to_start_index);
-
-  if (*from != 0) {
-    // if it's 0, then there's no point in doing the CAS
-    while (true) {
-      intptr_t old_value = *to;
-      intptr_t new_value = old_value | *from;
-      intptr_t res       = Atomic::cmpxchg_ptr(new_value, to, old_value);
-      if (res == old_value) break;
-    }
-  }
-  ++from;
-  ++to;
-
-  for (size_t i = 0; i < word_num - 2; ++i) {
-    if (*from != 0) {
-      // if it's 0, then there's no point in doing the CAS
-      assert(*to == 0, "nobody else should be writing here");
-      intptr_t new_value = *from;
-      *to = new_value;
-    }
-
-    ++from;
-    ++to;
-  }
-
-  if (*from != 0) {
-    // if it's 0, then there's no point in doing the CAS
-    while (true) {
-      intptr_t old_value = *to;
-      intptr_t new_value = old_value | *from;
-      intptr_t res       = Atomic::cmpxchg_ptr(new_value, to, old_value);
-      if (res == old_value) break;
-    }
-  }
-
-  // the -1 is because we didn't advance them after the final CAS
-  assert(from ==
-           (intptr_t*) from_bitmap->word_addr(from_start_index) + word_num - 1,
-            "invariant");
-  assert(to == (intptr_t*) word_addr(to_start_index) + word_num - 1,
-            "invariant");
-}
-
 void BitMap::at_put(idx_t offset, bool value) {
   if (value) {
     set_bit(offset);
--- a/src/share/vm/utilities/bitMap.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/utilities/bitMap.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -192,31 +192,6 @@
   void par_set_range(idx_t beg, idx_t end, RangeSizeHint hint);
   void par_clear_range  (idx_t beg, idx_t end, RangeSizeHint hint);
 
-  // It performs the union operation between subsets of equal length
-  // of two bitmaps (the target bitmap of the method and the
-  // from_bitmap) and stores the result to the target bitmap.  The
-  // from_start_index represents the first bit index of the subrange
-  // of the from_bitmap.  The to_start_index is the equivalent of the
-  // target bitmap. Both indexes should be word-aligned, i.e. they
-  // should correspond to the first bit on a bitmap word (it's up to
-  // the caller to ensure this; the method does check it).  The length
-  // of the subset is specified with word_num and it is in number of
-  // bitmap words. The caller should ensure that this is at least 2
-  // (smaller ranges are not support to save extra checks).  Again,
-  // this is checked in the method.
-  //
-  // Atomicity concerns: it is assumed that any contention on the
-  // target bitmap with other threads will happen on the first and
-  // last words; the ones in between will be "owned" exclusively by
-  // the calling thread and, in fact, they will already be 0. So, the
-  // method performs a CAS on the first word, copies the next
-  // word_num-2 words, and finally performs a CAS on the last word.
-  void mostly_disjoint_range_union(BitMap* from_bitmap,
-                                   idx_t   from_start_index,
-                                   idx_t   to_start_index,
-                                   size_t  word_num);
-
-
   // Clearing
   void clear_large();
   inline void clear();
--- a/src/share/vm/utilities/globalDefinitions_gcc.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/utilities/globalDefinitions_gcc.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,14 +87,7 @@
 #endif
 #ifdef __APPLE__
   #include <AvailabilityMacros.h>
-  #if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4)
-    // Mac OS X 10.4 defines EFL_AC and EFL_ID,
-    // which conflict with hotspot variable names.
-    //
-    // This has been fixed in Mac OS X 10.5.
-    #undef EFL_AC
-    #undef EFL_ID
-  #endif
+  #include <mach/mach.h>
 #endif
 #include <sys/time.h>
 #endif // LINUX || _ALLBSD_SOURCE
--- a/src/share/vm/utilities/growableArray.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/utilities/growableArray.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -198,8 +198,11 @@
     return idx;
   }
 
-  void append_if_missing(const E& elem) {
-    if (!contains(elem)) append(elem);
+  bool append_if_missing(const E& elem) {
+    // Returns TRUE if elem is added.
+    bool missed = !contains(elem);
+    if (missed) append(elem);
+    return missed;
   }
 
   E at(int i) const {
@@ -292,12 +295,22 @@
     ShouldNotReachHere();
   }
 
+  // The order is preserved.
   void remove_at(int index) {
     assert(0 <= index && index < _len, "illegal index");
     for (int j = index + 1; j < _len; j++) _data[j-1] = _data[j];
     _len--;
   }
 
+  // The order is changed.
+  void delete_at(int index) {
+    assert(0 <= index && index < _len, "illegal index");
+    if (index < --_len) {
+      // Replace removed element with last one.
+      _data[index] = _data[_len];
+    }
+  }
+
   // inserts the given element before the element at index i
   void insert_before(const int idx, const E& elem) {
     check_nesting();
--- a/src/share/vm/utilities/numberSeq.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/utilities/numberSeq.cpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -156,6 +156,10 @@
     _sequence[i] = 0.0;
 }
 
+TruncatedSeq::~TruncatedSeq() {
+  FREE_C_HEAP_ARRAY(double, _sequence);
+}
+
 void TruncatedSeq::add(double val) {
   AbsSeq::add(val);
 
--- a/src/share/vm/utilities/numberSeq.hpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/utilities/numberSeq.hpp	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -118,6 +118,7 @@
   // accepts a value for L
   TruncatedSeq(int length = DefaultSeqLength,
                double alpha = DEFAULT_ALPHA_VALUE);
+  ~TruncatedSeq();
   virtual void add(double val);
   virtual double maximum() const;
   virtual double last() const; // the last value added to the sequence
--- a/src/share/vm/utilities/vmError.cpp	Tue May 15 10:52:24 2012 -0700
+++ b/src/share/vm/utilities/vmError.cpp	Tue May 15 11:27:24 2012 -0700
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "compiler/compileBroker.hpp"
 #include "gc_interface/collectedHeap.hpp"
+#include "prims/whitebox.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/init.hpp"
@@ -684,6 +685,12 @@
        // extended (i.e., more detailed) version.
        Universe::print_on(st, true /* extended */);
        st->cr();
+
+       Universe::heap()->barrier_set()->print_on(st);
+       st->cr();
+
+       st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page());
+       st->cr();
      }
 
   STEP(195, "(printing code cache information)" )
@@ -717,6 +724,13 @@
        st->cr();
      }
 
+  STEP(215, "(printing warning if internal testing API used)" )
+
+     if (WhiteBox::used()) {
+       st->print_cr("Unsupported internal testing APIs have been used.");
+       st->cr();
+     }
+
   STEP(220, "(printing environment variables)" )
 
      if (_verbose) {
--- a/test/Makefile	Tue May 15 10:52:24 2012 -0700
+++ b/test/Makefile	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
 # Makefile to run various jdk tests
 #
 
+GETMIXEDPATH=echo
+
 # Get OS/ARCH specifics
 OSNAME = $(shell uname -s)
 ifeq ($(OSNAME), SunOS)
@@ -60,7 +62,14 @@
     ARCH = i586
   endif
 endif
-ifeq ($(OSNAME), Windows_NT)
+ifeq ($(PLATFORM),)
+  # detect wether we're running in MKS or cygwin
+  ifeq ($(OSNAME), Windows_NT) # MKS
+    GETMIXEDPATH=dosname -s
+  endif
+  ifeq ($(findstring CYGWIN,$(OSNAME)), CYGWIN)
+    GETMIXEDPATH=cygpath -m -s
+  endif
   PLATFORM = windows
   SLASH_JAVA = J:
   ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64)
@@ -228,6 +237,24 @@
 
 ################################################################
 
+# wbapitest (make sure the whitebox testing api classes work
+
+wbapitest: prep $(JT_HOME) $(PRODUCT_HOME) $(JTREG)
+	$(JTREG) -a -v:fail,error               \
+          $(JTREG_KEY_OPTION)                   \
+          $(EXTRA_JTREG_OPTIONS)                \
+          -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport    \
+          -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork      \
+          -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)")                  \
+          $(JAVA_OPTIONS:%=-vmoption:%)         \
+          $(shell $(GETMIXEDPATH) "$(TEST_ROOT)")/sanity                   \
+	  || $(BUNDLE_UP_FAILED)
+	$(BUNDLE_UP)
+
+PHONY_LIST += wbapitest
+
+################################################################
+
 # packtest
 
 # Expect JPRT to set JPRT_PACKTEST_HOME.
--- a/test/compiler/6894807/Test6894807.sh	Tue May 15 10:52:24 2012 -0700
+++ b/test/compiler/6894807/Test6894807.sh	Tue May 15 11:27:24 2012 -0700
@@ -18,8 +18,6 @@
   exit 1
 fi
 
-BIT_FLAG=""
-
 # set platform-dependent variables
 OS=`uname -s`
 case "$OS" in
@@ -27,12 +25,6 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    ## for solaris, linux it's HOME
-    FILE_LOCATION=$HOME
-    if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ]
-    then
-        BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT | grep -v '^#'`
-    fi
     ;;
   Windows_* )
     NULL=NUL
@@ -50,9 +42,9 @@
 
 THIS_DIR=`pwd`
 
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -version
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version
 
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -server IsInstanceTest > test.out 2>&1
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} IsInstanceTest > test.out 2>&1
 
 cat test.out
 
--- a/test/compiler/7070134/Stemmer.java	Tue May 15 10:52:24 2012 -0700
+++ b/test/compiler/7070134/Stemmer.java	Tue May 15 11:27:24 2012 -0700
@@ -13,7 +13,18 @@
        Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14,
        no. 3, pp 130-137,
 
-   See also http://www.tartarus.org/~martin/PorterStemmer
+   http://www.tartarus.org/~martin/PorterStemmer
+
+   The software is completely free for any purpose, unless notes at the head
+   of the program text indicates otherwise (which is rare). In any case,
+   the notes about licensing are never more restrictive than the BSD License.
+
+   In every case where the software is not written by me (Martin Porter),
+   this licensing arrangement has been endorsed by the contributor, and it is
+   therefore unnecessary to ask the contributor again to confirm it.
+
+   I have not asked any contributors (or their employers, if they have them)
+   for proofs that they have the right to distribute their software in this way.
 
    History:
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/7160610/Test7160610.java	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 7160610
+ * @summary Unknown Native Code compilation issue.
+ *
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-OptimizeFill Test7160610
+ */
+
+public class Test7160610 {
+  private static final byte[] BYTE_ARRAY = new byte[7];
+  private static int[] anIntArray1190 = new int[32768];
+  private static int[] anIntArray1191 = new int[32768];
+
+  public static void main(String arg[]) {
+    int i = 256;
+    for(int j = BYTE_ARRAY[2]; j < anIntArray1190.length; j++) {
+      anIntArray1190[j] = BYTE_ARRAY[2];
+    }
+
+    for(int k = BYTE_ARRAY[2]; (k ^ BYTE_ARRAY[1]) > -5001; k++) {
+      int i1 = (int)(Math.random() * 128D * (double)i);
+      anIntArray1190[i1] = (int)(Math.random() * 256D);
+    }
+
+    for(int l = BYTE_ARRAY[2]; (l ^ BYTE_ARRAY[1]) > -21; l++) {
+      for(int j1 = BYTE_ARRAY[0]; j1 < i + -BYTE_ARRAY[0]; j1++) {
+        for(int k1 = BYTE_ARRAY[0]; (k1 ^ BYTE_ARRAY[1]) > -128; k1++) {
+          int l1 = k1 - -(j1 << 0x26cb6487);
+          anIntArray1191[l1] = (anIntArray1190[l1 + -BYTE_ARRAY[0]] - -anIntArray1190[l1 - -BYTE_ARRAY[0]] - -anIntArray1190[-128 + l1] - -anIntArray1190[128 + l1]) / BYTE_ARRAY[6];
+        }
+      }
+      int ai[] = anIntArray1190;
+      anIntArray1190 = anIntArray1191;
+      anIntArray1191 = ai;
+    }
+  }
+
+  static {
+    BYTE_ARRAY[6] = 4;
+    BYTE_ARRAY[5] = 5;
+    BYTE_ARRAY[4] = 3;
+    BYTE_ARRAY[3] = 2;
+    BYTE_ARRAY[2] = 0;
+    BYTE_ARRAY[1] = -1;
+    BYTE_ARRAY[0] = 1;
+  }
+}
--- a/test/gc/6941923/test6941923.sh	Tue May 15 10:52:24 2012 -0700
+++ b/test/gc/6941923/test6941923.sh	Tue May 15 11:27:24 2012 -0700
@@ -30,7 +30,7 @@
   exit 0
 fi
 
-$JAVA_HOME/bin/java -version > $NULL 2>&1
+$JAVA_HOME/bin/java ${TESTVMOPTS} -version > $NULL 2>&1
 
 if [ $? != 0 ]; then
   echo "Wrong JAVA_HOME? JAVA_HOME: $JAVA_HOME"
@@ -119,7 +119,7 @@
 
 options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation  -XX:NumberOfGCLogFiles=1 -XX:GCLogFileSize=$gclogsize"
 echo "Test gc log rotation in same file, wait for $tts minutes ...."
-$JAVA_HOME/bin/java $options $testname $tts
+$JAVA_HOME/bin/java ${TESTVMOPTS} $options $testname $tts
 if [ $? != 0 ]; then
   echo "$msgfail"
   exit -1
@@ -148,7 +148,7 @@
 numoffiles=3
 options="-Xloggc:$logfile -XX:+UseConcMarkSweepGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseGCLogFileRotation  -XX:NumberOfGCLogFiles=$numoffiles -XX:GCLogFileSize=$gclogsize"
 echo "Test gc log rotation in $numoffiles files, wait for $tts minutes ...."
-$JAVA_HOME/bin/java $options $testname $tts
+$JAVA_HOME/bin/java ${TESTVMOPTS} $options $testname $tts
 if [ $? != 0 ]; then
   echo "$msgfail"
   exit -1
--- a/test/runtime/6626217/Test6626217.sh	Tue May 15 10:52:24 2012 -0700
+++ b/test/runtime/6626217/Test6626217.sh	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 # 
-#  Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+#  Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
 #  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 # 
 #  This code is free software; you can redistribute it and/or modify it
@@ -46,8 +46,6 @@
   exit 1
 fi
 
-BIT_FLAG=""
-
 # set platform-dependent variables
 OS=`uname -s`
 case "$OS" in
@@ -58,12 +56,6 @@
     RM=/bin/rm
     CP=/bin/cp
     MV=/bin/mv
-    ## for solaris, linux it's HOME
-    FILE_LOCATION=$HOME
-    if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ]
-    then
-        BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT`
-    fi
     ;;
   Windows_* )
     NULL=NUL
@@ -87,7 +79,7 @@
 JAVA=${TESTJAVA}${FS}bin${FS}java
 JAVAC=${TESTJAVA}${FS}bin${FS}javac
 
-${JAVA} ${BIT_FLAG} -version
+${JAVA} ${TESTVMOPTS} -version
 
 # Current directory is scratch directory, copy all the test source there
 # (for the subsequent moves to work).
@@ -113,7 +105,7 @@
 ${MV} many_loader.impl1 many_loader.class
 ${RM} many_loader.java
 
-${JAVA} ${BIT_FLAG} -Xverify -Xint -cp . bug_21227 >test.out 2>&1
+${JAVA} ${TESTVMOPTS} -Xverify -Xint -cp . bug_21227 >test.out 2>&1
 grep "loader constraint" test.out
 exit $?
 
--- a/test/runtime/6878713/Test6878713.sh	Tue May 15 10:52:24 2012 -0700
+++ b/test/runtime/6878713/Test6878713.sh	Tue May 15 11:27:24 2012 -0700
@@ -25,8 +25,6 @@
   exit 1
 fi
 
-BIT_FLAG=""
-
 # set platform-dependent variables
 OS=`uname -s`
 case "$OS" in
@@ -34,12 +32,6 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    ## for solaris, linux it's HOME
-    FILE_LOCATION=$HOME
-    if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ]
-    then
-        BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT | grep -v '^#'`
-    fi
     ;;
   Windows_* )
     NULL=NUL
@@ -57,11 +49,11 @@
 
 THIS_DIR=`pwd`
 
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -version
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version
 
 ${TESTJAVA}${FS}bin${FS}jar xvf ${TESTSRC}${FS}testcase.jar
 
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} OOMCrashClass1960_2 > test.out 2>&1
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} OOMCrashClass1960_2 > test.out 2>&1
 
 if [ -s core -o -s "hs_*.log" ]
 then
--- a/test/runtime/6929067/Test6929067.sh	Tue May 15 10:52:24 2012 -0700
+++ b/test/runtime/6929067/Test6929067.sh	Tue May 15 11:27:24 2012 -0700
@@ -19,8 +19,6 @@
   echo "If this is incorrect, try setting the variable manually."
 fi
 
-BIT_FLAG=""
-
 # set platform-dependent variables
 OS=`uname -s`
 case "$OS" in
@@ -42,7 +40,19 @@
     ;;
 esac
 
-LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/i386/client:/usr/openwin/lib:/usr/dt/lib:/usr/lib:$LD_LIBRARY_PATH
+# Choose arch: i386 or amd64 (test is Linux-specific)
+# Cannot simply look at TESTVMOPTS as -d64 is not
+# passed if there is only a 64-bit JVM available.
+
+${TESTJAVA}/bin/java ${TESTVMOPTS} -version 2>1 | grep "64-Bit" >/dev/null
+if [ "$?" = "0" ]
+then
+  ARCH=amd64
+else
+  ARCH=i386
+fi
+
+LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/${ARCH}/client:/usr/openwin/lib:/usr/dt/lib:/usr/lib:$LD_LIBRARY_PATH
 export LD_LIBRARY_PATH
 
 THIS_DIR=`pwd`
@@ -51,10 +61,10 @@
 cp ${TESTSRC}${FS}T.java ${THIS_DIR}
 
 
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -fullversion
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion
 
 ${TESTJAVA}${FS}bin${FS}javac T.java
 
-gcc -o invoke -I${TESTJAVA}/include -I${TESTJAVA}/include/linux invoke.c ${TESTJAVA}/jre/lib/i386/client/libjvm.so
+gcc -o invoke -I${TESTJAVA}/include -I${TESTJAVA}/include/linux invoke.c ${TESTJAVA}/jre/lib/${ARCH}/client/libjvm.so
 ./invoke
 exit $?
--- a/test/runtime/7020373/Test7020373.sh	Tue May 15 10:52:24 2012 -0700
+++ b/test/runtime/7020373/Test7020373.sh	Tue May 15 11:27:24 2012 -0700
@@ -27,8 +27,6 @@
   exit 1
 fi
 
-BIT_FLAG=""
-
 # set platform-dependent variables
 OS=`uname -s`
 case "$OS" in
@@ -36,12 +34,6 @@
     NULL=/dev/null
     PS=":"
     FS="/"
-    ## for solaris, linux it's HOME
-    FILE_LOCATION=$HOME
-    if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ]
-    then
-        BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT | grep -v '^#'`
-    fi
     ;;
   Windows_* )
     NULL=NUL
@@ -59,11 +51,11 @@
 
 THIS_DIR=`pwd`
 
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -version
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version
 
 ${TESTJAVA}${FS}bin${FS}jar xvf ${TESTSRC}${FS}testcase.jar
 
-${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} OOMCrashClass4000_1 > test.out 2>&1
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} OOMCrashClass4000_1 > test.out 2>&1
 
 cat test.out
 
--- a/test/runtime/7051189/Xchecksig.sh	Tue May 15 10:52:24 2012 -0700
+++ b/test/runtime/7051189/Xchecksig.sh	Tue May 15 11:27:24 2012 -0700
@@ -1,5 +1,5 @@
 # 
-#  Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+#  Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 #  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 # 
 #  This code is free software; you can redistribute it and/or modify it
@@ -41,18 +41,10 @@
 fi
 
 
-BIT_FLAG=""
-
 OS=`uname -s`
 case "$OS" in
   SunOS | Linux )
     FS="/"
-    ## for solaris, linux it's HOME
-    FILE_LOCATION=$HOME
-    if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ]
-    then
-        BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT`
-    fi
     ;;
   Windows_* )
     printf "Not testing libjsig.so on Windows. PASSED.\n "
@@ -69,20 +61,16 @@
 
 # LD_PRELOAD arch needs to match the binary we run, so run the java
 # 64-bit binary directly if we are testing 64-bit (bin/ARCH/java).
-
-# However JPRT runs: .../solaris_x64_5.10-debug/bin/java
-# ..which is 32-bit, when it has built the 64-bit version to test.
-#
-# How does this script know we are meant to run the 64-bit version?
-# Can check for the path of the binary containing "x64" on Solaris.
+# Check if TESTVMOPS contains -d64, but cannot use 
+# java ${TESTVMOPS} to run "java -d64"  with LD_PRELOAD.
 
 if [ ${OS} -eq "SunOS" ]
 then
-  printf  "SunOS test JAVA=${JAVA}"
-  printf ${JAVA} | grep x64 > /dev/null
+  printf  "SunOS test TESTVMOPTS = ${TESTVMOPTS}"
+  printf ${TESTVMOPTS} | grep d64 > /dev/null
   if [ $? -eq 0 ]
   then
-    printf "SunOS x64 test, forcing -d64\n"
+    printf "SunOS 64-bit test\n"
     BIT_FLAG=-d64
   fi
 fi
@@ -127,20 +115,19 @@
   printf "Skipping test: libjsig missing for given architecture: ${LIBJSIG}\n"
   exit 0
 fi
-# Use java -version to test, java version info appeas on stderr,
+# Use java -version to test, java version info appears on stderr,
 # the libjsig message we are removing appears on stdout.
 
 # grep returns zero meaning found, non-zero means not found:
 
-LD_PRELOAD=${LIBJSIG} ${JAVA} ${BIT_FLAG} -Xcheck:jni -version 2>&1  | grep "libjsig is activated"
-
+LD_PRELOAD=${LIBJSIG} ${JAVA} ${TESTVMOPTS} -Xcheck:jni -version 2>&1  | grep "libjsig is activated"
 if [ $? -eq 0 ]; then
   printf "Failed: -Xcheck:jni prints message when libjsig.so is loaded.\n"
   exit 1
 fi
 
 
-LD_PRELOAD=${LIBJSIG} ${JAVA} ${BIT_FLAG} -Xcheck:jni -verbose:jni -version 2>&1 | grep "libjsig is activated"
+LD_PRELOAD=${LIBJSIG} ${JAVA} ${TESTVMOPTS} -Xcheck:jni -verbose:jni -version 2>&1 | grep "libjsig is activated"
 if [ $? != 0 ]; then
   printf "Failed: -Xcheck:jni does not print message when libjsig.so is loaded and -verbose:jni is set.\n"
   exit 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7158988/FieldMonitor.java	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2012 SAP AG.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test FieldMonitor.java
+ * @bug 7158988
+ * @summary verify jvm does not crash while debugging
+ * @run shell TestFieldMonitor.sh
+ * @author axel.siebenborn@sap.com
+ */
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.Field;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.Connector;
+import com.sun.jdi.connect.IllegalConnectorArgumentsException;
+import com.sun.jdi.connect.LaunchingConnector;
+import com.sun.jdi.connect.VMStartException;
+import com.sun.jdi.event.ClassPrepareEvent;
+import com.sun.jdi.event.Event;
+import com.sun.jdi.event.EventQueue;
+import com.sun.jdi.event.EventSet;
+import com.sun.jdi.event.ModificationWatchpointEvent;
+import com.sun.jdi.event.VMDeathEvent;
+import com.sun.jdi.event.VMDisconnectEvent;
+import com.sun.jdi.request.ClassPrepareRequest;
+import com.sun.jdi.request.EventRequest;
+import com.sun.jdi.request.EventRequestManager;
+import com.sun.jdi.request.ModificationWatchpointRequest;
+
+public class FieldMonitor {
+
+  public static final String CLASS_NAME = "TestPostFieldModification";
+  public static final String FIELD_NAME = "value";
+  public static final String ARGUMENTS = "-Xshare:off -XX:+PrintGC";
+
+  public static void main(String[] args)
+      throws IOException, InterruptedException {
+
+    StringBuffer sb = new StringBuffer();
+
+    for (int i=0; i < args.length; i++) {
+        sb.append(' ');
+        sb.append(args[i]);
+    }
+    //VirtualMachine vm = launchTarget(sb.toString());
+    VirtualMachine vm = launchTarget(CLASS_NAME);
+
+    System.out.println("Vm launched");
+    // set watch field on already loaded classes
+    List<ReferenceType> referenceTypes = vm
+        .classesByName(CLASS_NAME);
+    for (ReferenceType refType : referenceTypes) {
+      addFieldWatch(vm, refType);
+    }
+    // watch for loaded classes
+    addClassWatch(vm);
+
+    // process events
+    EventQueue eventQueue = vm.eventQueue();
+    // resume the vm
+
+    Process process = vm.process();
+
+
+    // Copy target's output and error to our output and error.
+    Thread outThread = new StreamRedirectThread("out reader", process.getInputStream());
+    Thread errThread = new StreamRedirectThread("error reader", process.getErrorStream());
+
+    errThread.start();
+    outThread.start();
+
+
+    vm.resume();
+    boolean connected = true;
+    while (connected) {
+      EventSet eventSet = eventQueue.remove();
+      for (Event event : eventSet) {
+        if (event instanceof VMDeathEvent
+            || event instanceof VMDisconnectEvent) {
+          // exit
+          connected = false;
+        } else if (event instanceof ClassPrepareEvent) {
+          // watch field on loaded class
+          System.out.println("ClassPrepareEvent");
+          ClassPrepareEvent classPrepEvent = (ClassPrepareEvent) event;
+          ReferenceType refType = classPrepEvent
+              .referenceType();
+          addFieldWatch(vm, refType);
+        } else if (event instanceof ModificationWatchpointEvent) {
+          System.out.println("sleep for 500 ms");
+          Thread.sleep(500);
+          System.out.println("resume...");
+
+          ModificationWatchpointEvent modEvent = (ModificationWatchpointEvent) event;
+          System.out.println("old="
+              + modEvent.valueCurrent());
+          System.out.println("new=" + modEvent.valueToBe());
+          System.out.println();
+        }
+      }
+      eventSet.resume();
+    }
+    // Shutdown begins when event thread terminates
+    try {
+        errThread.join(); // Make sure output is forwarded
+        outThread.join();
+    } catch (InterruptedException exc) {
+        // we don't interrupt
+    }
+  }
+
+  /**
+   * Find a com.sun.jdi.CommandLineLaunch connector
+   */
+  static LaunchingConnector findLaunchingConnector() {
+    List <Connector> connectors = Bootstrap.virtualMachineManager().allConnectors();
+    Iterator <Connector> iter = connectors.iterator();
+    while (iter.hasNext()) {
+      Connector connector = iter.next();
+      if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) {
+        return (LaunchingConnector)connector;
+      }
+    }
+    throw new Error("No launching connector");
+  }
+  /**
+   * Return the launching connector's arguments.
+   */
+ static Map <String,Connector.Argument> connectorArguments(LaunchingConnector connector, String mainArgs) {
+      Map<String,Connector.Argument> arguments = connector.defaultArguments();
+      for (String key : arguments.keySet()) {
+        System.out.println(key);
+      }
+
+      Connector.Argument mainArg = (Connector.Argument)arguments.get("main");
+      if (mainArg == null) {
+          throw new Error("Bad launching connector");
+      }
+      mainArg.setValue(mainArgs);
+
+      Connector.Argument optionsArg = (Connector.Argument)arguments.get("options");
+      if (optionsArg == null) {
+        throw new Error("Bad launching connector");
+      }
+      optionsArg.setValue(ARGUMENTS);
+      return arguments;
+  }
+
+ static VirtualMachine launchTarget(String mainArgs) {
+    LaunchingConnector connector = findLaunchingConnector();
+    Map  arguments = connectorArguments(connector, mainArgs);
+    try {
+        return (VirtualMachine) connector.launch(arguments);
+    } catch (IOException exc) {
+        throw new Error("Unable to launch target VM: " + exc);
+    } catch (IllegalConnectorArgumentsException exc) {
+        throw new Error("Internal error: " + exc);
+    } catch (VMStartException exc) {
+        throw new Error("Target VM failed to initialize: " +
+                        exc.getMessage());
+    }
+}
+
+
+  private static void addClassWatch(VirtualMachine vm) {
+    EventRequestManager erm = vm.eventRequestManager();
+    ClassPrepareRequest classPrepareRequest = erm
+        .createClassPrepareRequest();
+    classPrepareRequest.addClassFilter(CLASS_NAME);
+    classPrepareRequest.setEnabled(true);
+  }
+
+
+  private static void addFieldWatch(VirtualMachine vm,
+      ReferenceType refType) {
+    EventRequestManager erm = vm.eventRequestManager();
+    Field field = refType.fieldByName(FIELD_NAME);
+    ModificationWatchpointRequest modificationWatchpointRequest = erm
+        .createModificationWatchpointRequest(field);
+    modificationWatchpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
+    modificationWatchpointRequest.setEnabled(true);
+  }
+}
+
+class StreamRedirectThread extends Thread {
+
+  private final BufferedReader in;
+
+  private static final int BUFFER_SIZE = 2048;
+
+  /**
+   * Set up for copy.
+   * @param name  Name of the thread
+   * @param in    Stream to copy from
+   * @param out   Stream to copy to
+   */
+  StreamRedirectThread(String name, InputStream in) {
+    super(name);
+    this.in = new BufferedReader(new InputStreamReader(in));
+  }
+
+  /**
+   * Copy.
+   */
+  public void run() {
+    try {
+      String line;
+        while ((line = in.readLine ()) != null) {
+          System.out.println ("testvm: " + line);
+      }
+     System.out.flush();
+    } catch(IOException exc) {
+      System.err.println("Child I/O Transfer - " + exc);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7158988/TestFieldMonitor.sh	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+if [ "${TESTSRC}" = "" ]
+then TESTSRC=.
+fi
+
+if [ "${TESTJAVA}" = "" ]
+then
+  PARENT=`dirname \`which java\``
+  TESTJAVA=`dirname ${PARENT}`
+  echo "TESTJAVA not set, selecting " ${TESTJAVA}
+  echo "If this is incorrect, try setting the variable manually."
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  SunOS | Linux )
+    NULL=/dev/null
+    PS=":"
+    FS="/"
+    ;;
+  Windows_95 | Windows_98 | Windows_ME )
+    NULL=NUL
+    PS=";"
+    FS="\\"
+    echo "Test skipped, only for WinNT"
+    exit 0
+    ;;
+  Windows_NT )
+    NULL=NUL
+    PS=";"
+    FS="\\"
+    ;;
+  * )
+    echo "Unrecognized system!"
+    exit 1;
+    ;;
+esac
+
+#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH
+
+cp ${TESTSRC}${FS}*.java .
+
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion
+
+${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java
+
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out 2>&1 &
+
+P_PID=$!
+
+sleep 60
+STATUS=0
+
+case "$OS" in
+    SunOS | Linux )
+        ps -ef | grep $P_PID | grep -v grep > ${NULL}
+        if [ $? = 0 ]; then
+            kill -9 $P_PID
+            STATUS=1
+        fi
+        ;;
+      * )
+        ps | grep -i "FieldMonitor" | grep -v grep > ${NULL}
+        if [ $? = 0 ]; then
+            C_PID=`ps | grep -i "FieldMonitor" | awk '{print $1}'`
+            kill -s 9 $C_PID
+            STATUS=1
+        fi
+        ;;
+esac
+
+grep "A fatal error has been detected" test.out > ${NULL}
+if [ $? = 0 ]; then
+    cat test.out
+    STATUS=1
+fi
+
+exit $STATUS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7158988/TestPostFieldModification.java	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 SAP AG.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class TestPostFieldModification {
+
+  public String value;  // watch modification of value
+
+  public static void main(String[] args){
+
+    System.out.println("Start threads");
+    // this thread modifies the field 'value'
+    new Thread() {
+      TestPostFieldModification test = new TestPostFieldModification();
+      public void run() {
+        test.value="test";
+        for(int i = 0; i < 10; i++) {
+          test.value += new String("_test");
+        }
+      }
+    }.start();
+
+    // this thread is used to trigger a gc
+    Thread d = new Thread() {
+      public void run() {
+        while(true) {
+          try {
+            Thread.sleep(100);
+          } catch (InterruptedException e) {
+
+          }
+          System.gc();
+        }
+      }
+    };
+    d.setDaemon(true);
+    d.start();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7162488/Test7162488.sh	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,77 @@
+#
+#  Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+#  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+#  This code is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License version 2 only, as
+#  published by the Free Software Foundation.
+#
+#  This code is distributed in the hope that it will be useful, but WITHOUT
+#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+#  version 2 for more details (a copy is included in the LICENSE file that
+#  accompanied this code).
+#
+#  You should have received a copy of the GNU General Public License version
+#  2 along with this work; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#  Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+#  or visit www.oracle.com if you need additional information or have any
+#  questions.
+#
+
+
+# @test Test7162488.sh
+# @bug 7162488
+# @summary VM not printing unknown -XX options
+# @run shell Test7162488.sh
+#
+
+if [ "${TESTSRC}" = "" ]
+  then TESTSRC=.
+fi
+
+if [ "${TESTJAVA}" = "" ]
+then
+  PARENT=`dirname \`which java\``
+  TESTJAVA=`dirname ${PARENT}`
+  printf "TESTJAVA not set, selecting " ${TESTJAVA}
+  printf "  If this is incorrect, try setting the variable manually.\n"
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  Windows_* )
+    FS="\\"
+    ;;
+  * )
+    FS="/"
+    ;;
+esac
+
+JAVA=${TESTJAVA}${FS}bin${FS}java
+
+#
+# Just run with an option we are confident will not be recognized,
+# and check for the message:
+#
+OPTION=this_is_not_an_option
+
+${JAVA} ${TESTVMOPTS} -showversion -XX:${OPTION} 2>&1 | grep "Unrecognized VM option" 
+if [ "$?" != "0" ]
+then
+  printf "FAILED: option not flagged as unrecognized.\n"
+  exit 1
+fi
+
+${JAVA} ${TESTVMOPTS} -showversion -XX:${OPTION} 2>&1 | grep ${OPTION}
+if [ "$?" != "0" ]
+then
+  printf "FAILED: bad option not named as being bad.\n"
+  exit 1
+fi
+
+printf "Passed.\n"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sanity/WBApi.java	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,13 @@
+/*
+ * @test WBApi
+ * @summary verify that whitebox functions can be linked and executed
+ * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI WBApi.java
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI WBApi
+ */
+
+import sun.hotspot.WhiteBox;
+public class WBApi {
+    public static void main(String... args) {
+        System.out.printf("args at: %x\n",WhiteBox.getWhiteBox().getObjectAddress(args));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/serviceability/ParserTest.java	Tue May 15 11:27:24 2012 -0700
@@ -0,0 +1,152 @@
+/*
+ * @test ParserTest
+ * @summary verify that whitebox functions can be linked and executed
+ * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI ParserTest.java
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest
+ */
+
+import java.math.BigInteger;
+
+import sun.hotspot.parser.DiagnosticCommand;
+import sun.hotspot.parser.DiagnosticCommand.DiagnosticArgumentType;
+import sun.hotspot.WhiteBox;
+
+public class ParserTest {
+    WhiteBox wb;
+
+    public ParserTest() throws Exception {
+        wb = WhiteBox.getWhiteBox();
+
+        testNanoTime();
+        testJLong();
+        testBool();
+        testMemorySize();
+    }
+
+    public static void main(String... args) throws Exception  {
+         new ParserTest();
+    }
+
+    public void testNanoTime() throws Exception {
+        String name = "name";
+        DiagnosticCommand arg = new DiagnosticCommand(name,
+                "desc", DiagnosticArgumentType.NANOTIME,
+                false, "0");
+        DiagnosticCommand[] args = {arg};
+
+        BigInteger bi = new BigInteger("7");
+        //These should work
+        parse(name, bi.toString(), name + "=7ns", args);
+
+        bi = bi.multiply(BigInteger.valueOf(1000));
+        parse(name, bi.toString(), name + "=7us", args);
+
+        bi = bi.multiply(BigInteger.valueOf(1000));
+        parse(name, bi.toString(), name + "=7ms", args);
+
+        bi = bi.multiply(BigInteger.valueOf(1000));
+        parse(name, bi.toString(), name + "=7s", args);
+
+        bi = bi.multiply(BigInteger.valueOf(60));
+        parse(name, bi.toString() , name + "=7m", args);
+
+        bi = bi.multiply(BigInteger.valueOf(60));
+        parse(name, bi.toString() , name + "=7h", args);
+
+        bi = bi.multiply(BigInteger.valueOf(24));
+        parse(name, bi.toString() , name + "=7d", args);
+
+        parse(name, "0", name + "=0", args);
+
+        shouldFail(name + "=7xs", args);
+        shouldFail(name + "=7mms", args);
+        shouldFail(name + "=7f", args);
+        //Currently, only value 0 is allowed without unit
+        shouldFail(name + "=7", args);
+    }
+
+    public void testJLong() throws Exception {
+        String name = "name";
+        DiagnosticCommand arg = new DiagnosticCommand(name,
+                "desc", DiagnosticArgumentType.JLONG,
+                false, "0");
+        DiagnosticCommand[] args = {arg};
+
+        wb.parseCommandLine(name + "=10", args);
+        parse(name, "10", name + "=10", args);
+        parse(name, "-5", name + "=-5", args);
+
+        //shouldFail(name + "=12m", args); <-- should fail, doesn't
+    }
+
+    public void testBool() throws Exception {
+        String name = "name";
+        DiagnosticCommand arg = new DiagnosticCommand(name,
+                "desc", DiagnosticArgumentType.BOOLEAN,
+                false, "false");
+        DiagnosticCommand[] args = {arg};
+
+        parse(name, "true", name + "=true", args);
+        parse(name, "false", name + "=false", args);
+        parse(name, "true", name, args);
+
+        //Empty commandline to parse, tests default value
+        //of the parameter "name"
+        parse(name, "false", "", args);
+    }
+
+    public void testMemorySize() throws Exception {
+        String name = "name";
+        String defaultValue = "1024";
+        DiagnosticCommand arg = new DiagnosticCommand(name,
+                "desc", DiagnosticArgumentType.MEMORYSIZE,
+                false, defaultValue);
+        DiagnosticCommand[] args = {arg};
+
+        BigInteger bi = new BigInteger("7");
+        parse(name, bi.toString(), name + "=7b", args);
+
+        bi = bi.multiply(BigInteger.valueOf(1024));
+        parse(name, bi.toString(), name + "=7k", args);
+
+        bi = bi.multiply(BigInteger.valueOf(1024));
+        parse(name, bi.toString(), name + "=7m", args);
+
+        bi = bi.multiply(BigInteger.valueOf(1024));
+        parse(name, bi.toString(), name + "=7g", args);
+        parse(name, defaultValue, "", args);
+
+        //shouldFail(name + "=7gg", args); <---- should fail, doesn't
+        //shouldFail(name + "=7t", args);  <----- should fail, doesn't
+    }
+
+    public void parse(String searchName, String expectedValue,
+            String cmdLine, DiagnosticCommand[] argumentTypes) throws Exception {
+        //parseCommandLine will return an object array that looks like
+        //{<name of parsed object>, <of parsed object> ... }
+        Object[] res = wb.parseCommandLine(cmdLine, argumentTypes);
+        for (int i = 0; i < res.length-1; i+=2) {
+            String parsedName = (String) res[i];
+            if (searchName.equals(parsedName)) {
+                String parsedValue = (String) res[i+1];
+                if (expectedValue.equals(parsedValue)) {
+                    return;
+                } else {
+                    throw new Exception("Parsing of cmdline '" + cmdLine + "' failed!\n"
+                            + searchName + " parsed as " + parsedValue
+                            + "! Expected: " + expectedValue);
+                }
+            }
+        }
+        throw new Exception(searchName + " not found as a parsed Argument!");
+    }
+
+    private void shouldFail(String argument, DiagnosticCommand[] argumentTypes) throws Exception {
+        try {
+            wb.parseCommandLine(argument, argumentTypes);
+            throw new Exception("Parser accepted argument: " + argument);
+        } catch (IllegalArgumentException e) {
+            //expected
+        }
+    }
+}