changeset 194:4f91c08b3e44 jdk7-b29

Merge
author trims
date Tue, 17 Jun 2008 15:27:05 -0700
parents abe7181cbe8a (current diff) 44a553b2809d (diff)
children 93435819dba2 66cdb30329a6
files
diffstat 134 files changed, 3336 insertions(+), 1152 deletions(-) [+]
line wrap: on
line diff
--- a/agent/make/Makefile	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/make/Makefile	Tue Jun 17 15:27:05 2008 -0700
@@ -246,16 +246,16 @@
 all: filelist
 	@mkdir -p $(OUTPUT_DIR)
 	@echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
-	@javac -source 1.4 -classpath $(CLASSPATH) -deprecation -sourcepath $(SRC_DIR) -g -d $(OUTPUT_DIR) @filelist
-	@rmic -classpath $(OUTPUT_DIR) -d $(OUTPUT_DIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
+	@${JDK_HOME}/bin/javac -source 1.4 -classpath $(CLASSPATH) -deprecation -sourcepath $(SRC_DIR) -g -d $(OUTPUT_DIR) @filelist
+	@${JDK_HOME}/bin/rmic -classpath $(OUTPUT_DIR) -d $(OUTPUT_DIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
 	rm -f $(OUTPUT_DIR)/sun/jvm/hotspot/utilities/soql/sa.js
 	cp $(SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(OUTPUT_DIR)/sun/jvm/hotspot/utilities/soql
 
 allprof: filelist
 	@mkdir -p $(OUTPUT_DIR)
 	@echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
-	@javac -source 1.4 -J-Xprof -classpath $(CLASSPATH) -deprecation -sourcepath $(SRC_DIR) -g -d $(OUTPUT_DIR) @filelist
-	@rmic -classpath $(OUTPUT_DIR) -d $(OUTPUT_DIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
+	@${JDK_HOME}/bin/javac -source 1.4 -J-Xprof -classpath $(CLASSPATH) -deprecation -sourcepath $(SRC_DIR) -g -d $(OUTPUT_DIR) @filelist
+	@${JDK_HOME}/bin/rmic -classpath $(OUTPUT_DIR) -d $(OUTPUT_DIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
 	rm -f $(OUTPUT_DIR)/sun/jvm/hotspot/utilities/soql/sa.js
 	cp $(SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(OUTPUT_DIR)/sun/jvm/hotspot/utilities/soql
 
--- a/agent/src/share/classes/sun/jvm/hotspot/HSDB.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/HSDB.java	Tue Jun 17 15:27:05 2008 -0700
@@ -398,7 +398,7 @@
     frame.getContentPane().add(desktop);
     GraphicsUtilities.reshapeToAspectRatio(frame, 4.0f/3.0f, 0.75f, Toolkit.getDefaultToolkit().getScreenSize());
     GraphicsUtilities.centerInContainer(frame, Toolkit.getDefaultToolkit().getScreenSize());
-    frame.show();
+    frame.setVisible(true);
 
     Runtime.getRuntime().addShutdownHook(new java.lang.Thread() {
         public void run() {
--- a/agent/src/share/classes/sun/jvm/hotspot/SALauncherLoader.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/SALauncherLoader.java	Tue Jun 17 15:27:05 2008 -0700
@@ -148,7 +148,7 @@
         }
 
         try {
-            return file.toURL();
+            return file.toURI().toURL();
         } catch (MalformedURLException mue) {
             throw new InternalError(mue.getMessage());
         }
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/Main.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/bugspot/Main.java	Tue Jun 17 15:27:05 2008 -0700
@@ -47,6 +47,6 @@
                                            4.0f/3.0f, 0.85f, Toolkit.getDefaultToolkit().getScreenSize());
     GraphicsUtilities.centerInContainer(frame,
                                         Toolkit.getDefaultToolkit().getScreenSize());
-    frame.show();
+    frame.setVisible(true);
   }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/jdi/SAJDIClassLoader.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/SAJDIClassLoader.java	Tue Jun 17 15:27:05 2008 -0700
@@ -78,7 +78,7 @@
         this(parent);
         this.classPathSet = true;
         try {
-            addURL(new File(classPath).toURL());
+            addURL(new File(classPath).toURI().toURL());
         } catch(MalformedURLException mue) {
             throw new RuntimeException(mue);
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java	Tue Jun 17 15:27:05 2008 -0700
@@ -0,0 +1,59 @@
+/*
+ * @(#)BinaryTreeDictionary.java
+ * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package sun.jvm.hotspot.memory;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.runtime.*;
+
+public class BinaryTreeDictionary extends VMObject {
+   static {
+      VM.registerVMInitializedObserver(new Observer() {
+         public void update(Observable o, Object data) {
+            initialize(VM.getVM().getTypeDataBase());
+         }
+      });
+   }
+
+   private static synchronized void initialize(TypeDataBase db) {
+      Type type = db.lookupType("BinaryTreeDictionary");
+      totalSizeField = type.getCIntegerField("_totalSize");
+   }
+
+   // Fields
+   private static CIntegerField totalSizeField;
+
+   // Accessors
+   public long size() {
+      return totalSizeField.getValue(addr);
+   }
+
+   // Constructor
+   public BinaryTreeDictionary(Address addr) {
+      super(addr);
+   }
+}
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Tue Jun 17 15:27:05 2008 -0700
@@ -35,6 +35,20 @@
 public class CompactibleFreeListSpace extends CompactibleSpace {
    private static AddressField collectorField;
 
+   // for free size, three fields
+   //       FreeBlockDictionary* _dictionary;        // ptr to dictionary for large size blocks
+   //       FreeList _indexedFreeList[IndexSetSize]; // indexed array for small size blocks
+   //       LinearAllocBlock _smallLinearAllocBlock; // small linear alloc in TLAB
+   private static AddressField indexedFreeListField;
+   private static AddressField dictionaryField;
+   private static long         smallLinearAllocBlockFieldOffset;
+   private static long indexedFreeListSizeOf;
+
+   private int    heapWordSize;     // 4 for 32bit, 8 for 64 bits
+   private int    IndexSetStart;    // for small indexed list
+   private int    IndexSetSize;
+   private int    IndexSetStride;
+
    static {
       VM.registerVMInitializedObserver(new Observer() {
          public void update(Observable o, Object data) {
@@ -51,10 +65,26 @@
 
      Type type = db.lookupType("CompactibleFreeListSpace");
      collectorField = type.getAddressField("_collector");
+     collectorField       = type.getAddressField("_collector");
+     dictionaryField      = type.getAddressField("_dictionary");
+     indexedFreeListField = type.getAddressField("_indexedFreeList[0]");
+     smallLinearAllocBlockFieldOffset = type.getField("_smallLinearAllocBlock").getOffset();
    }
 
    public CompactibleFreeListSpace(Address addr) {
       super(addr);
+      if ( VM.getVM().isLP64() ) {
+         heapWordSize = 8;
+         IndexSetStart = 1;
+         IndexSetStride = 1;
+      }
+      else {
+         heapWordSize = 4;
+         IndexSetStart = 2;
+         IndexSetStride = 2;
+      }
+
+      IndexSetSize = 257;
    }
 
    // Accessing block offset table
@@ -62,9 +92,17 @@
     return (CMSCollector) VMObjectFactory.newObject(
                                  CMSCollector.class,
                                  collectorField.getValue(addr));
-  }
+   }
+
+   public long free0() {
+     return capacity() - used0();
+   }
 
    public long used() {
+     return capacity() - free();
+   }
+
+   public long used0() {
       List regions = getLiveRegions();
       long usedSize = 0L;
       for (Iterator itr = regions.iterator(); itr.hasNext();) {
@@ -75,11 +113,41 @@
    }
 
    public long free() {
-      return capacity() - used();
-   }
+      // small chunks
+      long size = 0;
+      Address cur = addr.addOffsetTo( indexedFreeListField.getOffset() );
+      cur = cur.addOffsetTo(IndexSetStart*FreeList.sizeOf());
+      for (int i=IndexSetStart; i<IndexSetSize; i += IndexSetStride) {
+         FreeList freeList = (FreeList) VMObjectFactory.newObject(FreeList.class, cur);
+         size += i*freeList.count();
+         cur= cur.addOffsetTo(IndexSetStride*FreeList.sizeOf());
+      }
+
+      // large block
+      BinaryTreeDictionary bfbd = (BinaryTreeDictionary) VMObjectFactory.newObject(BinaryTreeDictionary.class,
+                                                                                   dictionaryField.getValue(addr));
+      size += bfbd.size();
+
+
+      // linear block in TLAB
+      LinearAllocBlock lab = (LinearAllocBlock) VMObjectFactory.newObject(LinearAllocBlock.class,
+                                                                          addr.addOffsetTo(smallLinearAllocBlockFieldOffset));
+      size += lab.word_size();
+
+      return size*heapWordSize;
+  }
 
    public void printOn(PrintStream tty) {
       tty.print("free-list-space");
+      tty.print("[ " + bottom() + " , " + end() + " ) ");
+      long cap = capacity();
+      long used_size = used();
+      long free_size = free();
+      int  used_perc = (int)((double)used_size/cap*100);
+      tty.print("space capacity = " + cap + " used(" + used_perc + "%)= " + used_size + " ");
+      tty.print("free= " + free_size );
+      tty.print("\n");
+
    }
 
    public Address skipBlockSizeUsingPrintezisBits(Address pos) {
@@ -121,7 +189,7 @@
             cur = cur.addOffsetTo(adjustObjectSizeInBytes(size));
          }
 
-         if (FreeChunk.secondWordIndicatesFreeChunk(dbg.getAddressValue(klassOop))) {
+         if (FreeChunk.indicatesFreeChunk(cur)) {
             if (! cur.equals(regionStart)) {
                res.add(new MemRegion(regionStart, cur));
             }
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/DefNewGeneration.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/DefNewGeneration.java	Tue Jun 17 15:27:05 2008 -0700
@@ -96,9 +96,9 @@
   public void printOn(PrintStream tty) {
     tty.print("  eden");
     eden().printOn(tty);
-    tty.print("  from");
+    tty.print("\n  from");
     from().printOn(tty);
-    tty.print("  to  ");
+    tty.print("\n  to  ");
     to().printOn(tty);
   }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/FreeChunk.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/FreeChunk.java	Tue Jun 17 15:27:05 2008 -0700
@@ -28,6 +28,7 @@
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.oops.*;
 
 public class FreeChunk extends VMObject {
    static {
@@ -42,13 +43,13 @@
       Type type = db.lookupType("FreeChunk");
       nextField = type.getAddressField("_next");
       prevField = type.getAddressField("_prev");
-      sizeField = type.getCIntegerField("_size");
+      sizeField = type.getAddressField("_size");
    }
 
    // Fields
    private static AddressField nextField;
    private static AddressField prevField;
-   private static CIntegerField sizeField;
+   private static AddressField sizeField;
 
    // Accessors
    public FreeChunk next() {
@@ -61,20 +62,34 @@
    }
 
    public long size() {
-      return sizeField.getValue(addr);
+      if (VM.getVM().isCompressedOopsEnabled()) {
+        Mark mark = new Mark(sizeField.getValue(addr));
+        return mark.getSize();
+      } else {
+        Address size = sizeField.getValue(addr);
+        Debugger dbg = VM.getVM().getDebugger();
+        return dbg.getAddressValue(size);
+      }
    }
 
    public FreeChunk(Address addr) {
       super(addr);
    }
 
-   public static boolean secondWordIndicatesFreeChunk(long word) {
-      return (word & 0x1L) == 0x1L;
+   public static boolean indicatesFreeChunk(Address cur) {
+      FreeChunk f = new FreeChunk(cur);
+      return f.isFree();
    }
 
    public boolean isFree() {
-      Debugger dbg = VM.getVM().getDebugger();
-      Address prev = prevField.getValue(addr);
-      return secondWordIndicatesFreeChunk(dbg.getAddressValue(prev));
+      if (VM.getVM().isCompressedOopsEnabled()) {
+        Mark mark = new Mark(sizeField.getValue(addr));
+        return mark.isCmsFreeChunk();
+      } else {
+        Address prev = prevField.getValue(addr);
+        Debugger dbg = VM.getVM().getDebugger();
+        long word = dbg.getAddressValue(prev);
+        return (word & 0x1L) == 0x1L;
+      }
    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java	Tue Jun 17 15:27:05 2008 -0700
@@ -0,0 +1,72 @@
+/*
+ * @(#)FreeList.java
+ *
+ * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package sun.jvm.hotspot.memory;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.runtime.*;
+
+public class FreeList extends VMObject {
+   static {
+      VM.registerVMInitializedObserver(new Observer() {
+         public void update(Observable o, Object data) {
+            initialize(VM.getVM().getTypeDataBase());
+         }
+      });
+   }
+
+   private static synchronized void initialize(TypeDataBase db) {
+      Type type = db.lookupType("FreeList");
+      sizeField = type.getCIntegerField("_size");
+      countField = type.getCIntegerField("_count");
+      headerSize = type.getSize();
+   }
+
+   // Fields
+   private static CIntegerField sizeField;
+   private static CIntegerField countField;
+   private static long          headerSize;
+
+   //Constructor
+   public FreeList(Address address) {
+     super(address);
+   }
+
+   // Accessors
+   public long size() {
+      return sizeField.getValue(addr);
+   }
+
+   public long count() {
+      return  countField.getValue(addr);
+   }
+
+   public static long sizeOf() {
+     return headerSize;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/LinearAllocBlock.java	Tue Jun 17 15:27:05 2008 -0700
@@ -0,0 +1,59 @@
+/*
+ * @(#)BinaryTreeDictionary.java
+ * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package sun.jvm.hotspot.memory;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.runtime.*;
+
+public class LinearAllocBlock extends VMObject {
+   static {
+      VM.registerVMInitializedObserver(new Observer() {
+         public void update(Observable o, Object data) {
+            initialize(VM.getVM().getTypeDataBase());
+         }
+      });
+   }
+
+   private static synchronized void initialize(TypeDataBase db) {
+      Type type = db.lookupType("LinearAllocBlock");
+      word_sizeField= type.getCIntegerField("_word_size");
+   }
+
+   // Fields
+   private static CIntegerField word_sizeField;
+
+   // Accessors
+   public long word_size() {
+      return word_sizeField.getValue(addr);
+   }
+
+   // Constructor
+   public LinearAllocBlock(Address addr) {
+      super(addr);
+   }
+}
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/Mark.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Mark.java	Tue Jun 17 15:27:05 2008 -0700
@@ -79,6 +79,11 @@
     noHashInPlace       = db.lookupLongConstant("markOopDesc::no_hash_in_place").longValue();
     noLockInPlace       = db.lookupLongConstant("markOopDesc::no_lock_in_place").longValue();
     maxAge              = db.lookupLongConstant("markOopDesc::max_age").longValue();
+
+    /* Constants in markOop used by CMS. */
+    cmsShift            = db.lookupLongConstant("markOopDesc::cms_shift").longValue();
+    cmsMask             = db.lookupLongConstant("markOopDesc::cms_mask").longValue();
+    sizeShift           = db.lookupLongConstant("markOopDesc::size_shift").longValue();
   }
 
   // Field accessors
@@ -120,6 +125,11 @@
 
   private static long maxAge;
 
+  /* Constants in markOop used by CMS. */
+  private static long cmsShift;
+  private static long cmsMask;
+  private static long sizeShift;
+
   public Mark(Address addr) {
     super(addr);
   }
@@ -290,4 +300,11 @@
   //
   //  // Recover address of oop from encoded form used in mark
   //  inline void* decode_pointer() { return clear_lock_bits(); }
+
+  // Copy markOop methods for CMS here.
+  public boolean isCmsFreeChunk() {
+    return isUnlocked() &&
+           (Bits.maskBitsLong(value() >> cmsShift, cmsMask) & 0x1L) == 0x1L;
+  }
+  public long getSize() { return (long)(value() >> sizeShift); }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java	Tue Jun 17 15:27:05 2008 -0700
@@ -274,10 +274,10 @@
        // hc_klass is a HotSpot magic field and hence we can't
        // find it from InstanceKlass for java.lang.Class.
        TypeDataBase db = VM.getVM().getTypeDataBase();
-       int hcKlassOffset = (int) Oop.getHeaderSize();
+       int hcKlassOffset = (int) Instance.getHeaderSize();
        try {
           hcKlassOffset += (db.lookupIntConstant("java_lang_Class::hc_klass_offset").intValue() *
-                           db.getAddressSize());
+                           VM.getVM().getHeapOopSize());
        } catch (RuntimeException re) {
           // ignore, currently java_lang_Class::hc_klass_offset is zero
        }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/AnnotatedMemoryPanel.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/AnnotatedMemoryPanel.java	Tue Jun 17 15:27:05 2008 -0700
@@ -648,6 +648,6 @@
           System.exit(0);
         }
       });
-    frame.show();
+    frame.setVisible(true);
   }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/CommandProcessorPanel.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/CommandProcessorPanel.java	Tue Jun 17 15:27:05 2008 -0700
@@ -220,7 +220,7 @@
                 }
             });
         frame.setSize(500, 500);
-        frame.show();
+        frame.setVisible(true);
         panel.requestFocus();
     }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/DebuggerConsolePanel.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/DebuggerConsolePanel.java	Tue Jun 17 15:27:05 2008 -0700
@@ -226,7 +226,7 @@
         }
       });
     frame.setSize(500, 500);
-    frame.show();
+    frame.setVisible(true);
     panel.requestFocus();
   }
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/HighPrecisionJScrollBar.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/HighPrecisionJScrollBar.java	Tue Jun 17 15:27:05 2008 -0700
@@ -424,7 +424,7 @@
         }
       });
     frame.getContentPane().add(hpsb);
-    frame.show();
+    frame.setVisible(true);
   }
 
 }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/JFrameWrapper.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/JFrameWrapper.java	Tue Jun 17 15:27:05 2008 -0700
@@ -43,7 +43,7 @@
   public void       setVisible(boolean visible) { frame.setVisible(visible);     }
   public void       setSize(int x, int y)       { frame.setSize(x, y);           }
   public void       pack()                      { frame.pack();                  }
-  public void       show()                      { frame.show();                  }
+  public void       show()                      { frame.setVisible(true);        }
   public void       dispose()                   { frame.dispose();               }
   public void       setBackground(Color color)  { frame.setBackground(color);    }
   public void       setResizable(boolean resizable) { frame.setResizable(resizable); }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/treetable/JTreeTable.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/treetable/JTreeTable.java	Tue Jun 17 15:27:05 2008 -0700
@@ -477,9 +477,9 @@
     static class TreeTableTextField extends JTextField {
         public int offset;
 
-        public void reshape(int x, int y, int w, int h) {
+        public void setBounds(int x, int y, int w, int h) {
             int newX = Math.max(x, offset);
-            super.reshape(newX, y, w - (newX - x), h);
+            super.setBounds(newX, y, w - (newX - x), h);
         }
     }
 
--- a/make/hotspot_version	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/hotspot_version	Tue Jun 17 15:27:05 2008 -0700
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=13
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=01
+HS_BUILD_NUMBER=02
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7
--- a/make/jprt.config	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/jprt.config	Tue Jun 17 15:27:05 2008 -0700
@@ -68,8 +68,23 @@
 	solaris_arch=i386
     fi
 
-    # Get the SS11 compilers into path (make sure it matches ALT setting)
-    compiler_path=${slashjava}/devtools/${solaris_arch}/SUNWspro/SS11/bin
+    if [ "${JPRT_SOLARIS_COMPILER_NAME}" != "" ] ; then
+        compiler_name=${JPRT_SOLARIS_COMPILER_NAME}
+    else
+        if [ "${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6"      -o \
+             "${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6u10"   -o \
+             "${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6perf" ] ; then
+            # All jdk6 builds use SS11
+            compiler_name=SS11
+        else
+            # FIXUP: Change to SS12 once it has been validated.
+	    #compiler_name=SS12
+            compiler_name=SS11
+        fi
+    fi
+    
+    # Get into path (make sure it matches ALT setting)
+    compiler_path=${slashjava}/devtools/${solaris_arch}/SUNWspro/${compiler_name}/bin
     dirMustExist "${compiler_path}" COMPILER_PATH
     path4sdk=${compiler_path}
 
--- a/make/jprt.properties	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/jprt.properties	Tue Jun 17 15:27:05 2008 -0700
@@ -24,209 +24,274 @@
 
 # Properties for jprt
 
-JPRT.tools.default.release=jdk1.7.0
+# All build result bundles are full jdks, so the 64bit testing does not 
+#    need the 32bit sibling bundle installed.
+#    Note: If the hotspot/make/Makefile changed to only bundle the 64bit files
+#          when bundling 64bit, and stripped out the 64bit files from any 32bit
+#          bundles, then this setting would be need to be "true".
+
+jprt.need.sibling.build=false
+
+# At submit time, the release supplied will be in jprt.submit.release
+#    and will be one of the official release names defined in jprt.
+#    jprt supports property value expansion using ${property.name} syntax.
 
-# Build result bundles are not partial builds| but include everything
-JPRT.need.sibling.build=false
+# This tells jprt what default release we want to build
+
+jprt.tools.default.release=${jprt.submit.release}
+
+# Define the Solaris platforms we want for the various releases
+
+jprt.my.solaris.sparc.jdk7=solaris_sparc_5.10
+jprt.my.solaris.sparc.jdk6=solaris_sparc_5.8
+jprt.my.solaris.sparc.jdk6perf=solaris_sparc_5.8
+jprt.my.solaris.sparc.jdk6u10=solaris_sparc_5.8
+jprt.my.solaris.sparc=${jprt.my.solaris.sparc.${jprt.tools.default.release}}
 
-# Directories needed to build
-JPRT.bundle.src.dirs=make src agent
-JPRT.bundle.exclude.src.dirs=build
+jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10
+jprt.my.solaris.sparcv9.jdk6=solaris_sparcv9_5.8
+jprt.my.solaris.sparcv9.jdk6perf=solaris_sparcv9_5.8
+jprt.my.solaris.sparcv9.jdk6u10=solaris_sparcv9_5.8
+jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}}
+
+jprt.my.solaris.i586.jdk7=solaris_i586_5.10
+jprt.my.solaris.i586.jdk6=solaris_i586_5.8
+jprt.my.solaris.i586.jdk6perf=solaris_i586_5.8
+jprt.my.solaris.i586.jdk6u10=solaris_i586_5.8
+jprt.my.solaris.i586=${jprt.my.solaris.i586.${jprt.tools.default.release}}
 
+jprt.my.solaris.x64.jdk7=solaris_x64_5.10
+jprt.my.solaris.x64.jdk6=solaris_x64_5.10
+jprt.my.solaris.x64.jdk6perf=solaris_x64_5.10
+jprt.my.solaris.x64.jdk6u10=solaris_x64_5.10
+jprt.my.solaris.x64=${jprt.my.solaris.x64.${jprt.tools.default.release}}
+
+jprt.my.linux.i586=linux_i586
+jprt.my.linux.x64=linux_x64
+jprt.my.windows.i586=windows_i586
+jprt.my.windows.x64=windows_x64
+
+# Standard list of jprt build targets for this source tree
+
+jprt.build.targets= \
+    ${jprt.my.solaris.sparc}-{product|fastdebug|debug}, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug|debug}, \
+    ${jprt.my.solaris.i586}-{product|fastdebug|debug}, \
+    ${jprt.my.solaris.x64}-{product|fastdebug|debug}, \
+    ${jprt.my.linux.i586}-{product|fastdebug|debug}, \
+    ${jprt.my.linux.x64}-{product|fastdebug}, \
+    ${jprt.my.windows.i586}-{product|fastdebug|debug}, \
+    ${jprt.my.windows.x64}-{product|fastdebug|debug}
 
-# Standard list of JPRT build targets for this workspace
-JPRT.build.targets= \
-    solaris_sparc_5.10-{product|fastdebug|debug}, \
-    solaris_sparcv9_5.10-{product|fastdebug|debug}, \
-    solaris_i586_5.10-{product|fastdebug|debug}, \
-    solaris_x64_5.10-{product|fastdebug|debug}, \
-    linux_i586-{product|fastdebug|debug}, \
-    linux_x64-{product|fastdebug}, \
-    windows_i586-{product|fastdebug|debug}, \
-    windows_x64-{product|fastdebug|debug}
+# Subset lists of test targets for this source tree
+
+jprt.my.solaris.sparc.test.targets= \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jvm98, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark, \
+    ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese, \
+    ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese_Xcomp, \
+    ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese_Xcomp_2, \
+    ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese_Xcomp_3, \
+    ${jprt.my.solaris.sparc}-fastdebug-c1-runThese_Xshare, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_default, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_default_2, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC_2, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC_2, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC_2, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_CMS_2, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_default, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_SerialGC, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParallelGC, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParNewGC, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_CMS, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_default, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_SerialGC, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParallelGC, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_CMS, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark_2, \
+    ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark_3
+
+jprt.my.solaris.sparcv9.test.targets= \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark, \
+    ${jprt.my.solaris.sparcv9}-product-c2-runThese, \
+    ${jprt.my.solaris.sparcv9}-product-c2-runThese_Xcomp, \
+    ${jprt.my.solaris.sparcv9}-product-c2-runThese_Xcomp_2, \
+    ${jprt.my.solaris.sparcv9}-product-c2-runThese_Xcomp_3, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_SerialGC, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParallelGC, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParNewGC, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_CMS, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default_2, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_SerialGC_2, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParallelGC_2, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_ParNewGC_2, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_CMS_2, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_default, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_SerialGC, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParallelGC, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParNewGC, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_CMS, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_SerialGC, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_ParallelGC, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_CMS, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark_2, \
+    ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark_3
 
-# Standard list of JPRT test targets for this workspace
-JPRT.test.targets = \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-jvm98, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-scimark, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-jvm98, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-scimark, \
-    solaris_i586_5.10-{product|fastdebug}-{c1|c2}-jvm98, \
-    solaris_i586_5.10-{product|fastdebug}-{c1|c2}-scimark, \
-    solaris_x64_5.10-{product|fastdebug}-c2-jvm98, \
-    solaris_x64_5.10-{product|fastdebug}-c2-scimark, \
-    linux_i586-{product|fastdebug}-{c1|c2}-jvm98, \
-    linux_i586-{product|fastdebug}-{c1|c2}-scimark, \
-    linux_x64-{product|fastdebug}-c2-jvm98, \
-    linux_x64-{product|fastdebug}-c2-scimark, \
-    windows_i586-{product|fastdebug}-{c1|c2}-jvm98, \
-    windows_i586-{product|fastdebug}-{c1|c2}-scimark, \
-    windows_x64-{product|fastdebug}-c2-jvm98, \
-    windows_x64-{product|fastdebug}-c2-scimark, \
-    solaris_sparc_5.10-product-{c1|c2}-runThese, \
-    solaris_sparc_5.10-product-{c1|c2}-runThese_Xcomp, \
-    solaris_sparc_5.10-product-{c1|c2}-runThese_Xcomp_2, \
-    solaris_sparc_5.10-product-{c1|c2}-runThese_Xcomp_3, \
-    solaris_sparc_5.10-fastdebug-c1-runThese_Xshare, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_default, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_default_2, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC_2, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC_2, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC_2, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCBasher_CMS_2, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCOld_default, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCOld_SerialGC, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCOld_ParallelGC, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCOld_ParNewGC, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-GCOld_CMS, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-jbb_default, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-jbb_SerialGC, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-jbb_ParallelGC, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-jbb_CMS, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-scimark_2, \
-    solaris_sparc_5.10-{product|fastdebug}-{c1|c2}-scimark_3, \
-    solaris_sparcv9_5.10-product-c2-runThese, \
-    solaris_sparcv9_5.10-product-c2-runThese_Xcomp, \
-    solaris_sparcv9_5.10-product-c2-runThese_Xcomp_2, \
-    solaris_sparcv9_5.10-product-c2-runThese_Xcomp_3, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_default, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_SerialGC, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_ParallelGC, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_ParNewGC, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_CMS, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_default_2, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_SerialGC_2, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_ParallelGC_2, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_ParNewGC_2, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_CMS_2, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_default, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_SerialGC, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_ParallelGC, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_ParNewGC, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_CMS, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_default, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_SerialGC, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_ParallelGC, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_CMS, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-scimark_2, \
-    solaris_sparcv9_5.10-{product|fastdebug}-c2-scimark_3, \
-    solaris_x64-product-c2-runThese, \
-    solaris_x64-product-c2-runThese_Xcomp, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_default, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_SerialGC, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_ParallelGC, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_ParNewGC, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_CMS, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_default_2, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_SerialGC_2, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_ParallelGC_2, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_ParNewGC_2, \
-    solaris_x64-{product|fastdebug}-c2-GCBasher_CMS_2, \
-    solaris_x64-{product|fastdebug}-c2-GCOld_default, \
-    solaris_x64-{product|fastdebug}-c2-GCOld_SerialGC, \
-    solaris_x64-{product|fastdebug}-c2-GCOld_ParallelGC, \
-    solaris_x64-{product|fastdebug}-c2-GCOld_ParNewGC, \
-    solaris_x64-{product|fastdebug}-c2-GCOld_CMS, \
-    solaris_x64-{product|fastdebug}-c2-jbb_default, \
-    solaris_x64-{product|fastdebug}-c2-jbb_SerialGC, \
-    solaris_x64-{product|fastdebug}-c2-jbb_ParallelGC, \
-    solaris_x64-{product|fastdebug}-c2-jbb_CMS, \
-    solaris_i586_5.10-product-{c1|c2}-runThese_Xcomp, \
-    solaris_i586_5.10-product-c2-runThese_Xcomp_2, \
-    solaris_i586_5.10-fastdebug-c1-runThese_Xcomp_2, \
-    solaris_i586_5.10-fastdebug-c1-runThese_Xshare, \
-    solaris_i586_5.10-product-c1-GCBasher_default, \
-    solaris_i586_5.10-product-c1-GCBasher_SerialGC, \
-    solaris_i586_5.10-product-c1-GCBasher_ParallelGC, \
-    solaris_i586_5.10-product-c1-GCBasher_ParNewGC, \
-    solaris_i586_5.10-product-c1-GCBasher_CMS, \
-    solaris_i586_5.10-fastdebug-c2-GCBasher_default, \
-    solaris_i586_5.10-fastdebug-c2-GCBasher_SerialGC, \
-    solaris_i586_5.10-fastdebug-c2-GCBasher_ParallelGC, \
-    solaris_i586_5.10-fastdebug-c2-GCBasher_ParNewGC, \
-    solaris_i586_5.10-fastdebug-c2-GCBasher_CMS, \
-    solaris_i586_5.10-product-c1-GCOld_default, \
-    solaris_i586_5.10-product-c1-GCOld_SerialGC, \
-    solaris_i586_5.10-product-c1-GCOld_ParallelGC, \
-    solaris_i586_5.10-product-c1-GCOld_ParNewGC, \
-    solaris_i586_5.10-product-c1-GCOld_CMS, \
-    solaris_i586_5.10-fastdebug-c2-jbb_default, \
-    solaris_i586_5.10-fastdebug-c2-jbb_ParallelGC, \
-    solaris_i586_5.10-fastdebug-c2-jbb_CMS, \
-    solaris_i586_5.10-{product|fastdebug}-{c1|c2}-scimark_2, \
-    solaris_i586_5.10-{product|fastdebug}-{c1|c2}-scimark_3, \
-    linux_i586-product-c1-runThese_Xcomp, \
-    linux_i586-product-c1-runThese_Xcomp_2, \
-    linux_i586-product-c1-runThese_Xcomp_3, \
-    linux_i586-fastdebug-c1-runThese_Xshare, \
-    linux_i586-fastdebug-c2-runThese_Xcomp, \
-    linux_i586-fastdebug-c2-runThese_Xcomp_2, \
-    linux_i586-{product|fastdebug}-{c1|c2}-GCBasher_default, \
-    linux_i586-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \
-    linux_i586-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \
-    linux_i586-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \
-    linux_i586-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \
-    linux_i586-product-{c1|c2}-GCOld_default, \
-    linux_i586-product-{c1|c2}-GCOld_SerialGC, \
-    linux_i586-product-{c1|c2}-GCOld_ParallelGC, \
-    linux_i586-product-{c1|c2}-GCOld_ParNewGC, \
-    linux_i586-product-{c1|c2}-GCOld_CMS, \
-    linux_i586-{product|fastdebug}-c1-jbb_default, \
-    linux_i586-{product|fastdebug}-c1-jbb_ParallelGC, \
-    linux_i586-{product|fastdebug}-c1-jbb_CMS, \
-    linux_i586-{product|fastdebug}-c2-scimark_2, \
-    linux_i586-{product|fastdebug}-c2-scimark_3, \
-    linux_x64-{product|fastdebug}-c2-GCBasher_default, \
-    linux_x64-{product|fastdebug}-c2-GCBasher_SerialGC, \
-    linux_x64-{product|fastdebug}-c2-GCBasher_ParallelGC, \
-    linux_x64-{product|fastdebug}-c2-GCBasher_ParNewGC, \
-    linux_x64-{product|fastdebug}-c2-GCBasher_CMS, \
-    linux_x64-{product|fastdebug}-c2-GCOld_default, \
-    linux_x64-{product|fastdebug}-c2-GCOld_SerialGC, \
-    linux_x64-{product|fastdebug}-c2-GCOld_ParallelGC, \
-    linux_x64-{product|fastdebug}-c2-GCOld_ParNewGC, \
-    linux_x64-{product|fastdebug}-c2-GCOld_CMS, \
-    linux_x64-{product|fastdebug}-c2-jbb_default, \
-    linux_x64-{product|fastdebug}-c2-jbb_ParallelGC, \
-    linux_x64-{product|fastdebug}-c2-scimark_2, \
-    linux_x64-{product|fastdebug}-c2-scimark_3, \
-    windows_i586-product-{c1|c2}-runThese, \
-    windows_i586-product-{c1|c2}-runThese_Xcomp, \
-    windows_i586-fastdebug-c1-runThese_Xshare, \
-    windows_i586-{product|fastdebug}-{c1|c2}-GCBasher_default, \
-    windows_i586-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \
-    windows_i586-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \
-    windows_i586-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \
-    windows_i586-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \
-    windows_i586-product-{c1|c2}-GCOld_default, \
-    windows_i586-product-{c1|c2}-GCOld_SerialGC, \
-    windows_i586-product-{c1|c2}-GCOld_ParallelGC, \
-    windows_i586-product-{c1|c2}-GCOld_ParNewGC, \
-    windows_i586-product-{c1|c2}-GCOld_CMS, \
-    windows_i586-{product|fastdebug}-{c1|c2}-jbb_default, \
-    windows_i586-product-{c1|c2}-jbb_ParallelGC, \
-    windows_i586-product-{c1|c2}-jbb_CMS, \
-    windows_i586-product-{c1|c2}-scimark_2, \
-    windows_i586-product-{c1|c2}-scimark_3, \
-    windows_x64-product-c2-runThese, \
-    windows_x64-product-c2-runThese_Xcomp, \
-    windows_x64-{product|fastdebug}-c2-GCBasher_default, \
-    windows_x64-{product|fastdebug}-c2-GCBasher_SerialGC, \
-    windows_x64-{product|fastdebug}-c2-GCBasher_ParallelGC, \
-    windows_x64-{product|fastdebug}-c2-GCBasher_ParNewGC, \
-    windows_x64-{product|fastdebug}-c2-GCBasher_CMS, \
-    windows_x64-{product|fastdebug}-c2-GCOld_default, \
-    windows_x64-{product|fastdebug}-c2-GCOld_SerialGC, \
-    windows_x64-{product|fastdebug}-c2-GCOld_ParallelGC, \
-    windows_x64-{product|fastdebug}-c2-GCOld_ParNewGC, \
-    windows_x64-{product|fastdebug}-c2-GCOld_CMS, \
-    windows_x64-{product|fastdebug}-c2-jbb_default, \
-    windows_x64-product-c2-jbb_CMS, \
-    windows_x64-product-c2-jbb_ParallelGC, \
-    windows_x64-{product|fastdebug}-c2-scimark_2, \
-    windows_x64-{product|fastdebug}-c2-scimark_3
+jprt.my.solaris.x64.test.targets= \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-scimark, \
+    ${jprt.my.solaris.x64}-product-c2-runThese, \
+    ${jprt.my.solaris.x64}-product-c2-runThese_Xcomp, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_default, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_CMS, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_default_2, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_SerialGC_2, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC_2, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC_2, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCBasher_CMS_2, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_default, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_CMS, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_SerialGC, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \
+    ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_CMS
+
+jprt.my.solaris.i586.test.targets= \
+    ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
+    ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark, \
+    ${jprt.my.solaris.i586}-product-{c1|c2}-runThese_Xcomp, \
+    ${jprt.my.solaris.i586}-product-c2-runThese_Xcomp_2, \
+    ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp_2, \
+    ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xshare, \
+    ${jprt.my.solaris.i586}-product-c1-GCBasher_default, \
+    ${jprt.my.solaris.i586}-product-c1-GCBasher_SerialGC, \
+    ${jprt.my.solaris.i586}-product-c1-GCBasher_ParallelGC, \
+    ${jprt.my.solaris.i586}-product-c1-GCBasher_ParNewGC, \
+    ${jprt.my.solaris.i586}-product-c1-GCBasher_CMS, \
+    ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_default, \
+    ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_SerialGC, \
+    ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParallelGC, \
+    ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParNewGC, \
+    ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_CMS, \
+    ${jprt.my.solaris.i586}-product-c1-GCOld_default, \
+    ${jprt.my.solaris.i586}-product-c1-GCOld_SerialGC, \
+    ${jprt.my.solaris.i586}-product-c1-GCOld_ParallelGC, \
+    ${jprt.my.solaris.i586}-product-c1-GCOld_ParNewGC, \
+    ${jprt.my.solaris.i586}-product-c1-GCOld_CMS, \
+    ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default, \
+    ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParallelGC, \
+    ${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \
+    ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark_2, \
+    ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark_3
 
+jprt.my.linux.i586.test.targets = \
+    ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-scimark, \
+    ${jprt.my.linux.i586}-product-c1-runThese_Xcomp, \
+    ${jprt.my.linux.i586}-product-c1-runThese_Xcomp_2, \
+    ${jprt.my.linux.i586}-product-c1-runThese_Xcomp_3, \
+    ${jprt.my.linux.i586}-fastdebug-c1-runThese_Xshare, \
+    ${jprt.my.linux.i586}-fastdebug-c2-runThese_Xcomp, \
+    ${jprt.my.linux.i586}-fastdebug-c2-runThese_Xcomp_2, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_default, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \
+    ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_default, \
+    ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_SerialGC, \
+    ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParallelGC, \
+    ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParNewGC, \
+    ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_CMS, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_default, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParallelGC, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_CMS, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-c2-scimark_2, \
+    ${jprt.my.linux.i586}-{product|fastdebug}-c2-scimark_3
+
+jprt.my.linux.x64.test.targets = \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_default, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_CMS, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_default, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_CMS, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark_2, \
+    ${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark_3
+
+jprt.my.windows.i586.test.targets = \
+    ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
+    ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-scimark, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-runThese, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-runThese_Xcomp, \
+    ${jprt.my.windows.i586}-fastdebug-c1-runThese_Xshare, \
+    ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_default, \
+    ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \
+    ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \
+    ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \
+    ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_default, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_SerialGC, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParallelGC, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParNewGC, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_CMS, \
+    ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jbb_default, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-jbb_ParallelGC, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-jbb_CMS, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-scimark_2, \
+    ${jprt.my.windows.i586}-product-{c1|c2}-scimark_3
+
+jprt.my.windows.x64.test.targets = \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark, \
+    ${jprt.my.windows.x64}-product-c2-runThese, \
+    ${jprt.my.windows.x64}-product-c2-runThese_Xcomp, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_default, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParallelGC, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_ParNewGC, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCBasher_CMS, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_default, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_SerialGC, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParallelGC, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_CMS, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-jbb_default, \
+    ${jprt.my.windows.x64}-product-c2-jbb_CMS, \
+    ${jprt.my.windows.x64}-product-c2-jbb_ParallelGC, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark_2, \
+    ${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark_3
+
+# The complete list of test targets for jprt
+
+jprt.test.targets = \
+  ${jprt.my.solaris.sparc.test.targets}, \
+  ${jprt.my.solaris.sparcv9.test.targets}, \
+  ${jprt.my.solaris.i586.test.targets}, \
+  ${jprt.my.solaris.x64.test.targets}, \
+  ${jprt.my.linux.i586.test.targets}, \
+  ${jprt.my.linux.x64.test.targets}, \
+  ${jprt.my.windows.i586.test.targets}, \
+  ${jprt.my.windows.x64.test.targets}
+
--- a/make/solaris/makefiles/amd64.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/amd64.make	Tue Jun 17 15:27:05 2008 -0700
@@ -45,10 +45,6 @@
 OPT_CFLAGS/generateOptoStub.o = -xO2
 OPT_CFLAGS/thread.o = -xO2
 
-# Work around for 6624782
-OPT_CFLAGS/instanceKlass.o = -Qoption ube -no_a2lf
-OPT_CFLAGS/objArrayKlass.o = -Qoption ube -no_a2lf
-
 else
 
 ifeq ("${Platform_compiler}", "gcc")
--- a/make/solaris/makefiles/debug.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/debug.make	Tue Jun 17 15:27:05 2008 -0700
@@ -29,7 +29,8 @@
 DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@))
 
 ifeq ("${Platform_compiler}", "sparcWorks")
-ifeq ($(shell expr $(COMPILER_REV) \>= 5.8), 1)
+
+ifeq ($(COMPILER_REV),5.8)
   # SS11 SEGV when compiling with -g and -xarch=v8, using different backend
   DEBUG_CFLAGS/compileBroker.o = $(DEBUG_CFLAGS) -xO0
   DEBUG_CFLAGS/jvmtiTagMap.o   = $(DEBUG_CFLAGS) -xO0
--- a/make/solaris/makefiles/dtrace.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/dtrace.make	Tue Jun 17 15:27:05 2008 -0700
@@ -92,12 +92,12 @@
 $(XLIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS).h $(LIBJVM_DB_MAPFILE)
 	@echo Making $@
 	$(QUIETLY) mkdir -p 64/ ; \
-	$(CC) $(SYMFLAG) -xarch=$(XARCH) -D$(TYPE) -I. -I$(GENERATED) \
+	$(CC) $(SYMFLAG) $(ARCHFLAG/$(XARCH)) -D$(TYPE) -I. -I$(GENERATED) \
 		$(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc
 $(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE)
 	@echo Making $@
 	$(QUIETLY) mkdir -p 64/ ; \
-	$(CC) $(SYMFLAG) -xarch=$(XARCH) -D$(TYPE) -I. \
+	$(CC) $(SYMFLAG) $(ARCHFLAG/$(XARCH)) -D$(TYPE) -I. \
 		$(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor
 endif # ifneq ("${ISA}","${BUILDARCH}")
 
--- a/make/solaris/makefiles/fastdebug.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/fastdebug.make	Tue Jun 17 15:27:05 2008 -0700
@@ -25,7 +25,7 @@
 # Sets make macros for making debug version of VM
 
 # Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make
-# They may also specify FASTDEBUG_CFLAGS, but it defaults to DEBUG_FLAGS.
+# They may also specify FASTDEBUG_CFLAGS, but it defaults to DEBUG_CFLAGS.
 
 FASTDEBUG_CFLAGS$(FASTDEBUG_CFLAGS) = $(DEBUG_CFLAGS)
 
@@ -35,15 +35,26 @@
 
 ifeq ("${Platform_compiler}", "sparcWorks")
 OPT_CFLAGS/SLOWER = -xO2
-ifeq ($(shell expr $(COMPILER_REV) \>= 5.5), 1)
-# CC 5.5 has bug 4908364 with -xO4 
+
+# Problem with SS12 compiler, dtrace doesn't like the .o files  (bug 6693876)
+ifeq ($(COMPILER_REV), 5.9)
+  # Not clear this workaround could be skipped in some cases.
+  OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER)
+  OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER)
+  OPT_CFLAGS/jni.o = $(OPT_CFLAGS/SLOWER)
+endif
+
+ifeq ($(COMPILER_REV), 5.5)
+# CC 5.5 has bug 4908364 with -xO4  (Fixed in 5.6)
 OPT_CFLAGS/library_call.o = $(OPT_CFLAGS/SLOWER)
-else # COMPILER_REV >= 5.5
+endif # COMPILER_REV == 5.5
+
+ifeq ($(shell expr $(COMPILER_REV) \<= 5.4), 1)
 # Compilation of *_<arch>.cpp can take an hour or more at O3.  Use O2
 # See comments at top of sparc.make.
 OPT_CFLAGS/ad_$(Platform_arch).o = $(OPT_CFLAGS/SLOWER)
 OPT_CFLAGS/dfa_$(Platform_arch).o = $(OPT_CFLAGS/SLOWER)
-endif # COMPILER_REV >= 5.5
+endif # COMPILER_REV <= 5.4
 
 ifeq (${COMPILER_REV}, 5.0)
 # Avoid a compiler bug caused by using -xO<level> -g<level>
--- a/make/solaris/makefiles/jvmg.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/jvmg.make	Tue Jun 17 15:27:05 2008 -0700
@@ -29,7 +29,8 @@
 DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@))
 
 ifeq ("${Platform_compiler}", "sparcWorks")
-ifeq ($(shell expr $(COMPILER_REV) \>= 5.8), 1)
+
+ifeq ($(COMPILER_REV),5.8))
   # SS11 SEGV when compiling with -g and -xarch=v8, using different backend
   DEBUG_CFLAGS/compileBroker.o = $(DEBUG_CFLAGS) -xO0
   DEBUG_CFLAGS/jvmtiTagMap.o   = $(DEBUG_CFLAGS) -xO0
--- a/make/solaris/makefiles/optimized.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/optimized.make	Tue Jun 17 15:27:05 2008 -0700
@@ -30,12 +30,21 @@
 OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
 
 # (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
+ifeq ("${Platform_compiler}", "sparcWorks")
 
-# Workaround SS11 bug 6345274 (all platforms)
-ifeq ("${Platform_compiler}", "sparcWorks")
-ifeq ($(shell expr $(COMPILER_REV) \>= 5.8), 1)
+# Problem with SS12 compiler, dtrace doesn't like the .o files  (bug 6693876)
+ifeq ($(COMPILER_REV),5.9)
+  # Not clear this workaround could be skipped in some cases.
+  OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER) -g
+  OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER) -g
+  OPT_CFLAGS/jni.o = $(OPT_CFLAGS/SLOWER) -g
+endif
+
+# Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12)
+ifeq ($(COMPILER_REV),5.8))
 OPT_CFLAGS/ciTypeFlow.o = $(OPT_CFLAGS/O2)
-endif # COMPILER_REV >= 5.8
+endif # COMPILER_REV == 5.8
+
 endif # Platform_compiler == sparcWorks
 
 # If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings
--- a/make/solaris/makefiles/product.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/product.make	Tue Jun 17 15:27:05 2008 -0700
@@ -38,12 +38,21 @@
 endif
 
 # (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
+ifeq ("${Platform_compiler}", "sparcWorks")
 
-# Workaround SS11 bug 6345274 (all platforms)
-ifeq ("${Platform_compiler}", "sparcWorks")
-ifeq ($(shell expr $(COMPILER_REV) \>= 5.8), 1)
+# Problem with SS12 compiler, dtrace doesn't like the .o files  (bug 6693876)
+ifeq ($(COMPILER_REV),5.9)
+  # Not clear this workaround could be skipped in some cases.
+  OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER) -g
+  OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER) -g
+  OPT_CFLAGS/jni.o = $(OPT_CFLAGS/SLOWER) -g
+endif
+
+# Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12)
+ifeq ($(COMPILER_REV),5.8)
 OPT_CFLAGS/ciTypeFlow.o = $(OPT_CFLAGS/O2)
-endif # COMPILER_REV >= 5.8
+endif # COMPILER_REV == 5.8
+
 endif # Platform_compiler == sparcWorks
 
 # If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings
--- a/make/solaris/makefiles/sparc.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/sparc.make	Tue Jun 17 15:27:05 2008 -0700
@@ -23,7 +23,7 @@
 #
 
 Obj_Files += solaris_sparc.o
-ASFLAGS += $(ARCHFLAG)
+ASFLAGS += $(AS_ARCHFLAG)
 
 ifeq ("${Platform_compiler}", "sparcWorks")
 ifeq ($(shell expr $(COMPILER_REV) \< 5.5), 1)
--- a/make/solaris/makefiles/sparcWorks.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/sparcWorks.make	Tue Jun 17 15:27:05 2008 -0700
@@ -28,6 +28,8 @@
 CC	= cc
 CPP	= 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
 
 NM	= /usr/ccs/bin/nm
@@ -43,25 +45,33 @@
 C_COMPILER_REV := \
 $(shell $(CC) -V 2>&1 | grep -i "cc:" |  sed -e 's/^.*\([1-9]\.[0-9][0-9]*\).*/\1/')
 
-VALIDATED_COMPILER_REV   := 5.8
-VALIDATED_C_COMPILER_REV := 5.8
+# Pick which compiler is validated
+ifeq ($(JDK_MINOR_VERSION),6)
+  # Validated compiler for JDK6 is SS11 (5.8)
+  VALIDATED_COMPILER_REV   := 5.8
+  VALIDATED_C_COMPILER_REV := 5.8
+else
+  # FIXUP: Change to SS12 (5.9) once it has been validated.
+  # Validated compiler for JDK7 is SS12 (5.9)
+  #VALIDATED_COMPILER_REV   := 5.9
+  #VALIDATED_C_COMPILER_REV := 5.9
+  VALIDATED_COMPILER_REV   := 5.8
+  VALIDATED_C_COMPILER_REV := 5.8
+endif
 
+# Warning messages about not using the above validated version
 ENFORCE_COMPILER_REV${ENFORCE_COMPILER_REV} := ${VALIDATED_COMPILER_REV}
 ifneq (${COMPILER_REV},${ENFORCE_COMPILER_REV})
-dummy_target_to_enforce_compiler_rev:
-	@echo "Wrong ${CPP} version:  ${COMPILER_REV}. " \
-	"Use version ${ENFORCE_COMPILER_REV}, or set" \
-	"ENFORCE_COMPILER_REV=${COMPILER_REV}."
-	@exit 1
+dummy_target_to_enforce_compiler_rev:=\
+$(info WARNING: You are using CC version ${COMPILER_REV} \
+and should be using version ${ENFORCE_COMPILER_REV})
 endif
 
 ENFORCE_C_COMPILER_REV${ENFORCE_C_COMPILER_REV} := ${VALIDATED_C_COMPILER_REV}
 ifneq (${C_COMPILER_REV},${ENFORCE_C_COMPILER_REV})
-dummy_target_to_enforce_c_compiler_rev:
-	@echo "Wrong ${CC} version:  ${C_COMPILER_REV}. " \
-	"Use version ${ENFORCE_C_COMPILER_REV}, or set" \
-	"ENFORCE_C_COMPILER_REV=${C_COMPILER_REV}."
-	@exit 1
+dummy_target_to_enforce_c_compiler_rev:=\
+$(info WARNING: You are using cc version ${C_COMPILER_REV} \
+and should be using version ${ENFORCE_C_COMPILER_REV})
 endif
 
 # Fail the build if __fabsf is used.  __fabsf exists only in Solaris 8 2/04
@@ -90,20 +100,44 @@
 $(shell uname -r | awk -F. '{ if ($$2 >= 7) print "-DSOLARIS_7_OR_LATER"; }')
 CFLAGS += ${SOLARIS_7_OR_LATER}
 
-ARCHFLAG         = $(ARCHFLAG/$(BUILDARCH))
-# set ARCHFLAG/BUILDARCH which will ultimately be ARCHFLAG
+# New architecture options started in SS12 (5.9), we need both styles to build.
+#   The older arch options for SS11 (5.8) or older and also for /usr/ccs/bin/as.
+#   Note: SS12 default for 32bit sparc is now the same as v8plus, so the
+#         settings below have changed all SS12 32bit sparc builds to be v8plus.
+#         The older SS11 (5.8) settings have remained as they always have been.
 ifeq ($(TYPE),COMPILER2)
-ARCHFLAG/sparc   = -xarch=v8plus
+  ARCHFLAG_OLD/sparc   = -xarch=v8plus
 else
-ifeq ($(TYPE),TIERED)
-ARCHFLAG/sparc   = -xarch=v8plus
-else
-ARCHFLAG/sparc   = -xarch=v8
+  ifeq ($(TYPE),TIERED)
+    ARCHFLAG_OLD/sparc = -xarch=v8plus
+  else
+    ARCHFLAG_OLD/sparc = -xarch=v8
+  endif
 endif
+ARCHFLAG_NEW/sparc   = -m32 -xarch=sparc
+ARCHFLAG_OLD/sparcv9 = -xarch=v9
+ARCHFLAG_NEW/sparcv9 = -m64 -xarch=sparc
+ARCHFLAG_OLD/i486    =
+ARCHFLAG_NEW/i486    = -m32
+ARCHFLAG_OLD/amd64   = -xarch=amd64
+ARCHFLAG_NEW/amd64   = -m64
+
+# Select the ARCHFLAGs and other SS12 (5.9) options
+ifeq ($(shell expr $(COMPILER_REV) \>= 5.9), 1)
+  ARCHFLAG/sparc   = $(ARCHFLAG_NEW/sparc)
+  ARCHFLAG/sparcv9 = $(ARCHFLAG_NEW/sparcv9)
+  ARCHFLAG/i486    = $(ARCHFLAG_NEW/i486)
+  ARCHFLAG/amd64   = $(ARCHFLAG_NEW/amd64)
+else
+  ARCHFLAG/sparc   = $(ARCHFLAG_OLD/sparc)
+  ARCHFLAG/sparcv9 = $(ARCHFLAG_OLD/sparcv9)
+  ARCHFLAG/i486    = $(ARCHFLAG_OLD/i486)
+  ARCHFLAG/amd64   = $(ARCHFLAG_OLD/amd64)
 endif
-ARCHFLAG/sparcv9 = -xarch=v9
-ARCHFLAG/i486  =
-ARCHFLAG/amd64  = -xarch=amd64
+
+# ARCHFLAGS for the current build arch
+ARCHFLAG    = $(ARCHFLAG/$(BUILDARCH))
+AS_ARCHFLAG = $(ARCHFLAG_OLD/$(BUILDARCH))
 
 # Optional sub-directory in /usr/lib where BUILDARCH libraries are kept.
 ISA_DIR=$(ISA_DIR/$(BUILDARCH))
@@ -166,13 +200,13 @@
 
 ifeq ("${Platform_arch_model}", "x86_64")
 
-ASFLAGS += -xarch=amd64
-CFLAGS  += -xarch=amd64
+ASFLAGS += $(AS_ARCHFLAG)
+CFLAGS  += $(ARCHFLAG/amd64)
 # this one seemed useless
-LFLAGS_VM  += -xarch=amd64
+LFLAGS_VM  += $(ARCHFLAG/amd64)
 # this one worked
-LFLAGS  += -xarch=amd64
-AOUT_FLAGS += -xarch=amd64
+LFLAGS  += $(ARCHFLAG/amd64)
+AOUT_FLAGS += $(ARCHFLAG/amd64)
 
 # -xO3 is faster than -xO4 on specjbb with SS10 compiler
 OPT_CFLAGS=-xO4 $(EXTRA_OPT_CFLAGS)
@@ -224,7 +258,7 @@
 
 LFLAGS += -mt
 
-endif	# COMPILER_REV >= VALIDATED_COMPILER_REV
+endif	# COMPILER_REV >= 5.5
 
 ######################################
 # End 5.5 Forte compiler options     #
@@ -293,7 +327,7 @@
 LFLAGS += -library=Crun
 LIBS   += -library=Crun -lCrun
 
-endif	# COMPILER_REV >= VALIDATED_COMPILER_REV
+endif	# COMPILER_REV == 5.2
 
 ##################################
 # End 5.2 Forte compiler options #
@@ -320,6 +354,7 @@
 
 # Had to hoist this higher apparently because of other changes. Must
 # come before -xarch specification.
+#  NOTE: native says optimize for the machine doing the compile, bad news.
 CFLAGS += -xtarget=native
 
 CFLAGS     += $(ARCHFLAG)
@@ -359,7 +394,7 @@
 endif  # 32bit x86
 
 # The following options run into misaligned ldd problem (raj)
-#OPT_CFLAGS = -fast -O4 -xarch=v8 -xchip=ultra
+#OPT_CFLAGS = -fast -O4 $(ARCHFLAG/sparc) -xchip=ultra
 
 # no more exceptions
 CFLAGS/NOEX=-noex
@@ -427,6 +462,15 @@
 FASTDEBUG_CFLAGS = -g0
 # The -g0 setting allows the C++ frontend to inline, which is a big win.
 
+# Special global options for SS12
+ifeq ($(COMPILER_REV),5.9)
+  # There appears to be multiple issues with the new Dwarf2 debug format, so
+  #   we tell the compiler to use the older 'stabs' debug format all the time.
+  #   Note that this needs to be used in optimized compiles too to be 100%.
+  #   This is a workaround for SS12 (5.9) bug 6694600
+  CFLAGS += -xdebugformat=stabs
+endif
+
 # Enable the following CFLAGS additions if you need to compare the
 # built ELF objects.
 #
--- a/make/solaris/makefiles/sparcv9.make	Tue Jun 10 10:22:49 2008 -0700
+++ b/make/solaris/makefiles/sparcv9.make	Tue Jun 17 15:27:05 2008 -0700
@@ -23,7 +23,7 @@
 #
 
 Obj_Files += solaris_sparc.o
-ASFLAGS += $(ARCHFLAG)
+ASFLAGS += $(AS_ARCHFLAG)
 
 ifeq ("${Platform_compiler}", "sparcWorks")
 ifeq ($(shell expr $(COMPILER_REV) \< 5.5), 1)
--- a/src/cpu/sparc/vm/assembler_sparc.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/sparc/vm/assembler_sparc.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1523,6 +1523,21 @@
   return Address(d, address(obj), oop_Relocation::spec(oop_index));
 }
 
+void  MacroAssembler::set_narrow_oop(jobject obj, Register d) {
+  assert(oop_recorder() != NULL, "this assembler needs an OopRecorder");
+  int oop_index = oop_recorder()->find_index(obj);
+  RelocationHolder rspec = oop_Relocation::spec(oop_index);
+
+  assert_not_delayed();
+  // Relocation with special format (see relocInfo_sparc.hpp).
+  relocate(rspec, 1);
+  // Assembler::sethi(0x3fffff, d);
+  emit_long( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(0x3fffff) );
+  // Don't add relocation for 'add'. Do patching during 'sethi' processing.
+  add(d, 0x3ff, d);
+
+}
+
 
 void MacroAssembler::align(int modulus) {
   while (offset() % modulus != 0) nop();
@@ -3406,13 +3421,15 @@
   set((intptr_t)markOopDesc::prototype()->copy_set_hash(0x2), t2);
   st_ptr(t2, top, oopDesc::mark_offset_in_bytes()); // set up the mark word
   // set klass to intArrayKlass
-  set((intptr_t)Universe::intArrayKlassObj_addr(), t2);
-  ld_ptr(t2, 0, t2);
-  store_klass(t2, top);
   sub(t1, typeArrayOopDesc::header_size(T_INT), t1);
   add(t1, ThreadLocalAllocBuffer::alignment_reserve(), t1);
   sll_ptr(t1, log2_intptr(HeapWordSize/sizeof(jint)), t1);
   st(t1, top, arrayOopDesc::length_offset_in_bytes());
+  set((intptr_t)Universe::intArrayKlassObj_addr(), t2);
+  ld_ptr(t2, 0, t2);
+  // store klass last.  concurrent gcs assumes klass length is valid if
+  // klass field is not null.
+  store_klass(t2, top);
   verify_oop(top);
 
   // refill the tlab with an eden allocation
@@ -3537,28 +3554,32 @@
   }
 }
 
-void MacroAssembler::load_klass(Register s, Register d) {
+void MacroAssembler::load_klass(Register src_oop, Register klass) {
   // The number of bytes in this code is used by
   // MachCallDynamicJavaNode::ret_addr_offset()
   // if this changes, change that.
   if (UseCompressedOops) {
-    lduw(s, oopDesc::klass_offset_in_bytes(), d);
-    decode_heap_oop_not_null(d);
+    lduw(src_oop, oopDesc::klass_offset_in_bytes(), klass);
+    decode_heap_oop_not_null(klass);
   } else {
-    ld_ptr(s, oopDesc::klass_offset_in_bytes(), d);
+    ld_ptr(src_oop, oopDesc::klass_offset_in_bytes(), klass);
   }
 }
 
-// ??? figure out src vs. dst!
-void MacroAssembler::store_klass(Register d, Register s1) {
+void MacroAssembler::store_klass(Register klass, Register dst_oop) {
   if (UseCompressedOops) {
-    assert(s1 != d, "not enough registers");
-    encode_heap_oop_not_null(d);
-    // Zero out entire klass field first.
-    st_ptr(G0, s1, oopDesc::klass_offset_in_bytes());
-    st(d, s1, oopDesc::klass_offset_in_bytes());
+    assert(dst_oop != klass, "not enough registers");
+    encode_heap_oop_not_null(klass);
+    st(klass, dst_oop, oopDesc::klass_offset_in_bytes());
   } else {
-    st_ptr(d, s1, oopDesc::klass_offset_in_bytes());
+    st_ptr(klass, dst_oop, oopDesc::klass_offset_in_bytes());
+  }
+}
+
+void MacroAssembler::store_klass_gap(Register s, Register d) {
+  if (UseCompressedOops) {
+    assert(s != d, "not enough registers");
+    st(s, d, oopDesc::klass_gap_offset_in_bytes());
   }
 }
 
@@ -3622,6 +3643,7 @@
 
 void MacroAssembler::encode_heap_oop(Register src, Register dst) {
   assert (UseCompressedOops, "must be compressed");
+  verify_oop(src);
   Label done;
   if (src == dst) {
     // optimize for frequent case src == dst
@@ -3643,12 +3665,14 @@
 
 void MacroAssembler::encode_heap_oop_not_null(Register r) {
   assert (UseCompressedOops, "must be compressed");
+  verify_oop(r);
   sub(r, G6_heapbase, r);
   srlx(r, LogMinObjAlignmentInBytes, r);
 }
 
 void MacroAssembler::encode_heap_oop_not_null(Register src, Register dst) {
   assert (UseCompressedOops, "must be compressed");
+  verify_oop(src);
   sub(src, G6_heapbase, dst);
   srlx(dst, LogMinObjAlignmentInBytes, dst);
 }
@@ -3661,11 +3685,13 @@
   bpr(rc_nz, true, Assembler::pt, dst, done);
   delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken
   bind(done);
+  verify_oop(dst);
 }
 
 void  MacroAssembler::decode_heap_oop_not_null(Register r) {
   // Do not add assert code to this unless you change vtableStubs_sparc.cpp
   // pd_code_size_limit.
+  // Also do not verify_oop as this is called by verify_oop.
   assert (UseCompressedOops, "must be compressed");
   sllx(r, LogMinObjAlignmentInBytes, r);
   add(r, G6_heapbase, r);
@@ -3674,6 +3700,7 @@
 void  MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) {
   // Do not add assert code to this unless you change vtableStubs_sparc.cpp
   // pd_code_size_limit.
+  // Also do not verify_oop as this is called by verify_oop.
   assert (UseCompressedOops, "must be compressed");
   sllx(src, LogMinObjAlignmentInBytes, dst);
   add(dst, G6_heapbase, dst);
--- a/src/cpu/sparc/vm/assembler_sparc.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1977,8 +1977,9 @@
   inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); }
 
   // klass oop manipulations if compressed
-  void load_klass(Register  src_oop, Register dst);
-  void store_klass(Register dst_oop, Register s1);
+  void load_klass(Register src_oop, Register klass);
+  void store_klass(Register klass, Register dst_oop);
+  void store_klass_gap(Register s, Register dst_oop);
 
    // oop manipulations
   void load_heap_oop(const Address& s, Register d, int offset = 0);
@@ -2103,6 +2104,8 @@
   inline void set_oop_constant( jobject obj, Register d ); // uses constant_oop_address
   inline void set_oop         ( Address obj_addr );        // same as load_address
 
+  void set_narrow_oop( jobject obj, Register d );
+
   // nop padding
   void align(int modulus);
 
--- a/src/cpu/sparc/vm/relocInfo_sparc.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/sparc/vm/relocInfo_sparc.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -87,6 +87,17 @@
 #ifdef _LP64
     jint inst2;
     guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi");
+    if (format() != 0) {
+      assert(type() == relocInfo::oop_type, "only narrow oops case");
+      jint np = oopDesc::encode_heap_oop((oop)x);
+      inst &= ~Assembler::hi22(-1);
+      inst |=  Assembler::hi22((intptr_t)np);
+      ip->set_long_at(0, inst);
+      inst2 = ip->long_at( NativeInstruction::nop_instruction_size );
+      guarantee(Assembler::inv_op(inst2)==Assembler::arith_op, "arith op");
+      ip->set_long_at(NativeInstruction::nop_instruction_size, ip->set_data32_simm13( inst2, (intptr_t)np));
+      break;
+    }
     ip->set_data64_sethi( ip->addr_at(0), (intptr_t)x );
 #ifdef COMPILER2
     // [RGV] Someone must have missed putting in a reloc entry for the
--- a/src/cpu/sparc/vm/relocInfo_sparc.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/sparc/vm/relocInfo_sparc.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -31,7 +31,12 @@
 
     // There is no need for format bits; the instructions are
     // sufficiently self-identifying.
+#ifndef _LP64
     format_width       =  0
+#else
+    // Except narrow oops in 64-bits VM.
+    format_width       =  1
+#endif
   };
 
 
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -2556,7 +2556,6 @@
   int total_strings = 0;
   int first_arg_to_pass = 0;
   int total_c_args = 0;
-  int box_offset = java_lang_boxing_object::value_offset_in_bytes();
 
   // Skip the receiver as dtrace doesn't want to see it
   if( !method->is_static() ) {
@@ -2721,7 +2720,8 @@
 #endif /* ASSERT */
 
   VMRegPair zero;
-  zero.set2(G0->as_VMReg());
+  const Register g0 = G0; // without this we get a compiler warning (why??)
+  zero.set2(g0->as_VMReg());
 
   int c_arg, j_arg;
 
@@ -2778,7 +2778,9 @@
             __ br_null(in_reg, true, Assembler::pn, skipUnbox);
             __ delayed()->mov(G0, tmp);
 
-            switch (out_sig_bt[c_arg]) {
+            BasicType bt = out_sig_bt[c_arg];
+            int box_offset = java_lang_boxing_object::value_offset_in_bytes(bt);
+            switch (bt) {
                 case T_BYTE:
                   __ ldub(in_reg, box_offset, tmp); break;
                 case T_SHORT:
--- a/src/cpu/sparc/vm/sparc.ad	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/sparc/vm/sparc.ad	Tue Jun 17 15:27:05 2008 -0700
@@ -5471,7 +5471,6 @@
 // Load Klass Pointer
 instruct loadKlass(iRegP dst, memory mem) %{
   match(Set dst (LoadKlass mem));
-  predicate(!n->in(MemNode::Address)->bottom_type()->is_narrow());
   ins_cost(MEMORY_REF_COST);
   size(4);
 
@@ -5486,11 +5485,11 @@
   ins_pipe(iload_mem);
 %}
 
-// Load Klass Pointer
-instruct loadKlassComp(iRegP dst, memory mem) %{
-  match(Set dst (LoadKlass mem));
-  predicate(n->in(MemNode::Address)->bottom_type()->is_narrow());
+// Load narrow Klass Pointer
+instruct loadNKlass(iRegN dst, memory mem) %{
+  match(Set dst (LoadNKlass mem));
   ins_cost(MEMORY_REF_COST);
+  size(4);
 
   format %{ "LDUW   $mem,$dst\t! compressed klass ptr" %}
 
@@ -5503,9 +5502,6 @@
      } else {
        __ lduw(base, $mem$$disp, dst);
      }
-     // klass oop never null but this is generated for nonheader klass loads
-     // too which can be null.
-     __ decode_heap_oop(dst);
   %}
   ins_pipe(iload_mem);
 %}
@@ -5609,22 +5605,24 @@
   ins_pipe(loadConP_poll);
 %}
 
+instruct loadConN0(iRegN dst, immN0 src) %{
+  match(Set dst src);
+
+  size(4);
+  format %{ "CLR    $dst\t! compressed NULL ptr" %}
+  ins_encode( SetNull( dst ) );
+  ins_pipe(ialu_imm);
+%}
+
 instruct loadConN(iRegN dst, immN src) %{
   match(Set dst src);
-  ins_cost(DEFAULT_COST * 2);
-  format %{ "SET    $src,$dst\t!ptr" %}
+  ins_cost(DEFAULT_COST * 3/2);
+  format %{ "SET    $src,$dst\t! compressed ptr" %}
   ins_encode %{
-    address con = (address)$src$$constant;
     Register dst = $dst$$Register;
-    if (con == NULL) {
-      __ mov(G0, dst);
-    } else {
-      __ set_oop((jobject)$src$$constant, dst);
-      __ encode_heap_oop(dst);
-    }
-  %}
-  ins_pipe(loadConP);
-
+    __ set_narrow_oop((jobject)$src$$constant, dst);
+  %}
+  ins_pipe(ialu_hi_lo_reg);
 %}
 
 instruct loadConL(iRegL dst, immL src, o7RegL tmp) %{
@@ -5977,7 +5975,8 @@
 %}
 
 instruct decodeHeapOop(iRegP dst, iRegN src) %{
-  predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull);
+  predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull &&
+            n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant);
   match(Set dst (DecodeN src));
   format %{ "decode_heap_oop $src, $dst" %}
   ins_encode %{
@@ -5987,7 +5986,8 @@
 %}
 
 instruct decodeHeapOop_not_null(iRegP dst, iRegN src) %{
-  predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull);
+  predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull ||
+            n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant);
   match(Set dst (DecodeN src));
   format %{ "decode_heap_oop_not_null $src, $dst" %}
   ins_encode %{
@@ -6258,6 +6258,34 @@
   ins_pipe(ialu_imm);
 %}
 
+// Conditional move for RegN. Only cmov(reg,reg).
+instruct cmovNP_reg(cmpOpP cmp, flagsRegP pcc, iRegN dst, iRegN src) %{
+  match(Set dst (CMoveN (Binary cmp pcc) (Binary dst src)));
+  ins_cost(150);
+  format %{ "MOV$cmp $pcc,$src,$dst" %}
+  ins_encode( enc_cmov_reg(cmp,dst,src, (Assembler::ptr_cc)) );
+  ins_pipe(ialu_reg);
+%}
+
+// This instruction also works with CmpN so we don't need cmovNN_reg.
+instruct cmovNI_reg(cmpOp cmp, flagsReg icc, iRegN dst, iRegN src) %{
+  match(Set dst (CMoveN (Binary cmp icc) (Binary dst src)));
+  ins_cost(150);
+  size(4);
+  format %{ "MOV$cmp  $icc,$src,$dst" %}
+  ins_encode( enc_cmov_reg(cmp,dst,src, (Assembler::icc)) );
+  ins_pipe(ialu_reg);
+%}
+
+instruct cmovNF_reg(cmpOpF cmp, flagsRegF fcc, iRegN dst, iRegN src) %{
+  match(Set dst (CMoveN (Binary cmp fcc) (Binary dst src)));
+  ins_cost(150);
+  size(4);
+  format %{ "MOV$cmp $fcc,$src,$dst" %}
+  ins_encode( enc_cmov_reg_f(cmp,dst,src, fcc) );
+  ins_pipe(ialu_reg);
+%}
+
 // Conditional move
 instruct cmovPP_reg(cmpOpP cmp, flagsRegP pcc, iRegP dst, iRegP src) %{
   match(Set dst (CMoveP (Binary cmp pcc) (Binary dst src)));
@@ -6275,6 +6303,7 @@
   ins_pipe(ialu_imm);
 %}
 
+// This instruction also works with CmpN so we don't need cmovPN_reg.
 instruct cmovPI_reg(cmpOp cmp, flagsReg icc, iRegP dst, iRegP src) %{
   match(Set dst (CMoveP (Binary cmp icc) (Binary dst src)));
   ins_cost(150);
@@ -6650,10 +6679,9 @@
   ins_pipe( long_memory_op );
 %}
 
-instruct compareAndSwapN_bool_comp(iRegP mem_ptr, iRegN oldval, iRegN newval, iRegI res, o7RegI tmp, flagsReg ccr ) %{
+instruct compareAndSwapN_bool(iRegP mem_ptr, iRegN oldval, iRegN newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{
   match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval)));
-  effect( USE mem_ptr, KILL ccr, KILL tmp);
-
+  effect( USE mem_ptr, KILL ccr, KILL tmp1);
   format %{
             "MOV    $newval,O7\n\t"
             "CASA   [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t"
@@ -6661,18 +6689,8 @@
             "MOV    1,$res\n\t"
             "MOVne  icc,R_G0,$res"
   %}
-  ins_encode %{
-    Register Rmem = reg_to_register_object($mem_ptr$$reg);
-    Register Rold = reg_to_register_object($oldval$$reg);
-    Register Rnew = reg_to_register_object($newval$$reg);
-    Register Rres = reg_to_register_object($res$$reg);
-
-    __ cas(Rmem, Rold, Rnew);
-    __ cmp( Rold, Rnew );
-    __ mov(1, Rres);
-    __ movcc( Assembler::notEqual, false, Assembler::icc, G0, Rres );
-  %}
-
+  ins_encode( enc_casi(mem_ptr, oldval, newval),
+              enc_iflags_ne_to_boolean(res) );
   ins_pipe( long_memory_op );
 %}
 
@@ -8265,6 +8283,27 @@
   ins_pipe(ialu_cconly_reg_imm);
 %}
 
+// Compare Narrow oops
+instruct compN_iRegN(flagsReg icc, iRegN op1, iRegN op2 ) %{
+  match(Set icc (CmpN op1 op2));
+
+  size(4);
+  format %{ "CMP    $op1,$op2\t! compressed ptr" %}
+  opcode(Assembler::subcc_op3, Assembler::arith_op);
+  ins_encode( form3_rs1_rs2_rd( op1, op2, R_G0 ) );
+  ins_pipe(ialu_cconly_reg_reg);
+%}
+
+instruct compN_iRegN_immN0(flagsReg icc, iRegN op1, immN0 op2 ) %{
+  match(Set icc (CmpN op1 op2));
+
+  size(4);
+  format %{ "CMP    $op1,$op2\t! compressed ptr" %}
+  opcode(Assembler::subcc_op3, Assembler::arith_op);
+  ins_encode( form3_rs1_simm13_rd( op1, op2, R_G0 ) );
+  ins_pipe(ialu_cconly_reg_imm);
+%}
+
 //----------Max and Min--------------------------------------------------------
 // Min Instructions
 // Conditional move for min
@@ -8595,6 +8634,14 @@
   ins_pipe(ialu_imm);
 %}
 
+instruct cmovNL_reg(cmpOp cmp, flagsRegL xcc, iRegN dst, iRegN src) %{
+  match(Set dst (CMoveN (Binary cmp xcc) (Binary dst src)));
+  ins_cost(150);
+  format %{ "MOV$cmp  $xcc,$src,$dst" %}
+  ins_encode( enc_cmov_reg(cmp,dst,src, (Assembler::xcc)) );
+  ins_pipe(ialu_reg);
+%}
+
 instruct cmovPL_reg(cmpOp cmp, flagsRegL xcc, iRegP dst, iRegP src) %{
   match(Set dst (CMoveP (Binary cmp xcc) (Binary dst src)));
   ins_cost(150);
@@ -8826,16 +8873,6 @@
 %}
 
 
-instruct compP_iRegN_immN0(flagsRegP pcc, iRegN op1, immN0 op2 ) %{
-  match(Set pcc (CmpN op1 op2));
-
-  size(4);
-  format %{ "CMP    $op1,$op2\t! ptr" %}
-  opcode(Assembler::subcc_op3, Assembler::arith_op);
-  ins_encode( form3_rs1_simm13_rd( op1, op2, R_G0 ) );
-  ins_pipe(ialu_cconly_reg_imm);
-%}
-
 // ============================================================================
 // inlined locking and unlocking
 
--- a/src/cpu/sparc/vm/templateTable_sparc.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/sparc/vm/templateTable_sparc.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -3222,7 +3222,8 @@
     __ set((intptr_t)markOopDesc::prototype(), G4_scratch);
   }
   __ st_ptr(G4_scratch, RallocatedObject, oopDesc::mark_offset_in_bytes());       // mark
-  __ store_klass(RinstanceKlass, RallocatedObject); // klass
+  __ store_klass_gap(G0, RallocatedObject);         // klass gap if compressed
+  __ store_klass(RinstanceKlass, RallocatedObject); // klass (last for cms)
 
   {
     SkipIfEqual skip_if(
--- a/src/cpu/x86/vm/assembler_x86_32.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/assembler_x86_32.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1054,7 +1054,7 @@
   // range (0 <= offset <= page_size).
 
   void null_check(Register reg, int offset = -1);
-  static bool needs_explicit_null_check(int offset);
+  static bool needs_explicit_null_check(intptr_t offset);
 
   // Required platform-specific helpers for Label::patch_instructions.
   // They _shadow_ the declarations in AbstractAssembler, which are undefined.
--- a/src/cpu/x86/vm/assembler_x86_64.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/assembler_x86_64.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -683,7 +683,8 @@
 
   case REP8(0xB8): // movl/q r, #32/#64(oop?)
     if (which == end_pc_operand)  return ip + (is_64bit ? 8 : 4);
-    assert((which == call32_operand || which == imm64_operand) && is_64bit, "");
+    assert((which == call32_operand || which == imm64_operand) && is_64bit ||
+           which == narrow_oop_operand && !is_64bit, "");
     return ip;
 
   case 0x69: // imul r, a, #32
@@ -909,7 +910,8 @@
   } else if (r->is_call() || format == call32_operand) {
     opnd = locate_operand(inst, call32_operand);
   } else if (r->is_data()) {
-    assert(format == imm64_operand || format == disp32_operand, "format ok");
+    assert(format == imm64_operand || format == disp32_operand ||
+           format == narrow_oop_operand, "format ok");
     opnd = locate_operand(inst, (WhichOperand) format);
   } else {
     assert(format == 0, "cannot specify a format");
@@ -4933,6 +4935,8 @@
   movq(Address(top, arrayOopDesc::length_offset_in_bytes()), t1);
   // set klass to intArrayKlass
   movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr()));
+  // store klass last.  concurrent gcs assumes klass length is valid if
+  // klass field is not null.
   store_klass(top, t1);
 
   // refill the tlab with an eden allocation
@@ -5003,8 +5007,7 @@
   jcc(Assembler::notEqual, cas_label);
   // The bias pattern is present in the object's header. Need to check
   // whether the bias owner and the epoch are both still current.
-  load_klass(tmp_reg, obj_reg);
-  movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
+  load_prototype_header(tmp_reg, obj_reg);
   orq(tmp_reg, r15_thread);
   xorq(tmp_reg, swap_reg);
   andq(tmp_reg, ~((int) markOopDesc::age_mask_in_place));
@@ -5078,8 +5081,7 @@
   //
   // FIXME: due to a lack of registers we currently blow away the age
   // bits in this situation. Should attempt to preserve them.
-  load_klass(tmp_reg, obj_reg);
-  movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
+  load_prototype_header(tmp_reg, obj_reg);
   orq(tmp_reg, r15_thread);
   if (os::is_MP()) {
     lock();
@@ -5109,8 +5111,7 @@
   //
   // FIXME: due to a lack of registers we currently blow away the age
   // bits in this situation. Should attempt to preserve them.
-  load_klass(tmp_reg, obj_reg);
-  movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
+  load_prototype_header(tmp_reg, obj_reg);
   if (os::is_MP()) {
     lock();
   }
@@ -5154,17 +5155,32 @@
   }
 }
 
+void MacroAssembler::load_prototype_header(Register dst, Register src) {
+  if (UseCompressedOops) {
+    movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
+    movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
+  } else {
+    movq(dst, Address(src, oopDesc::klass_offset_in_bytes()));
+    movq(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
+  }
+}
+
 void MacroAssembler::store_klass(Register dst, Register src) {
   if (UseCompressedOops) {
     encode_heap_oop_not_null(src);
-    // zero the entire klass field first as the gap needs to be zeroed too.
-    movptr(Address(dst, oopDesc::klass_offset_in_bytes()), NULL_WORD);
     movl(Address(dst, oopDesc::klass_offset_in_bytes()), src);
   } else {
     movq(Address(dst, oopDesc::klass_offset_in_bytes()), src);
   }
 }
 
+void MacroAssembler::store_klass_gap(Register dst, Register src) {
+  if (UseCompressedOops) {
+    // Store to klass gap in destination
+    movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src);
+  }
+}
+
 void MacroAssembler::load_heap_oop(Register dst, Address src) {
   if (UseCompressedOops) {
     movl(dst, src);
@@ -5188,13 +5204,15 @@
 void MacroAssembler::encode_heap_oop(Register r) {
   assert (UseCompressedOops, "should be compressed");
 #ifdef ASSERT
-  Label ok;
-  pushq(rscratch1); // cmpptr trashes rscratch1
-  cmpptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr()));
-  jcc(Assembler::equal, ok);
-  stop("MacroAssembler::encode_heap_oop: heap base corrupted?");
-  bind(ok);
-  popq(rscratch1);
+  if (CheckCompressedOops) {
+    Label ok;
+    pushq(rscratch1); // cmpptr trashes rscratch1
+    cmpptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr()));
+    jcc(Assembler::equal, ok);
+    stop("MacroAssembler::encode_heap_oop: heap base corrupted?");
+    bind(ok);
+    popq(rscratch1);
+  }
 #endif
   verify_oop(r, "broken oop in encode_heap_oop");
   testq(r, r);
@@ -5206,11 +5224,13 @@
 void MacroAssembler::encode_heap_oop_not_null(Register r) {
   assert (UseCompressedOops, "should be compressed");
 #ifdef ASSERT
-  Label ok;
-  testq(r, r);
-  jcc(Assembler::notEqual, ok);
-  stop("null oop passed to encode_heap_oop_not_null");
-  bind(ok);
+  if (CheckCompressedOops) {
+    Label ok;
+    testq(r, r);
+    jcc(Assembler::notEqual, ok);
+    stop("null oop passed to encode_heap_oop_not_null");
+    bind(ok);
+  }
 #endif
   verify_oop(r, "broken oop in encode_heap_oop_not_null");
   subq(r, r12_heapbase);
@@ -5220,11 +5240,13 @@
 void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) {
   assert (UseCompressedOops, "should be compressed");
 #ifdef ASSERT
-  Label ok;
-  testq(src, src);
-  jcc(Assembler::notEqual, ok);
-  stop("null oop passed to encode_heap_oop_not_null2");
-  bind(ok);
+  if (CheckCompressedOops) {
+    Label ok;
+    testq(src, src);
+    jcc(Assembler::notEqual, ok);
+    stop("null oop passed to encode_heap_oop_not_null2");
+    bind(ok);
+  }
 #endif
   verify_oop(src, "broken oop in encode_heap_oop_not_null2");
   if (dst != src) {
@@ -5237,14 +5259,16 @@
 void  MacroAssembler::decode_heap_oop(Register r) {
   assert (UseCompressedOops, "should be compressed");
 #ifdef ASSERT
-  Label ok;
-  pushq(rscratch1);
-  cmpptr(r12_heapbase,
-         ExternalAddress((address)Universe::heap_base_addr()));
-  jcc(Assembler::equal, ok);
-  stop("MacroAssembler::decode_heap_oop: heap base corrupted?");
-  bind(ok);
-  popq(rscratch1);
+  if (CheckCompressedOops) {
+    Label ok;
+    pushq(rscratch1);
+    cmpptr(r12_heapbase,
+           ExternalAddress((address)Universe::heap_base_addr()));
+    jcc(Assembler::equal, ok);
+    stop("MacroAssembler::decode_heap_oop: heap base corrupted?");
+    bind(ok);
+    popq(rscratch1);
+  }
 #endif
 
   Label done;
@@ -5265,6 +5289,7 @@
   assert (UseCompressedOops, "should only be used for compressed headers");
   // Cannot assert, unverified entry point counts instructions (see .ad file)
   // vtableStubs also counts instructions in pd_code_size_limit.
+  // Also do not verify_oop as this is called by verify_oop.
   assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong");
   leaq(r, Address(r12_heapbase, r, Address::times_8, 0));
 }
@@ -5273,10 +5298,24 @@
   assert (UseCompressedOops, "should only be used for compressed headers");
   // Cannot assert, unverified entry point counts instructions (see .ad file)
   // vtableStubs also counts instructions in pd_code_size_limit.
+  // Also do not verify_oop as this is called by verify_oop.
   assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong");
   leaq(dst, Address(r12_heapbase, src, Address::times_8, 0));
 }
 
+void  MacroAssembler::set_narrow_oop(Register dst, jobject obj) {
+  assert(oop_recorder() != NULL, "this assembler needs an OopRecorder");
+  int oop_index = oop_recorder()->find_index(obj);
+  RelocationHolder rspec = oop_Relocation::spec(oop_index);
+
+  // movl dst,obj
+  InstructionMark im(this);
+  int encode = prefix_and_encode(dst->encoding());
+  emit_byte(0xB8 | encode);
+  emit_data(oop_index, rspec, narrow_oop_operand);
+}
+
+
 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) {
   switch (cond) {
     // Note some conditions are synonyms for others
--- a/src/cpu/x86/vm/assembler_x86_64.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/assembler_x86_64.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -490,7 +490,12 @@
     imm64_operand  = 0,          // embedded 64-bit immediate operand
     disp32_operand = 1,          // embedded 32-bit displacement
     call32_operand = 2,          // embedded 32-bit self-relative displacement
+#ifndef AMD64
     _WhichOperand_limit = 3
+#else
+     narrow_oop_operand = 3,     // embedded 32-bit immediate narrow oop
+    _WhichOperand_limit = 4
+#endif
   };
 
   public:
@@ -1023,7 +1028,7 @@
   // is needed if the offset is within a certain range (0 <= offset <=
   // page_size).
   void null_check(Register reg, int offset = -1);
-  static bool needs_explicit_null_check(int offset);
+  static bool needs_explicit_null_check(intptr_t offset);
 
   // Required platform-specific helpers for Label::patch_instructions.
   // They _shadow_ the declarations in AbstractAssembler, which are undefined.
@@ -1104,6 +1109,9 @@
   // oop manipulations
   void load_klass(Register dst, Register src);
   void store_klass(Register dst, Register src);
+  void store_klass_gap(Register dst, Register src);
+
+  void load_prototype_header(Register dst, Register src);
 
   void load_heap_oop(Register dst, Address src);
   void store_heap_oop(Address dst, Register src);
@@ -1114,6 +1122,8 @@
   void encode_heap_oop_not_null(Register dst, Register src);
   void decode_heap_oop_not_null(Register dst, Register src);
 
+  void set_narrow_oop(Register dst, jobject obj);
+
   // Stack frame creation/removal
   void enter();
   void leave();
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -233,7 +233,7 @@
   assert(Rsub_klass != rcx, "rcx holds 2ndary super array length");
   assert(Rsub_klass != rdi, "rdi holds 2ndary super array scan ptr");
 
-  Label not_subtype, loop;
+  Label not_subtype, not_subtype_pop, loop;
 
   // Profile the not-null value's klass.
   profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, rdi
@@ -272,12 +272,13 @@
   // and we store values in objArrays always encoded, thus we need to encode value
   // before repne
   if (UseCompressedOops) {
+    pushq(rax);
     encode_heap_oop(rax);
     repne_scanl();
     // Not equal?
-    jcc(Assembler::notEqual, not_subtype);
-    // decode heap oop here for movq
-    decode_heap_oop(rax);
+    jcc(Assembler::notEqual, not_subtype_pop);
+    // restore heap oop here for movq
+    popq(rax);
   } else {
     repne_scanq();
     jcc(Assembler::notEqual, not_subtype);
@@ -287,9 +288,10 @@
                Klass::secondary_super_cache_offset_in_bytes()), rax);
   jmp(ok_is_subtype);
 
+  bind(not_subtype_pop);
+  // restore heap oop here for miss
+  if (UseCompressedOops) popq(rax);
   bind(not_subtype);
-  // decode heap oop here for miss
-  if (UseCompressedOops) decode_heap_oop(rax);
   profile_typecheck_failed(rcx); // blows rcx
 }
 
--- a/src/cpu/x86/vm/relocInfo_x86.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/relocInfo_x86.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -30,11 +30,15 @@
 #ifdef AMD64
   x += o;
   typedef Assembler::WhichOperand WhichOperand;
-  WhichOperand which = (WhichOperand) format(); // that is, disp32 or imm64, call32
+  WhichOperand which = (WhichOperand) format(); // that is, disp32 or imm64, call32, narrow oop
   assert(which == Assembler::disp32_operand ||
+         which == Assembler::narrow_oop_operand ||
          which == Assembler::imm64_operand, "format unpacks ok");
   if (which == Assembler::imm64_operand) {
     *pd_address_in_code() = x;
+  } else if (which == Assembler::narrow_oop_operand) {
+    address disp = Assembler::locate_operand(addr(), which);
+    *(int32_t*) disp = oopDesc::encode_heap_oop((oop)x);
   } else {
     // Note:  Use runtime_call_type relocations for call32_operand.
     address ip = addr();
--- a/src/cpu/x86/vm/relocInfo_x86.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/relocInfo_x86.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -29,5 +29,10 @@
     offset_unit        =  1,
 
     // Encodes Assembler::disp32_operand vs. Assembler::imm32_operand.
+#ifndef AMD64
     format_width       =  1
+#else
+    // vs Assembler::narrow_oop_operand.
+    format_width       =  2
+#endif
   };
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1920,7 +1920,6 @@
   int total_strings = 0;
   int first_arg_to_pass = 0;
   int total_c_args = 0;
-  int box_offset = java_lang_boxing_object::value_offset_in_bytes();
 
   if( !method->is_static() ) {  // Pass in receiver first
     in_sig_bt[i++] = T_OBJECT;
@@ -2131,7 +2130,10 @@
           assert(dst.first()->is_stack() &&
                  (!dst.second()->is_valid() || dst.second()->is_stack()),
                  "value(s) must go into stack slots");
-          if ( out_sig_bt[c_arg] == T_LONG ) {
+
+          BasicType bt = out_sig_bt[c_arg];
+          int box_offset = java_lang_boxing_object::value_offset_in_bytes(bt);
+          if ( bt == T_LONG ) {
             __ movl(rbx, Address(in_reg,
                                  box_offset + VMRegImpl::stack_slot_size));
             __ movl(Address(rsp, reg2offset_out(dst.second())), rbx);
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1950,7 +1950,6 @@
   int total_strings = 0;
   int first_arg_to_pass = 0;
   int total_c_args = 0;
-  int box_offset = java_lang_boxing_object::value_offset_in_bytes();
 
   // Skip the receiver as dtrace doesn't want to see it
   if( !method->is_static() ) {
@@ -2197,8 +2196,10 @@
               __ testq(in_reg, in_reg);
               __ jcc(Assembler::zero, skipUnbox);
 
+              BasicType bt = out_sig_bt[c_arg];
+              int box_offset = java_lang_boxing_object::value_offset_in_bytes(bt);
               Address src1(in_reg, box_offset);
-              if ( out_sig_bt[c_arg] == T_LONG ) {
+              if ( bt == T_LONG ) {
                 __ movq(in_reg,  src1);
                 __ movq(stack_dst, in_reg);
                 assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
@@ -2460,8 +2461,10 @@
           Label skip;
           __ testq(r, r);
           __ jcc(Assembler::equal, skip);
+          BasicType bt = out_sig_bt[c_arg];
+          int box_offset = java_lang_boxing_object::value_offset_in_bytes(bt);
           Address src1(r, box_offset);
-          if ( out_sig_bt[c_arg] == T_LONG ) {
+          if ( bt == T_LONG ) {
             __ movq(r, src1);
           } else {
             __ movl(r, src1);
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -3163,7 +3163,9 @@
       __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()),
                (intptr_t) markOopDesc::prototype()); // header (address 0x1)
     }
-    __ store_klass(rax, rsi);  // klass
+    __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code)
+    __ store_klass_gap(rax, rcx);  // zero klass gap for compressed oops
+    __ store_klass(rax, rsi);      // store klass last
     __ jmp(done);
   }
 
--- a/src/cpu/x86/vm/x86_32.ad	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/x86_32.ad	Tue Jun 17 15:27:05 2008 -0700
@@ -3806,6 +3806,78 @@
     masm.bind(DONE_LABEL);
   %}
 
+  enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result) %{
+    Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP;
+    MacroAssembler masm(&cbuf);
+
+    Register ary1Reg   = as_Register($ary1$$reg);
+    Register ary2Reg   = as_Register($ary2$$reg);
+    Register tmp1Reg   = as_Register($tmp1$$reg);
+    Register tmp2Reg   = as_Register($tmp2$$reg);
+    Register resultReg = as_Register($result$$reg);
+
+    int length_offset  = arrayOopDesc::length_offset_in_bytes();
+    int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
+
+    // Check the input args
+    masm.cmpl(ary1Reg, ary2Reg);
+    masm.jcc(Assembler::equal, TRUE_LABEL);
+    masm.testl(ary1Reg, ary1Reg);
+    masm.jcc(Assembler::zero, FALSE_LABEL);
+    masm.testl(ary2Reg, ary2Reg);
+    masm.jcc(Assembler::zero, FALSE_LABEL);
+
+    // Check the lengths
+    masm.movl(tmp2Reg, Address(ary1Reg, length_offset));
+    masm.movl(resultReg, Address(ary2Reg, length_offset));
+    masm.cmpl(tmp2Reg, resultReg);
+    masm.jcc(Assembler::notEqual, FALSE_LABEL);
+    masm.testl(resultReg, resultReg);
+    masm.jcc(Assembler::zero, TRUE_LABEL);
+
+    // Get the number of 4 byte vectors to compare
+    masm.shrl(resultReg, 1);
+
+    // Check for odd-length arrays
+    masm.andl(tmp2Reg, 1);
+    masm.testl(tmp2Reg, tmp2Reg);
+    masm.jcc(Assembler::zero, COMPARE_LOOP_HDR);
+
+    // Compare 2-byte "tail" at end of arrays
+    masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
+    masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
+    masm.cmpl(tmp1Reg, tmp2Reg);
+    masm.jcc(Assembler::notEqual, FALSE_LABEL);
+    masm.testl(resultReg, resultReg);
+    masm.jcc(Assembler::zero, TRUE_LABEL);
+
+    // Setup compare loop
+    masm.bind(COMPARE_LOOP_HDR);
+    // Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays
+    masm.leal(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
+    masm.leal(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
+    masm.negl(resultReg);
+
+    // 4-byte-wide compare loop
+    masm.bind(COMPARE_LOOP);
+    masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0));
+    masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0));
+    masm.cmpl(ary1Reg, ary2Reg);
+    masm.jcc(Assembler::notEqual, FALSE_LABEL);
+    masm.increment(resultReg);
+    masm.jcc(Assembler::notZero, COMPARE_LOOP);
+
+    masm.bind(TRUE_LABEL);
+    masm.movl(resultReg, 1);   // return true
+    masm.jmp(DONE_LABEL);
+
+    masm.bind(FALSE_LABEL);
+    masm.xorl(resultReg, resultReg); // return false
+
+    // That's it
+    masm.bind(DONE_LABEL);
+  %}
+
   enc_class enc_pop_rdx() %{
     emit_opcode(cbuf,0x5A);
   %}
@@ -11565,6 +11637,17 @@
   ins_pipe( pipe_slow );
 %}
 
+// fast array equals
+instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI tmp1, eBXRegI tmp2, eCXRegI result, eFlagsReg cr) %{
+  match(Set result (AryEq ary1 ary2));
+  effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr);
+  //ins_cost(300);
+
+  format %{ "Array Equals $ary1,$ary2 -> $result    // KILL EAX, EBX" %}
+  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) );
+  ins_pipe( pipe_slow );
+%}
+
 //----------Control Flow Instructions------------------------------------------
 // Signed compare Instructions
 instruct compI_eReg(eFlagsReg cr, eRegI op1, eRegI op2) %{
--- a/src/cpu/x86/vm/x86_64.ad	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/cpu/x86/vm/x86_64.ad	Tue Jun 17 15:27:05 2008 -0700
@@ -3808,6 +3808,78 @@
     masm.bind(DONE_LABEL);
   %}
 
+  enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, rbx_RegI tmp2, rcx_RegI result) %{
+    Label TRUE_LABEL, FALSE_LABEL, DONE_LABEL, COMPARE_LOOP_HDR, COMPARE_LOOP;
+    MacroAssembler masm(&cbuf);
+
+    Register ary1Reg   = as_Register($ary1$$reg);
+    Register ary2Reg   = as_Register($ary2$$reg);
+    Register tmp1Reg   = as_Register($tmp1$$reg);
+    Register tmp2Reg   = as_Register($tmp2$$reg);
+    Register resultReg = as_Register($result$$reg);
+
+    int length_offset  = arrayOopDesc::length_offset_in_bytes();
+    int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
+
+    // Check the input args
+    masm.cmpq(ary1Reg, ary2Reg);                        
+    masm.jcc(Assembler::equal, TRUE_LABEL);
+    masm.testq(ary1Reg, ary1Reg);                       
+    masm.jcc(Assembler::zero, FALSE_LABEL);
+    masm.testq(ary2Reg, ary2Reg);                       
+    masm.jcc(Assembler::zero, FALSE_LABEL);
+
+    // Check the lengths
+    masm.movl(tmp2Reg, Address(ary1Reg, length_offset));
+    masm.movl(resultReg, Address(ary2Reg, length_offset));
+    masm.cmpl(tmp2Reg, resultReg);
+    masm.jcc(Assembler::notEqual, FALSE_LABEL);
+    masm.testl(resultReg, resultReg);
+    masm.jcc(Assembler::zero, TRUE_LABEL);
+
+    // Get the number of 4 byte vectors to compare
+    masm.shrl(resultReg, 1);
+
+    // Check for odd-length arrays
+    masm.andl(tmp2Reg, 1);
+    masm.testl(tmp2Reg, tmp2Reg);
+    masm.jcc(Assembler::zero, COMPARE_LOOP_HDR);
+
+    // Compare 2-byte "tail" at end of arrays
+    masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
+    masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
+    masm.cmpl(tmp1Reg, tmp2Reg);
+    masm.jcc(Assembler::notEqual, FALSE_LABEL);
+    masm.testl(resultReg, resultReg);
+    masm.jcc(Assembler::zero, TRUE_LABEL);
+
+    // Setup compare loop
+    masm.bind(COMPARE_LOOP_HDR);
+    // Shift tmp1Reg and tmp2Reg to the last 4-byte boundary of the arrays
+    masm.leaq(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
+    masm.leaq(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
+    masm.negq(resultReg);
+
+    // 4-byte-wide compare loop
+    masm.bind(COMPARE_LOOP);
+    masm.movl(ary1Reg, Address(tmp1Reg, resultReg, Address::times_4, 0));
+    masm.movl(ary2Reg, Address(tmp2Reg, resultReg, Address::times_4, 0));
+    masm.cmpl(ary1Reg, ary2Reg);
+    masm.jcc(Assembler::notEqual, FALSE_LABEL);
+    masm.incrementq(resultReg);
+    masm.jcc(Assembler::notZero, COMPARE_LOOP);
+
+    masm.bind(TRUE_LABEL);
+    masm.movl(resultReg, 1);   // return true
+    masm.jmp(DONE_LABEL);
+
+    masm.bind(FALSE_LABEL);
+    masm.xorl(resultReg, resultReg); // return false
+
+    // That's it
+    masm.bind(DONE_LABEL);
+  %}
+
   enc_class enc_rethrow()
   %{
     cbuf.set_inst_mark();
@@ -5202,15 +5274,15 @@
   %}
 %}
 
-// Indirect Memory Times Scale Plus Index Register Plus Offset Operand
-operand indIndexScaleOffsetComp(rRegN src, immL32 off, r12RegL base) %{
+// Indirect Narrow Oop Plus Offset Operand
+operand indNarrowOopOffset(rRegN src, immL32 off) %{
   constraint(ALLOC_IN_RC(ptr_reg));
-  match(AddP (DecodeN src base) off);
+  match(AddP (DecodeN src) off);
 
   op_cost(10);
-  format %{"[$base + $src << 3 + $off] (compressed)" %}
+  format %{"[R12 + $src << 3 + $off] (compressed oop addressing)" %}
   interface(MEMORY_INTER) %{
-    base($base);
+    base(0xc); // R12
     index($src);
     scale(0x3);
     disp($off);
@@ -5365,7 +5437,7 @@
 
 opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
                indIndexScale, indIndexScaleOffset, indPosIndexScaleOffset,
-               indIndexScaleOffsetComp);
+               indNarrowOopOffset);
 
 //----------PIPELINE-----------------------------------------------------------
 // Rules which define the behavior of the target architectures pipeline.
@@ -6044,10 +6116,9 @@
 %}
 
 // Load Compressed Pointer
-instruct loadN(rRegN dst, memory mem, rFlagsReg cr)
+instruct loadN(rRegN dst, memory mem)
 %{
    match(Set dst (LoadN mem));
-   effect(KILL cr);
 
    ins_cost(125); // XXX
    format %{ "movl    $dst, $mem\t# compressed ptr" %}
@@ -6064,7 +6135,6 @@
 instruct loadKlass(rRegP dst, memory mem)
 %{
   match(Set dst (LoadKlass mem));
-  predicate(!n->in(MemNode::Address)->bottom_type()->is_narrow());
 
   ins_cost(125); // XXX
   format %{ "movq    $dst, $mem\t# class" %}
@@ -6073,22 +6143,17 @@
   ins_pipe(ialu_reg_mem); // XXX
 %}
 
-// Load Klass Pointer
-instruct loadKlassComp(rRegP dst, memory mem)
-%{
-  match(Set dst (LoadKlass mem));
-  predicate(n->in(MemNode::Address)->bottom_type()->is_narrow());
+// Load narrow Klass Pointer
+instruct loadNKlass(rRegN dst, memory mem)
+%{
+  match(Set dst (LoadNKlass mem));
 
   ins_cost(125); // XXX
-  format %{ "movl    $dst, $mem\t# compressed class\n\t"
-            "decode_heap_oop $dst,$dst" %}
+  format %{ "movl    $dst, $mem\t# compressed klass ptr" %}
   ins_encode %{
     Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
     Register dst = as_Register($dst$$reg);
     __ movl(dst, addr);
-    // klass is never null in the header but this is generated for all
-    // klass loads not just the _klass field in the header.
-    __ decode_heap_oop(dst);
   %}
   ins_pipe(ialu_reg_mem); // XXX
 %}
@@ -6362,16 +6427,14 @@
   match(Set dst src);
 
   ins_cost(125);
-  format %{ "movq    $dst, $src\t# compressed ptr\n\t"
-            "encode_heap_oop_not_null $dst,$dst" %}
+  format %{ "movl    $dst, $src\t# compressed ptr" %}
   ins_encode %{
     address con = (address)$src$$constant;
     Register dst = $dst$$Register;
     if (con == NULL) {
       ShouldNotReachHere();
     } else {
-      __ movoop(dst, (jobject)$src$$constant);
-      __ encode_heap_oop_not_null(dst);
+      __ set_narrow_oop(dst, (jobject)$src$$constant);
     }
   %}
   ins_pipe(ialu_reg_fat); // XXX
@@ -6633,13 +6696,12 @@
 %}
 
 // Store Compressed Pointer
-instruct storeN(memory mem, rRegN src, rFlagsReg cr)
+instruct storeN(memory mem, rRegN src)
 %{
   match(Set mem (StoreN mem src));
-  effect(KILL cr);
 
   ins_cost(125); // XXX
-  format %{ "movl    $mem, $src\t# ptr" %}
+  format %{ "movl    $mem, $src\t# compressed ptr" %}
   ins_encode %{
     Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
     Register src = as_Register($src$$reg);
@@ -7027,7 +7089,8 @@
 %}
 
 instruct decodeHeapOop(rRegP dst, rRegN src, rFlagsReg cr) %{
-  predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull);
+  predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull &&
+            n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant);
   match(Set dst (DecodeN src));
   effect(KILL cr);
   format %{ "decode_heap_oop $dst,$src" %}
@@ -7043,7 +7106,8 @@
 %}
 
 instruct decodeHeapOop_not_null(rRegP dst, rRegN src) %{
-  predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull);
+  predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull ||
+            n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant);
   match(Set dst (DecodeN src));
   format %{ "decode_heap_oop_not_null $dst,$src" %}
   ins_encode %{
@@ -7143,6 +7207,30 @@
 %}
 
 // Conditional move
+instruct cmovN_reg(rRegN dst, rRegN src, rFlagsReg cr, cmpOp cop)
+%{
+  match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
+
+  ins_cost(200); // XXX
+  format %{ "cmovl$cop $dst, $src\t# signed, compressed ptr" %}
+  opcode(0x0F, 0x40);
+  ins_encode(REX_reg_reg(dst, src), enc_cmov(cop), reg_reg(dst, src));
+  ins_pipe(pipe_cmov_reg);
+%}
+
+// Conditional move
+instruct cmovN_regU(rRegN dst, rRegN src, rFlagsRegU cr, cmpOpU cop)
+%{
+  match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
+
+  ins_cost(200); // XXX
+  format %{ "cmovl$cop $dst, $src\t# unsigned, compressed ptr" %}
+  opcode(0x0F, 0x40);
+  ins_encode(REX_reg_reg(dst, src), enc_cmov(cop), reg_reg(dst, src));
+  ins_pipe(pipe_cmov_reg);
+%}
+
+// Conditional move
 instruct cmovP_reg(rRegP dst, rRegP src, rFlagsReg cr, cmpOp cop)
 %{
   match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
@@ -10862,6 +10950,18 @@
   ins_pipe( pipe_slow );
 %}
 
+// fast array equals
+instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI tmp1, 
+                      rbx_RegI tmp2, rcx_RegI result, rFlagsReg cr) %{
+  match(Set result (AryEq ary1 ary2));
+  effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL cr);
+  //ins_cost(300);
+
+  format %{ "Array Equals $ary1,$ary2 -> $result    // KILL RAX, RBX" %}
+  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result) );
+  ins_pipe( pipe_slow );
+%}
+
 //----------Control Flow Instructions------------------------------------------
 // Signed compare Instructions
 
@@ -11055,14 +11155,50 @@
   ins_pipe(ialu_cr_reg_imm);
 %}
 
+
+instruct compN_rReg(rFlagsRegU cr, rRegN op1, rRegN op2)
+%{
+  match(Set cr (CmpN op1 op2));
+
+  format %{ "cmpl    $op1, $op2\t# compressed ptr" %}
+  ins_encode %{ __ cmpl(as_Register($op1$$reg), as_Register($op2$$reg)); %}
+  ins_pipe(ialu_cr_reg_reg);
+%}
+
+instruct compN_rReg_mem(rFlagsRegU cr, rRegN src, memory mem)
+%{
+  match(Set cr (CmpN src (LoadN mem)));
+
+  ins_cost(500); // XXX
+  format %{ "cmpl    $src, mem\t# compressed ptr" %}
+  ins_encode %{
+    Address adr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
+    __ cmpl(as_Register($src$$reg), adr);
+  %}
+  ins_pipe(ialu_cr_reg_mem);
+%}
+
 instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{
   match(Set cr (CmpN src zero));
 
-  format %{ "testl   $src, $src" %}
+  format %{ "testl   $src, $src\t# compressed ptr" %}
   ins_encode %{ __ testl($src$$Register, $src$$Register); %}
   ins_pipe(ialu_cr_reg_imm);
 %}
 
+instruct testN_reg_mem(rFlagsReg cr, memory mem, immN0 zero)
+%{
+  match(Set cr (CmpN (LoadN mem) zero));
+
+  ins_cost(500); // XXX
+  format %{ "testl   $mem, 0xffffffff\t# compressed ptr" %}
+  ins_encode %{
+    Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
+    __ cmpl(addr, (int)0xFFFFFFFF);
+  %}
+  ins_pipe(ialu_cr_reg_mem);
+%}
+
 // Yanked all unsigned pointer compare operations.
 // Pointer compares are done with CmpP which is already unsigned.
 
--- a/src/os_cpu/linux_x86/vm/assembler_linux_x86_32.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/os_cpu/linux_x86/vm/assembler_linux_x86_32.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -40,7 +40,7 @@
   movptr(thread, tls);
 }
 
-bool MacroAssembler::needs_explicit_null_check(int offset) {
+bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
   // Linux kernel guarantees that the first page is always unmapped. Don't
   // assume anything more than that.
   bool offset_in_first_page =   0 <= offset  &&  offset < os::vm_page_size();
--- a/src/os_cpu/linux_x86/vm/assembler_linux_x86_64.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/os_cpu/linux_x86/vm/assembler_linux_x86_64.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -66,8 +66,21 @@
    }
 }
 
-// NOTE: since the linux kernel resides at the low end of
-// user address space, no null pointer check is needed.
-bool MacroAssembler::needs_explicit_null_check(int offset) {
-  return offset < 0 || offset >= 0x100000;
+bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
+  // Exception handler checks the nmethod's implicit null checks table
+  // only when this method returns false.
+  if (UseCompressedOops) {
+    // The first page after heap_base is unmapped and
+    // the 'offset' is equal to [heap_base + offset] for
+    // narrow oop implicit null checks.
+    uintptr_t heap_base = (uintptr_t)Universe::heap_base();
+    if ((uintptr_t)offset >= heap_base) {
+      // Normalize offset for the next check.
+      offset = (intptr_t)(pointer_delta((void*)offset, (void*)heap_base, 1));
+    }
+  }
+  // Linux kernel guarantees that the first page is always unmapped. Don't
+  // assume anything more than that.
+  bool offset_in_first_page =   0 <= offset  &&  offset < os::vm_page_size();
+  return !offset_in_first_page;
 }
--- a/src/os_cpu/solaris_x86/vm/assembler_solaris_x86_32.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/os_cpu/solaris_x86/vm/assembler_solaris_x86_32.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -80,7 +80,7 @@
   popl(thread);
 }
 
-bool MacroAssembler::needs_explicit_null_check(int offset) {
+bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
   // Identical to Sparc/Solaris code
   bool offset_in_first_page =   0 <= offset  &&  offset < os::vm_page_size();
   return !offset_in_first_page;
--- a/src/os_cpu/solaris_x86/vm/assembler_solaris_x86_64.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/os_cpu/solaris_x86/vm/assembler_solaris_x86_64.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -86,8 +86,21 @@
   }
 }
 
-bool MacroAssembler::needs_explicit_null_check(int offset) {
+bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
   // Identical to Sparc/Solaris code
+
+  // Exception handler checks the nmethod's implicit null checks table
+  // only when this method returns false.
+  if (UseCompressedOops) {
+    // The first page after heap_base is unmapped and
+    // the 'offset' is equal to [heap_base + offset] for
+    // narrow oop implicit null checks.
+    uintptr_t heap_base = (uintptr_t)Universe::heap_base();
+    if ((uintptr_t)offset >= heap_base) {
+      // Normalize offset for the next check.
+      offset = (intptr_t)(pointer_delta((void*)offset, (void*)heap_base, 1));
+    }
+  }
   bool offset_in_first_page = 0 <= offset && offset < os::vm_page_size();
   return !offset_in_first_page;
 }
--- a/src/os_cpu/windows_x86/vm/assembler_windows_x86_32.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/os_cpu/windows_x86/vm/assembler_windows_x86_32.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -59,6 +59,6 @@
   movl(thread, Address(thread, ThreadLocalStorage::get_thread_ptr_offset()));
 }
 
-bool MacroAssembler::needs_explicit_null_check(int offset) {
+bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
   return offset < 0 || (int)os::vm_page_size() <= offset;
 }
--- a/src/os_cpu/windows_x86/vm/assembler_windows_x86_64.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/os_cpu/windows_x86/vm/assembler_windows_x86_64.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -66,6 +66,18 @@
    }
 }
 
-bool MacroAssembler::needs_explicit_null_check(int offset) {
-  return offset < 0 || (int)os::vm_page_size() <= offset;
+bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
+  // Exception handler checks the nmethod's implicit null checks table
+  // only when this method returns false.
+  if (UseCompressedOops) {
+    // The first page after heap_base is unmapped and
+    // the 'offset' is equal to [heap_base + offset] for
+    // narrow oop implicit null checks.
+    uintptr_t heap_base = (uintptr_t)Universe::heap_base();
+    if ((uintptr_t)offset >= heap_base) {
+      // Normalize offset for the next check.
+      offset = (intptr_t)(pointer_delta((void*)offset, (void*)heap_base, 1));
+    }
+  }
+  return offset < 0 || os::vm_page_size() <= offset;
 }
--- a/src/share/vm/adlc/forms.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/adlc/forms.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -252,6 +252,7 @@
   if( strcmp(opType,"LoadF")==0 )  return Form::idealF;
   if( strcmp(opType,"LoadI")==0 )  return Form::idealI;
   if( strcmp(opType,"LoadKlass")==0 )  return Form::idealP;
+  if( strcmp(opType,"LoadNKlass")==0 ) return Form::idealN;
   if( strcmp(opType,"LoadL")==0 )  return Form::idealL;
   if( strcmp(opType,"LoadL_unaligned")==0 )  return Form::idealL;
   if( strcmp(opType,"LoadPLocked")==0 )  return Form::idealP;
--- a/src/share/vm/adlc/formssel.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/adlc/formssel.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -3313,7 +3313,7 @@
     "Store8B","Store4B","Store8C","Store4C","Store2C",
     "Load4I" ,"Load2I" ,"Load2L" ,"Load2D" ,"Load4F" ,"Load2F" ,"Load16B" ,
     "Load8B" ,"Load4B" ,"Load8C" ,"Load4C" ,"Load2C" ,"Load8S", "Load4S","Load2S",
-    "LoadRange", "LoadKlass", "LoadL_unaligned", "LoadD_unaligned",
+    "LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned",
     "LoadPLocked", "LoadLLocked",
     "StorePConditional", "StoreLConditional",
     "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN",
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -218,6 +218,13 @@
   ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder);
   ciInstanceKlass* actual_recv = callee_holder;
 
+  // some methods are obviously bindable without any type checks so
+  // convert them directly to an invokespecial.
+  if (target->is_loaded() && !target->is_abstract() &&
+      target->can_be_statically_bound() && code == Bytecodes::_invokevirtual) {
+    code = Bytecodes::_invokespecial;
+  }
+
   // compute size of arguments
   int arg_size = target->arg_size();
   if (!target->is_loaded() && code == Bytecodes::_invokestatic) {
--- a/src/share/vm/ci/ciInstanceKlass.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/ci/ciInstanceKlass.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -392,12 +392,12 @@
   assert(!is_java_lang_Object(), "bootstrap OK");
 
   // Size in bytes of my fields, including inherited fields.
-  int fsize = nonstatic_field_size() * wordSize;
+  int fsize = nonstatic_field_size() * heapOopSize;
 
   ciInstanceKlass* super = this->super();
   GrowableArray<ciField*>* super_fields = NULL;
   if (super != NULL && super->has_nonstatic_fields()) {
-    int super_fsize  = super->nonstatic_field_size() * wordSize;
+    int super_fsize  = super->nonstatic_field_size() * heapOopSize;
     int super_flen   = super->nof_nonstatic_fields();
     super_fields = super->_nonstatic_fields;
     assert(super_flen == 0 || super_fields != NULL, "first get nof_fields");
@@ -438,7 +438,7 @@
     // This is a minor inefficiency classFileParser.cpp.
     last_offset = offset + size;
   }
-  assert(last_offset <= (int)sizeof(oopDesc) + fsize, "no overflow");
+  assert(last_offset <= (int)instanceOopDesc::base_offset_in_bytes() + fsize, "no overflow");
 #endif
 
   _nonstatic_fields = fields;
--- a/src/share/vm/ci/ciMethod.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/ci/ciMethod.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -878,7 +878,7 @@
         (TieredCompilation && code->compiler() != NULL && code->compiler()->is_c1())) {
       return 0;
     }
-    return code->code_size();
+    return code->code_end() - code->verified_entry_point();
   )
 }
 
--- a/src/share/vm/classfile/classFileParser.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -44,6 +44,7 @@
 
 // Used for backward compatibility reasons:
 // - to check for javac bug fixes that happened after 1.5
+// - also used as the max version when running in jdk6
 #define JAVA_6_VERSION                    50
 
 
@@ -2664,8 +2665,8 @@
                                   fac.static_byte_count ), wordSize );
     static_field_size           = (next_static_type_offset -
                                   next_static_oop_offset) / wordSize;
-    first_nonstatic_field_offset = (instanceOopDesc::header_size() +
-                                    nonstatic_field_size) * wordSize;
+    first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() +
+                                   nonstatic_field_size * heapOopSize;
     next_nonstatic_field_offset = first_nonstatic_field_offset;
 
     // Add fake fields for java.lang.Class instances (also see below)
@@ -2734,9 +2735,9 @@
       next_nonstatic_byte_offset  = next_nonstatic_short_offset +
                                     (nonstatic_short_count * BytesPerShort);
       next_nonstatic_type_offset  = align_size_up((next_nonstatic_byte_offset +
-                                    nonstatic_byte_count ), wordSize );
+                                    nonstatic_byte_count ), heapOopSize );
       orig_nonstatic_field_size   = nonstatic_field_size +
-        ((next_nonstatic_type_offset - first_nonstatic_field_offset)/wordSize);
+      ((next_nonstatic_type_offset - first_nonstatic_field_offset)/heapOopSize);
     }
 #endif
     bool compact_fields   = CompactFields;
@@ -2791,18 +2792,8 @@
     int nonstatic_short_space_offset;
     int nonstatic_byte_space_offset;
 
-    bool compact_into_header = (UseCompressedOops &&
-                                allocation_style == 1 && compact_fields &&
-                                !super_has_nonstatic_fields);
-
-    if( compact_into_header || nonstatic_double_count > 0 ) {
-      int offset;
-      // Pack something in with the header if no super klass has done so.
-      if (compact_into_header) {
-        offset = oopDesc::klass_gap_offset_in_bytes();
-      } else {
-        offset = next_nonstatic_double_offset;
-      }
+    if( nonstatic_double_count > 0 ) {
+      int offset = next_nonstatic_double_offset;
       next_nonstatic_double_offset = align_size_up(offset, BytesPerLong);
       if( compact_fields && offset != next_nonstatic_double_offset ) {
         // Allocate available fields into the gap before double field.
@@ -2830,8 +2821,7 @@
         }
         // Allocate oop field in the gap if there are no other fields for that.
         nonstatic_oop_space_offset = offset;
-        if(!compact_into_header && length >= heapOopSize &&
-            nonstatic_oop_count > 0 &&
+        if( length >= heapOopSize && nonstatic_oop_count > 0 &&
             allocation_style != 0 ) { // when oop fields not first
           nonstatic_oop_count      -= 1;
           nonstatic_oop_space_count = 1; // Only one will fit
@@ -2854,14 +2844,13 @@
     } else { // allocation_style == 1
       next_nonstatic_oop_offset = next_nonstatic_byte_offset + nonstatic_byte_count;
       if( nonstatic_oop_count > 0 ) {
-        notaligned_offset = next_nonstatic_oop_offset;
         next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize);
       }
       notaligned_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
     }
-    next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
+    next_nonstatic_type_offset = align_size_up(notaligned_offset, heapOopSize );
     nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset
-                                      - first_nonstatic_field_offset)/wordSize);
+                                   - first_nonstatic_field_offset)/heapOopSize);
 
     // Iterate over fields again and compute correct offsets.
     // The field allocation type was temporarily stored in the offset slot.
@@ -2962,9 +2951,10 @@
     // Size of instances
     int instance_size;
 
+    next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize );
     instance_size = align_object_size(next_nonstatic_type_offset / wordSize);
 
-    assert(instance_size == align_object_size(instanceOopDesc::header_size() + nonstatic_field_size), "consistent layout helper value");
+    assert(instance_size == align_object_size(align_size_up((instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size*heapOopSize), wordSize) / wordSize), "consistent layout helper value");
 
     // Size of non-static oop map blocks (in words) allocated at end of klass
     int nonstatic_oop_map_size = compute_oop_map_size(super_klass, nonstatic_oop_map_count, first_nonstatic_oop_offset);
@@ -3122,13 +3112,15 @@
 #ifndef PRODUCT
     if( PrintCompactFieldsSavings ) {
       if( nonstatic_field_size < orig_nonstatic_field_size ) {
-        tty->print("[Saved %d of %3d words in %s]\n",
-                 orig_nonstatic_field_size - nonstatic_field_size,
-                 orig_nonstatic_field_size, this_klass->external_name());
+        tty->print("[Saved %d of %d bytes in %s]\n",
+                 (orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
+                 orig_nonstatic_field_size*heapOopSize,
+                 this_klass->external_name());
       } else if( nonstatic_field_size > orig_nonstatic_field_size ) {
-        tty->print("[Wasted %d over %3d words in %s]\n",
-                 nonstatic_field_size - orig_nonstatic_field_size,
-                 orig_nonstatic_field_size, this_klass->external_name());
+        tty->print("[Wasted %d over %d bytes in %s]\n",
+                 (nonstatic_field_size - orig_nonstatic_field_size)*heapOopSize,
+                 orig_nonstatic_field_size*heapOopSize,
+                 this_klass->external_name());
       }
     }
 #endif
@@ -3516,9 +3508,11 @@
 }
 
 bool ClassFileParser::is_supported_version(u2 major, u2 minor) {
+  u2 max_version = JDK_Version::is_gte_jdk17x_version() ?
+    JAVA_MAX_SUPPORTED_VERSION : JAVA_6_VERSION;
   return (major >= JAVA_MIN_SUPPORTED_VERSION) &&
-         (major <= JAVA_MAX_SUPPORTED_VERSION) &&
-         ((major != JAVA_MAX_SUPPORTED_VERSION) ||
+         (major <= max_version) &&
+         ((major != max_version) ||
           (minor <= JAVA_MAX_SUPPORTED_MINOR_VERSION));
 }
 
--- a/src/share/vm/classfile/javaClasses.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/classfile/javaClasses.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1872,7 +1872,7 @@
       box->float_field_put(value_offset, value->f);
       break;
     case T_DOUBLE:
-      box->double_field_put(value_offset, value->d);
+      box->double_field_put(long_value_offset, value->d);
       break;
     case T_BYTE:
       box->byte_field_put(value_offset, value->b);
@@ -1884,7 +1884,7 @@
       box->int_field_put(value_offset, value->i);
       break;
     case T_LONG:
-      box->long_field_put(value_offset, value->j);
+      box->long_field_put(long_value_offset, value->j);
       break;
     default:
       return NULL;
@@ -1915,7 +1915,7 @@
     value->f = box->float_field(value_offset);
     break;
   case T_DOUBLE:
-    value->d = box->double_field(value_offset);
+    value->d = box->double_field(long_value_offset);
     break;
   case T_BYTE:
     value->b = box->byte_field(value_offset);
@@ -1927,7 +1927,7 @@
     value->i = box->int_field(value_offset);
     break;
   case T_LONG:
-    value->j = box->long_field(value_offset);
+    value->j = box->long_field(long_value_offset);
     break;
   default:
     return T_ILLEGAL;
@@ -1949,7 +1949,7 @@
     box->float_field_put(value_offset, value->f);
     break;
   case T_DOUBLE:
-    box->double_field_put(value_offset, value->d);
+    box->double_field_put(long_value_offset, value->d);
     break;
   case T_BYTE:
     box->byte_field_put(value_offset, value->b);
@@ -1961,7 +1961,7 @@
     box->int_field_put(value_offset, value->i);
     break;
   case T_LONG:
-    box->long_field_put(value_offset, value->j);
+    box->long_field_put(long_value_offset, value->j);
     break;
   default:
     return T_ILLEGAL;
@@ -2163,6 +2163,7 @@
 int java_lang_reflect_Field::signature_offset;
 int java_lang_reflect_Field::annotations_offset;
 int java_lang_boxing_object::value_offset;
+int java_lang_boxing_object::long_value_offset;
 int java_lang_ref_Reference::referent_offset;
 int java_lang_ref_Reference::queue_offset;
 int java_lang_ref_Reference::next_offset;
@@ -2282,10 +2283,7 @@
 // are not available to determine the offset_of_static_fields.
 void JavaClasses::compute_hard_coded_offsets() {
   const int x = heapOopSize;
-  // Objects don't get allocated in the gap in the header with compressed oops
-  // for these special classes because hard coded offsets can't be conditional
-  // so base_offset_in_bytes() is wrong here, allocate after the header.
-  const int header = sizeof(instanceOopDesc);
+  const int header = instanceOopDesc::base_offset_in_bytes();
 
   // Do the String Class
   java_lang_String::value_offset  = java_lang_String::hc_value_offset  * x + header;
@@ -2308,7 +2306,8 @@
   java_lang_Throwable::stackTrace_offset = java_lang_Throwable::hc_stackTrace_offset * x + header;
 
   // java_lang_boxing_object
-  java_lang_boxing_object::value_offset = java_lang_boxing_object::hc_value_offset * x + header;
+  java_lang_boxing_object::value_offset = java_lang_boxing_object::hc_value_offset + header;
+  java_lang_boxing_object::long_value_offset = align_size_up((java_lang_boxing_object::hc_value_offset + header), BytesPerLong);
 
   // java_lang_ref_Reference:
   java_lang_ref_Reference::referent_offset = java_lang_ref_Reference::hc_referent_offset * x + header;
@@ -2322,7 +2321,7 @@
   java_lang_ref_Reference::number_of_fake_oop_fields = 1;
 
   // java_lang_ref_SoftReference Class
-  java_lang_ref_SoftReference::timestamp_offset = java_lang_ref_SoftReference::hc_timestamp_offset * x + header;
+  java_lang_ref_SoftReference::timestamp_offset = align_size_up((java_lang_ref_SoftReference::hc_timestamp_offset * x + header), BytesPerLong);
   // Don't multiply static fields because they are always in wordSize units
   java_lang_ref_SoftReference::static_clock_offset = java_lang_ref_SoftReference::hc_static_clock_offset * x;
 
@@ -2469,6 +2468,9 @@
 #define CHECK_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
   valid &= check_offset(klass_name, cpp_klass_name :: field_name ## _offset, #field_name, field_sig)
 
+#define CHECK_LONG_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
+  valid &= check_offset(klass_name, cpp_klass_name :: long_ ## field_name ## _offset, #field_name, field_sig)
+
 #define CHECK_STATIC_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
   valid &= check_static_offset(klass_name, cpp_klass_name :: static_ ## field_name ## _offset, #field_name, field_sig)
 
@@ -2501,11 +2503,11 @@
   CHECK_OFFSET("java/lang/Boolean",   java_lang_boxing_object, value, "Z");
   CHECK_OFFSET("java/lang/Character", java_lang_boxing_object, value, "C");
   CHECK_OFFSET("java/lang/Float",     java_lang_boxing_object, value, "F");
-  CHECK_OFFSET("java/lang/Double",    java_lang_boxing_object, value, "D");
+  CHECK_LONG_OFFSET("java/lang/Double", java_lang_boxing_object, value, "D");
   CHECK_OFFSET("java/lang/Byte",      java_lang_boxing_object, value, "B");
   CHECK_OFFSET("java/lang/Short",     java_lang_boxing_object, value, "S");
   CHECK_OFFSET("java/lang/Integer",   java_lang_boxing_object, value, "I");
-  CHECK_OFFSET("java/lang/Long",      java_lang_boxing_object, value, "J");
+  CHECK_LONG_OFFSET("java/lang/Long", java_lang_boxing_object, value, "J");
 
   // java.lang.ClassLoader
 
--- a/src/share/vm/classfile/javaClasses.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/classfile/javaClasses.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -653,6 +653,7 @@
    hc_value_offset = 0
   };
   static int value_offset;
+  static int long_value_offset;
 
   static oop initialize_and_allocate(BasicType type, TRAPS);
  public:
@@ -665,7 +666,10 @@
   static bool is_instance(oop box)                 { return basic_type(box) != T_ILLEGAL; }
   static bool is_instance(oop box, BasicType type) { return basic_type(box) == type; }
 
-  static int value_offset_in_bytes() { return value_offset; }
+  static int value_offset_in_bytes(BasicType type) {
+    return ( type == T_LONG || type == T_DOUBLE ) ? long_value_offset :
+                                                    value_offset;
+  }
 
   // Debugging
   friend class JavaClasses;
@@ -747,7 +751,7 @@
  public:
   enum {
    // The timestamp is a long field and may need to be adjusted for alignment.
-   hc_timestamp_offset    = align_object_offset_(hc_discovered_offset + 1)
+   hc_timestamp_offset  = hc_discovered_offset + 1
   };
   enum {
    hc_static_clock_offset = 0
--- a/src/share/vm/classfile/vmSymbols.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/classfile/vmSymbols.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -283,6 +283,7 @@
   template(cache_field_name,                          "cache")                                    \
   template(value_name,                                "value")                                    \
   template(frontCacheEnabled_name,                    "frontCacheEnabled")                        \
+  template(stringCacheEnabled_name,                   "stringCacheEnabled")                       \
                                                                                                   \
   /* non-intrinsic name/signature pairs: */                                                       \
   template(register_method_name,                      "register")                                 \
@@ -564,6 +565,10 @@
    do_name(     copyOfRange_name,                                "copyOfRange")                                         \
    do_signature(copyOfRange_signature,        "([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object;")            \
                                                                                                                         \
+  do_intrinsic(_equalsC,                  java_util_Arrays,       equals_name,    equalsC_signature,             F_S)   \
+   do_name(     equals_name,                                     "equals")                                              \
+   do_signature(equalsC_signature,                               "([C[C)Z")                                             \
+                                                                                                                        \
   do_intrinsic(_invoke,                   java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \
   /*   (symbols invoke_name and invoke_signature defined above) */                                                      \
                                                                                                                         \
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -130,6 +130,7 @@
 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;
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -805,28 +805,30 @@
   // This must be volatile, or else there is a danger that the compiler
   // will compile the code below into a sometimes-infinite loop, by keeping
   // the value read the first time in a register.
-  oop o = (oop)p;
-  volatile oop* second_word_addr = o->klass_addr();
   while (true) {
-    klassOop k = (klassOop)(*second_word_addr);
     // We must do this until we get a consistent view of the object.
-    if (FreeChunk::secondWordIndicatesFreeChunk((intptr_t)k)) {
-      FreeChunk* fc = (FreeChunk*)p;
-      volatile size_t* sz_addr = (volatile size_t*)(fc->size_addr());
-      size_t res = (*sz_addr);
-      klassOop k2 = (klassOop)(*second_word_addr);  // Read to confirm.
-      if (k == k2) {
+    if (FreeChunk::indicatesFreeChunk(p)) {
+      volatile FreeChunk* fc = (volatile FreeChunk*)p;
+      size_t res = fc->size();
+      // If the object is still a free chunk, return the size, else it
+      // has been allocated so try again.
+      if (FreeChunk::indicatesFreeChunk(p)) {
         assert(res != 0, "Block size should not be 0");
         return res;
       }
-    } else if (k != NULL) {
-      assert(k->is_oop(true /* ignore mark word */), "Should really be klass oop.");
-      assert(o->is_parsable(), "Should be parsable");
-      assert(o->is_oop(true /* ignore mark word */), "Should be an oop.");
-      size_t res = o->size_given_klass(k->klass_part());
-      res = adjustObjectSize(res);
-      assert(res != 0, "Block size should not be 0");
-      return res;
+    } else {
+      // must read from what 'p' points to in each loop.
+      klassOop k = ((volatile oopDesc*)p)->klass_or_null();
+      if (k != NULL) {
+        assert(k->is_oop(true /* ignore mark word */), "Should really be klass oop.");
+        oop o = (oop)p;
+        assert(o->is_parsable(), "Should be parsable");
+        assert(o->is_oop(true /* ignore mark word */), "Should be an oop.");
+        size_t res = o->size_given_klass(k->klass_part());
+        res = adjustObjectSize(res);
+        assert(res != 0, "Block size should not be 0");
+        return res;
+      }
     }
   }
 }
@@ -845,31 +847,31 @@
   // This must be volatile, or else there is a danger that the compiler
   // will compile the code below into a sometimes-infinite loop, by keeping
   // the value read the first time in a register.
-  oop o = (oop)p;
-  volatile oop* second_word_addr = o->klass_addr();
   DEBUG_ONLY(uint loops = 0;)
   while (true) {
-    klassOop k = (klassOop)(*second_word_addr);
     // We must do this until we get a consistent view of the object.
-    if (FreeChunk::secondWordIndicatesFreeChunk((intptr_t)k)) {
-      FreeChunk* fc = (FreeChunk*)p;
-      volatile size_t* sz_addr = (volatile size_t*)(fc->size_addr());
-      size_t res = (*sz_addr);
-      klassOop k2 = (klassOop)(*second_word_addr);  // Read to confirm.
-      if (k == k2) {
+    if (FreeChunk::indicatesFreeChunk(p)) {
+      volatile FreeChunk* fc = (volatile FreeChunk*)p;
+      size_t res = fc->size();
+      if (FreeChunk::indicatesFreeChunk(p)) {
         assert(res != 0, "Block size should not be 0");
         assert(loops == 0, "Should be 0");
         return res;
       }
-    } else if (k != NULL && o->is_parsable()) {
-      assert(k->is_oop(), "Should really be klass oop.");
-      assert(o->is_oop(), "Should be an oop");
-      size_t res = o->size_given_klass(k->klass_part());
-      res = adjustObjectSize(res);
-      assert(res != 0, "Block size should not be 0");
-      return res;
     } else {
-      return c->block_size_if_printezis_bits(p);
+      // must read from what 'p' points to in each loop.
+      klassOop k = ((volatile oopDesc*)p)->klass_or_null();
+      if (k != NULL && ((oopDesc*)p)->is_parsable()) {
+        assert(k->is_oop(), "Should really be klass oop.");
+        oop o = (oop)p;
+        assert(o->is_oop(), "Should be an oop");
+        size_t res = o->size_given_klass(k->klass_part());
+        res = adjustObjectSize(res);
+        assert(res != 0, "Block size should not be 0");
+        return res;
+      } else {
+        return c->block_size_if_printezis_bits(p);
+      }
     }
     assert(loops == 0, "Can loop at most once");
     DEBUG_ONLY(loops++;)
@@ -907,9 +909,8 @@
   // and those objects (if garbage) may have been modified to hold
   // live range information.
   // assert(ParallelGCThreads > 0 || _bt.block_start(p) == p, "Should be a block boundary");
-  klassOop k = oop(p)->klass();
-  intptr_t ki = (intptr_t)k;
-  if (FreeChunk::secondWordIndicatesFreeChunk(ki)) return false;
+  if (FreeChunk::indicatesFreeChunk(p)) return false;
+  klassOop k = oop(p)->klass_or_null();
   if (k != NULL) {
     // Ignore mark word because it may have been used to
     // chain together promoted objects (the last one
@@ -1027,7 +1028,7 @@
     FreeChunk* fc = (FreeChunk*)res;
     fc->markNotFree();
     assert(!fc->isFree(), "shouldn't be marked free");
-    assert(oop(fc)->klass() == NULL, "should look uninitialized");
+    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.
     _bt.verify_single_block(res, size);
@@ -2593,7 +2594,7 @@
   }
   res->markNotFree();
   assert(!res->isFree(), "shouldn't be marked free");
-  assert(oop(res)->klass() == NULL, "should look uninitialized");
+  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));
   return (HeapWord*)res;
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -190,7 +190,8 @@
   // depends on this property.
   debug_only(
     FreeChunk* junk = NULL;
-    assert(junk->prev_addr() == (void*)(oop(junk)->klass_addr()),
+    assert(UseCompressedOops ||
+           junk->prev_addr() == (void*)(oop(junk)->klass_addr()),
            "Offset of FreeChunk::_prev within FreeChunk must match"
            "  that of OopDesc::_klass within OopDesc");
   )
@@ -1039,7 +1040,7 @@
                                       // mark end of object
   }
   // check that oop looks uninitialized
-  assert(oop(start)->klass() == NULL, "_klass should be NULL");
+  assert(oop(start)->klass_or_null() == NULL, "_klass should be NULL");
 }
 
 void CMSCollector::promoted(bool par, HeapWord* start,
@@ -1309,17 +1310,25 @@
      }
   }
   oop obj = oop(obj_ptr);
-  assert(obj->klass() == NULL, "Object should be uninitialized here.");
+  assert(obj->klass_or_null() == NULL, "Object should be uninitialized here.");
   // Otherwise, copy the object.  Here we must be careful to insert the
   // klass pointer last, since this marks the block as an allocated object.
+  // Except with compressed oops it's the mark word.
   HeapWord* old_ptr = (HeapWord*)old;
   if (word_sz > (size_t)oopDesc::header_size()) {
     Copy::aligned_disjoint_words(old_ptr + oopDesc::header_size(),
                                  obj_ptr + oopDesc::header_size(),
                                  word_sz - oopDesc::header_size());
   }
+
+  if (UseCompressedOops) {
+    // Copy gap missed by (aligned) header size calculation above
+    obj->set_klass_gap(old->klass_gap());
+  }
+
   // Restore the mark word copied above.
   obj->set_mark(m);
+
   // Now we can track the promoted object, if necessary.  We take care
   // To delay the transition from uninitialized to full object
   // (i.e., insertion of klass pointer) until after, so that it
@@ -1327,7 +1336,8 @@
   if (promoInfo->tracking()) {
     promoInfo->track((PromotedObject*)obj, old->klass());
   }
-  // Finally, install the klass pointer.
+
+  // Finally, install the klass pointer (this should be volatile).
   obj->set_klass(old->klass());
 
   assert(old->is_oop(), "Will dereference klass ptr below");
@@ -6165,7 +6175,7 @@
 HeapWord* CMSCollector::next_card_start_after_block(HeapWord* addr) const {
   size_t sz = 0;
   oop p = (oop)addr;
-  if (p->klass() != NULL && p->is_parsable()) {
+  if (p->klass_or_null() != NULL && p->is_parsable()) {
     sz = CompactibleFreeListSpace::adjustObjectSize(p->size());
   } else {
     sz = block_size_using_printezis_bits(addr);
@@ -6602,7 +6612,7 @@
   }
   if (_bitMap->isMarked(addr)) {
     // it's marked; is it potentially uninitialized?
-    if (p->klass() != NULL) {
+    if (p->klass_or_null() != NULL) {
       if (CMSPermGenPrecleaningEnabled && !p->is_parsable()) {
         // Signal precleaning to redirty the card since
         // the klass pointer is already installed.
@@ -6615,11 +6625,8 @@
         if (p->is_objArray()) {
           // objArrays are precisely marked; restrict scanning
           // to dirty cards only.
-          size = p->oop_iterate(_scanningClosure, mr);
-          assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
-                 "adjustObjectSize should be the identity for array sizes, "
-                 "which are necessarily larger than minimum object size of "
-                 "two heap words");
+          size = CompactibleFreeListSpace::adjustObjectSize(
+                   p->oop_iterate(_scanningClosure, mr));
         } else {
           // A non-array may have been imprecisely marked; we need
           // to scan object in its entirety.
@@ -6653,7 +6660,7 @@
     }
   } else {
     // Either a not yet marked object or an uninitialized object
-    if (p->klass() == NULL || !p->is_parsable()) {
+    if (p->klass_or_null() == NULL || !p->is_parsable()) {
       // An uninitialized object, skip to the next card, since
       // we may not be able to read its P-bits yet.
       assert(size == 0, "Initial value");
@@ -6710,7 +6717,7 @@
   HeapWord* addr = (HeapWord*)p;
   DEBUG_ONLY(_collector->verify_work_stacks_empty();)
   assert(!_span.contains(addr), "we are scanning the survivor spaces");
-  assert(p->klass() != NULL, "object should be initializd");
+  assert(p->klass_or_null() != NULL, "object should be initializd");
   assert(p->is_parsable(), "must be parsable.");
   // an initialized object; ignore mark word in verification below
   // since we are running concurrent with mutators
@@ -6868,7 +6875,7 @@
     assert(_skipBits == 0, "tautology");
     _skipBits = 2;  // skip next two marked bits ("Printezis-marks")
     oop p = oop(addr);
-    if (p->klass() == NULL || !p->is_parsable()) {
+    if (p->klass_or_null() == NULL || !p->is_parsable()) {
       DEBUG_ONLY(if (!_verifying) {)
         // We re-dirty the cards on which this object lies and increase
         // the _threshold so that we'll come back to scan this object
@@ -6890,7 +6897,7 @@
           if (_threshold < end_card_addr) {
             _threshold = end_card_addr;
           }
-          if (p->klass() != NULL) {
+          if (p->klass_or_null() != NULL) {
             // Redirty the range of cards...
             _mut->mark_range(redirty_range);
           } // ...else the setting of klass will dirty the card anyway.
@@ -7048,7 +7055,7 @@
     assert(_skip_bits == 0, "tautology");
     _skip_bits = 2;  // skip next two marked bits ("Printezis-marks")
     oop p = oop(addr);
-    if (p->klass() == NULL || !p->is_parsable()) {
+    if (p->klass_or_null() == NULL || !p->is_parsable()) {
       // in the case of Clean-on-Enter optimization, redirty card
       // and avoid clearing card by increasing  the threshold.
       return;
@@ -8023,7 +8030,7 @@
            "alignment problem");
 
     #ifdef DEBUG
-      if (oop(addr)->klass() != NULL &&
+      if (oop(addr)->klass_or_null() != NULL &&
           (   !_collector->should_unload_classes()
            || oop(addr)->is_parsable())) {
         // Ignore mark word because we are running concurrent with mutators
@@ -8036,7 +8043,7 @@
 
   } else {
     // This should be an initialized object that's alive.
-    assert(oop(addr)->klass() != NULL &&
+    assert(oop(addr)->klass_or_null() != NULL &&
            (!_collector->should_unload_classes()
             || oop(addr)->is_parsable()),
            "Should be an initialized object");
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeBlockDictionary.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -22,88 +22,6 @@
  *
  */
 
-//
-// Free block maintenance for Concurrent Mark Sweep Generation
-//
-// The main data structure for free blocks are
-// . an indexed array of small free blocks, and
-// . a dictionary of large free blocks
-//
-
-// No virtuals in FreeChunk (don't want any vtables).
-
-// A FreeChunk is merely a chunk that can be in a doubly linked list
-// and has a size field. NOTE: FreeChunks are distinguished from allocated
-// objects in two ways (by the sweeper). The second word (prev) has the
-// LSB set to indicate a free chunk; allocated objects' klass() pointers
-// don't have their LSB set. The corresponding bit in the CMSBitMap is
-// set when the chunk is allocated. There are also blocks that "look free"
-// but are not part of the free list and should not be coalesced into larger
-// free blocks. These free blocks have their two LSB's set.
-
-class FreeChunk VALUE_OBJ_CLASS_SPEC {
-  friend class VMStructs;
-  FreeChunk* _next;
-  FreeChunk* _prev;
-  size_t     _size;
-
- public:
-  NOT_PRODUCT(static const size_t header_size();)
-  // Returns "true" if the "wrd", which is required to be the second word
-  // of a block, indicates that the block represents a free chunk.
-  static bool secondWordIndicatesFreeChunk(intptr_t wrd) {
-    return (wrd & 0x1) == 0x1;
-  }
-  bool isFree()       const {
-    return secondWordIndicatesFreeChunk((intptr_t)_prev);
-  }
-  bool cantCoalesce() const { return (((intptr_t)_prev) & 0x3) == 0x3; }
-  FreeChunk* next()   const { return _next; }
-  FreeChunk* prev()   const { return (FreeChunk*)(((intptr_t)_prev) & ~(0x3)); }
-  debug_only(void* prev_addr() const { return (void*)&_prev; })
-
-  void linkAfter(FreeChunk* ptr) {
-    linkNext(ptr);
-    if (ptr != NULL) ptr->linkPrev(this);
-  }
-  void linkAfterNonNull(FreeChunk* ptr) {
-    assert(ptr != NULL, "precondition violation");
-    linkNext(ptr);
-    ptr->linkPrev(this);
-  }
-  void linkNext(FreeChunk* ptr) { _next = ptr; }
-  void linkPrev(FreeChunk* ptr) { _prev = (FreeChunk*)((intptr_t)ptr | 0x1); }
-  void clearPrev()              { _prev = NULL; }
-  void clearNext()              { _next = NULL; }
-  void dontCoalesce()      {
-    // the block should be free
-    assert(isFree(), "Should look like a free block");
-    _prev = (FreeChunk*)(((intptr_t)_prev) | 0x2);
-  }
-  void markFree()    { _prev = (FreeChunk*)((intptr_t)_prev | 0x1);    }
-  void markNotFree() { _prev = NULL; }
-
-  size_t size()           const { return _size; }
-  void setSize(size_t size)     { _size = size; }
-
-  // For volatile reads:
-  size_t* size_addr()           { return &_size; }
-
-  // Return the address past the end of this chunk
-  HeapWord* end() const { return ((HeapWord*) this) + _size; }
-
-  // debugging
-  void verify()             const PRODUCT_RETURN;
-  void verifyList()         const PRODUCT_RETURN;
-  void mangleAllocated(size_t size) PRODUCT_RETURN;
-  void mangleFreed(size_t size)     PRODUCT_RETURN;
-};
-
-// Alignment helpers etc.
-#define numQuanta(x,y) ((x+y-1)/y)
-enum AlignmentConstants {
-  MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment
-};
 
 // A FreeBlockDictionary is an abstract superclass that will allow
 // a number of alternative implementations in the future.
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -47,15 +47,15 @@
   Copy::fill_to_words(addr + hdr, size - hdr, baadbabeHeapWord);
 }
 
-void FreeChunk::mangleFreed(size_t size) {
+void FreeChunk::mangleFreed(size_t sz) {
   assert(baadbabeHeapWord != deadbeefHeapWord, "Need distinct patterns");
   // mangle all but the header of a just-freed block of storage
   // just prior to passing it to the storage dictionary
-  assert(size >= MinChunkSize, "smallest size of object");
-  assert(size == _size, "just checking");
+  assert(sz >= MinChunkSize, "smallest size of object");
+  assert(sz == size(), "just checking");
   HeapWord* addr = (HeapWord*)this;
   size_t hdr = header_size();
-  Copy::fill_to_words(addr + hdr, size - hdr, deadbeefHeapWord);
+  Copy::fill_to_words(addr + hdr, sz - hdr, deadbeefHeapWord);
 }
 
 void FreeChunk::verifyList() const {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2001-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+//
+// Free block maintenance for Concurrent Mark Sweep Generation
+//
+// The main data structure for free blocks are
+// . an indexed array of small free blocks, and
+// . a dictionary of large free blocks
+//
+
+// No virtuals in FreeChunk (don't want any vtables).
+
+// A FreeChunk is merely a chunk that can be in a doubly linked list
+// and has a size field. NOTE: FreeChunks are distinguished from allocated
+// objects in two ways (by the sweeper), depending on whether the VM is 32 or
+// 64 bits.
+// In 32 bits or 64 bits without CompressedOops, the second word (prev) has the
+// LSB set to indicate a free chunk; allocated objects' klass() pointers
+// don't have their LSB set. The corresponding bit in the CMSBitMap is
+// set when the chunk is allocated. There are also blocks that "look free"
+// but are not part of the free list and should not be coalesced into larger
+// free blocks. These free blocks have their two LSB's set.
+
+class FreeChunk VALUE_OBJ_CLASS_SPEC {
+  friend class VMStructs;
+  // For 64 bit compressed oops, the markOop encodes both the size and the
+  // indication that this is a FreeChunk and not an object.
+  volatile size_t   _size;
+  FreeChunk* _prev;
+  FreeChunk* _next;
+
+  markOop mark()     const volatile { return (markOop)_size; }
+  void set_mark(markOop m)          { _size = (size_t)m; }
+
+ public:
+  NOT_PRODUCT(static const size_t header_size();)
+
+  // Returns "true" if the address indicates that the block represents
+  // a free chunk.
+  static bool indicatesFreeChunk(const HeapWord* addr) {
+    // Force volatile read from addr because value might change between
+    // 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();
+  }
+
+  bool isFree() 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");
+    return (((intptr_t)_prev) & 0x2) == 0x2;
+  }
+  void dontCoalesce() {
+    // the block should be free
+    assert(isFree(), "Should look like a free block");
+    _prev = (FreeChunk*)(((intptr_t)_prev) | 0x2);
+  }
+  FreeChunk* prev() const {
+    return (FreeChunk*)(((intptr_t)_prev) & ~(0x3));
+  }
+
+  debug_only(void* prev_addr() const { return (void*)&_prev; })
+
+  size_t size() const volatile {
+    LP64_ONLY(if (UseCompressedOops) return mark()->get_size(); else )
+    return _size;
+  }
+  void setSize(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 linkAfterNonNull(FreeChunk* ptr) {
+    assert(ptr != NULL, "precondition violation");
+    linkNext(ptr);
+    ptr->linkPrev(this);
+  }
+  void linkNext(FreeChunk* ptr) { _next = ptr; }
+  void linkPrev(FreeChunk* ptr) {
+     LP64_ONLY(if (UseCompressedOops) _prev = ptr; else)
+     _prev = (FreeChunk*)((intptr_t)ptr | 0x1);
+  }
+  void clearPrev()              { _prev = NULL; }
+  void clearNext()              { _next = NULL; }
+  void markNotFree() {
+   LP64_ONLY(if (UseCompressedOops) set_mark(markOopDesc::prototype());)
+   // Also set _prev to null
+   _prev = NULL;
+  }
+
+  // Return the address past the end of this chunk
+  HeapWord* end() const { return ((HeapWord*) this) + size(); }
+
+  // debugging
+  void verify()             const PRODUCT_RETURN;
+  void verifyList()         const PRODUCT_RETURN;
+  void mangleAllocated(size_t size) PRODUCT_RETURN;
+  void mangleFreed(size_t size)     PRODUCT_RETURN;
+};
+
+// Alignment helpers etc.
+#define numQuanta(x,y) ((x+y-1)/y)
+enum AlignmentConstants {
+  MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment
+};
+
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeList.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -38,6 +38,7 @@
 
 class FreeList VALUE_OBJ_CLASS_SPEC {
   friend class CompactibleFreeListSpace;
+  friend class VMStructs;
   friend class printTreeCensusClosure;
   FreeChunk*    _head;          // List of free chunks
   FreeChunk*    _tail;          // Tail of list of free chunks
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -23,6 +23,7 @@
  */
 
 #define VM_STRUCTS_CMS(nonstatic_field, \
+                   volatile_nonstatic_field, \
                    static_field) \
   nonstatic_field(CompactibleFreeListSpace,    _collector,                                    CMSCollector*)                         \
   nonstatic_field(CompactibleFreeListSpace,    _bt,                                           BlockOffsetArrayNonContigSpace)        \
@@ -36,9 +37,17 @@
   nonstatic_field(CMSCollector,                _markBitMap,                                   CMSBitMap)                             \
   nonstatic_field(ConcurrentMarkSweepGeneration, _cmsSpace,                                   CompactibleFreeListSpace*)             \
      static_field(ConcurrentMarkSweepThread,   _collector,                                    CMSCollector*)                         \
+  volatile_nonstatic_field(FreeChunk,          _size,                                         size_t)                                \
   nonstatic_field(FreeChunk,                   _next,                                         FreeChunk*)                            \
   nonstatic_field(FreeChunk,                   _prev,                                         FreeChunk*)                            \
-  nonstatic_field(FreeChunk,                   _size,                                         size_t)
+  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(CompactibleFreeListSpace,    _smallLinearAllocBlock,                        LinearAllocBlock)
+
 
 #define VM_TYPES_CMS(declare_type,                                        \
                      declare_toplevel_type)                               \
@@ -57,7 +66,14 @@
   declare_toplevel_type(SurrogateLockerThread*)                           \
   declare_toplevel_type(CompactibleFreeListSpace*)                        \
   declare_toplevel_type(CMSCollector*)                                    \
-  declare_toplevel_type(FreeChunk*)
+  declare_toplevel_type(FreeChunk*)                                       \
+  declare_toplevel_type(BinaryTreeDictionary*)                            \
+  declare_toplevel_type(FreeBlockDictionary*)                             \
+  declare_toplevel_type(FreeList*)                                        \
+  declare_toplevel_type(FreeList)                                         \
+  declare_toplevel_type(LinearAllocBlock)                                 \
+  declare_toplevel_type(FreeBlockDictionary)                              \
+            declare_type(BinaryTreeDictionary,        FreeBlockDictionary)
 
 #define VM_INT_CONSTANTS_CMS(declare_constant)                            \
   declare_constant(Generation::ConcurrentMarkSweep)                       \
--- a/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep	Tue Jun 17 15:27:05 2008 -0700
@@ -206,6 +206,7 @@
 
 freeBlockDictionary.hpp                 allocation.hpp
 freeBlockDictionary.hpp                 debug.hpp
+freeBlockDictionary.hpp                 freeChunk.hpp
 freeBlockDictionary.hpp                 globalDefinitions.hpp
 freeBlockDictionary.hpp                 memRegion.hpp
 freeBlockDictionary.hpp                 mutex.hpp
@@ -214,6 +215,14 @@
 freeChunk.cpp                           copy.hpp
 freeChunk.cpp                           freeBlockDictionary.hpp
 
+freeChunk.hpp                           allocation.hpp
+freeChunk.hpp                           debug.hpp
+freeChunk.hpp                           globalDefinitions.hpp
+freeChunk.hpp                           markOop.hpp
+freeChunk.hpp                           memRegion.hpp
+freeChunk.hpp                           mutex.hpp
+freeChunk.hpp                           ostream.hpp
+
 freeList.cpp                            freeBlockDictionary.hpp
 freeList.cpp                            freeList.hpp
 freeList.cpp                            globals.hpp
--- a/src/share/vm/gc_implementation/includeDB_gc_shared	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/includeDB_gc_shared	Tue Jun 17 15:27:05 2008 -0700
@@ -54,6 +54,7 @@
 markSweep.inline.hpp                    psParallelCompact.hpp
 
 mutableNUMASpace.cpp                    mutableNUMASpace.hpp
+mutableNUMASpace.cpp                    oop.inline.hpp
 mutableNUMASpace.cpp                    sharedHeap.hpp
 mutableNUMASpace.cpp                    thread_<os_family>.inline.hpp
 
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1169,18 +1169,18 @@
   // Trim off a prefix of at most objsFromOverflow items
   int i = 1;
   oop cur = prefix;
-  while (i < objsFromOverflow && cur->klass() != NULL) {
+  while (i < objsFromOverflow && cur->klass_or_null() != NULL) {
     i++; cur = oop(cur->klass());
   }
 
   // Reattach remaining (suffix) to overflow list
-  if (cur->klass() != NULL) {
+  if (cur->klass_or_null() != NULL) {
     oop suffix = oop(cur->klass());
     cur->set_klass_to_list_ptr(NULL);
 
     // Find last item of suffix list
     oop last = suffix;
-    while (last->klass() != NULL) {
+    while (last->klass_or_null() != NULL) {
       last = oop(last->klass());
     }
     // Atomically prepend suffix to current overflow list
--- a/src/share/vm/gc_implementation/shared/immutableSpace.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/shared/immutableSpace.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -66,7 +66,7 @@
 
 #endif
 
-void ImmutableSpace::verify(bool allow_dirty) const {
+void ImmutableSpace::verify(bool allow_dirty) {
   HeapWord* p = bottom();
   HeapWord* t = end();
   HeapWord* prev_p = NULL;
--- a/src/share/vm/gc_implementation/shared/immutableSpace.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/shared/immutableSpace.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -59,5 +59,5 @@
   // Debugging
   virtual void print() const            PRODUCT_RETURN;
   virtual void print_short() const      PRODUCT_RETURN;
-  virtual void verify(bool allow_dirty) const;
+  virtual void verify(bool allow_dirty);
 };
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -599,12 +599,28 @@
 // Mark the the holes in chunks below the top() as invalid.
 void MutableNUMASpace::set_top(HeapWord* value) {
   bool found_top = false;
-  for (int i = 0; i < lgrp_spaces()->length(); i++) {
+  for (int i = 0; i < lgrp_spaces()->length();) {
     LGRPSpace *ls = lgrp_spaces()->at(i);
     MutableSpace *s = ls->space();
     HeapWord *top = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom());
 
     if (s->contains(value)) {
+      // Check if setting the chunk's top to a given value would create a hole less than
+      // a minimal object; assuming that's not the last chunk in which case we don't care.
+      if (i < lgrp_spaces()->length() - 1) {
+        size_t remainder = pointer_delta(s->end(), value);
+        const size_t minimal_object_size = oopDesc::header_size();
+        if (remainder < minimal_object_size && remainder > 0) {
+          // Add a filler object of a minimal size, it will cross the chunk boundary.
+          SharedHeap::fill_region_with_object(MemRegion(value, minimal_object_size));
+          value += minimal_object_size;
+          assert(!s->contains(value), "Should be in the next chunk");
+          // Restart the loop from the same chunk, since the value has moved
+          // to the next one.
+          continue;
+        }
+      }
+
       if (!os::numa_has_static_binding() && top < value && top < s->end()) {
         ls->add_invalid_region(MemRegion(top, value));
       }
@@ -620,6 +636,7 @@
           s->set_top(s->end());
         }
     }
+    i++;
   }
   MutableSpace::set_top(value);
 }
@@ -700,12 +717,14 @@
   MutableSpace *s = lgrp_spaces()->at(i)->space();
   HeapWord *p = s->cas_allocate(size);
   if (p != NULL) {
-    size_t remainder = pointer_delta(s->end(), p);
+    size_t remainder = pointer_delta(s->end(), p + size);
     if (remainder < (size_t)oopDesc::header_size() && remainder > 0) {
       if (s->cas_deallocate(p, size)) {
         // We were the last to allocate and created a fragment less than
         // a minimal object.
         p = NULL;
+      } else {
+        guarantee(false, "Deallocation should always succeed");
       }
     }
   }
@@ -761,10 +780,12 @@
   }
 }
 
-void MutableNUMASpace::verify(bool allow_dirty) const {
- for (int i = 0; i < lgrp_spaces()->length(); i++) {
-    lgrp_spaces()->at(i)->space()->verify(allow_dirty);
-  }
+void MutableNUMASpace::verify(bool allow_dirty) {
+  // 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);
 }
 
 // Scan pages and gather stats about page placement and size.
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -192,7 +192,7 @@
   // Debugging
   virtual void print_on(outputStream* st) const;
   virtual void print_short_on(outputStream* st) const;
-  virtual void verify(bool allow_dirty) const;
+  virtual void verify(bool allow_dirty);
 
   virtual void set_top(HeapWord* value);
 };
--- a/src/share/vm/gc_implementation/shared/mutableSpace.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/shared/mutableSpace.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -118,7 +118,7 @@
                  bottom(), top(), end());
 }
 
-void MutableSpace::verify(bool allow_dirty) const {
+void MutableSpace::verify(bool allow_dirty) {
   HeapWord* p = bottom();
   HeapWord* t = top();
   HeapWord* prev_p = NULL;
--- a/src/share/vm/gc_implementation/shared/mutableSpace.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_implementation/shared/mutableSpace.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -98,5 +98,5 @@
   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) const;
+  virtual void verify(bool allow_dirty);
 };
--- a/src/share/vm/gc_interface/collectedHeap.inline.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -90,11 +90,12 @@
                                                 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);
-  // Must set length after installing klass as set_klass zeros the length
-  // field in UseCompressedOops
-  ((arrayOop)obj)->set_length(length);
   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);
@@ -224,6 +225,7 @@
   assert(obj != NULL, "cannot initialize NULL object");
   const size_t hs = oopDesc::header_size();
   assert(size >= hs, "unexpected object size");
+  ((oop)obj)->set_klass_gap(0);
   Copy::fill_to_aligned_words(obj + hs, size - hs);
 }
 
--- a/src/share/vm/includeDB_core	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/includeDB_core	Tue Jun 17 15:27:05 2008 -0700
@@ -3492,6 +3492,7 @@
 relocInfo_<arch>.cpp                    assembler.inline.hpp
 relocInfo_<arch>.cpp                    assembler_<arch_model>.inline.hpp
 relocInfo_<arch>.cpp                    nativeInst_<arch>.hpp
+relocInfo_<arch>.cpp                    oop.inline.hpp
 relocInfo_<arch>.cpp                    relocInfo.hpp
 relocInfo_<arch>.cpp                    safepoint.hpp
 
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1931,6 +1931,7 @@
               } else {
                 result->set_mark(markOopDesc::prototype());
               }
+              result->set_klass_gap(0);
               result->set_klass(k_entry);
               SET_STACK_OBJECT(result, 0);
               UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);
--- a/src/share/vm/interpreter/bytecodeInterpreterWithChecks.xml	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/interpreter/bytecodeInterpreterWithChecks.xml	Tue Jun 17 15:27:05 2008 -0700
@@ -1,7 +1,25 @@
 <?xml version="1.0"?> 
 <!-- 
-     Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-     SUN PROPRIETARY/CONFIDENTIAL.  Use is subject to license terms.
+     Copyright 1997-2000 Sun Microsystems, Inc.  All Rights Reserved.
+     DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+     This code is free software; you can redistribute it and/or modify it
+     under the terms of the GNU General Public License version 2 only, as
+     published by the Free Software Foundation.
+
+     This code is distributed in the hope that it will be useful, but WITHOUT
+     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+     version 2 for more details (a copy is included in the LICENSE file that
+     accompanied this code).
+
+     You should have received a copy of the GNU General Public License version
+     2 along with this work; if not, write to the Free Software Foundation,
+     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+     Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+     CA 95054 USA or visit www.sun.com if you need additional information or
+     have any questions.
 -->
 <!DOCTYPE processcode [
   <!ELEMENT processcode ANY>
--- a/src/share/vm/interpreter/bytecodeInterpreterWithChecks.xsl	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/interpreter/bytecodeInterpreterWithChecks.xsl	Tue Jun 17 15:27:05 2008 -0700
@@ -1,10 +1,29 @@
 <?xml version="1.0"?> 
 <!-- 
-     Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-     SUN PROPRIETARY/CONFIDENTIAL.  Use is subject to license terms.
+     Copyright 1997-2000 Sun Microsystems, Inc.  All Rights Reserved.
+     DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+     This code is free software; you can redistribute it and/or modify it
+     under the terms of the GNU General Public License version 2 only, as
+     published by the Free Software Foundation.
+
+     This code is distributed in the hope that it will be useful, but WITHOUT
+     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+     version 2 for more details (a copy is included in the LICENSE file that
+     accompanied this code).
+
+     You should have received a copy of the GNU General Public License version
+     2 along with this work; if not, write to the Free Software Foundation,
+     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+     Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+     CA 95054 USA or visit www.sun.com if you need additional information or
+     have any questions.
 -->
 
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="text" indent="no" omit-xml-declaration="yes"/>
 
 <xsl:template match="processcode">
 <xsl:text>
@@ -15,7 +34,6 @@
 
 </xsl:text>
 
-<xsl:output method="text" indent="no" omit-xml-declaration="yes"/>
 </xsl:template>
 
 </xsl:stylesheet>
--- a/src/share/vm/memory/space.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/memory/space.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -815,6 +815,7 @@
            "size for smallest fake object doesn't match");
     instanceOop obj = (instanceOop) allocate(size);
     obj->set_mark(markOopDesc::prototype());
+    obj->set_klass_gap(0);
     obj->set_klass(SystemDictionary::object_klass());
   }
 }
--- a/src/share/vm/oops/arrayOop.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/oops/arrayOop.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -41,11 +41,10 @@
   // Header size computation.
   // The header is considered the oop part of this type plus the length.
   // Returns the aligned header_size_in_bytes.  This is not equivalent to
-  // sizeof(arrayOopDesc) which should not appear in the code, except here.
+  // sizeof(arrayOopDesc) which should not appear in the code.
   static int header_size_in_bytes() {
-    size_t hs = UseCompressedOops ?
-            sizeof(arrayOopDesc) :
-            align_size_up(sizeof(arrayOopDesc) + sizeof(int), HeapWordSize);
+    size_t hs = align_size_up(length_offset_in_bytes() + sizeof(int),
+                              HeapWordSize);
 #ifdef ASSERT
     // make sure it isn't called before UseCompressedOops is initialized.
     static size_t arrayoopdesc_hs = 0;
--- a/src/share/vm/oops/instanceKlass.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/oops/instanceKlass.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -180,9 +180,8 @@
   // End of the oop block.
   //
 
-  // number of words used by non-static fields in this klass (including
-  // inherited fields but after header_size()).  If fields are compressed into
-  // header, this can be zero so it's not the same as number of static fields.
+  // Number of heapOopSize words used by non-static fields in this klass
+  // (including inherited fields but after header_size()).
   int             _nonstatic_field_size;
   int             _static_field_size;    // number words used by static fields (oop and non-oop) in this klass
   int             _static_oop_field_size;// number of static oop fields in this klass
--- a/src/share/vm/oops/instanceKlassKlass.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/oops/instanceKlassKlass.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -581,7 +581,7 @@
   OopMapBlock* map     = ik->start_of_nonstatic_oop_maps();
   OopMapBlock* end_map = map + ik->nonstatic_oop_map_size();
   while (map < end_map) {
-    st->print("%d-%d ", map->offset(), map->offset() + oopSize*(map->length() - 1));
+    st->print("%d-%d ", map->offset(), map->offset() + heapOopSize*(map->length() - 1));
     map++;
   }
   st->cr();
--- a/src/share/vm/oops/instanceOop.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/oops/instanceOop.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -39,14 +39,7 @@
 
   static bool contains_field_offset(int offset, int nonstatic_field_size) {
     int base_in_bytes = base_offset_in_bytes();
-    if (UseCompressedOops) {
-      return (offset >= base_in_bytes &&
-              // field can be embedded in header, or is after header.
-              (offset < (int)sizeof(instanceOopDesc) ||
-              (offset-(int)sizeof(instanceOopDesc))/wordSize < nonstatic_field_size));
-    } else {
-      return (offset >= base_in_bytes &&
-              (offset-base_in_bytes)/wordSize < nonstatic_field_size);
-    }
+    return (offset >= base_in_bytes &&
+            (offset-base_in_bytes) < nonstatic_field_size * heapOopSize);
   }
 };
--- a/src/share/vm/oops/markOop.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/oops/markOop.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -29,8 +29,10 @@
 //
 // Bit-format of an object header (most significant first):
 //
-//
-//  unused:0/25 hash:25/31 age:4 biased_lock:1 lock:2 = 32/64 bits
+//  32 bits: unused:0  hash:25 age:4 biased_lock:1 lock:2
+//  64 bits: unused:24 hash:31 cms:2 age:4 biased_lock:1 lock:2
+//           unused:20 size:35 cms:2 age:4 biased_lock:1 lock:2 (if cms
+//                                                               free chunk)
 //
 //  - hash contains the identity hash value: largest value is
 //    31 bits, see os::random().  Also, 64-bit vm's require
@@ -91,6 +93,7 @@
          biased_lock_bits         = 1,
          max_hash_bits            = BitsPerWord - age_bits - lock_bits - biased_lock_bits,
          hash_bits                = max_hash_bits > 31 ? 31 : max_hash_bits,
+         cms_bits                 = LP64_ONLY(1) NOT_LP64(0),
          epoch_bits               = 2
   };
 
@@ -106,7 +109,8 @@
   enum { lock_shift               = 0,
          biased_lock_shift        = lock_bits,
          age_shift                = lock_bits + biased_lock_bits,
-         hash_shift               = lock_bits + biased_lock_bits + age_bits,
+         cms_shift                = age_shift + age_bits,
+         hash_shift               = cms_shift + cms_bits,
          epoch_shift              = hash_shift
   };
 
@@ -118,7 +122,9 @@
          age_mask                 = right_n_bits(age_bits),
          age_mask_in_place        = age_mask << age_shift,
          epoch_mask               = right_n_bits(epoch_bits),
-         epoch_mask_in_place      = epoch_mask << epoch_shift
+         epoch_mask_in_place      = epoch_mask << epoch_shift,
+         cms_mask                 = right_n_bits(cms_bits),
+         cms_mask_in_place        = cms_mask << cms_shift
 #ifndef _WIN64
          ,hash_mask               = right_n_bits(hash_bits),
          hash_mask_in_place       = (address_word)hash_mask << hash_shift
@@ -360,4 +366,40 @@
 
   // see the definition in markOop.cpp for the gory details
   bool should_not_be_cached() const;
+
+  // These markOops indicate cms free chunk blocks and not objects.
+  // In 64 bit, the markOop is set to distinguish them from oops.
+  // These are defined in 32 bit mode for vmStructs.
+  const static uintptr_t cms_free_chunk_pattern  = 0x1;
+
+  // Constants for the size field.
+  enum { size_shift                = cms_shift + cms_bits,
+         size_bits                 = 35    // need for compressed oops 32G
+       };
+  // These values are too big for Win64
+  const static uintptr_t size_mask = LP64_ONLY(right_n_bits(size_bits))
+                                     NOT_LP64(0);
+  const static uintptr_t size_mask_in_place =
+                                     (address_word)size_mask << size_shift;
+
+#ifdef _LP64
+  static markOop cms_free_prototype() {
+    return markOop(((intptr_t)prototype() & ~cms_mask_in_place) |
+                   ((cms_free_chunk_pattern & cms_mask) << cms_shift));
+  }
+  uintptr_t cms_encoding() const {
+    return mask_bits(value() >> cms_shift, cms_mask);
+  }
+  bool is_cms_free_chunk() const {
+    return is_neutral() &&
+           (cms_encoding() & cms_free_chunk_pattern) == cms_free_chunk_pattern;
+  }
+
+  size_t get_size() const       { return (size_t)(value() >> size_shift); }
+  static markOop set_size_and_free(size_t size) {
+    assert((size & ~size_mask) == 0, "shouldn't overflow size field");
+    return markOop(((intptr_t)cms_free_prototype() & ~size_mask_in_place) |
+                   (((intptr_t)size & size_mask) << size_shift));
+  }
+#endif // _LP64
 };
--- a/src/share/vm/oops/methodDataOop.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/oops/methodDataOop.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -158,7 +158,6 @@
     assert(ProfileTraps, "used only under +ProfileTraps");
     uint old_flags = (_header._struct._flags & flag_mask);
     _header._struct._flags = (new_state << trap_shift) | old_flags;
-    assert(trap_state() == new_state, "sanity");
   }
 
   u1 flags() {
--- a/src/share/vm/oops/oop.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/oops/oop.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -77,10 +77,15 @@
   void init_mark();
 
   klassOop klass() const;
+  klassOop klass_or_null() const volatile;
   oop* klass_addr();
   narrowOop* compressed_klass_addr();
 
   void set_klass(klassOop k);
+
+  // For klass field compression
+  int klass_gap() const;
+  void set_klass_gap(int z);
   // For when the klass pointer is being used as a linked list "next" field.
   void set_klass_to_list_ptr(oop k);
 
--- a/src/share/vm/oops/oop.inline.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/oops/oop.inline.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -36,7 +36,15 @@
 inline klassOop oopDesc::klass() const {
   if (UseCompressedOops) {
     return (klassOop)decode_heap_oop_not_null(_metadata._compressed_klass);
-      // can be NULL in CMS, but isn't supported on CMS yet.
+  } else {
+    return _metadata._klass;
+  }
+}
+
+inline klassOop oopDesc::klass_or_null() const volatile {
+  // can be NULL in CMS
+  if (UseCompressedOops) {
+    return (klassOop)decode_heap_oop(_metadata._compressed_klass);
   } else {
     return _metadata._klass;
   }
@@ -64,15 +72,22 @@
   assert(Universe::is_bootstrapping() || k != NULL, "must be a real klassOop");
   assert(Universe::is_bootstrapping() || k->is_klass(), "not a klassOop");
   if (UseCompressedOops) {
-    // zero the gap when the klass is set, by zeroing the pointer sized
-    // part of the union.
-    _metadata._klass = NULL;
     oop_store_without_check(compressed_klass_addr(), (oop)k);
   } else {
     oop_store_without_check(klass_addr(), (oop) k);
   }
 }
 
+inline int oopDesc::klass_gap() const {
+  return *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes());
+}
+
+inline void oopDesc::set_klass_gap(int v) {
+  if (UseCompressedOops) {
+    *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes()) = v;
+  }
+}
+
 inline void oopDesc::set_klass_to_list_ptr(oop k) {
   // This is only to be used during GC, for from-space objects, so no
   // barrier is needed.
@@ -505,7 +520,7 @@
   // try to find metaclass cycle safely without seg faulting on bad input
   // we should reach klassKlassObj by following klass link at most 3 times
   for (int i = 0; i < 3; i++) {
-    obj = obj->klass();
+    obj = obj->klass_or_null();
     // klass should be aligned and in permspace
     if (!check_obj_alignment(obj)) return false;
     if (!Universe::heap()->is_in_permanent(obj)) return false;
--- a/src/share/vm/opto/c2_globals.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/c2_globals.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -390,5 +390,8 @@
                                                                             \
   product(intx, MaxLabelRootDepth, 1100,                                    \
           "Maximum times call Label_Root to prevent stack overflow")        \
+                                                                            \
+  diagnostic(intx, DominatorSearchLimit, 1000,                              \
+          "Iterations limit in Node::dominates")                            \
 
 C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
--- a/src/share/vm/opto/callnode.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/callnode.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -637,7 +637,7 @@
   }
   Compile *C = phase->C;
   int offset = adrInst_t->offset();
-  assert(offset >= 0, "should be valid offset");
+  assert(adrInst_t->klass_is_exact() && offset >= 0, "should be valid offset");
   ciKlass* adr_k = adrInst_t->klass();
   assert(adr_k->is_loaded() &&
          adr_k->is_java_klass() &&
@@ -674,12 +674,11 @@
       ciKlass* at_k = at_ptr->klass();
       if ((adrInst_t->base() == at_ptr->base()) &&
           at_k->is_loaded() &&
-          at_k->is_java_klass() &&
-          !at_k->is_interface()) {
+          at_k->is_java_klass()) {
         // If we have found an argument matching addr_t, check if the field
         // at the specified offset is modified.
-        int at_idx = C->get_alias_index(at_ptr->add_offset(offset)->isa_oopptr());
-        if (base_idx == at_idx &&
+        if ((at_k->is_interface() || adr_k == at_k ||
+             adr_k->is_subclass_of(at_k) && !at_ptr->klass_is_exact()) &&
             (bcea == NULL ||
              bcea->is_arg_modified(i - TypeFunc::Parms, offset, size))) {
           return true;
--- a/src/share/vm/opto/callnode.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/callnode.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -388,9 +388,6 @@
   void               set_next_exception(SafePointNode* n);
   bool                   has_exceptions() const { return next_exception() != NULL; }
 
-  // Does this node have a use of n other than in debug information?
-  virtual bool           has_non_debug_use(Node *n)  {return false; }
-
   // Standard Node stuff
   virtual int            Opcode() const;
   virtual bool           pinned() const { return true; }
@@ -497,7 +494,7 @@
   // Returns true if the call may modify n
   virtual bool        may_modify(const TypePtr *addr_t, PhaseTransform *phase);
   // Does this node have a use of n other than in debug information?
-  virtual bool        has_non_debug_use(Node *n);
+  bool                has_non_debug_use(Node *n);
   // Returns the unique CheckCastPP of a call
   // or result projection is there are several CheckCastPP
   // or returns NULL if there is no one.
--- a/src/share/vm/opto/cfgnode.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/cfgnode.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -707,8 +707,14 @@
 //------------------------split_out_instance-----------------------------------
 // Split out an instance type from a bottom phi.
 PhiNode* PhiNode::split_out_instance(const TypePtr* at, PhaseIterGVN *igvn) const {
-  assert(type() == Type::MEMORY && (adr_type() == TypePtr::BOTTOM ||
-         adr_type() == TypeRawPtr::BOTTOM) , "bottom or raw memory required");
+  const TypeOopPtr *t_oop = at->isa_oopptr();
+  assert(t_oop != NULL && t_oop->is_instance(), "expecting instance oopptr");
+  const TypePtr *t = adr_type();
+  assert(type() == Type::MEMORY &&
+         (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM ||
+          t->isa_oopptr() && !t->is_oopptr()->is_instance() &&
+          t->is_oopptr()->cast_to_instance(t_oop->instance_id()) == t_oop),
+         "bottom or raw memory required");
 
   // Check if an appropriate node already exists.
   Node *region = in(0);
@@ -1342,7 +1348,7 @@
     Node *n = phi->in(i);
     if( !n ) return NULL;
     if( phase->type(n) == Type::TOP ) return NULL;
-    if( n->Opcode() == Op_ConP )
+    if( n->Opcode() == Op_ConP || n->Opcode() == Op_ConN )
       break;
   }
   if( i >= phi->req() )         // Only split for constants
@@ -1615,64 +1621,6 @@
     if (opt != NULL)  return opt;
   }
 
-  if (in(1) != NULL && in(1)->Opcode() == Op_AddP && can_reshape) {
-    // Try to undo Phi of AddP:
-    //   (Phi (AddP base base y) (AddP base2 base2 y))
-    // becomes:
-    //   newbase := (Phi base base2)
-    //   (AddP newbase newbase y)
-    //
-    // This occurs as a result of unsuccessful split_thru_phi and
-    // interferes with taking advantage of addressing modes.  See the
-    // clone_shift_expressions code in matcher.cpp
-    Node* addp = in(1);
-    const Type* type = addp->in(AddPNode::Base)->bottom_type();
-    Node* y = addp->in(AddPNode::Offset);
-    if (y != NULL && addp->in(AddPNode::Base) == addp->in(AddPNode::Address)) {
-      // make sure that all the inputs are similar to the first one,
-      // i.e. AddP with base == address and same offset as first AddP
-      bool doit = true;
-      for (uint i = 2; i < req(); i++) {
-        if (in(i) == NULL ||
-            in(i)->Opcode() != Op_AddP ||
-            in(i)->in(AddPNode::Base) != in(i)->in(AddPNode::Address) ||
-            in(i)->in(AddPNode::Offset) != y) {
-          doit = false;
-          break;
-        }
-        // Accumulate type for resulting Phi
-        type = type->meet(in(i)->in(AddPNode::Base)->bottom_type());
-      }
-      Node* base = NULL;
-      if (doit) {
-        // Check for neighboring AddP nodes in a tree.
-        // If they have a base, use that it.
-        for (DUIterator_Fast kmax, k = this->fast_outs(kmax); k < kmax; k++) {
-          Node* u = this->fast_out(k);
-          if (u->is_AddP()) {
-            Node* base2 = u->in(AddPNode::Base);
-            if (base2 != NULL && !base2->is_top()) {
-              if (base == NULL)
-                base = base2;
-              else if (base != base2)
-                { doit = false; break; }
-            }
-          }
-        }
-      }
-      if (doit) {
-        if (base == NULL) {
-          base = new (phase->C, in(0)->req()) PhiNode(in(0), type, NULL);
-          for (uint i = 1; i < req(); i++) {
-            base->init_req(i, in(i)->in(AddPNode::Base));
-          }
-          phase->is_IterGVN()->register_new_node_with_optimizer(base);
-        }
-        return new (phase->C, 4) AddPNode(base, base, y);
-      }
-    }
-  }
-
   // Split phis through memory merges, so that the memory merges will go away.
   // Piggy-back this transformation on the search for a unique input....
   // It will be as if the merged memory is the unique value of the phi.
--- a/src/share/vm/opto/chaitin.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/chaitin.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1385,7 +1385,7 @@
             cisc->ins_req(1,src);         // Requires a memory edge
           }
           b->_nodes.map(j,cisc);          // Insert into basic block
-          n->replace_by(cisc); // Correct graph
+          n->subsume_by(cisc); // Correct graph
           //
           ++_used_cisc_instructions;
 #ifndef PRODUCT
--- a/src/share/vm/opto/classes.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/classes.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -37,6 +37,7 @@
 macro(AllocateArray)
 macro(AndI)
 macro(AndL)
+macro(AryEq)
 macro(AtanD)
 macro(Binary)
 macro(Bool)
@@ -64,6 +65,7 @@
 macro(CMoveI)
 macro(CMoveL)
 macro(CMoveP)
+macro(CMoveN)
 macro(CmpN)
 macro(CmpD)
 macro(CmpD3)
@@ -133,6 +135,7 @@
 macro(LoadF)
 macro(LoadI)
 macro(LoadKlass)
+macro(LoadNKlass)
 macro(LoadL)
 macro(LoadL_unaligned)
 macro(LoadPLocked)
--- a/src/share/vm/opto/compile.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/compile.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -368,7 +368,12 @@
   BufferBlob* blob = BufferBlob::create("Compile::scratch_buffer", size);
   // Record the buffer blob for next time.
   set_scratch_buffer_blob(blob);
-  guarantee(scratch_buffer_blob() != NULL, "Need BufferBlob for code generation");
+  // Have we run out of code space?
+  if (scratch_buffer_blob() == NULL) {
+    // Let CompilerBroker disable further compilations.
+    record_failure("Not enough space for scratch buffer in CodeCache");
+    return;
+  }
 
   // Initialize the relocation buffers
   relocInfo* locs_buf = (relocInfo*) blob->instructions_end() - MAX_locs_size;
@@ -1065,6 +1070,8 @@
       // No constant oop pointers (such as Strings); they alias with
       // unknown strings.
       tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset);
+    } else if( to->is_instance_field() ) {
+      tj = to; // Keep NotNull and klass_is_exact for instance type
     } else if( ptr == TypePtr::NotNull || to->klass_is_exact() ) {
       // During the 2nd round of IterGVN, NotNull castings are removed.
       // Make sure the Bottom and NotNull variants alias the same.
@@ -1084,7 +1091,7 @@
     } else {
       ciInstanceKlass *canonical_holder = k->get_canonical_holder(offset);
       if (!k->equals(canonical_holder) || tj->offset() != offset) {
-        tj = to = TypeInstPtr::make(TypePtr::BotPTR, canonical_holder, false, NULL, offset, to->instance_id());
+        tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, false, NULL, offset, to->instance_id());
       }
     }
   }
@@ -1835,6 +1842,7 @@
 // Implement items 1-5 from final_graph_reshaping below.
 static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) {
 
+  if ( n->outcnt() == 0 ) return; // dead node
   uint nop = n->Opcode();
 
   // Check for 2-input instruction with "last use" on right input.
@@ -1901,7 +1909,7 @@
     break;
   case Op_Opaque1:              // Remove Opaque Nodes before matching
   case Op_Opaque2:              // Remove Opaque Nodes before matching
-    n->replace_by(n->in(1));
+    n->subsume_by(n->in(1));
     break;
   case Op_CallStaticJava:
   case Op_CallJava:
@@ -1961,6 +1969,7 @@
   case Op_LoadC:
   case Op_LoadI:
   case Op_LoadKlass:
+  case Op_LoadNKlass:
   case Op_LoadL:
   case Op_LoadL_unaligned:
   case Op_LoadPLocked:
@@ -1983,14 +1992,94 @@
   }
 
   case Op_AddP: {               // Assert sane base pointers
-    const Node *addp = n->in(AddPNode::Address);
+    Node *addp = n->in(AddPNode::Address);
     assert( !addp->is_AddP() ||
             addp->in(AddPNode::Base)->is_top() || // Top OK for allocation
             addp->in(AddPNode::Base) == n->in(AddPNode::Base),
             "Base pointers must match" );
+#ifdef _LP64
+    if (UseCompressedOops &&
+        addp->Opcode() == Op_ConP &&
+        addp == n->in(AddPNode::Base) &&
+        n->in(AddPNode::Offset)->is_Con()) {
+      // Use addressing with narrow klass to load with offset on x86.
+      // On sparc loading 32-bits constant and decoding it have less
+      // instructions (4) then load 64-bits constant (7).
+      // Do this transformation here since IGVN will convert ConN back to ConP.
+      const Type* t = addp->bottom_type();
+      if (t->isa_oopptr()) {
+        Node* nn = NULL;
+
+        // Look for existing ConN node of the same exact type.
+        Compile* C = Compile::current();
+        Node* r  = C->root();
+        uint cnt = r->outcnt();
+        for (uint i = 0; i < cnt; i++) {
+          Node* m = r->raw_out(i);
+          if (m!= NULL && m->Opcode() == Op_ConN &&
+              m->bottom_type()->is_narrowoop()->make_oopptr() == t) {
+            nn = m;
+            break;
+          }
+        }
+        if (nn != NULL) {
+          // Decode a narrow oop to match address
+          // [R12 + narrow_oop_reg<<3 + offset]
+          nn = new (C,  2) DecodeNNode(nn, t);
+          n->set_req(AddPNode::Base, nn);
+          n->set_req(AddPNode::Address, nn);
+          if (addp->outcnt() == 0) {
+            addp->disconnect_inputs(NULL);
+          }
+        }
+      }
+    }
+#endif
     break;
   }
 
+#ifdef _LP64
+  case Op_CmpP:
+    // Do this transformation here to preserve CmpPNode::sub() and
+    // other TypePtr related Ideal optimizations (for example, ptr nullness).
+    if( n->in(1)->is_DecodeN() ) {
+      Compile* C = Compile::current();
+      Node* in2 = NULL;
+      if( n->in(2)->is_DecodeN() ) {
+        in2 = n->in(2)->in(1);
+      } else if ( n->in(2)->Opcode() == Op_ConP ) {
+        const Type* t = n->in(2)->bottom_type();
+        if (t == TypePtr::NULL_PTR) {
+          Node *in1 = n->in(1);
+          if (Matcher::clone_shift_expressions) {
+            // x86, ARM and friends can handle 2 adds in addressing mode.
+            // Decode a narrow oop and do implicit NULL check in address
+            // [R12 + narrow_oop_reg<<3 + offset]
+            in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR);
+          } else {
+            // Don't replace CmpP(o ,null) if 'o' is used in AddP
+            // to generate implicit NULL check on Sparc where
+            // narrow oops can't be used in address.
+            uint i = 0;
+            for (; i < in1->outcnt(); i++) {
+              if (in1->raw_out(i)->is_AddP())
+                break;
+            }
+            if (i >= in1->outcnt()) {
+              in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR);
+            }
+          }
+        } else if (t->isa_oopptr()) {
+          in2 = ConNode::make(C, t->is_oopptr()->make_narrowoop());
+        }
+      }
+      if( in2 != NULL ) {
+        Node* cmpN = new (C, 3) CmpNNode(n->in(1)->in(1), in2);
+        n->subsume_by( cmpN );
+      }
+    }
+#endif
+
   case Op_ModI:
     if (UseDivMod) {
       // Check if a%b and a/b both exist
@@ -2000,13 +2089,13 @@
         Compile* C = Compile::current();
         if (Matcher::has_match_rule(Op_DivModI)) {
           DivModINode* divmod = DivModINode::make(C, n);
-          d->replace_by(divmod->div_proj());
-          n->replace_by(divmod->mod_proj());
+          d->subsume_by(divmod->div_proj());
+          n->subsume_by(divmod->mod_proj());
         } else {
           // replace a%b with a-((a/b)*b)
           Node* mult = new (C, 3) MulINode(d, d->in(2));
           Node* sub  = new (C, 3) SubINode(d->in(1), mult);
-          n->replace_by( sub );
+          n->subsume_by( sub );
         }
       }
     }
@@ -2021,13 +2110,13 @@
         Compile* C = Compile::current();
         if (Matcher::has_match_rule(Op_DivModL)) {
           DivModLNode* divmod = DivModLNode::make(C, n);
-          d->replace_by(divmod->div_proj());
-          n->replace_by(divmod->mod_proj());
+          d->subsume_by(divmod->div_proj());
+          n->subsume_by(divmod->mod_proj());
         } else {
           // replace a%b with a-((a/b)*b)
           Node* mult = new (C, 3) MulLNode(d, d->in(2));
           Node* sub  = new (C, 3) SubLNode(d->in(1), mult);
-          n->replace_by( sub );
+          n->subsume_by( sub );
         }
       }
     }
@@ -2073,7 +2162,7 @@
       // Replace many operand PackNodes with a binary tree for matching
       PackNode* p = (PackNode*) n;
       Node* btp = p->binaryTreePack(Compile::current(), 1, n->req());
-      n->replace_by(btp);
+      n->subsume_by(btp);
     }
     break;
   default:
--- a/src/share/vm/opto/connode.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/connode.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -35,16 +35,16 @@
 
 //------------------------------make-------------------------------------------
 ConNode *ConNode::make( Compile* C, const Type *t ) {
-  if (t->isa_narrowoop()) return new (C, 1) ConNNode( t->is_narrowoop() );
   switch( t->basic_type() ) {
   case T_INT:       return new (C, 1) ConINode( t->is_int() );
-  case T_ARRAY:     return new (C, 1) ConPNode( t->is_aryptr() );
   case T_LONG:      return new (C, 1) ConLNode( t->is_long() );
   case T_FLOAT:     return new (C, 1) ConFNode( t->is_float_constant() );
   case T_DOUBLE:    return new (C, 1) ConDNode( t->is_double_constant() );
   case T_VOID:      return new (C, 1) ConNode ( Type::TOP );
   case T_OBJECT:    return new (C, 1) ConPNode( t->is_oopptr() );
+  case T_ARRAY:     return new (C, 1) ConPNode( t->is_aryptr() );
   case T_ADDRESS:   return new (C, 1) ConPNode( t->is_ptr() );
+  case T_NARROWOOP: return new (C, 1) ConNNode( t->is_narrowoop() );
     // Expected cases:  TypePtr::NULL_PTR, any is_rawptr()
     // Also seen: AnyPtr(TopPTR *+top); from command line:
     //   r -XX:+PrintOpto -XX:CIStart=285 -XX:+CompileTheWorld -XX:CompileTheWorldStartAt=660
@@ -185,6 +185,7 @@
   case T_LONG:    return new (C, 4) CMoveLNode( bol, left, right, t->is_long() );
   case T_OBJECT:  return new (C, 4) CMovePNode( c, bol, left, right, t->is_oopptr() );
   case T_ADDRESS: return new (C, 4) CMovePNode( c, bol, left, right, t->is_ptr() );
+  case T_NARROWOOP: return new (C, 4) CMoveNNode( c, bol, left, right, t );
   default:
     ShouldNotReachHere();
     return NULL;
@@ -556,7 +557,7 @@
   const Type *t = phase->type( in(1) );
   if( t == Type::TOP ) return in(1);
 
-  if (in(1)->Opcode() == Op_EncodeP) {
+  if (in(1)->is_EncodeP()) {
     // (DecodeN (EncodeP p)) -> p
     return in(1)->in(1);
   }
@@ -570,16 +571,19 @@
   return bottom_type();
 }
 
-Node* DecodeNNode::decode(PhaseGVN* phase, Node* value) {
-  if (value->Opcode() == Op_EncodeP) {
+Node* DecodeNNode::decode(PhaseTransform* phase, Node* value) {
+  if (value->is_EncodeP()) {
     // (DecodeN (EncodeP p)) -> p
     return value->in(1);
   }
   const Type* newtype = value->bottom_type();
   if (newtype == TypeNarrowOop::NULL_PTR) {
     return phase->transform(new (phase->C, 1) ConPNode(TypePtr::NULL_PTR));
+  } else if (newtype->isa_narrowoop()) {
+    return phase->transform(new (phase->C, 2) DecodeNNode(value, newtype->is_narrowoop()->make_oopptr()));
   } else {
-    return phase->transform(new (phase->C, 2) DecodeNNode(value, newtype->is_narrowoop()->make_oopptr()));
+    ShouldNotReachHere();
+    return NULL; // to make C++ compiler happy.
   }
 }
 
@@ -587,7 +591,7 @@
   const Type *t = phase->type( in(1) );
   if( t == Type::TOP ) return in(1);
 
-  if (in(1)->Opcode() == Op_DecodeN) {
+  if (in(1)->is_DecodeN()) {
     // (EncodeP (DecodeN p)) -> p
     return in(1)->in(1);
   }
@@ -601,8 +605,8 @@
   return bottom_type();
 }
 
-Node* EncodePNode::encode(PhaseGVN* phase, Node* value) {
-  if (value->Opcode() == Op_DecodeN) {
+Node* EncodePNode::encode(PhaseTransform* phase, Node* value) {
+  if (value->is_DecodeN()) {
     // (EncodeP (DecodeN p)) -> p
     return value->in(1);
   }
@@ -617,6 +621,9 @@
   }
 }
 
+Node *EncodePNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
+  return MemNode::Ideal_common_DU_postCCP(ccp, this, in(1));
+}
 
 //=============================================================================
 //------------------------------Identity---------------------------------------
--- a/src/share/vm/opto/connode.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/connode.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -70,11 +70,6 @@
     else
       return new (C, 1) ConPNode( TypeRawPtr::make(con) );
   }
-
-  static ConPNode* make( Compile *C, ciObject* con ) {
-    return new (C, 1) ConPNode( TypeOopPtr::make_from_constant(con) );
-  }
-
 };
 
 
@@ -84,11 +79,6 @@
 public:
   ConNNode( const TypeNarrowOop *t ) : ConNode(t) {}
   virtual int Opcode() const;
-
-  static ConNNode* make( Compile *C, ciObject* con ) {
-    return new (C, 1) ConNNode( TypeNarrowOop::make_from_constant(con) );
-  }
-
 };
 
 
@@ -210,7 +200,14 @@
   virtual int Opcode() const;
 };
 
-//------------------------------ConstraintCastNode-------------------------------------
+//------------------------------CMoveNNode-------------------------------------
+class CMoveNNode : public CMoveNode {
+public:
+  CMoveNNode( Node *c, Node *bol, Node *left, Node *right, const Type* t ) : CMoveNode(bol,left,right,t) { init_req(Control,c); }
+  virtual int Opcode() const;
+};
+
+//------------------------------ConstraintCastNode-----------------------------
 // cast to a different range
 class ConstraintCastNode: public TypeNode {
 public:
@@ -274,6 +271,7 @@
  public:
   EncodePNode(Node* value, const Type* type):
     TypeNode(type, 2) {
+    init_class_id(Class_EncodeP);
     init_req(0, NULL);
     init_req(1, value);
   }
@@ -282,7 +280,8 @@
   virtual const Type *Value( PhaseTransform *phase ) const;
   virtual uint  ideal_reg() const { return Op_RegN; }
 
-  static Node* encode(PhaseGVN* phase, Node* value);
+  static Node* encode(PhaseTransform* phase, Node* value);
+  virtual Node *Ideal_DU_postCCP( PhaseCCP *ccp );
 };
 
 //------------------------------DecodeN--------------------------------
@@ -293,6 +292,7 @@
  public:
   DecodeNNode(Node* value, const Type* type):
     TypeNode(type, 2) {
+    init_class_id(Class_DecodeN);
     init_req(0, NULL);
     init_req(1, value);
   }
@@ -301,7 +301,7 @@
   virtual const Type *Value( PhaseTransform *phase ) const;
   virtual uint  ideal_reg() const { return Op_RegP; }
 
-  static Node* decode(PhaseGVN* phase, Node* value);
+  static Node* decode(PhaseTransform* phase, Node* value);
 };
 
 //------------------------------Conv2BNode-------------------------------------
--- a/src/share/vm/opto/doCall.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/doCall.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -580,7 +580,7 @@
   Node* ex_klass_node = NULL;
   if (has_ex_handler() && !ex_type->klass_is_exact()) {
     Node* p = basic_plus_adr( ex_node, ex_node, oopDesc::klass_offset_in_bytes());
-    ex_klass_node = _gvn.transform(new (C, 3) LoadKlassNode(NULL, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT));
+    ex_klass_node = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT) );
 
     // Compute the exception klass a little more cleverly.
     // Obvious solution is to simple do a LoadKlass from the 'ex_node'.
@@ -592,7 +592,7 @@
       ex_klass_node = new (C, ex_node->req()) PhiNode( ex_node->in(0), TypeKlassPtr::OBJECT );
       for( uint i = 1; i < ex_node->req(); i++ ) {
         Node* p = basic_plus_adr( ex_node->in(i), ex_node->in(i), oopDesc::klass_offset_in_bytes() );
-        Node* k = _gvn.transform(new (C, 3) LoadKlassNode(0, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT));
+        Node* k = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT) );
         ex_klass_node->init_req( i, k );
       }
       _gvn.set_type(ex_klass_node, TypeKlassPtr::OBJECT);
--- a/src/share/vm/opto/escape.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/escape.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -417,11 +417,18 @@
   //       | |
   //       AddP  ( base == address )
   //
+  // case #8. narrow Klass's field reference.
+  //      LoadNKlass
+  //       |
+  //      DecodeN
+  //       | |
+  //       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();
     assert(base->Opcode() == Op_ConP || base->Opcode() == Op_ThreadLocal ||
-           base->Opcode() == Op_CastX2P ||
+           base->Opcode() == Op_CastX2P || base->is_DecodeN() ||
            (base->is_Mem() && base->bottom_type() == TypeRawPtr::NOTNULL) ||
            (base->is_Proj() && base->in(0)->is_Allocate()), "sanity");
   }
@@ -888,6 +895,23 @@
       record_for_optimizer(n);
       if (alloc->is_Allocate() && ptn->_scalar_replaceable &&
           (t->isa_instptr() || t->isa_aryptr())) {
+
+        // 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 = _nodes->adr_at(ptn->edge_target(e))->_node;
+          assert(ptn->edge_type(e) == PointsToNode::FieldEdge && 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));
+            if (addp2 != NULL) {
+              assert(alloc->is_AllocateArray(),"array allocation was expected");
+              alloc_worklist.append_if_missing(addp2);
+            }
+            alloc_worklist.append_if_missing(use);
+          }
+        }
+
         // An allocation may have an Initialize which has raw stores. Scan
         // the users of the raw allocation result and push AddP users
         // on alloc_worklist.
@@ -919,6 +943,8 @@
       tinst = igvn->type(base)->isa_oopptr();
     } else if (n->is_Phi() ||
                n->is_CheckCastPP() ||
+               n->is_EncodeP() ||
+               n->is_DecodeN() ||
                (n->is_ConstraintCast() && n->Opcode() == Op_CastPP)) {
       if (visited.test_set(n->_idx)) {
         assert(n->is_Phi(), "loops only through Phi's");
@@ -935,13 +961,25 @@
         tinst = igvn->type(val)->isa_oopptr();
         assert(tinst != NULL && tinst->is_instance() &&
                tinst->instance_id() == elem , "instance type expected.");
-        const TypeOopPtr *tn_t = igvn->type(tn)->isa_oopptr();
+
+        const TypeOopPtr *tn_t = NULL;
+        const Type *tn_type = igvn->type(tn);
+        if (tn_type->isa_narrowoop()) {
+          tn_t = tn_type->is_narrowoop()->make_oopptr()->isa_oopptr();
+        } else {
+          tn_t = tn_type->isa_oopptr();
+        }
 
         if (tn_t != NULL &&
  tinst->cast_to_instance(TypeOopPtr::UNKNOWN_INSTANCE)->higher_equal(tn_t)) {
+          if (tn_type->isa_narrowoop()) {
+            tn_type = tinst->make_narrowoop();
+          } else {
+            tn_type = tinst;
+          }
           igvn->hash_delete(tn);
-          igvn->set_type(tn, tinst);
-          tn->set_type(tinst);
+          igvn->set_type(tn, tn_type);
+          tn->set_type(tn_type);
           igvn->hash_insert(tn);
           record_for_optimizer(n);
         }
@@ -978,6 +1016,8 @@
         alloc_worklist.append_if_missing(use);
       } else if (use->is_Phi() ||
                  use->is_CheckCastPP() ||
+                 use->is_EncodeP() ||
+                 use->is_DecodeN() ||
                  (use->is_ConstraintCast() && use->Opcode() == Op_CastPP)) {
         alloc_worklist.append_if_missing(use);
       }
@@ -1199,7 +1239,7 @@
 
 void ConnectionGraph::compute_escape() {
 
-  // 1. Populate Connection Graph with Ideal nodes.
+  // 1. Populate Connection Graph (CG) with Ideal nodes.
 
   Unique_Node_List worklist_init;
   worklist_init.map(_compile->unique(), NULL);  // preallocate space
@@ -1281,11 +1321,13 @@
       remove_deferred(ni, &deferred_edges, &visited);
       if (n->is_AddP()) {
         // If this AddP computes an address which may point to more that one
-        // object, nothing the address points to can be scalar replaceable.
+        // object or more then one field (array's element), nothing the address
+        // points to can be scalar replaceable.
         Node *base = get_addp_base(n);
         ptset.Clear();
         PointsTo(ptset, base, igvn);
-        if (ptset.Size() > 1) {
+        if (ptset.Size() > 1 ||
+            (ptset.Size() != 0 && ptn->offset() == Type::OffsetBot)) {
           for( VectorSetI j(&ptset); j.test(); ++j ) {
             uint pt = j.elem;
             ptnode_adr(pt)->_scalar_replaceable = false;
@@ -1538,6 +1580,7 @@
       if (k->Opcode() == Op_LoadKlass) {
         kt = k->as_Load()->type()->isa_klassptr();
       } else {
+        // Also works for DecodeN(LoadNKlass).
         kt = k->as_Type()->type()->isa_klassptr();
       }
       assert(kt != NULL, "TypeKlassPtr  required.");
@@ -1776,6 +1819,7 @@
       break;
     }
     case Op_LoadKlass:
+    case Op_LoadNKlass:
     {
       add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
       break;
@@ -1979,12 +2023,18 @@
       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;
--- a/src/share/vm/opto/graphKit.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/graphKit.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -532,7 +532,7 @@
         C->log()->elem("hot_throw preallocated='1' reason='%s'",
                        Deoptimization::trap_reason_name(reason));
       const TypeInstPtr* ex_con  = TypeInstPtr::make(ex_obj);
-      Node*              ex_node = _gvn.transform(new (C, 1) ConPNode(ex_con));
+      Node*              ex_node = _gvn.transform( ConNode::make(C, ex_con) );
 
       // Clear the detail message of the preallocated exception object.
       // Weblogic sometimes mutates the detail message of exceptions
@@ -1043,7 +1043,7 @@
   Node* akls = AllocateNode::Ideal_klass(obj, &_gvn);
   if (akls != NULL)  return akls;
   Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes());
-  return _gvn.transform( new (C, 3) LoadKlassNode(0, immutable_memory(), k_adr, TypeInstPtr::KLASS) );
+  return _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), k_adr, TypeInstPtr::KLASS) );
 }
 
 //-------------------------load_array_length-----------------------------------
@@ -2210,7 +2210,7 @@
   // cache which is mutable so can't use immutable memory.  Other
   // types load from the super-class display table which is immutable.
   Node *kmem = might_be_cache ? memory(p2) : immutable_memory();
-  Node *nkls = _gvn.transform( new (C, 3) LoadKlassNode( NULL, kmem, p2, _gvn.type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL ) );
+  Node *nkls = _gvn.transform( LoadKlassNode::make( _gvn, kmem, p2, _gvn.type(p2)->is_ptr(), TypeKlassPtr::OBJECT_OR_NULL ) );
 
   // Compile speed common case: ARE a subtype and we canNOT fail
   if( superklass == nkls )
@@ -2801,7 +2801,6 @@
     // initialization, and source them from the new InitializeNode.
     // This will allow us to observe initializations when they occur,
     // and link them properly (as a group) to the InitializeNode.
-    Node* klass_node = alloc->in(AllocateNode::KlassNode);
     assert(init->in(InitializeNode::Memory) == malloc, "");
     MergeMemNode* minit_in = MergeMemNode::make(C, malloc);
     init->set_req(InitializeNode::Memory, minit_in);
--- a/src/share/vm/opto/lcm.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/lcm.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -113,6 +113,7 @@
     case Op_LoadN:
     case Op_LoadS:
     case Op_LoadKlass:
+    case Op_LoadNKlass:
     case Op_LoadRange:
     case Op_LoadD_unaligned:
     case Op_LoadL_unaligned:
@@ -133,6 +134,7 @@
       if( mach->in(2) != val ) continue;
       break;                    // Found a memory op?
     case Op_StrComp:
+    case Op_AryEq:
       // Not a legit memory op for implicit null check regardless of
       // embedded loads
       continue;
--- a/src/share/vm/opto/library_call.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/library_call.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -163,6 +163,7 @@
   bool inline_native_newArray();
   bool inline_native_getLength();
   bool inline_array_copyOf(bool is_copyOfRange);
+  bool inline_array_equals();
   bool inline_native_clone(bool is_virtual);
   bool inline_native_Reflection_getCallerClass();
   bool inline_native_AtomicLong_get();
@@ -259,6 +260,7 @@
     switch (id) {
     case vmIntrinsics::_indexOf:
     case vmIntrinsics::_compareTo:
+    case vmIntrinsics::_equalsC:
       break;  // InlineNatives does not control String.compareTo
     default:
       return NULL;
@@ -272,6 +274,9 @@
   case vmIntrinsics::_indexOf:
     if (!SpecialStringIndexOf)  return NULL;
     break;
+  case vmIntrinsics::_equalsC:
+    if (!SpecialArraysEquals)  return NULL;
+    break;
   case vmIntrinsics::_arraycopy:
     if (!InlineArrayCopy)  return NULL;
     break;
@@ -586,6 +591,8 @@
     return inline_array_copyOf(false);
   case vmIntrinsics::_copyOfRange:
     return inline_array_copyOf(true);
+  case vmIntrinsics::_equalsC:
+    return inline_array_equals();
   case vmIntrinsics::_clone:
     return inline_native_clone(intrinsic()->is_virtual());
 
@@ -813,6 +820,24 @@
   return true;
 }
 
+//------------------------------inline_array_equals----------------------------
+bool LibraryCallKit::inline_array_equals() {
+
+  if (!Matcher::has_match_rule(Op_AryEq)) return false;
+
+  _sp += 2;
+  Node *argument2 = pop();
+  Node *argument1 = pop();
+
+  Node* equals =
+    _gvn.transform(new (C, 3) AryEqNode(control(),
+                                        argument1,
+                                        argument2)
+                   );
+  push(equals);
+  return true;
+}
+
 // Java version of String.indexOf(constant string)
 // class StringDecl {
 //   StringDecl(char[] ca) {
@@ -896,7 +921,7 @@
   Node* sourcea       = basic_plus_adr(string_object, string_object, value_offset);
   Node* source        = make_load(no_ctrl, sourcea, source_type, T_OBJECT, string_type->add_offset(value_offset));
 
-  Node* target = _gvn.transform(ConPNode::make(C, target_array));
+  Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array)) );
   jint target_length = target_array->length();
   const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin));
   const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot);
@@ -2168,7 +2193,7 @@
     // (They don't if CAS fails, but it isn't worth checking.)
     pre_barrier(control(), base, adr, alias_idx, newval, value_type, T_OBJECT);
 #ifdef _LP64
-    if (adr->bottom_type()->is_narrow()) {
+    if (adr->bottom_type()->is_ptr_to_narrowoop()) {
       cas = _gvn.transform(new (C, 5) CompareAndSwapNNode(control(), mem, adr,
                                                            EncodePNode::encode(&_gvn, newval),
                                                            EncodePNode::encode(&_gvn, oldval)));
@@ -2454,7 +2479,7 @@
   if (region == NULL)  never_see_null = true;
   Node* p = basic_plus_adr(mirror, offset);
   const TypeKlassPtr*  kls_type = TypeKlassPtr::OBJECT_OR_NULL;
-  Node* kls = _gvn.transform(new (C, 3) LoadKlassNode(0, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type));
+  Node* kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type) );
   _sp += nargs; // any deopt will start just before call to enclosing method
   Node* null_ctl = top();
   kls = null_check_oop(kls, &null_ctl, never_see_null);
@@ -2634,7 +2659,7 @@
       phi->add_req(makecon(TypeInstPtr::make(env()->Object_klass()->java_mirror())));
     // If we fall through, it's a plain class.  Get its _super.
     p = basic_plus_adr(kls, Klass::super_offset_in_bytes() + sizeof(oopDesc));
-    kls = _gvn.transform(new (C, 3) LoadKlassNode(0, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL));
+    kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, TypeKlassPtr::OBJECT_OR_NULL) );
     null_ctl = top();
     kls = null_check_oop(kls, &null_ctl);
     if (null_ctl != top()) {
@@ -2720,7 +2745,7 @@
     args[which_arg] = _gvn.transform(arg);
 
     Node* p = basic_plus_adr(arg, class_klass_offset);
-    Node* kls = new (C, 3) LoadKlassNode(0, immutable_memory(), p, adr_type, kls_type);
+    Node* kls = LoadKlassNode::make(_gvn, immutable_memory(), p, adr_type, kls_type);
     klasses[which_arg] = _gvn.transform(kls);
   }
 
@@ -2838,6 +2863,8 @@
   _sp += nargs;  // set original stack for use by uncommon_trap
   mirror = do_null_check(mirror, T_OBJECT);
   _sp -= nargs;
+  // If mirror or obj is dead, only null-path is taken.
+  if (stopped())  return true;
 
   enum { _normal_path = 1, _slow_path = 2, PATH_LIMIT };
   RegionNode* result_reg = new(C, PATH_LIMIT) RegionNode(PATH_LIMIT);
@@ -3827,24 +3854,22 @@
   if (!stopped()) {
     // Copy the fastest available way.
     // (No need for PreserveJVMState, since we're using it all up now.)
+    // TODO: generate fields/elements copies for small objects instead.
     Node* src  = obj;
     Node* dest = raw_obj;
-    Node* end  = dest;
     Node* size = _gvn.transform(alloc_siz);
 
     // Exclude the header.
     int base_off = instanceOopDesc::base_offset_in_bytes();
     if (UseCompressedOops) {
-      // copy the header gap though.
-      Node* sptr = basic_plus_adr(src,  base_off);
-      Node* dptr = basic_plus_adr(dest, base_off);
-      Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, raw_adr_type);
-      store_to_memory(control(), dptr, sval, T_INT, raw_adr_type);
-      base_off += sizeof(int);
+      assert(base_off % BytesPerLong != 0, "base with compressed oops");
+      // With compressed oops base_offset_in_bytes is 12 which creates
+      // the gap since countx is rounded by 8 bytes below.
+      // Copy klass and the gap.
+      base_off = instanceOopDesc::klass_offset_in_bytes();
     }
     src  = basic_plus_adr(src,  base_off);
     dest = basic_plus_adr(dest, base_off);
-    end  = basic_plus_adr(end,  size);
 
     // Compute the length also, if needed:
     Node* countx = size;
@@ -4388,7 +4413,7 @@
       // (At this point we can assume disjoint_bases, since types differ.)
       int ek_offset = objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc);
       Node* p1 = basic_plus_adr(dest_klass, ek_offset);
-      Node* n1 = new (C, 3) LoadKlassNode(0, immutable_memory(), p1, TypeRawPtr::BOTTOM);
+      Node* n1 = LoadKlassNode::make(_gvn, immutable_memory(), p1, TypeRawPtr::BOTTOM);
       Node* dest_elem_klass = _gvn.transform(n1);
       Node* cv = generate_checkcast_arraycopy(adr_type,
                                               dest_elem_klass,
--- a/src/share/vm/opto/loopnode.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/loopnode.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -2632,6 +2632,7 @@
     case Op_LoadD_unaligned:
     case Op_LoadL_unaligned:
     case Op_StrComp:            // Does a bunch of load-like effects
+    case Op_AryEq:
       pinned = false;
     }
     if( pinned ) {
--- a/src/share/vm/opto/loopopts.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/loopopts.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -464,6 +464,7 @@
     case T_FLOAT:
     case T_DOUBLE:
     case T_ADDRESS:             // (RawPtr)
+    case T_NARROWOOP:
       cost++;
       break;
     case T_OBJECT: {            // Base oops are OK, but not derived oops
--- a/src/share/vm/opto/macro.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/macro.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -458,7 +458,7 @@
         }
       } else if (use->is_SafePoint()) {
         SafePointNode* sfpt = use->as_SafePoint();
-        if (sfpt->has_non_debug_use(res)) {
+        if (sfpt->is_Call() && sfpt->as_Call()->has_non_debug_use(res)) {
           // Object is passed as argument.
           DEBUG_ONLY(disq_node = use;)
           NOT_PRODUCT(fail_eliminate = "Object is passed as argument";)
@@ -1282,12 +1282,6 @@
   }
   rawmem = make_store(control, rawmem, object, oopDesc::mark_offset_in_bytes(), mark_node, T_ADDRESS);
 
-  if (UseCompressedOops) {
-    Node *zeronode = makecon(TypeInt::ZERO);
-    // store uncompressed 0 into klass ptr to zero out gap.  The gap is
-    // used for primitive fields and has to be zeroed.
-    rawmem = make_store(control, rawmem, object, oopDesc::klass_gap_offset_in_bytes(), zeronode, T_INT);
-  }
   rawmem = make_store(control, rawmem, object, oopDesc::klass_offset_in_bytes(), klass_node, T_OBJECT);
   int header_size = alloc->minimum_header_size();  // conservatively small
 
--- a/src/share/vm/opto/matcher.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/matcher.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -52,7 +52,7 @@
 #ifdef ASSERT
   _old2new_map(C->comp_arena()),
 #endif
-  _shared_constants(C->comp_arena()),
+  _shared_nodes(C->comp_arena()),
   _reduceOp(reduceOp), _leftOp(leftOp), _rightOp(rightOp),
   _swallowed(swallowed),
   _begin_inst_chain_rule(_BEGIN_INST_CHAIN_RULE),
@@ -744,6 +744,7 @@
   if (nidx == Compile::AliasIdxBot && midx == Compile::AliasIdxTop) {
     switch (n->Opcode()) {
     case Op_StrComp:
+    case Op_AryEq:
     case Op_MemBarVolatile:
     case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type?
       nidx = Compile::AliasIdxTop;
@@ -880,7 +881,7 @@
         Node *m = n->in(i);          // Get input
         int op = m->Opcode();
         assert((op == Op_BoxLock) == jvms->is_monitor_use(i), "boxes only at monitor sites");
-        if( op == Op_ConI || op == Op_ConP ||
+        if( op == Op_ConI || op == Op_ConP || op == Op_ConN ||
             op == Op_ConF || op == Op_ConD || op == Op_ConL
             // || op == Op_BoxLock  // %%%% enable this and remove (+++) in chaitin.cpp
             ) {
@@ -1191,7 +1192,7 @@
   uint cnt = n->req();
   uint start = 1;
   if( mem != (Node*)1 ) start = MemNode::Memory+1;
-  if( n->Opcode() == Op_AddP ) {
+  if( n->is_AddP() ) {
     assert( mem == (Node*)1, "" );
     start = AddPNode::Base+1;
   }
@@ -1219,7 +1220,7 @@
   if( t->singleton() ) {
     // Never force constants into registers.  Allow them to match as
     // constants or registers.  Copies of the same value will share
-    // the same register.  See find_shared_constant.
+    // the same register.  See find_shared_node.
     return false;
   } else {                      // Not a constant
     // Stop recursion if they have different Controls.
@@ -1243,12 +1244,10 @@
       if( j == max_scan )       // No post-domination before scan end?
         return true;            // Then break the match tree up
     }
-
-    if (m->Opcode() == Op_DecodeN && m->outcnt() == 2) {
+    if (m->is_DecodeN() && Matcher::clone_shift_expressions) {
       // These are commonly used in address expressions and can
-      // efficiently fold into them in some cases but because they are
-      // consumed by AddP they commonly have two users.
-      if (m->raw_out(0) == m->raw_out(1) && m->raw_out(0)->Opcode() == Op_AddP) return false;
+      // efficiently fold into them on X64 in some cases.
+      return false;
     }
   }
 
@@ -1368,13 +1367,16 @@
 // which reduces the number of copies of a constant in the final
 // program.  The register allocator is free to split uses later to
 // split live ranges.
-MachNode* Matcher::find_shared_constant(Node* leaf, uint rule) {
-  if (!leaf->is_Con()) return NULL;
+MachNode* Matcher::find_shared_node(Node* leaf, uint rule) {
+  if (!leaf->is_Con() && !leaf->is_DecodeN()) return NULL;
 
   // See if this Con has already been reduced using this rule.
-  if (_shared_constants.Size() <= leaf->_idx) return NULL;
-  MachNode* last = (MachNode*)_shared_constants.at(leaf->_idx);
+  if (_shared_nodes.Size() <= leaf->_idx) return NULL;
+  MachNode* last = (MachNode*)_shared_nodes.at(leaf->_idx);
   if (last != NULL && rule == last->rule()) {
+    // Don't expect control change for DecodeN
+    if (leaf->is_DecodeN())
+      return last;
     // Get the new space root.
     Node* xroot = new_node(C->root());
     if (xroot == NULL) {
@@ -1420,9 +1422,9 @@
 MachNode *Matcher::ReduceInst( State *s, int rule, Node *&mem ) {
   assert( rule >= NUM_OPERANDS, "called with operand rule" );
 
-  MachNode* shared_con = find_shared_constant(s->_leaf, rule);
-  if (shared_con != NULL) {
-    return shared_con;
+  MachNode* shared_node = find_shared_node(s->_leaf, rule);
+  if (shared_node != NULL) {
+    return shared_node;
   }
 
   // Build the object to represent this state & prepare for recursive calls
@@ -1447,7 +1449,7 @@
     mach->ins_req(MemNode::Memory,mem);
 
   // If the _leaf is an AddP, insert the base edge
-  if( leaf->Opcode() == Op_AddP )
+  if( leaf->is_AddP() )
     mach->ins_req(AddPNode::Base,leaf->in(AddPNode::Base));
 
   uint num_proj = _proj_list.size();
@@ -1475,9 +1477,9 @@
     guarantee(_proj_list.size() == num_proj, "no allocation during spill generation");
   }
 
-  if (leaf->is_Con()) {
+  if (leaf->is_Con() || leaf->is_DecodeN()) {
     // Record the con for sharing
-    _shared_constants.map(leaf->_idx, ex);
+    _shared_nodes.map(leaf->_idx, ex);
   }
 
   return ex;
@@ -1716,6 +1718,7 @@
         mstack.push(n->in(0), Pre_Visit);     // Visit Control input
         continue;                             // while (mstack.is_nonempty())
       case Op_StrComp:
+      case Op_AryEq:
         set_shared(n); // Force result into register (it will be anyways)
         break;
       case Op_ConP: {  // Convert pointers above the centerline to NUL
@@ -1726,6 +1729,14 @@
         }
         break;
       }
+      case Op_ConN: {  // Convert narrow pointers above the centerline to NUL
+        TypeNode *tn = n->as_Type(); // Constants derive from type nodes
+        const TypePtr* tp = tn->type()->is_narrowoop()->make_oopptr();
+        if (tp->_ptr == TypePtr::AnyNull) {
+          tn->set_type(TypeNarrowOop::NULL_PTR);
+        }
+        break;
+      }
       case Op_Binary:         // These are introduced in the Post_Visit state.
         ShouldNotReachHere();
         break;
@@ -1760,6 +1771,7 @@
       case Op_LoadF:
       case Op_LoadI:
       case Op_LoadKlass:
+      case Op_LoadNKlass:
       case Op_LoadL:
       case Op_LoadS:
       case Op_LoadP:
@@ -1817,7 +1829,7 @@
             Node *adr = m->in(AddPNode::Address);
 
             // Intel, ARM and friends can handle 2 adds in addressing mode
-            if( clone_shift_expressions && adr->Opcode() == Op_AddP &&
+            if( clone_shift_expressions && adr->is_AddP() &&
                 // AtomicAdd is not an addressing expression.
                 // Cheap to find it by looking for screwy base.
                 !adr->in(AddPNode::Base)->is_top() ) {
@@ -1891,6 +1903,7 @@
       case Op_CMoveF:
       case Op_CMoveI:
       case Op_CMoveL:
+      case Op_CMoveN:
       case Op_CMoveP: {
         // Restructure into a binary tree for Matching.  It's possible that
         // we could move this code up next to the graph reshaping for IfNodes
--- a/src/share/vm/opto/matcher.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/matcher.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -48,7 +48,7 @@
   void ReduceOper( State *s, int newrule, Node *&mem, MachNode *mach );
 
   // If this node already matched using "rule", return the MachNode for it.
-  MachNode* find_shared_constant(Node* con, uint rule);
+  MachNode* find_shared_node(Node* n, uint rule);
 
   // Convert a dense opcode number to an expanded rule number
   const int *_reduceOp;
@@ -81,7 +81,7 @@
 
   Node_List &_proj_list;        // For Machine nodes killing many values
 
-  Node_Array _shared_constants;
+  Node_Array _shared_nodes;
 
   debug_only(Node_Array _old2new_map;)   // Map roots of ideal-trees to machine-roots
 
--- a/src/share/vm/opto/memnode.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/memnode.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -133,7 +133,9 @@
     PhiNode *mphi = result->as_Phi();
     assert(mphi->bottom_type() == Type::MEMORY, "memory phi required");
     const TypePtr *t = mphi->adr_type();
-    if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM) {
+    if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM ||
+        t->isa_oopptr() && !t->is_oopptr()->is_instance() &&
+        t->is_oopptr()->cast_to_instance(t_oop->instance_id()) == t_oop) {
       // clone the Phi with our address type
       result = mphi->split_out_instance(t_adr, igvn);
     } else {
@@ -154,7 +156,7 @@
                        phase->C->must_alias(adr_check, alias_idx );
     // Sometimes dead array references collapse to a[-1], a[-2], or a[-3]
     if( !consistent && adr_check != NULL && !adr_check->empty() &&
-           tp->isa_aryptr() &&    tp->offset() == Type::OffsetBot &&
+               tp->isa_aryptr() &&        tp->offset() == Type::OffsetBot &&
         adr_check->isa_aryptr() && adr_check->offset() != Type::OffsetBot &&
         ( adr_check->offset() == arrayOopDesc::length_offset_in_bytes() ||
           adr_check->offset() == oopDesc::klass_offset_in_bytes() ||
@@ -251,21 +253,31 @@
   if (dom == NULL || dom->is_top() || sub == NULL || sub->is_top())
     return false; // Conservative answer for dead code
 
-  // Check 'dom'.
+  // Check 'dom'. Skip Proj and CatchProj nodes.
   dom = dom->find_exact_control(dom);
   if (dom == NULL || dom->is_top())
     return false; // Conservative answer for dead code
 
-  if (dom->is_Start() || dom->is_Root() || dom == sub)
+  if (dom == sub) {
+    // For the case when, for example, 'sub' is Initialize and the original
+    // 'dom' is Proj node of the 'sub'.
+    return false;
+  }
+
+  if (dom->is_Con() || dom->is_Start() || dom->is_Root() || dom == sub)
     return true;
 
   // 'dom' dominates 'sub' if its control edge and control edges
   // of all its inputs dominate or equal to sub's control edge.
 
   // Currently 'sub' is either Allocate, Initialize or Start nodes.
-  assert(sub->is_Allocate() || sub->is_Initialize() || sub->is_Start(), "expecting only these nodes");
+  // Or Region for the check in LoadNode::Ideal();
+  // 'sub' should have sub->in(0) != NULL.
+  assert(sub->is_Allocate() || sub->is_Initialize() || sub->is_Start() ||
+         sub->is_Region(), "expecting only these nodes");
 
   // Get control edge of 'sub'.
+  Node* orig_sub = sub;
   sub = sub->find_exact_control(sub->in(0));
   if (sub == NULL || sub->is_top())
     return false; // Conservative answer for dead code
@@ -291,14 +303,16 @@
 
     for (uint next = 0; next < dom_list.size(); next++) {
       Node* n = dom_list.at(next);
+      if (n == orig_sub)
+        return false; // One of dom's inputs dominated by sub.
       if (!n->is_CFG() && n->pinned()) {
         // Check only own control edge for pinned non-control nodes.
         n = n->find_exact_control(n->in(0));
         if (n == NULL || n->is_top())
           return false; // Conservative answer for dead code
         assert(n->is_CFG(), "expecting control");
-      }
-      if (n->is_Start() || n->is_Root()) {
+        dom_list.push(n);
+      } else if (n->is_Con() || n->is_Start() || n->is_Root()) {
         only_dominating_controls = true;
       } else if (n->is_CFG()) {
         if (n->dominates(sub, nlist))
@@ -308,12 +322,11 @@
       } else {
         // First, own control edge.
         Node* m = n->find_exact_control(n->in(0));
-        if (m == NULL)
-          continue;
-        if (m->is_top())
-          return false; // Conservative answer for dead code
-        dom_list.push(m);
-
+        if (m != NULL) {
+          if (m->is_top())
+            return false; // Conservative answer for dead code
+          dom_list.push(m);
+        }
         // Now, the rest of edges.
         uint cnt = n->req();
         for (uint i = 1; i < cnt; i++) {
@@ -577,6 +590,9 @@
 // Find any cast-away of null-ness and keep its control.  Null cast-aways are
 // going away in this pass and we need to make this memory op depend on the
 // gating null check.
+Node *MemNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
+  return Ideal_common_DU_postCCP(ccp, this, in(MemNode::Address));
+}
 
 // I tried to leave the CastPP's in.  This makes the graph more accurate in
 // some sense; we get to keep around the knowledge that an oop is not-null
@@ -586,15 +602,14 @@
 // some of the more trivial cases in the optimizer.  Removing more useless
 // Phi's started allowing Loads to illegally float above null checks.  I gave
 // up on this approach.  CNC 10/20/2000
-Node *MemNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
-  Node *ctr = in(MemNode::Control);
-  Node *mem = in(MemNode::Memory);
-  Node *adr = in(MemNode::Address);
+// This static method may be called not from MemNode (EncodePNode calls it).
+// Only the control edge of the node 'n' might be updated.
+Node *MemNode::Ideal_common_DU_postCCP( PhaseCCP *ccp, Node* n, Node* adr ) {
   Node *skipped_cast = NULL;
   // Need a null check?  Regular static accesses do not because they are
   // from constant addresses.  Array ops are gated by the range check (which
   // always includes a NULL check).  Just check field ops.
-  if( !ctr ) {
+  if( n->in(MemNode::Control) == NULL ) {
     // Scan upwards for the highest location we can place this memory op.
     while( true ) {
       switch( adr->Opcode() ) {
@@ -619,10 +634,10 @@
         }
         // CastPP is going away in this pass!  We need this memory op to be
         // control-dependent on the test that is guarding the CastPP.
-        ccp->hash_delete(this);
-        set_req(MemNode::Control, adr->in(0));
-        ccp->hash_insert(this);
-        return this;
+        ccp->hash_delete(n);
+        n->set_req(MemNode::Control, adr->in(0));
+        ccp->hash_insert(n);
+        return n;
 
       case Op_Phi:
         // Attempt to float above a Phi to some dominating point.
@@ -653,10 +668,10 @@
           adr = adr->in(1);
           continue;
         }
-        ccp->hash_delete(this);
-        set_req(MemNode::Control, adr->in(0));
-        ccp->hash_insert(this);
-        return this;
+        ccp->hash_delete(n);
+        n->set_req(MemNode::Control, adr->in(0));
+        ccp->hash_insert(n);
+        return n;
 
         // List of "safe" opcodes; those that implicitly block the memory
         // op below any null check.
@@ -665,10 +680,13 @@
       case Op_LoadP:            // Loading from within a klass
       case Op_LoadN:            // Loading from within a klass
       case Op_LoadKlass:        // Loading from within a klass
+      case Op_LoadNKlass:       // Loading from within a klass
       case Op_ConP:             // Loading from a klass
+      case Op_ConN:             // Loading from a klass
       case Op_CreateEx:         // Sucking up the guts of an exception oop
       case Op_Con:              // Reading from TLS
       case Op_CMoveP:           // CMoveP is pinned
+      case Op_CMoveN:           // CMoveN is pinned
         break;                  // No progress
 
       case Op_Proj:             // Direct call to an allocation routine
@@ -677,8 +695,8 @@
         {
           assert(adr->as_Proj()->_con == TypeFunc::Parms, "must be return value");
           const Node* call = adr->in(0);
-          if (call->is_CallStaticJava()) {
-            const CallStaticJavaNode* call_java = call->as_CallStaticJava();
+          if (call->is_CallJava()) {
+            const CallJavaNode* call_java = call->as_CallJava();
             const TypeTuple *r = call_java->tf()->range();
             assert(r->cnt() > TypeFunc::Parms, "must return value");
             const Type* ret_type = r->field_at(TypeFunc::Parms);
@@ -750,7 +768,7 @@
   case T_ADDRESS: return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_ptr()    );
   case T_OBJECT:
 #ifdef _LP64
-    if (adr->bottom_type()->is_narrow()) {
+    if (adr->bottom_type()->is_ptr_to_narrowoop()) {
       const TypeNarrowOop* narrowtype;
       if (rt->isa_narrowoop()) {
         narrowtype = rt->is_narrowoop();
@@ -762,10 +780,10 @@
       return DecodeNNode::decode(&gvn, load);
     } else
 #endif
-      {
-        assert(!adr->bottom_type()->is_narrow(), "should have got back a narrow oop");
-        return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr());
-      }
+    {
+      assert(!adr->bottom_type()->is_ptr_to_narrowoop(), "should have got back a narrow oop");
+      return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr());
+    }
   }
   ShouldNotReachHere();
   return (LoadNode*)NULL;
@@ -1119,6 +1137,127 @@
   return NULL;
 }
 
+//------------------------------split_through_phi------------------------------
+// Split instance field load through Phi.
+Node *LoadNode::split_through_phi(PhaseGVN *phase) {
+  Node* mem     = in(MemNode::Memory);
+  Node* address = in(MemNode::Address);
+  const TypePtr *addr_t = phase->type(address)->isa_ptr();
+  const TypeOopPtr *t_oop = addr_t->isa_oopptr();
+
+  assert(mem->is_Phi() && (t_oop != NULL) &&
+         t_oop->is_instance_field(), "invalide conditions");
+
+  Node *region = mem->in(0);
+  if (region == NULL) {
+    return NULL; // Wait stable graph
+  }
+  uint cnt = mem->req();
+  for( uint i = 1; i < cnt; i++ ) {
+    Node *in = mem->in(i);
+    if( in == NULL ) {
+      return NULL; // Wait stable graph
+    }
+  }
+  // Check for loop invariant.
+  if (cnt == 3) {
+    for( uint i = 1; i < cnt; i++ ) {
+      Node *in = mem->in(i);
+      Node* m = MemNode::optimize_memory_chain(in, addr_t, phase);
+      if (m == mem) {
+        set_req(MemNode::Memory, mem->in(cnt - i)); // Skip this phi.
+        return this;
+      }
+    }
+  }
+  // Split through Phi (see original code in loopopts.cpp).
+  assert(phase->C->have_alias_type(addr_t), "instance should have alias type");
+
+  // Do nothing here if Identity will find a value
+  // (to avoid infinite chain of value phis generation).
+  if ( !phase->eqv(this, this->Identity(phase)) )
+    return NULL;
+
+  // Skip the split if the region dominates some control edge of the address.
+  if (cnt == 3 && !MemNode::all_controls_dominate(address, region))
+    return NULL;
+
+  const Type* this_type = this->bottom_type();
+  int this_index  = phase->C->get_alias_index(addr_t);
+  int this_offset = addr_t->offset();
+  int this_iid    = addr_t->is_oopptr()->instance_id();
+  int wins = 0;
+  PhaseIterGVN *igvn = phase->is_IterGVN();
+  Node *phi = new (igvn->C, region->req()) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset);
+  for( uint i = 1; i < region->req(); i++ ) {
+    Node *x;
+    Node* the_clone = NULL;
+    if( region->in(i) == phase->C->top() ) {
+      x = phase->C->top();      // Dead path?  Use a dead data op
+    } else {
+      x = this->clone();        // Else clone up the data op
+      the_clone = x;            // Remember for possible deletion.
+      // Alter data node to use pre-phi inputs
+      if( this->in(0) == region ) {
+        x->set_req( 0, region->in(i) );
+      } else {
+        x->set_req( 0, NULL );
+      }
+      for( uint j = 1; j < this->req(); j++ ) {
+        Node *in = this->in(j);
+        if( in->is_Phi() && in->in(0) == region )
+          x->set_req( j, in->in(i) ); // Use pre-Phi input for the clone
+      }
+    }
+    // Check for a 'win' on some paths
+    const Type *t = x->Value(igvn);
+
+    bool singleton = t->singleton();
+
+    // See comments in PhaseIdealLoop::split_thru_phi().
+    if( singleton && t == Type::TOP ) {
+      singleton &= region->is_Loop() && (i != LoopNode::EntryControl);
+    }
+
+    if( singleton ) {
+      wins++;
+      x = igvn->makecon(t);
+    } else {
+      // We now call Identity to try to simplify the cloned node.
+      // Note that some Identity methods call phase->type(this).
+      // Make sure that the type array is big enough for
+      // our new node, even though we may throw the node away.
+      // (This tweaking with igvn only works because x is a new node.)
+      igvn->set_type(x, t);
+      Node *y = x->Identity(igvn);
+      if( y != x ) {
+        wins++;
+        x = y;
+      } else {
+        y = igvn->hash_find(x);
+        if( y ) {
+          wins++;
+          x = y;
+        } else {
+          // Else x is a new node we are keeping
+          // We do not need register_new_node_with_optimizer
+          // because set_type has already been called.
+          igvn->_worklist.push(x);
+        }
+      }
+    }
+    if (x != the_clone && the_clone != NULL)
+      igvn->remove_dead_node(the_clone);
+    phi->set_req(i, x);
+  }
+  if( wins > 0 ) {
+    // Record Phi
+    igvn->register_new_node_with_optimizer(phi);
+    return phi;
+  }
+  igvn->remove_dead_node(phi);
+  return NULL;
+}
 
 //------------------------------Ideal------------------------------------------
 // If the load is from Field memory and the pointer is non-null, we can
@@ -1176,112 +1315,9 @@
     const TypeOopPtr *t_oop = addr_t->isa_oopptr();
     if (can_reshape && opt_mem->is_Phi() &&
         (t_oop != NULL) && t_oop->is_instance_field()) {
-      assert(t_oop->offset() != Type::OffsetBot && t_oop->offset() != Type::OffsetTop, "");
-      Node *region = opt_mem->in(0);
-      uint cnt = opt_mem->req();
-      for( uint i = 1; i < cnt; i++ ) {
-        Node *in = opt_mem->in(i);
-        if( in == NULL ) {
-          region = NULL; // Wait stable graph
-          break;
-        }
-      }
-      if (region != NULL) {
-        // Check for loop invariant.
-        if (cnt == 3) {
-          for( uint i = 1; i < cnt; i++ ) {
-            Node *in = opt_mem->in(i);
-            Node* m = MemNode::optimize_memory_chain(in, addr_t, phase);
-            if (m == opt_mem) {
-              set_req(MemNode::Memory, opt_mem->in(cnt - i)); // Skip this phi.
-              return this;
-            }
-          }
-        }
-        // Split through Phi (see original code in loopopts.cpp).
-        assert(phase->C->have_alias_type(addr_t), "instance should have alias type");
-
-        // Do nothing here if Identity will find a value
-        // (to avoid infinite chain of value phis generation).
-        if ( !phase->eqv(this, this->Identity(phase)) )
-          return NULL;
-
-        const Type* this_type = this->bottom_type();
-        int this_index  = phase->C->get_alias_index(addr_t);
-        int this_offset = addr_t->offset();
-        int this_iid    = addr_t->is_oopptr()->instance_id();
-        int wins = 0;
-        PhaseIterGVN *igvn = phase->is_IterGVN();
-        Node *phi = new (igvn->C, region->req()) PhiNode(region, this_type, NULL, this_iid, this_index, this_offset);
-        for( uint i = 1; i < region->req(); i++ ) {
-          Node *x;
-          Node* the_clone = NULL;
-          if( region->in(i) == phase->C->top() ) {
-            x = phase->C->top();      // Dead path?  Use a dead data op
-          } else {
-            x = this->clone();        // Else clone up the data op
-            the_clone = x;            // Remember for possible deletion.
-            // Alter data node to use pre-phi inputs
-            if( this->in(0) == region ) {
-              x->set_req( 0, region->in(i) );
-            } else {
-              x->set_req( 0, NULL );
-            }
-            for( uint j = 1; j < this->req(); j++ ) {
-              Node *in = this->in(j);
-              if( in->is_Phi() && in->in(0) == region )
-                x->set_req( j, in->in(i) ); // Use pre-Phi input for the clone
-            }
-          }
-          // Check for a 'win' on some paths
-          const Type *t = x->Value(igvn);
-
-          bool singleton = t->singleton();
-
-          // See comments in PhaseIdealLoop::split_thru_phi().
-          if( singleton && t == Type::TOP ) {
-            singleton &= region->is_Loop() && (i != LoopNode::EntryControl);
-          }
-
-          if( singleton ) {
-            wins++;
-            x = igvn->makecon(t);
-          } else {
-            // We now call Identity to try to simplify the cloned node.
-            // Note that some Identity methods call phase->type(this).
-            // Make sure that the type array is big enough for
-            // our new node, even though we may throw the node away.
-            // (This tweaking with igvn only works because x is a new node.)
-            igvn->set_type(x, t);
-            Node *y = x->Identity(igvn);
-            if( y != x ) {
-              wins++;
-              x = y;
-            } else {
-              y = igvn->hash_find(x);
-              if( y ) {
-                wins++;
-                x = y;
-              } else {
-                // Else x is a new node we are keeping
-                // We do not need register_new_node_with_optimizer
-                // because set_type has already been called.
-                igvn->_worklist.push(x);
-              }
-            }
-          }
-          if (x != the_clone && the_clone != NULL)
-            igvn->remove_dead_node(the_clone);
-          phi->set_req(i, x);
-        }
-        if( wins > 0 ) {
-          // Record Phi
-          igvn->register_new_node_with_optimizer(phi);
-          return phi;
-        } else {
-          igvn->remove_dead_node(phi);
-        }
-      }
+      // Split instance field load through Phi.
+      Node* result = split_through_phi(phase);
+      if (result != NULL) return result;
     }
   }
 
@@ -1585,8 +1621,31 @@
 }
 
 //=============================================================================
+//----------------------------LoadKlassNode::make------------------------------
+// Polymorphic factory method:
+Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* at, const TypeKlassPtr *tk ) {
+  Compile* C = gvn.C;
+  Node *ctl = NULL;
+  // sanity check the alias category against the created node type
+  const TypeOopPtr *adr_type = adr->bottom_type()->isa_oopptr();
+  assert(adr_type != NULL, "expecting TypeOopPtr");
+#ifdef _LP64
+  if (adr_type->is_ptr_to_narrowoop()) {
+    const TypeNarrowOop* narrowtype = tk->is_oopptr()->make_narrowoop();
+    Node* load_klass = gvn.transform(new (C, 3) LoadNKlassNode(ctl, mem, adr, at, narrowtype));
+    return DecodeNNode::decode(&gvn, load_klass);
+  }
+#endif
+  assert(!adr_type->is_ptr_to_narrowoop(), "should have got back a narrow oop");
+  return new (C, 3) LoadKlassNode(ctl, mem, adr, at, tk);
+}
+
 //------------------------------Value------------------------------------------
 const Type *LoadKlassNode::Value( PhaseTransform *phase ) const {
+  return klass_value_common(phase);
+}
+
+const Type *LoadNode::klass_value_common( PhaseTransform *phase ) const {
   // Either input is TOP ==> the result is TOP
   const Type *t1 = phase->type( in(MemNode::Memory) );
   if (t1 == Type::TOP)  return Type::TOP;
@@ -1718,6 +1777,10 @@
 // To clean up reflective code, simplify k.java_mirror.as_klass to plain k.
 // Also feed through the klass in Allocate(...klass...)._klass.
 Node* LoadKlassNode::Identity( PhaseTransform *phase ) {
+  return klass_identity_common(phase);
+}
+
+Node* LoadNode::klass_identity_common(PhaseTransform *phase ) {
   Node* x = LoadNode::Identity(phase);
   if (x != this)  return x;
 
@@ -1776,6 +1839,34 @@
   return this;
 }
 
+
+//------------------------------Value------------------------------------------
+const Type *LoadNKlassNode::Value( PhaseTransform *phase ) const {
+  const Type *t = klass_value_common(phase);
+
+  if (t == TypePtr::NULL_PTR) {
+    return TypeNarrowOop::NULL_PTR;
+  }
+  if (t != Type::TOP && !t->isa_narrowoop()) {
+    assert(t->is_oopptr(), "sanity");
+    t = t->is_oopptr()->make_narrowoop();
+  }
+  return t;
+}
+
+//------------------------------Identity---------------------------------------
+// To clean up reflective code, simplify k.java_mirror.as_klass to narrow k.
+// Also feed through the klass in Allocate(...klass...)._klass.
+Node* LoadNKlassNode::Identity( PhaseTransform *phase ) {
+  Node *x = klass_identity_common(phase);
+
+  const Type *t = phase->type( x );
+  if( t == Type::TOP ) return x;
+  if( t->isa_narrowoop()) return x;
+
+  return EncodePNode::encode(phase, x);
+}
+
 //------------------------------Value-----------------------------------------
 const Type *LoadRangeNode::Value( PhaseTransform *phase ) const {
   // Either input is TOP ==> the result is TOP
@@ -1836,7 +1927,7 @@
   case T_ADDRESS:
   case T_OBJECT:
 #ifdef _LP64
-    if (adr->bottom_type()->is_narrow() ||
+    if (adr->bottom_type()->is_ptr_to_narrowoop() ||
         (UseCompressedOops && val->bottom_type()->isa_klassptr() &&
          adr->bottom_type()->isa_rawptr())) {
       const TypePtr* type = val->bottom_type()->is_ptr();
@@ -2312,6 +2403,13 @@
   return remove_dead_region(phase, can_reshape) ? this : NULL;
 }
 
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.  Strip out
+// control copies
+Node *AryEqNode::Ideal(PhaseGVN *phase, bool can_reshape){
+  return remove_dead_region(phase, can_reshape) ? this : NULL;
+}
+
 
 //=============================================================================
 MemBarNode::MemBarNode(Compile* C, int alias_idx, Node* precedent)
--- a/src/share/vm/opto/memnode.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/memnode.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -72,7 +72,8 @@
   // This one should probably be a phase-specific function:
   static bool all_controls_dominate(Node* dom, Node* sub);
 
-  // Is this Node a MemNode or some descendent?  Default is YES.
+  // Find any cast-away of null-ness and keep its control.
+  static  Node *Ideal_common_DU_postCCP( PhaseCCP *ccp, Node* n, Node* adr );
   virtual Node *Ideal_DU_postCCP( PhaseCCP *ccp );
 
   virtual const class TypePtr *adr_type() const;  // returns bottom_type of address
@@ -150,6 +151,9 @@
   // zero out the control input.
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
 
+  // Split instance field load through Phi.
+  Node* split_through_phi(PhaseGVN *phase);
+
   // Recover original value from boxed values
   Node *eliminate_autobox(PhaseGVN *phase);
 
@@ -157,6 +161,10 @@
   // then call the virtual add() to set the type.
   virtual const Type *Value( PhaseTransform *phase ) const;
 
+  // Common methods for LoadKlass and LoadNKlass nodes.
+  const Type *klass_value_common( PhaseTransform *phase ) const;
+  Node *klass_identity_common( PhaseTransform *phase );
+
   virtual uint ideal_reg() const;
   virtual const Type *bottom_type() const;
   // Following method is copied from TypeNode:
@@ -358,14 +366,35 @@
 // Load a Klass from an object
 class LoadKlassNode : public LoadPNode {
 public:
-  LoadKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk = TypeKlassPtr::OBJECT )
+  LoadKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeKlassPtr *tk )
     : LoadPNode(c,mem,adr,at,tk) {}
   virtual int Opcode() const;
   virtual const Type *Value( PhaseTransform *phase ) const;
   virtual Node *Identity( PhaseTransform *phase );
   virtual bool depends_only_on_test() const { return true; }
+
+  // Polymorphic factory method:
+  static Node* make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* at,
+                     const TypeKlassPtr *tk = TypeKlassPtr::OBJECT );
 };
 
+//------------------------------LoadNKlassNode---------------------------------
+// Load a narrow Klass from an object.
+class LoadNKlassNode : public LoadNNode {
+public:
+  LoadNKlassNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const TypeNarrowOop *tk )
+    : LoadNNode(c,mem,adr,at,tk) {}
+  virtual int Opcode() const;
+  virtual uint ideal_reg() const { return Op_RegN; }
+  virtual int store_Opcode() const { return Op_StoreN; }
+  virtual BasicType memory_type() const { return T_NARROWOOP; }
+
+  virtual const Type *Value( PhaseTransform *phase ) const;
+  virtual Node *Identity( PhaseTransform *phase );
+  virtual bool depends_only_on_test() const { return true; }
+};
+
+
 //------------------------------LoadSNode--------------------------------------
 // Load a short (16bits signed) from memory
 class LoadSNode : public LoadNode {
@@ -696,6 +725,18 @@
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
 };
 
+//------------------------------AryEq---------------------------------------
+class AryEqNode: public Node {
+public:
+  AryEqNode(Node *control, Node* s1, Node* s2): Node(control, s1, s2) {};
+  virtual int Opcode() const;
+  virtual bool depends_only_on_test() const { return false; }
+  virtual const Type* bottom_type() const { return TypeInt::BOOL; }
+  virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; }
+  virtual uint ideal_reg() const { return Op_RegI; }
+  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+};
+
 //------------------------------MemBar-----------------------------------------
 // There are different flavors of Memory Barriers to match the Java Memory
 // Model.  Monitor-enter and volatile-load act as Aquires: no following ref
--- a/src/share/vm/opto/node.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/node.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1039,76 +1039,125 @@
 //--------------------------dominates------------------------------------------
 // Helper function for MemNode::all_controls_dominate().
 // Check if 'this' control node dominates or equal to 'sub' control node.
+// We already know that if any path back to Root or Start reaches 'this',
+// then all paths so, so this is a simple search for one example,
+// not an exhaustive search for a counterexample.
 bool Node::dominates(Node* sub, Node_List &nlist) {
   assert(this->is_CFG(), "expecting control");
   assert(sub != NULL && sub->is_CFG(), "expecting control");
 
+  // detect dead cycle without regions
+  int iterations_without_region_limit = DominatorSearchLimit;
+
   Node* orig_sub = sub;
+  Node* dom      = this;
+  bool  met_dom  = false;
   nlist.clear();
-  bool this_dominates = false;
-  uint region_input = 0;
-  while (sub != NULL) {        // walk 'sub' up the chain to 'this'
-    if (sub == this) {
+
+  // Walk 'sub' backward up the chain to 'dom', watching for regions.
+  // After seeing 'dom', continue up to Root or Start.
+  // If we hit a region (backward split point), it may be a loop head.
+  // Keep going through one of the region's inputs.  If we reach the
+  // same region again, go through a different input.  Eventually we
+  // will either exit through the loop head, or give up.
+  // (If we get confused, break out and return a conservative 'false'.)
+  while (sub != NULL) {
+    if (sub->is_top())  break; // Conservative answer for dead code.
+    if (sub == dom) {
       if (nlist.size() == 0) {
         // No Region nodes except loops were visited before and the EntryControl
         // path was taken for loops: it did not walk in a cycle.
         return true;
-      } else if (!this_dominates) {
+      } else if (met_dom) {
+        break;          // already met before: walk in a cycle
+      } else {
         // Region nodes were visited. Continue walk up to Start or Root
         // to make sure that it did not walk in a cycle.
-        this_dominates = true; // first time meet
-      } else {
-        return false;          // already met before: walk in a cycle
-      }
+        met_dom = true; // first time meet
+        iterations_without_region_limit = DominatorSearchLimit; // Reset
+     }
+    }
+    if (sub->is_Start() || sub->is_Root()) {
+      // Success if we met 'dom' along a path to Start or Root.
+      // We assume there are no alternative paths that avoid 'dom'.
+      // (This assumption is up to the caller to ensure!)
+      return met_dom;
     }
-    if (sub->is_Start() || sub->is_Root())
-      return this_dominates;
-
-    Node* up = sub->find_exact_control(sub->in(0));
-    if (up == NULL || up->is_top())
-      return false; // Conservative answer for dead code
-
+    Node* up = sub->in(0);
+    // Normalize simple pass-through regions and projections:
+    up = sub->find_exact_control(up);
+    // If sub == up, we found a self-loop.  Try to push past it.
     if (sub == up && sub->is_Loop()) {
-      up = sub->in(0); // in(LoopNode::EntryControl);
+      // Take loop entry path on the way up to 'dom'.
+      up = sub->in(1); // in(LoopNode::EntryControl);
+    } else if (sub == up && sub->is_Region() && sub->req() != 3) {
+      // Always take in(1) path on the way up to 'dom' for clone regions
+      // (with only one input) or regions which merge > 2 paths
+      // (usually used to merge fast/slow paths).
+      up = sub->in(1);
     } else if (sub == up && sub->is_Region()) {
-      uint i = 1;
-      if (nlist.size() == 0) {
-        // No Region nodes (except Loops) were visited before.
-        // Take first valid path on the way up to 'this'.
-      } else if (nlist.at(nlist.size() - 1) == sub) {
-        // This Region node was just visited. Take other path.
-        i = region_input + 1;
-        nlist.pop();
-      } else {
-        // Was this Region node visited before?
-        uint size = nlist.size();
-        for (uint j = 0; j < size; j++) {
-          if (nlist.at(j) == sub) {
-            return false; // The Region node was visited before. Give up.
+      // Try both paths for Regions with 2 input paths (it may be a loop head).
+      // It could give conservative 'false' answer without information
+      // which region's input is the entry path.
+      iterations_without_region_limit = DominatorSearchLimit; // Reset
+
+      bool region_was_visited_before = false;
+      // Was this Region node visited before?
+      // If so, we have reached it because we accidentally took a
+      // loop-back edge from 'sub' back into the body of the loop,
+      // and worked our way up again to the loop header 'sub'.
+      // So, take the first unexplored path on the way up to 'dom'.
+      for (int j = nlist.size() - 1; j >= 0; j--) {
+        intptr_t ni = (intptr_t)nlist.at(j);
+        Node* visited = (Node*)(ni & ~1);
+        bool  visited_twice_already = ((ni & 1) != 0);
+        if (visited == sub) {
+          if (visited_twice_already) {
+            // Visited 2 paths, but still stuck in loop body.  Give up.
+            return false;
           }
-        }
-        // The Region node was not visited before.
-        // Take first valid path on the way up to 'this'.
-      }
-      for (; i < sub->req(); i++) {
-        Node* in = sub->in(i);
-        if (in != NULL && !in->is_top() && in != sub) {
+          // The Region node was visited before only once.
+          // (We will repush with the low bit set, below.)
+          nlist.remove(j);
+          // We will find a new edge and re-insert.
+          region_was_visited_before = true;
           break;
         }
       }
-      if (i < sub->req()) {
-        nlist.push(sub);
-        up = sub->in(i);
-        region_input = i;
+
+      // Find an incoming edge which has not been seen yet; walk through it.
+      assert(up == sub, "");
+      uint skip = region_was_visited_before ? 1 : 0;
+      for (uint i = 1; i < sub->req(); i++) {
+        Node* in = sub->in(i);
+        if (in != NULL && !in->is_top() && in != sub) {
+          if (skip == 0) {
+            up = in;
+            break;
+          }
+          --skip;               // skip this nontrivial input
+        }
       }
+
+      // Set 0 bit to indicate that both paths were taken.
+      nlist.push((Node*)((intptr_t)sub + (region_was_visited_before ? 1 : 0)));
     }
-    if (sub == up)
-      return false;    // some kind of tight cycle
-    if (orig_sub == up)
-      return false;    // walk in a cycle
 
+    if (up == sub) {
+      break;    // some kind of tight cycle
+    }
+    if (up == orig_sub && met_dom) {
+      // returned back after visiting 'dom'
+      break;    // some kind of cycle
+    }
+    if (--iterations_without_region_limit < 0) {
+      break;    // dead cycle
+    }
     sub = up;
   }
+
+  // Did not meet Root or Start node in pred. chain.
+  // Conservative answer for dead code.
   return false;
 }
 
--- a/src/share/vm/opto/node.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/node.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -53,6 +53,8 @@
 class ConNode;
 class CountedLoopNode;
 class CountedLoopEndNode;
+class DecodeNNode;
+class EncodePNode;
 class FastLockNode;
 class FastUnlockNode;
 class IfNode;
@@ -438,6 +440,12 @@
 public:
   // Globally replace this node by a given new node, updating all uses.
   void replace_by(Node* new_node);
+  // Globally replace this node by a given new node, updating all uses
+  // and cutting input edges of old node.
+  void subsume_by(Node* new_node) {
+    replace_by(new_node);
+    disconnect_inputs(NULL);
+  }
   void set_req_X( uint i, Node *n, PhaseIterGVN *igvn );
   // Find the one non-null required input.  RegionNode only
   Node *nonnull_req() const;
@@ -577,6 +585,8 @@
       DEFINE_CLASS_ID(CheckCastPP, Type, 2)
       DEFINE_CLASS_ID(CMove, Type, 3)
       DEFINE_CLASS_ID(SafePointScalarObject, Type, 4)
+      DEFINE_CLASS_ID(DecodeN, Type, 5)
+      DEFINE_CLASS_ID(EncodeP, Type, 6)
 
     DEFINE_CLASS_ID(Mem,   Node, 6)
       DEFINE_CLASS_ID(Load,  Mem, 0)
@@ -685,6 +695,8 @@
   DEFINE_CLASS_QUERY(Cmp)
   DEFINE_CLASS_QUERY(CountedLoop)
   DEFINE_CLASS_QUERY(CountedLoopEnd)
+  DEFINE_CLASS_QUERY(DecodeN)
+  DEFINE_CLASS_QUERY(EncodeP)
   DEFINE_CLASS_QUERY(FastLock)
   DEFINE_CLASS_QUERY(FastUnlock)
   DEFINE_CLASS_QUERY(If)
--- a/src/share/vm/opto/output.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/output.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -48,6 +48,7 @@
   // Initialize the space for the BufferBlob used to find and verify
   // instruction size in MachNode::emit_size()
   init_scratch_buffer_blob();
+  if (failing())  return; // Out of memory
 
   // Make sure I can find the Start Node
   Block_Array& bbs = _cfg->_bbs;
--- a/src/share/vm/opto/parse1.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/parse1.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1901,7 +1901,7 @@
   // finalization.  In general this will fold up since the concrete
   // class is often visible so the access flags are constant.
   Node* klass_addr = basic_plus_adr( receiver, receiver, oopDesc::klass_offset_in_bytes() );
-  Node* klass = _gvn.transform(new (C, 3) LoadKlassNode(NULL, immutable_memory(), klass_addr, TypeInstPtr::KLASS));
+  Node* klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), klass_addr, TypeInstPtr::KLASS) );
 
   Node* access_flags_addr = basic_plus_adr(klass, klass, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc));
   Node* access_flags = make_load(NULL, access_flags_addr, TypeInt::INT, T_INT);
--- a/src/share/vm/opto/parseHelper.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/parseHelper.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -38,7 +38,7 @@
 
   // Get method
   const TypeInstPtr* method_type = TypeInstPtr::make(TypePtr::Constant, method->klass(), true, method, 0);
-  Node *method_node = _gvn.transform( new (C, 1) ConPNode(method_type) );
+  Node *method_node = _gvn.transform( ConNode::make(C, method_type) );
 
   kill_dead_locals();
 
@@ -143,7 +143,7 @@
   int klass_offset = oopDesc::klass_offset_in_bytes();
   Node* p = basic_plus_adr( ary, ary, klass_offset );
   // p's type is array-of-OOPS plus klass_offset
-  Node* array_klass = _gvn.transform(new (C, 3) LoadKlassNode(0, immutable_memory(), p, TypeInstPtr::KLASS));
+  Node* array_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS) );
   // Get the array klass
   const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr();
 
@@ -189,7 +189,7 @@
   // Extract the array element class
   int element_klass_offset = objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc);
   Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset);
-  Node *a_e_klass = _gvn.transform(new (C, 3) LoadKlassNode(0, immutable_memory(), p2, tak));
+  Node *a_e_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p2, tak) );
 
   // Check (the hard way) and throw if not a subklass.
   // Result is ignored, we just need the CFG effects.
--- a/src/share/vm/opto/type.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/type.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -311,8 +311,18 @@
   mreg2type[Op_RegFlags] = TypeInt::CC;
 
   TypeAryPtr::RANGE   = TypeAryPtr::make( TypePtr::BotPTR, TypeAry::make(Type::BOTTOM,TypeInt::POS), current->env()->Object_klass(), false, arrayOopDesc::length_offset_in_bytes());
-  // There is no shared klass for Object[].  See note in TypeAryPtr::klass().
-  TypeAryPtr::OOPS    = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInstPtr::BOTTOM,TypeInt::POS), NULL /*ciArrayKlass::make(o)*/,  false,  Type::OffsetBot);
+
+  TypeAryPtr::NARROWOOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeNarrowOop::BOTTOM, TypeInt::POS), NULL /*ciArrayKlass::make(o)*/,  false,  Type::OffsetBot);
+
+#ifdef _LP64
+  if (UseCompressedOops) {
+    TypeAryPtr::OOPS  = TypeAryPtr::NARROWOOPS;
+  } else
+#endif
+  {
+    // There is no shared klass for Object[].  See note in TypeAryPtr::klass().
+    TypeAryPtr::OOPS  = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInstPtr::BOTTOM,TypeInt::POS), NULL /*ciArrayKlass::make(o)*/,  false,  Type::OffsetBot);
+  }
   TypeAryPtr::BYTES   = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::BYTE      ,TypeInt::POS), ciTypeArrayKlass::make(T_BYTE),   true,  Type::OffsetBot);
   TypeAryPtr::SHORTS  = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::SHORT     ,TypeInt::POS), ciTypeArrayKlass::make(T_SHORT),  true,  Type::OffsetBot);
   TypeAryPtr::CHARS   = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::CHAR      ,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR),   true,  Type::OffsetBot);
@@ -321,9 +331,10 @@
   TypeAryPtr::FLOATS  = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::FLOAT        ,TypeInt::POS), ciTypeArrayKlass::make(T_FLOAT),  true,  Type::OffsetBot);
   TypeAryPtr::DOUBLES = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::DOUBLE       ,TypeInt::POS), ciTypeArrayKlass::make(T_DOUBLE), true,  Type::OffsetBot);
 
-  TypeAryPtr::_array_body_type[T_NARROWOOP] = NULL; // what should this be?
+  // Nobody should ask _array_body_type[T_NARROWOOP]. Use NULL as assert.
+  TypeAryPtr::_array_body_type[T_NARROWOOP] = NULL;
   TypeAryPtr::_array_body_type[T_OBJECT]  = TypeAryPtr::OOPS;
-  TypeAryPtr::_array_body_type[T_ARRAY]   = TypeAryPtr::OOPS;   // arrays are stored in oop arrays
+  TypeAryPtr::_array_body_type[T_ARRAY]   = TypeAryPtr::OOPS; // arrays are stored in oop arrays
   TypeAryPtr::_array_body_type[T_BYTE]    = TypeAryPtr::BYTES;
   TypeAryPtr::_array_body_type[T_BOOLEAN] = TypeAryPtr::BYTES;  // boolean[] is a byte array
   TypeAryPtr::_array_body_type[T_SHORT]   = TypeAryPtr::SHORTS;
@@ -696,7 +707,7 @@
   ResourceMark rm;
   Dict d(cmpkey,hashkey);       // Stop recursive type dumping
   dump2(d,1, st);
-  if (isa_ptr() && is_ptr()->is_narrow()) {
+  if (is_ptr_to_narrowoop()) {
     st->print(" [narrow]");
   }
 }
@@ -929,6 +940,7 @@
   case InstPtr:
   case KlassPtr:
   case AryPtr:
+  case NarrowOop:
   case Int:
   case Long:
   case FloatTop:
@@ -1075,6 +1087,7 @@
   case InstPtr:
   case KlassPtr:
   case AryPtr:
+  case NarrowOop:
   case Long:
   case FloatTop:
   case FloatCon:
@@ -1082,7 +1095,6 @@
   case DoubleTop:
   case DoubleCon:
   case DoubleBot:
-  case NarrowOop:
   case Bottom:                  // Ye Olde Default
     return Type::BOTTOM;
   default:                      // All else is a mistake
@@ -1317,6 +1329,7 @@
   case InstPtr:
   case KlassPtr:
   case AryPtr:
+  case NarrowOop:
   case Int:
   case FloatTop:
   case FloatCon:
@@ -2146,6 +2159,67 @@
 // Convenience common pre-built type.
 const TypeOopPtr *TypeOopPtr::BOTTOM;
 
+//------------------------------TypeOopPtr-------------------------------------
+TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id )
+  : TypePtr(t, ptr, offset),
+    _const_oop(o), _klass(k),
+    _klass_is_exact(xk),
+    _is_ptr_to_narrowoop(false),
+    _instance_id(instance_id) {
+#ifdef _LP64
+  if (UseCompressedOops && _offset != 0) {
+    if (klass() == NULL) {
+      assert(this->isa_aryptr(), "only arrays without klass");
+      _is_ptr_to_narrowoop = true;
+    } else if (_offset == oopDesc::klass_offset_in_bytes()) {
+      _is_ptr_to_narrowoop = true;
+    } else if (this->isa_aryptr()) {
+      _is_ptr_to_narrowoop = (klass()->is_obj_array_klass() &&
+                             _offset != arrayOopDesc::length_offset_in_bytes());
+    } else if (klass() == ciEnv::current()->Class_klass() &&
+               (_offset == java_lang_Class::klass_offset_in_bytes() ||
+                _offset == java_lang_Class::array_klass_offset_in_bytes())) {
+      // Special hidden fields from the Class.
+      assert(this->isa_instptr(), "must be an instance ptr.");
+      _is_ptr_to_narrowoop = true;
+    } else if (klass()->is_instance_klass()) {
+      ciInstanceKlass* ik = klass()->as_instance_klass();
+      ciField* field = NULL;
+      if (this->isa_klassptr()) {
+        // Perm objects don't use compressed references, except for
+        // static fields which are currently compressed.
+        field = ik->get_field_by_offset(_offset, true);
+        if (field != NULL) {
+          BasicType basic_elem_type = field->layout_type();
+          _is_ptr_to_narrowoop = (basic_elem_type == T_OBJECT ||
+                                  basic_elem_type == T_ARRAY);
+        }
+      } else if (_offset == OffsetBot || _offset == OffsetTop) {
+        // unsafe access
+        _is_ptr_to_narrowoop = true;
+      } else { // exclude unsafe ops
+        assert(this->isa_instptr(), "must be an instance ptr.");
+        // Field which contains a compressed oop references.
+        field = ik->get_field_by_offset(_offset, false);
+        if (field != NULL) {
+          BasicType basic_elem_type = field->layout_type();
+          _is_ptr_to_narrowoop = (basic_elem_type == T_OBJECT ||
+                                  basic_elem_type == T_ARRAY);
+        } else if (klass()->equals(ciEnv::current()->Object_klass())) {
+          // Compile::find_alias_type() cast exactness on all types to verify
+          // that it does not affect alias type.
+          _is_ptr_to_narrowoop = true;
+        } else {
+          // Type for the copy start in LibraryCallKit::inline_native_clone().
+          assert(!klass_is_exact(), "only non-exact klass");
+          _is_ptr_to_narrowoop = true;
+        }
+      }
+    }
+  }
+#endif
+}
+
 //------------------------------make-------------------------------------------
 const TypeOopPtr *TypeOopPtr::make(PTR ptr,
                                    int offset) {
@@ -2593,9 +2667,13 @@
 //-----------------------------cast_to_instance-------------------------------
 const TypeOopPtr *TypeInstPtr::cast_to_instance(int instance_id) const {
   if( instance_id == _instance_id) return this;
-  bool exact = (instance_id == UNKNOWN_INSTANCE) ? _klass_is_exact : true;
-
-  return make(ptr(), klass(), exact, const_oop(), _offset, instance_id);
+  bool exact = true;
+  PTR  ptr_t = NotNull;
+  if (instance_id == UNKNOWN_INSTANCE) {
+    exact = _klass_is_exact;
+    ptr_t = _ptr;
+  }
+  return make(ptr_t, klass(), exact, const_oop(), _offset, instance_id);
 }
 
 //------------------------------xmeet_unloaded---------------------------------
@@ -3014,6 +3092,7 @@
 // Convenience common pre-built types.
 const TypeAryPtr *TypeAryPtr::RANGE;
 const TypeAryPtr *TypeAryPtr::OOPS;
+const TypeAryPtr *TypeAryPtr::NARROWOOPS;
 const TypeAryPtr *TypeAryPtr::BYTES;
 const TypeAryPtr *TypeAryPtr::SHORTS;
 const TypeAryPtr *TypeAryPtr::CHARS;
@@ -3063,8 +3142,13 @@
 //-----------------------------cast_to_instance-------------------------------
 const TypeOopPtr *TypeAryPtr::cast_to_instance(int instance_id) const {
   if( instance_id == _instance_id) return this;
-  bool exact = (instance_id == UNKNOWN_INSTANCE) ? _klass_is_exact : true;
-  return make(ptr(), const_oop(), _ary, klass(), exact, _offset, instance_id);
+  bool exact = true;
+  PTR  ptr_t = NotNull;
+  if (instance_id == UNKNOWN_INSTANCE) {
+    exact = _klass_is_exact;
+    ptr_t = _ptr;
+  }
+  return make(ptr_t, const_oop(), _ary, klass(), exact, _offset, instance_id);
 }
 
 //-----------------------------narrow_size_type-------------------------------
@@ -3547,7 +3631,7 @@
     k_ary = ciTypeArrayKlass::make(el->basic_type());
   }
 
-  if( this != TypeAryPtr::OOPS )
+  if( this != TypeAryPtr::OOPS ) {
     // The _klass field acts as a cache of the underlying
     // ciKlass for this array type.  In order to set the field,
     // we need to cast away const-ness.
@@ -3562,6 +3646,11 @@
     // a bit less efficient than caching, but calls to
     // TypeAryPtr::OOPS->klass() are not common enough to matter.
     ((TypeAryPtr*)this)->_klass = k_ary;
+    if (UseCompressedOops && k_ary != NULL && k_ary->is_obj_array_klass() &&
+        _offset != 0 && _offset != arrayOopDesc::length_offset_in_bytes()) {
+      ((TypeAryPtr*)this)->_is_ptr_to_narrowoop = true;
+    }
+  }
   return k_ary;
 }
 
--- a/src/share/vm/opto/type.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/opto/type.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -191,9 +191,8 @@
   virtual const Type *filter( const Type *kills ) const;
 
   // Returns true if this pointer points at memory which contains a
-  // compressed oop references.  In 32-bit builds it's non-virtual
-  // since we don't support compressed oops at all in the mode.
-  LP64_ONLY(virtual) bool is_narrow() const { return false; }
+  // compressed oop references.
+  bool is_ptr_to_narrowoop() const;
 
   // Convenience access
   float getf() const;
@@ -213,8 +212,8 @@
   const TypePtr    *isa_ptr() const;             // Returns NULL if not ptr type
   const TypeRawPtr *isa_rawptr() const;          // NOT Java oop
   const TypeRawPtr *is_rawptr() const;           // Asserts is rawptr
-  const TypeNarrowOop  *is_narrowoop() const;        // Java-style GC'd pointer
-  const TypeNarrowOop  *isa_narrowoop() const;       // Returns NULL if not oop ptr type
+  const TypeNarrowOop  *is_narrowoop() const;    // Java-style GC'd pointer
+  const TypeNarrowOop  *isa_narrowoop() const;   // Returns NULL if not oop ptr type
   const TypeOopPtr   *isa_oopptr() const;        // Returns NULL if not oop ptr type
   const TypeOopPtr   *is_oopptr() const;         // Java-style GC'd pointer
   const TypeKlassPtr *isa_klassptr() const;      // Returns NULL if not KlassPtr
@@ -643,7 +642,7 @@
 // Some kind of oop (Java pointer), either klass or instance or array.
 class TypeOopPtr : public TypePtr {
 protected:
-  TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id ) : TypePtr(t, ptr, offset), _const_oop(o), _klass(k), _klass_is_exact(xk), _instance_id(instance_id) { }
+  TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id );
 public:
   virtual bool eq( const Type *t ) const;
   virtual int  hash() const;             // Type specific hashing
@@ -660,8 +659,9 @@
   ciKlass*      _klass;       // Klass object
   // Does the type exclude subclasses of the klass?  (Inexact == polymorphic.)
   bool          _klass_is_exact;
+  bool          _is_ptr_to_narrowoop;
 
-  int          _instance_id;   // if not UNKNOWN_INSTANCE, indicates that this is a particular instance
+  int           _instance_id;  // if not UNKNOWN_INSTANCE, indicates that this is a particular instance
                                // of this type which is distinct.  This is the  the node index of the
                                // node creating this instance
 
@@ -696,6 +696,11 @@
   ciObject* const_oop()    const { return _const_oop; }
   virtual ciKlass* klass() const { return _klass;     }
   bool klass_is_exact()    const { return _klass_is_exact; }
+
+  // Returns true if this pointer points at memory which contains a
+  // compressed oop references.
+  bool is_ptr_to_narrowoop_nv() const { return _is_ptr_to_narrowoop; }
+
   bool is_instance()       const { return _instance_id != UNKNOWN_INSTANCE; }
   uint instance_id()       const { return _instance_id; }
   bool is_instance_field() const { return _instance_id != UNKNOWN_INSTANCE && _offset >= 0; }
@@ -716,12 +721,6 @@
   // returns the equivalent compressed version of this pointer type
   virtual const TypeNarrowOop* make_narrowoop() const;
 
-#ifdef _LP64
-  virtual bool is_narrow() const {
-    return (UseCompressedOops && _offset != 0);
-  }
-#endif
-
   virtual const Type *xmeet( const Type *t ) const;
   virtual const Type *xdual() const;    // Compute dual right now.
 
@@ -843,15 +842,10 @@
   virtual const Type *xmeet( const Type *t ) const;
   virtual const Type *xdual() const;    // Compute dual right now.
 
-#ifdef _LP64
-  virtual bool is_narrow() const {
-    return (UseCompressedOops && klass() != NULL && _offset != 0);
-  }
-#endif
-
   // Convenience common pre-built types.
   static const TypeAryPtr *RANGE;
   static const TypeAryPtr *OOPS;
+  static const TypeAryPtr *NARROWOOPS;
   static const TypeAryPtr *BYTES;
   static const TypeAryPtr *SHORTS;
   static const TypeAryPtr *CHARS;
@@ -901,18 +895,6 @@
   virtual const Type    *xmeet( const Type *t ) const;
   virtual const Type    *xdual() const;      // Compute dual right now.
 
-#ifdef _LP64
-  // Perm objects don't use compressed references, except for static fields
-  // which are currently compressed
-  virtual bool is_narrow() const {
-    if (UseCompressedOops && _offset != 0 && _klass->is_instance_klass()) {
-      ciInstanceKlass* ik = _klass->as_instance_klass();
-      return ik != NULL && ik->get_field_by_offset(_offset, true) != NULL;
-    }
-    return false;
-  }
-#endif
-
   // Convenience common pre-built types.
   static const TypeKlassPtr* OBJECT; // Not-null object klass or below
   static const TypeKlassPtr* OBJECT_OR_NULL; // Maybe-null version of same
@@ -921,7 +903,7 @@
 #endif
 };
 
-//------------------------------TypeNarrowOop----------------------------------------
+//------------------------------TypeNarrowOop----------------------------------
 // A compressed reference to some kind of Oop.  This type wraps around
 // a preexisting TypeOopPtr and forwards most of it's operations to
 // the underlying type.  It's only real purpose is to track the
@@ -1013,6 +995,14 @@
 };
 
 //------------------------------accessors--------------------------------------
+inline bool Type::is_ptr_to_narrowoop() const {
+#ifdef _LP64
+  return (isa_oopptr() != NULL && is_oopptr()->is_ptr_to_narrowoop_nv());
+#else
+  return false;
+#endif
+}
+
 inline float Type::getf() const {
   assert( _base == FloatCon, "Not a FloatCon" );
   return ((TypeF*)this)->_f;
--- a/src/share/vm/runtime/arguments.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/runtime/arguments.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -1174,9 +1174,11 @@
   // field offset to determine free list chunk markers.
   // Check that UseCompressedOops can be set with the max heap size allocated
   // by ergonomics.
-  if (!UseConcMarkSweepGC && MaxHeapSize <= max_heap_for_compressed_oops()) {
+  if (MaxHeapSize <= max_heap_for_compressed_oops()) {
     if (FLAG_IS_DEFAULT(UseCompressedOops)) {
-      FLAG_SET_ERGO(bool, UseCompressedOops, true);
+      // Leave compressed oops off by default. Uncomment
+      // the following line to return it to default status.
+      // FLAG_SET_ERGO(bool, UseCompressedOops, true);
     }
   } else {
     if (UseCompressedOops && !FLAG_IS_DEFAULT(UseCompressedOops)) {
@@ -1312,6 +1314,9 @@
   if (AggressiveOpts && FLAG_IS_DEFAULT(DoEscapeAnalysis)) {
     FLAG_SET_DEFAULT(DoEscapeAnalysis, true);
   }
+  if (AggressiveOpts && FLAG_IS_DEFAULT(SpecialArraysEquals)) {
+    FLAG_SET_DEFAULT(SpecialArraysEquals, true);
+  }
 #endif
 
   if (AggressiveOpts) {
--- a/src/share/vm/runtime/globals.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/runtime/globals.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -291,6 +291,9 @@
             "Use 32-bit object references in 64-bit VM. "                   \
             "lp64_product means flag is always constant in 32 bit VM")      \
                                                                             \
+  lp64_product(bool, CheckCompressedOops, trueInDebug,                      \
+            "generate checks in encoding/decoding code")                    \
+                                                                            \
   /* UseMembar is theoretically a temp flag used for memory barrier         \
    * removal testing.  It was supposed to be removed before FCS but has     \
    * been re-added (see 6401008) */                                         \
@@ -457,6 +460,9 @@
   develop(bool, SpecialStringIndexOf, true,                                 \
           "special version of string indexOf")                              \
                                                                             \
+  product(bool, SpecialArraysEquals, false,                                 \
+          "special version of Arrays.equals(char[],char[])")                \
+                                                                            \
   develop(bool, TraceCallFixup, false,                                      \
           "traces all call fixups")                                         \
                                                                             \
@@ -2240,6 +2246,9 @@
   product(bool, AggressiveOpts, false,                                      \
           "Enable aggressive optimizations - see arguments.cpp")            \
                                                                             \
+  product(bool, UseStringCache, false,                                      \
+          "Enable String cache capabilities on String.java")                \
+                                                                            \
   /* statistics */                                                          \
   develop(bool, UseVTune, false,                                            \
           "enable support for Intel's VTune profiler")                      \
--- a/src/share/vm/runtime/java.hpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/runtime/java.hpp	Tue Jun 17 15:27:05 2008 -0700
@@ -68,8 +68,24 @@
   static bool is_jdk13x_version()           { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 3; }
   static bool is_jdk14x_version()           { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 4; }
   static bool is_jdk15x_version()           { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 5; }
-  static bool is_jdk16x_version()           { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 6; }
-  static bool is_jdk17x_version()           { assert(is_jdk_version_initialized(), "must have been initialized"); return _jdk_version == 7; }
+
+  static bool is_jdk16x_version() {
+    if (is_jdk_version_initialized()) {
+      return _jdk_version == 6;
+    } else {
+      assert(is_pre_jdk16_version(), "must have been initialized");
+      return false;
+    }
+  }
+
+  static bool is_jdk17x_version() {
+    if (is_jdk_version_initialized()) {
+      return _jdk_version == 7;
+    } else {
+      assert(is_pre_jdk16_version(), "must have been initialized");
+      return false;
+    }
+  }
 
   static bool supports_thread_park_blocker() { return _version_info.thread_park_blocker; }
 
@@ -85,14 +101,22 @@
   }
   static bool is_gte_jdk16x_version() {
     // Keep the semantics of this that the version number is >= 1.6
-    assert(is_jdk_version_initialized(), "Not initialized");
-    return _jdk_version >= 6;
+    if (is_jdk_version_initialized()) {
+      return _jdk_version >= 6;
+    } else {
+      assert(is_pre_jdk16_version(), "Not initialized");
+      return false;
+    }
   }
 
   static bool is_gte_jdk17x_version() {
     // Keep the semantics of this that the version number is >= 1.7
-    assert(is_jdk_version_initialized(), "Not initialized");
-    return _jdk_version >= 7;
+    if (is_jdk_version_initialized()) {
+      return _jdk_version >= 7;
+    } else {
+      assert(is_pre_jdk16_version(), "Not initialized");
+      return false;
+    }
   }
 
   static bool is_jdk_version_initialized() {
--- a/src/share/vm/runtime/thread.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/runtime/thread.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -2926,21 +2926,42 @@
     }
 
     if (AggressiveOpts) {
-      // Forcibly initialize java/util/HashMap and mutate the private
-      // static final "frontCacheEnabled" field before we start creating instances
+      {
+        // Forcibly initialize java/util/HashMap and mutate the private
+        // static final "frontCacheEnabled" field before we start creating instances
 #ifdef ASSERT
-      klassOop tmp_k = SystemDictionary::find(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
-      assert(tmp_k == NULL, "java/util/HashMap should not be loaded yet");
+        klassOop tmp_k = SystemDictionary::find(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
+        assert(tmp_k == NULL, "java/util/HashMap should not be loaded yet");
 #endif
-      klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
-      KlassHandle k = KlassHandle(THREAD, k_o);
-      guarantee(k.not_null(), "Must find java/util/HashMap");
-      instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
-      ik->initialize(CHECK_0);
-      fieldDescriptor fd;
-      // Possible we might not find this field; if so, don't break
-      if (ik->find_local_field(vmSymbols::frontCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
-        k()->bool_field_put(fd.offset(), true);
+        klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
+        KlassHandle k = KlassHandle(THREAD, k_o);
+        guarantee(k.not_null(), "Must find java/util/HashMap");
+        instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
+        ik->initialize(CHECK_0);
+        fieldDescriptor fd;
+        // Possible we might not find this field; if so, don't break
+        if (ik->find_local_field(vmSymbols::frontCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
+          k()->bool_field_put(fd.offset(), true);
+        }
+      }
+
+      if (UseStringCache) {
+        // Forcibly initialize java/lang/String and mutate the private
+        // static final "stringCacheEnabled" field before we start creating instances
+#ifdef ASSERT
+        klassOop tmp_k = SystemDictionary::find(vmSymbolHandles::java_lang_String(), Handle(), Handle(), CHECK_0);
+        assert(tmp_k == NULL, "java/lang/String should not be loaded yet");
+#endif
+        klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_String(), Handle(), Handle(), CHECK_0);
+        KlassHandle k = KlassHandle(THREAD, k_o);
+        guarantee(k.not_null(), "Must find java/lang/String");
+        instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
+        ik->initialize(CHECK_0);
+        fieldDescriptor fd;
+        // Possible we might not find this field; if so, don't break
+        if (ik->find_local_field(vmSymbols::stringCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
+          k()->bool_field_put(fd.offset(), true);
+        }
       }
     }
 
--- a/src/share/vm/runtime/vmStructs.cpp	Tue Jun 10 10:22:49 2008 -0700
+++ b/src/share/vm/runtime/vmStructs.cpp	Tue Jun 17 15:27:05 2008 -0700
@@ -894,6 +894,7 @@
   /*******************************************************************/   \
                                                                           \
   declare_unsigned_integer_type(size_t)                                   \
+  declare_integer_type(ssize_t)                                           \
   declare_unsigned_integer_type(const size_t)                             \
   declare_integer_type(intx)                                              \
   declare_integer_type(intptr_t)                                          \
@@ -1694,7 +1695,12 @@
   declare_constant(markOopDesc::no_hash)                                  \
   declare_constant(markOopDesc::no_hash_in_place)                         \
   declare_constant(markOopDesc::no_lock_in_place)                         \
-  declare_constant(markOopDesc::max_age)
+  declare_constant(markOopDesc::max_age)                                  \
+                                                                          \
+  /* Constants in markOop used by CMS. */                                 \
+  declare_constant(markOopDesc::cms_shift)                                \
+  declare_constant(markOopDesc::cms_mask)                                 \
+  declare_constant(markOopDesc::size_shift)                               \
 
   /* NOTE that we do not use the last_entry() macro here; it is used   */
   /* in vmStructs_<os>_<cpu>.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and */
@@ -1958,6 +1964,7 @@
                         GENERATE_STATIC_VM_STRUCT_ENTRY)
 
   VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \
+                 GENERATE_NONSTATIC_VM_STRUCT_ENTRY, \
                  GENERATE_STATIC_VM_STRUCT_ENTRY)
 #endif // SERIALGC
 
@@ -2099,6 +2106,7 @@
              CHECK_STATIC_VM_STRUCT_ENTRY);
 
   VM_STRUCTS_CMS(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
+             CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY,
              CHECK_STATIC_VM_STRUCT_ENTRY);
 #endif // SERIALGC
 
@@ -2203,6 +2211,7 @@
   debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT, \
                                    ENSURE_FIELD_TYPE_PRESENT));
   debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, \
+                            ENSURE_FIELD_TYPE_PRESENT, \
                             ENSURE_FIELD_TYPE_PRESENT));
 #endif // SERIALGC
   debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, \
--- a/test/compiler/6659207/Test.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/test/compiler/6659207/Test.java	Tue Jun 17 15:27:05 2008 -0700
@@ -1,23 +1,24 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
+ * Copyright 1997-2002 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
  *
  */
 
--- a/test/compiler/6661247/Test.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/test/compiler/6661247/Test.java	Tue Jun 17 15:27:05 2008 -0700
@@ -1,23 +1,24 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
+ * Copyright 1997-2002 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
  *
  */
 
--- a/test/compiler/6663621/IVTest.java	Tue Jun 10 10:22:49 2008 -0700
+++ b/test/compiler/6663621/IVTest.java	Tue Jun 17 15:27:05 2008 -0700
@@ -1,23 +1,24 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- *
+ * Copyright 1997-2002 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *
- *
- *
- *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- *
- *
- *
- *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
  *
- *
- *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- *
- *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
  *
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/6689060/Test.java	Tue Jun 17 15:27:05 2008 -0700
@@ -0,0 +1,577 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * @test
+ * @bug 6689060
+ * @summary Escape Analysis does not work with Compressed Oops
+ * @run main/othervm -Xbatch -XX:CompileCommand=exclude,Test.dummy -XX:+AggressiveOpts Test
+ */
+
+import java.lang.reflect.Array;
+
+class Point {
+  int x;
+  int y;
+  Point next;
+  int ax[];
+  int ay[];
+  Point pax[];
+  Point pay[];
+  public Point getNext() {
+    return next;
+  }
+}
+
+public class Test {
+
+  void dummy() {
+    // Empty method to verify correctness of DebugInfo.
+    // Use -XX:CompileCommand=exclude,Test.dummy
+  }
+
+  int ival(int i) {
+    return i*2;
+  }
+
+  int test80(int y, int l, int i) {
+    Point p = new Point();
+    p.ax = new int[2];
+    p.ay = new int[2];
+    int x = 3;
+    p.ax[0] = x;
+    p.ay[1] = 3 * x + y;
+    dummy();
+    return p.ax[0] * p.ay[1];
+  }
+
+  int test81(int y, int l, int i) {
+    Point p = new Point();
+    p.ax = new int[2];
+    p.ay = new int[2];
+    int x = 3;
+    p.ax[0] = x;
+    p.ay[1] = 3 * x + y;
+    dummy();
+    return p.ax[0] * p.ay[1];
+  }
+
+
+  int test44(int y) {
+    Point p1 = new Point();
+    p1.x = ival(3);
+    dummy();
+    p1.y = 3 * p1.x + y;
+    return p1.y;
+  }
+
+  int test43(int y) {
+    Point p1 = new Point();
+    if ( (y & 1) == 1 ) {
+      p1.x = ival(3);
+    } else {
+      p1.x = ival(5);
+    }
+    dummy();
+    p1.y = 3 * p1.x + y;
+    return p1.y;
+  }
+
+  int test42(int y) {
+    Point p1 = new Point();
+    p1.x = 3;
+    for (int i = 0; i < y; i++) {
+      if ( (i & 1) == 1 ) {
+        p1.x += 4;
+      }
+    }
+    p1.y = 3 * y + p1.x;
+    return p1.y;
+  }
+
+  int test40(int y) {
+    Point p1 = new Point();
+    if ( (y & 1) == 1 ) {
+      p1.x = 3;
+    } else {
+      p1.x = 5;
+    }
+    p1.y = 3 * p1.x + y;
+    return p1.y;
+  }
+
+  int test41(int y) {
+    Point p1 = new Point();
+    if ( (y & 1) == 1 ) {
+      p1.x += 4;
+    } else {
+      p1.x += 5;
+    }
+    p1.y = 3 * p1.x + y;
+    return p1.y;
+  }
+
+  Point test00(int y) {
+    int x = 3;
+    Point p = new Point();
+    p.x = x;
+    p.y = 3 * x + y;
+    return p;
+  }
+
+  Point test01(int y) {
+    int x = 3;
+    Point p = new Point();
+    p.x = x;
+    p.y = 3 * x + y;
+    dummy();
+    return p;
+  }
+
+  Point test02(int y) {
+    int x = 3;
+    Point p1 = null;
+    for (int i = 0; i < y; i++) {
+      Point p2 = new Point();
+      p2.x = x;
+      p2.y = 3 * y + x;
+      p2.next = p1;
+      p1 = p2;
+    }
+    return p1;
+  }
+
+  Point test03(int y) {
+    int x = 3;
+    Point p1 = null;
+    for (int i = 0; i < y; i++) {
+      Point p2 = new Point();
+      p2.x = x;
+      p2.y = 3 * y + x;
+      p2.next = p1;
+      p1 = p2;
+    }
+    dummy();
+    return p1;
+  }
+
+  Point test04(int y) {
+    int x = 3;
+    Point p1 = null;
+    for (int i = 0; i < y; i++) {
+      Point p2 = new Point();
+      p2.x = x;
+      p2.y = 3 * y + x;
+      p2.next = p1;
+      dummy();
+      p1 = p2;
+    }
+    return p1;
+  }
+
+  int test05(int y) {
+    int x = 3;
+    Point p1 = new Point();
+    for (int i = 0; i < y; i++) {
+      Point p2 = new Point();
+      p2.x = x;
+      p2.y = 3 * y + x;
+      p1.next = p2;
+      p1 = p2;
+    }
+    return p1.y;
+  }
+
+  int test0(int y) {
+    int x = 3;
+    Point p = new Point();
+    p.x = x;
+    p.y = 3 * x + y;
+    dummy();
+    return p.x * p.y;
+  }
+
+  int test1(int y) {
+    Point p = new Point();
+    if ( (y & 1) == 1 ) {
+      p = new Point(); // Kill previous
+    }
+    int x = 3;
+    p.x = x;
+    p.y = 3 * x + y;
+    dummy();
+    return p.x * p.y;
+  }
+
+  int test2(int y) {
+    Point p1 = new Point();
+    Point p2 = new Point();
+    p1.x = 3;
+    p2.x = 4;
+    p1.y = 3 * p2.x + y;
+    p2.y = 3 * p1.x + y;
+    dummy();
+    return p1.y * p2.y;
+  }
+
+  int test3(int y, Point p1) {
+    Point p2 = new Point();
+    p1.x = 3;
+    p2.x = 4;
+    p1.y = 3 * p2.x + y;
+    p2.y = 3 * p1.x + y;
+    dummy();
+    return p1.y * p2.y;
+  }
+
+  int test4(int y) {
+    Point p1 = new Point();
+    Point p2 = new Point();
+    if ( (y & 1) == 1 ) {
+      p1.x = 3;
+      p2.x = 4;
+    } else {
+      p1.x = 5;
+      p2.x = 6;
+    }
+    p1.y = 3 * p2.x + y;
+    p2.y = 3 * p1.x + y;
+    dummy();
+    return p1.y * p2.y;
+  }
+
+  int test5(int y, Point p1) {
+    Point p2 = new Point();
+    if ( (y & 1) == 1 ) {
+      p1.x = 3;
+      p2.x = 4;
+    } else {
+      p1.x = 5;
+      p2.x = 6;
+    }
+    p1.y = 3 * p2.x + y;
+    p2.y = 3 * p1.x + y;
+    dummy();
+    return p1.y * p2.y;
+  }
+
+  int test6(int y) {
+    Point p1 = new Point();
+    Point p2 = new Point();
+    p1.next = p2;
+    if ( (y & 1) == 1 ) {
+      p1.x = 3;
+      p1.getNext().x = 4;
+    } else {
+      p1.x = 5;
+      p1.getNext().x = 6;
+    }
+    p1.y = 3 * p2.x + y;
+    p2.y = 3 * p1.x + y;
+    dummy();
+    return p1.y * p2.y;
+  }
+
+  int test7(int y, Point p1) {
+    Point p2 = new Point();
+    p1.next = p2;
+    if ( (y & 1) == 1 ) {
+      p1.x = 3;
+      p1.getNext().x = 4;
+    } else {
+      p1.x = 5;
+      p1.getNext().x = 6;
+    }
+    p1.y = 3 * p2.x + y;
+    p2.y = 3 * p1.x + y;
+    dummy();
+    return p1.y * p2.y;
+  }
+
+  int test8(int y, int l, int i) {
+    Point p = new Point();
+    p.ax = new int[l];
+    p.ay = new int[l];
+    int x = 3;
+    p.ax[i] = x;
+    p.ay[i] = 3 * x + y;
+    dummy();
+    return p.ax[i] * p.ay[i];
+  }
+
+  int test9(int y, int l, int i) {
+    Point p = new Point();
+    p.pax = new Point[l];
+    p.pay = new Point[l];
+    p.pax[i] = new Point();
+    p.pay[i] = new Point();
+    p.pax[i].x = 3;
+    p.pay[i].x = 4;
+    p.pax[i].y = 3 * p.pay[i].x + y;
+    p.pay[i].y = 3 * p.pax[i].x + y;
+    dummy();
+    return p.pax[i].y * p.pay[i].y;
+  }
+
+  int test10(int y, int l, int i, Class cls) {
+    Point p = new Point();
+    try {
+      p.pax = (Point[])Array.newInstance(cls, l);
+      p.pax[i] = (Point)cls.newInstance();
+    }
+    catch(java.lang.InstantiationException ex) {
+      return 0;
+    }
+    catch(java.lang.IllegalAccessException ex) {
+      return 0;
+    }
+    p.pax[i].x = 3;
+    p.pax[i].y = 3 * p.pax[i].x + y;
+    dummy();
+    return p.pax[i].x * p.pax[i].y;
+  }
+
+  int test11(int y) {
+    Point p1 = new Point();
+    Point p2 = new Point();
+    p1.next = p2;
+    if ( (y & 1) == 1 ) {
+      p1.x = 3;
+      p1.next.x = 4;
+    } else {
+      p1.x = 5;
+      p1.next.x = 6;
+    }
+    p1.y = 3 * p1.next.x + y;
+    p1.next.y = 3 * p1.x + y;
+    dummy();
+    return p1.y * p1.next.y;
+  }
+
+  int test12(int y) {
+    Point p1 = new Point();
+    p1.next = p1;
+    if ( (y & 1) == 1 ) {
+      p1.x = 3;
+      p1.next.x = 4;
+    } else {
+      p1.x = 5;
+      p1.next.x = 6;
+    }
+    p1.y = 3 * p1.next.x + y;
+    p1.next.y = 3 * p1.x + y;
+    dummy();
+    return p1.y * p1.next.y;
+  }
+
+
+  public static void main(String args[]) {
+    Test tsr    = new Test();
+    Point p     = new Point();
+    Point ptmp  = p;
+    Class cls   = Point.class;
+    int y = 0;
+    for (int i=0; i<10000; i++) {
+      ptmp.next = tsr.test00(1);
+      ptmp.next = tsr.test01(1);
+      ptmp.next = tsr.test02(1);
+      ptmp.next = tsr.test03(1);
+      ptmp.next = tsr.test04(1);
+
+      y = tsr.test05(1);
+
+      y = tsr.test80(y, 1, 0);
+      y = tsr.test81(y, 1, 0);
+
+      y = tsr.test44(y);
+      y = tsr.test43(y);
+      y = tsr.test42(y);
+      y = tsr.test40(y);
+      y = tsr.test41(y);
+
+      y = tsr.test0(y);
+      y = tsr.test1(y);
+      y = tsr.test2(y);
+      y = tsr.test3(y, p);
+      y = tsr.test4(y);
+      y = tsr.test5(y, p);
+      y = tsr.test6(y);
+      y = tsr.test7(y, p);
+      y = tsr.test8(y, 1, 0);
+      y = tsr.test9(y, 1, 0);
+      y = tsr.test10(y, 1, 0, cls);
+      y = tsr.test11(y);
+      y = tsr.test12(y);
+    }
+    for (int i=0; i<10000; i++) {
+      ptmp.next = tsr.test00(1);
+      ptmp.next = tsr.test01(1);
+      ptmp.next = tsr.test02(1);
+      ptmp.next = tsr.test03(1);
+      ptmp.next = tsr.test04(1);
+
+      y = tsr.test05(1);
+
+      y = tsr.test80(y, 1, 0);
+      y = tsr.test81(y, 1, 0);
+
+      y = tsr.test44(y);
+      y = tsr.test43(y);
+      y = tsr.test42(y);
+      y = tsr.test40(y);
+      y = tsr.test41(y);
+
+      y = tsr.test0(y);
+      y = tsr.test1(y);
+      y = tsr.test2(y);
+      y = tsr.test3(y, p);
+      y = tsr.test4(y);
+      y = tsr.test5(y, p);
+      y = tsr.test6(y);
+      y = tsr.test7(y, p);
+      y = tsr.test8(y, 1, 0);
+      y = tsr.test9(y, 1, 0);
+      y = tsr.test10(y, 1, 0, cls);
+      y = tsr.test11(y);
+      y = tsr.test12(y);
+    }
+    for (int i=0; i<10000; i++) {
+      ptmp.next = tsr.test00(1);
+      ptmp.next = tsr.test01(1);
+      ptmp.next = tsr.test02(1);
+      ptmp.next = tsr.test03(1);
+      ptmp.next = tsr.test04(1);
+
+      y = tsr.test05(1);
+
+      y = tsr.test80(y, 1, 0);
+      y = tsr.test81(y, 1, 0);
+
+      y = tsr.test44(y);
+      y = tsr.test43(y);
+      y = tsr.test42(y);
+      y = tsr.test40(y);
+      y = tsr.test41(y);
+
+      y = tsr.test0(y);
+      y = tsr.test1(y);
+      y = tsr.test2(y);
+      y = tsr.test3(y, p);
+      y = tsr.test4(y);
+      y = tsr.test5(y, p);
+      y = tsr.test6(y);
+      y = tsr.test7(y, p);
+      y = tsr.test8(y, 1, 0);
+      y = tsr.test9(y, 1, 0);
+      y = tsr.test10(y, 1, 0, cls);
+      y = tsr.test11(y);
+      y = tsr.test12(y);
+    }
+
+    int z = 0;
+    y = tsr.test80(0, 1, 0);
+    z += y;
+    System.out.println("After 'test80' y=" + y);
+    y = tsr.test81(0, 1, 0);
+    z += y;
+    System.out.println("After 'test81' y=" + y);
+
+    y = tsr.test44(0);
+    z += y;
+    System.out.println("After 'test44' y=" + y);
+    y = tsr.test43(0);
+    z += y;
+    System.out.println("After 'test43' y=" + y);
+    y = tsr.test42(0);
+    z += y;
+    System.out.println("After 'test42' y=" + y);
+    y = tsr.test40(0);
+    z += y;
+    System.out.println("After 'test40' y=" + y);
+    y = tsr.test41(0);
+    z += y;
+    System.out.println("After 'test41' y=" + y);
+
+    ptmp.next = tsr.test00(1);
+    z += y;
+    System.out.println("After 'test00' p.y=" + ptmp.next.y);
+    ptmp.next = tsr.test01(1);
+    z += y;
+    System.out.println("After 'test01' p.y=" + ptmp.next.y);
+    ptmp.next = tsr.test02(1);
+    z += y;
+    System.out.println("After 'test02' p.y=" + ptmp.next.y);
+    ptmp.next = tsr.test03(1);
+    z += y;
+    System.out.println("After 'test03' p.y=" + ptmp.next.y);
+    ptmp.next = tsr.test04(1);
+    z += y;
+    System.out.println("After 'test04' p.y=" + ptmp.next.y);
+
+    y = tsr.test05(1);
+    z += y;
+    System.out.println("After 'test05' y=" + y);
+
+    y = tsr.test0(0);
+    z += y;
+    System.out.println("After 'test0' y=" + y);
+    y = tsr.test1(0);
+    z += y;
+    System.out.println("After 'test1' y=" + y);
+    y = tsr.test2(0);
+    z += y;
+    System.out.println("After 'test2' y=" + y);
+    y = tsr.test3(0, new Point());
+    z += y;
+    System.out.println("After 'test3' y=" + y);
+    y = tsr.test4(0);
+    z += y;
+    System.out.println("After 'test4' y=" + y);
+    y = tsr.test5(0, new Point());
+    z += y;
+    System.out.println("After 'test5' y=" + y);
+    y = tsr.test6(0);
+    z += y;
+    System.out.println("After 'test6' y=" + y);
+    y = tsr.test7(0, new Point());
+    z += y;
+    System.out.println("After 'test7' y=" + y);
+    y = tsr.test8(0, 1, 0);
+    z += y;
+    System.out.println("After 'test8' y=" + y);
+    y = tsr.test9(0, 1, 0);
+    z += y;
+    System.out.println("After 'test9' y=" + y);
+    y = tsr.test10(0, 1, 0, cls);
+    z += y;
+    System.out.println("After 'test10' y=" + y);
+    y = tsr.test11(0);
+    z += y;
+    System.out.println("After 'test11' y=" + y);
+    y = tsr.test12(0);
+    z += y;
+    System.out.println("After 'test12' y=" + y);
+    System.out.println("Sum of y =" + z);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/6695810/Test.java	Tue Jun 17 15:27:05 2008 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */
+
+/*
+ * @test
+ * @bug 6695810
+ * @summary null oop passed to encode_heap_oop_not_null
+ * @run main/othervm -Xbatch Test
+ */
+
+public class Test {
+    Test _t;
+
+    static void test(Test t1, Test t2) {
+        if (t2 != null)
+            t1._t = t2;
+
+        if (t2 != null)
+            t1._t = t2;
+    }
+
+    public static void main(String[] args) {
+        Test t = new Test();
+        for (int i = 0; i < 50; i++) {
+            for (int j = 0; j < 100; j++) {
+                test(t, t);
+            }
+            test(t, null);
+        }
+        for (int i = 0; i < 10000; i++) {
+            test(t, t);
+        }
+        test(t, null);
+    }
+}