changeset 2181:d25d4ca69222

Merge.
author Thomas Wuerthinger <wuerthinger@ssw.jku.at>
date Wed, 16 Feb 2011 13:47:20 +0100
parents 50b45e2d9725 (current diff) 14c2f31280dd (diff)
children 9569fdf936ff
files agent/src/share/classes/sun/jvm/hotspot/oops/SymbolKlass.java src/cpu/x86/vm/c1_Runtime1_x86.cpp src/cpu/x86/vm/sharedRuntime_x86_64.cpp src/os/linux/vm/os_linux.cpp src/share/vm/c1/c1_LIRGenerator.cpp src/share/vm/c1/c1_Runtime1.cpp src/share/vm/c1/c1_Runtime1.hpp src/share/vm/ci/ciEnv.cpp src/share/vm/ci/ciEnv.hpp src/share/vm/ci/ciField.cpp src/share/vm/ci/ciInstanceKlass.cpp src/share/vm/ci/ciObject.hpp src/share/vm/ci/ciObjectFactory.cpp src/share/vm/ci/ciObjectFactory.hpp src/share/vm/ci/ciSymbol.hpp src/share/vm/ci/ciSymbolKlass.cpp src/share/vm/ci/ciSymbolKlass.hpp src/share/vm/classfile/classLoader.cpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/code/compiledIC.cpp src/share/vm/code/nmethod.cpp src/share/vm/compiler/compileBroker.cpp src/share/vm/gc_implementation/g1/concurrentZFThread.cpp src/share/vm/gc_implementation/g1/concurrentZFThread.hpp src/share/vm/gc_implementation/g1/heapRegion.cpp src/share/vm/interpreter/rewriter.cpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/klass.cpp src/share/vm/oops/klass.hpp src/share/vm/oops/klassKlass.cpp src/share/vm/oops/oop.inline.hpp src/share/vm/oops/symbolKlass.cpp src/share/vm/oops/symbolKlass.hpp src/share/vm/oops/symbolOop.cpp src/share/vm/oops/symbolOop.hpp src/share/vm/prims/jni.cpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/globals.hpp src/share/vm/runtime/javaCalls.cpp src/share/vm/runtime/javaCalls.hpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/synchronizer.cpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/thread.hpp src/share/vm/runtime/vframe.cpp src/share/vm/runtime/vframeArray.cpp src/share/vm/utilities/exceptions.cpp src/share/vm/utilities/globalDefinitions.hpp
diffstat 344 files changed, 8574 insertions(+), 7596 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Feb 16 13:38:33 2011 +0100
+++ b/.hgtags	Wed Feb 16 13:47:20 2011 +0100
@@ -142,3 +142,9 @@
 0a8e0d4345b37b71ec49dda08ee03b68c4f1b592 hs20-b05
 e24ab3fa6aafad3efabbe7dba9918c5f461a20b1 jdk7-b125
 4c851c931d001a882cab809aaf3a55371b919244 jdk7-b126
+e24ab3fa6aafad3efabbe7dba9918c5f461a20b1 hs20-b06
+d535bf4c12355a2897e918da9f8910c0aceec4fb hs20-b07
+102466e70debc4b907afbd7624e34ddb1aafee9f jdk7-b127
+9a5762f448595794d449a8e17342abd81a3fadaf jdk7-b128
+ae4b185f2ed14af7bab610738c333840598cdcc4 jdk7-b129
+ae4b185f2ed14af7bab610738c333840598cdcc4 hs21-b01
--- a/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java	Wed Feb 16 13:47:20 2011 +0100
@@ -428,6 +428,36 @@
                 }
             }
         },
+        new Command("symbol", "symbol address", false) {
+            public void doit(Tokens t) {
+                if (t.countTokens() != 1) {
+                    usage();
+                } else {
+                    Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
+                    Symbol.create(a).printValueOn(out);
+                    out.println();
+                }
+            }
+        },
+        new Command("symboltable", "symboltable name", false) {
+            public void doit(Tokens t) {
+                if (t.countTokens() != 1) {
+                    usage();
+                } else {
+                    out.println(SymbolTable.getTheTable().probe(t.nextToken()));
+                }
+            }
+        },
+        new Command("symboldump", "symboldump", false) {
+            public void doit(Tokens t) {
+                SymbolTable.getTheTable().symbolsDo(new SymbolTable.SymbolVisitor() {
+                        public void visit(Symbol sym) {
+                            sym.printValueOn(out);
+                            out.println();
+                        }
+                    });
+            }
+        },
         new Command("flags", "flags [ flag ]", false) {
             public void doit(Tokens t) {
                 int tokens = t.countTokens();
@@ -629,17 +659,6 @@
                 }
             }
         },
-        new Command("symbol", "symbol name", false) {
-            public void doit(Tokens t) {
-                if (t.countTokens() != 1) {
-                    usage();
-                } else {
-                    String symbol = t.nextToken();
-                    Address a = lookup(symbol);
-                    out.println(symbol + " = " + a);
-                }
-            }
-        },
         new Command("printstatics", "printstatics [ type ]", false) {
             public void doit(Tokens t) {
                 if (t.countTokens() > 1) {
@@ -1262,6 +1281,9 @@
         this.err = err;
         for (int i = 0; i < commandList.length; i++) {
             Command c = commandList[i];
+            if (commands.get(c.name) != null) {
+                throw new InternalError(c.name + " has multiple definitions");
+            }
             commands.put(c.name, c);
         }
         if (debugger.isAttached()) {
--- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java	Wed Feb 16 13:47:20 2011 +0100
@@ -89,6 +89,37 @@
     readVMLongConstants();
   }
 
+  public Type lookupType(String cTypeName, boolean throwException) {
+    Type fieldType = super.lookupType(cTypeName, false);
+    if (fieldType == null && cTypeName.startsWith("const ")) {
+      fieldType = (BasicType)lookupType(cTypeName.substring(6), false);
+    }
+    if (fieldType == null && cTypeName.endsWith(" const")) {
+        fieldType = (BasicType)lookupType(cTypeName.substring(0, cTypeName.length() - 6), false);
+    }
+    if (fieldType == null) {
+      if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">*")) {
+        String ttype = cTypeName.substring("GrowableArray<".length(),
+                                            cTypeName.length() - 2);
+        Type templateType = lookupType(ttype, false);
+        if (templateType == null && typeNameIsPointerType(ttype)) {
+          templateType = recursiveCreateBasicPointerType(ttype);
+        }
+        if (templateType == null) {
+          lookupOrFail(ttype);
+        }
+        fieldType = recursiveCreateBasicPointerType(cTypeName);
+      }
+    }
+    if (fieldType == null && typeNameIsPointerType(cTypeName)) {
+      fieldType = recursiveCreateBasicPointerType(cTypeName);
+    }
+    if (fieldType == null && throwException) {
+      super.lookupType(cTypeName, true);
+    }
+    return fieldType;
+  }
+
   private void readVMTypes() {
     // Get the variables we need in order to traverse the VMTypeEntry[]
     long typeEntryTypeNameOffset;
@@ -250,7 +281,7 @@
         BasicType containingType = lookupOrFail(typeName);
 
         // The field's Type must already be in the database -- no exceptions
-        BasicType fieldType = lookupOrFail(typeString);
+        BasicType fieldType = (BasicType)lookupType(typeString);
 
         // Create field by type
         createField(containingType, fieldName, fieldType,
@@ -442,10 +473,17 @@
       workarounds due to incomplete information in the VMStructs
       database. */
   private BasicPointerType recursiveCreateBasicPointerType(String typeName) {
+    BasicPointerType result = (BasicPointerType)super.lookupType(typeName, false);
+    if (result != null) {
+      return result;
+    }
     String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim();
     Type targetType = null;
     if (typeNameIsPointerType(targetTypeName)) {
-      targetType = recursiveCreateBasicPointerType(targetTypeName);
+      targetType = lookupType(targetTypeName, false);
+      if (targetType == null) {
+        targetType = recursiveCreateBasicPointerType(targetTypeName);
+      }
     } else {
       targetType = lookupType(targetTypeName, false);
       if (targetType == null) {
@@ -466,6 +504,20 @@
           BasicType basicTargetType = createBasicType(targetTypeName, false, true, true);
           basicTargetType.setSize(1);
           targetType = basicTargetType;
+        } else if (targetTypeName.startsWith("GrowableArray<")) {
+          BasicType basicTargetType = createBasicType(targetTypeName, false, false, false);
+
+          // transfer fields from GenericGrowableArray to template instance
+          BasicType generic = lookupOrFail("GenericGrowableArray");
+          basicTargetType.setSize(generic.getSize());
+          Iterator fields = generic.getFields();
+          while (fields.hasNext()) {
+              Field f = (Field)fields.next();
+              basicTargetType.addField(internalCreateField(basicTargetType, f.getName(),
+                                                           f.getType(), f.isStatic(),
+                                                           f.getOffset(), null));
+          }
+          targetType = basicTargetType;
         } else {
           if (DEBUG) {
             System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\"");
@@ -474,7 +526,10 @@
         }
       }
     }
-    return new BasicPointerType(this, typeName, targetType);
+    result = new BasicPointerType(this, typeName, targetType);
+    result.setSize(UNINITIALIZED_SIZE);
+    addType(result);
+    return result;
   }
 
   private boolean typeNameIsPointerType(String typeName) {
--- a/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java	Wed Feb 16 13:47:20 2011 +0100
@@ -112,7 +112,7 @@
   }
 
   // return Symbol (if unresolved) or Klass (if resolved)
-  public Oop getKlass() {
+  public Object getKlass() {
     if (Assert.ASSERTS_ENABLED) {
       Assert.that(isKlassConstant(), "not a klass literal");
     }
@@ -121,11 +121,11 @@
     // decide based on the oop type.
     ConstantPool cpool = method().getConstants();
     int cpIndex = index();
-    Oop oop = cpool.getObjAt(cpIndex);
-    if (oop.isKlass()) {
-       return (Klass) oop;
-    } else if (oop.isSymbol()) {
-       return (Symbol) oop;
+    ConstantPool.CPSlot oop = cpool.getSlotAt(cpIndex);
+    if (oop.isOop()) {
+      return (Klass) oop.getOop();
+    } else if (oop.isMetaData()) {
+      return oop.getSymbol();
     } else {
        throw new RuntimeException("should not reach here");
     }
@@ -165,12 +165,12 @@
        // tag change from 'unresolved' to 'string' does not happen atomically.
        // We just look at the object at the corresponding index and
        // decide based on the oop type.
-       Oop obj = cpool.getObjAt(cpIndex);
-       if (obj.isSymbol()) {
-          Symbol sym = (Symbol) obj;
-          return "<String \"" + sym.asString() + "\">";
-       } else if (obj.isInstance()) {
-          return "<String \"" + OopUtilities.stringOopToString(obj) + "\">";
+       ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex);
+       if (obj.isMetaData()) {
+         Symbol sym = obj.getSymbol();
+         return "<String \"" + sym.asString() + "\">";
+       } else if (obj.isOop()) {
+         return "<String \"" + OopUtilities.stringOopToString(obj.getOop()) + "\">";
        } else {
           throw new RuntimeException("should not reach here");
        }
@@ -178,13 +178,13 @@
        // tag change from 'unresolved' to 'klass' does not happen atomically.
        // We just look at the object at the corresponding index and
        // decide based on the oop type.
-       Oop obj = cpool.getObjAt(cpIndex);
-       if (obj.isKlass()) {
-          Klass k = (Klass) obj;
-          return "<Class " + k.getName().asString() + "@" + k.getHandle() + ">";
-       } else if (obj.isSymbol()) {
-          Symbol sym = (Symbol) obj;
-          return "<Class " + sym.asString() + ">";
+       ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex);
+       if (obj.isOop()) {
+         Klass k = (Klass) obj.getOop();
+         return "<Class " + k.getName().asString() + "@" + k.getHandle() + ">";
+       } else if (obj.isMetaData()) {
+         Symbol sym = obj.getSymbol();
+         return "<Class " + sym.asString() + ">";
        } else {
           throw new RuntimeException("should not reach here");
        }
--- a/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java	Wed Feb 16 13:47:20 2011 +0100
@@ -37,11 +37,11 @@
   }
 
   public Symbol getClassName() {
-    Oop obj = method().getConstants().getObjAt(index());
-    if (obj instanceof Symbol) {
-       return (Symbol)obj;
+    ConstantPool.CPSlot obj = method().getConstants().getSlotAt(index());
+    if (obj.isMetaData()) {
+      return obj.getSymbol();
     } else {
-       return ((Klass)obj).getName();
+      return ((Klass)obj.getOop()).getName();
     }
   }
 
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java	Wed Feb 16 13:47:20 2011 +0100
@@ -63,7 +63,7 @@
   }
 
   public Klass klass() {
-    return (Klass) literal();
+    return (Klass)VM.getVM().getObjectHeap().newOop(literalValue().addOffsetToAsOopHandle(0));
   }
 
   public DictionaryEntry(Address addr) {
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java	Wed Feb 16 13:47:20 2011 +0100
@@ -42,14 +42,14 @@
 
   private static synchronized void initialize(TypeDataBase db) {
     Type type = db.lookupType("LoaderConstraintEntry");
-    nameField = type.getOopField("_name");
+    nameField = type.getAddressField("_name");
     numLoadersField = type.getCIntegerField("_num_loaders");
     maxLoadersField = type.getCIntegerField("_max_loaders");
     loadersField = type.getAddressField("_loaders");
   }
 
   // Fields
-  private static sun.jvm.hotspot.types.OopField nameField;
+  private static AddressField nameField;
   private static CIntegerField numLoadersField;
   private static CIntegerField maxLoadersField;
   private static AddressField loadersField;
@@ -57,7 +57,7 @@
   // Accessors
 
   public Symbol name() {
-    return (Symbol) VM.getVM().getObjectHeap().newOop(nameField.getValue(addr));
+    return Symbol.create(nameField.getValue(addr));
   }
 
   public int numLoaders() {
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java	Wed Feb 16 13:47:20 2011 +0100
@@ -58,7 +58,7 @@
   }
 
   public Symbol klass() {
-    return (Symbol) literal();
+    return Symbol.create(literalValue());
   }
 
   /* covariant return type :-(
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/StringTable.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/StringTable.java	Wed Feb 16 13:47:20 2011 +0100
@@ -70,11 +70,13 @@
   }
 
   public void stringsDo(StringVisitor visitor) {
+    ObjectHeap oh = VM.getVM().getObjectHeap();
     int numBuckets = tableSize();
     for (int i = 0; i < numBuckets; i++) {
       for (HashtableEntry e = (HashtableEntry) bucket(i); e != null;
            e = (HashtableEntry) e.next()) {
-        visitor.visit((Instance) e.literal());
+        Instance s = (Instance)oh.newOop(e.literalValue().addOffsetToAsOopHandle(0));
+        visitor.visit(s);
       }
     }
   }
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java	Wed Feb 16 13:47:20 2011 +0100
@@ -85,7 +85,7 @@
     long hashValue = hashSymbol(name);
     for (HashtableEntry e = (HashtableEntry) bucket(hashToIndex(hashValue)); e != null; e = (HashtableEntry) e.next()) {
       if (e.hash() == hashValue) {
-         Symbol sym = (Symbol) e.literal();
+         Symbol sym = Symbol.create(e.literalValue());
          if (sym.equals(name)) {
            return sym;
          }
@@ -103,7 +103,7 @@
     for (int i = 0; i < numBuckets; i++) {
       for (HashtableEntry e = (HashtableEntry) bucket(i); e != null;
            e = (HashtableEntry) e.next()) {
-        visitor.visit((Symbol) e.literal());
+        visitor.visit(Symbol.create(e.literalValue()));
       }
     }
   }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Wed Feb 16 13:47:20 2011 +0100
@@ -35,6 +35,38 @@
 // as described in the class file
 
 public class ConstantPool extends Oop implements ClassConstants {
+
+  public class CPSlot {
+    private Address ptr;
+
+    CPSlot(Address ptr) {
+      this.ptr = ptr;
+    }
+    CPSlot(Symbol sym) {
+      this.ptr = sym.getAddress().orWithMask(1);
+    }
+
+    public boolean isOop() {
+      return (ptr.minus(null) & 1) == 0;
+    }
+    public boolean isMetaData() {
+      return (ptr.minus(null) & 1) == 1;
+    }
+
+    public Symbol getSymbol() {
+      if (isMetaData()) {
+        return Symbol.create(ptr.xorWithMask(1));
+      }
+      throw new InternalError("not a symbol");
+    }
+    public Oop getOop() {
+      if (isOop()) {
+        return VM.getVM().getObjectHeap().newOop(ptr.addOffsetToAsOopHandle(0));
+      }
+      throw new InternalError("not an oop");
+    }
+  }
+
   // Used for debugging this code
   private static final boolean DEBUG = false;
 
@@ -110,12 +142,17 @@
     return new ConstantTag(getTags().getByteAt((int) index));
   }
 
-  public Oop getObjAt(long index){
+  public CPSlot getSlotAt(long index) {
+    return new CPSlot(getHandle().getAddressAt(indexOffset(index)));
+  }
+
+  public Oop getObjAtRaw(long index){
     return getHeap().newOop(getHandle().getOopHandleAt(indexOffset(index)));
   }
 
   public Symbol getSymbolAt(long index) {
-    return (Symbol) getObjAt(index);
+    CPSlot slot = getSlotAt(index);
+    return slot.getSymbol();
   }
 
   public int getIntAt(long index){
@@ -187,7 +224,7 @@
   // returns null, if not resolved.
   public Klass getKlassRefAt(int which) {
     if( ! getTagAt(which).isKlass()) return null;
-    return (Klass) getObjAt(which);
+    return (Klass) getObjAtRaw(which);
   }
 
   // returns null, if not resolved.
@@ -477,7 +514,7 @@
               case JVM_CONSTANT_Class: {
                   dos.writeByte(cpConstType);
                   // Klass already resolved. ConstantPool constains klassOop.
-                  Klass refKls = (Klass) getObjAt(ci);
+                  Klass refKls = (Klass) getObjAtRaw(ci);
                   String klassName = refKls.getName().asString();
                   Short s = (Short) utf8ToIndex.get(klassName);
                   dos.writeShort(s.shortValue());
@@ -498,7 +535,7 @@
 
               case JVM_CONSTANT_String: {
                   dos.writeByte(cpConstType);
-                  String str = OopUtilities.stringOopToString(getObjAt(ci));
+                  String str = OopUtilities.stringOopToString(getObjAtRaw(ci));
                   Short s = (Short) utf8ToIndex.get(str);
                   dos.writeShort(s.shortValue());
                   if (DEBUG) debugMessage("CP[" + ci + "] = string " + s);
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java	Wed Feb 16 13:47:20 2011 +0100
@@ -576,7 +576,7 @@
           ConstantPool cp       = method().getConstants();
           int nameAndTypeIdx    = cp.name_and_type_ref_index_at(idx);
           int signatureIdx      = cp.signature_ref_index_at(nameAndTypeIdx);
-          symbolOop signature   = cp.symbol_at(signatureIdx);
+          Symbol* signature     = cp.symbol_at(signatureIdx);
           tty.print("%s", signature.as_C_string());
         */
       }
@@ -616,7 +616,7 @@
           constantPoolOop cp    = method().constants();
           int nameAndTypeIdx    = cp.name_and_type_ref_index_at(idx);
           int signatureIdx      = cp.signature_ref_index_at(nameAndTypeIdx);
-          symbolOop signature   = cp.symbol_at(signatureIdx);
+          Symbol* signature     = cp.symbol_at(signatureIdx);
           tty.print("%s", signature.as_C_string());
         */
       }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Wed Feb 16 13:47:20 2011 +0100
@@ -82,8 +82,8 @@
     classLoader          = new OopField(type.getOopField("_class_loader"), Oop.getHeaderSize());
     protectionDomain     = new OopField(type.getOopField("_protection_domain"), Oop.getHeaderSize());
     signers              = new OopField(type.getOopField("_signers"), Oop.getHeaderSize());
-    sourceFileName       = new OopField(type.getOopField("_source_file_name"), Oop.getHeaderSize());
-    sourceDebugExtension = new OopField(type.getOopField("_source_debug_extension"), Oop.getHeaderSize());
+    sourceFileName       = type.getAddressField("_source_file_name");
+    sourceDebugExtension = type.getAddressField("_source_debug_extension");
     innerClasses         = new OopField(type.getOopField("_inner_classes"), Oop.getHeaderSize());
     nonstaticFieldSize   = new CIntField(type.getCIntegerField("_nonstatic_field_size"), Oop.getHeaderSize());
     staticFieldSize      = new CIntField(type.getCIntegerField("_static_field_size"), Oop.getHeaderSize());
@@ -94,7 +94,7 @@
     vtableLen            = new CIntField(type.getCIntegerField("_vtable_len"), Oop.getHeaderSize());
     itableLen            = new CIntField(type.getCIntegerField("_itable_len"), Oop.getHeaderSize());
     breakpoints          = type.getAddressField("_breakpoints");
-    genericSignature     = new OopField(type.getOopField("_generic_signature"), Oop.getHeaderSize());
+    genericSignature     = type.getAddressField("_generic_signature");
     majorVersion         = new CIntField(type.getCIntegerField("_major_version"), Oop.getHeaderSize());
     minorVersion         = new CIntField(type.getCIntegerField("_minor_version"), Oop.getHeaderSize());
     headerSize           = alignObjectOffset(Oop.getHeaderSize() + type.getSize());
@@ -135,8 +135,8 @@
   private static OopField  classLoader;
   private static OopField  protectionDomain;
   private static OopField  signers;
-  private static OopField  sourceFileName;
-  private static OopField  sourceDebugExtension;
+  private static AddressField  sourceFileName;
+  private static AddressField  sourceDebugExtension;
   private static OopField  innerClasses;
   private static CIntField nonstaticFieldSize;
   private static CIntField staticFieldSize;
@@ -147,7 +147,7 @@
   private static CIntField vtableLen;
   private static CIntField itableLen;
   private static AddressField breakpoints;
-  private static OopField  genericSignature;
+  private static AddressField  genericSignature;
   private static CIntField majorVersion;
   private static CIntField minorVersion;
 
@@ -257,8 +257,8 @@
   public Oop       getClassLoader()         { return                classLoader.getValue(this); }
   public Oop       getProtectionDomain()    { return                protectionDomain.getValue(this); }
   public ObjArray  getSigners()             { return (ObjArray)     signers.getValue(this); }
-  public Symbol    getSourceFileName()      { return (Symbol)       sourceFileName.getValue(this); }
-  public Symbol    getSourceDebugExtension(){ return (Symbol)       sourceDebugExtension.getValue(this); }
+  public Symbol    getSourceFileName()      { return getSymbol(sourceFileName); }
+  public Symbol    getSourceDebugExtension(){ return getSymbol(sourceDebugExtension); }
   public TypeArray getInnerClasses()        { return (TypeArray)    innerClasses.getValue(this); }
   public long      getNonstaticFieldSize()  { return                nonstaticFieldSize.getValue(this); }
   public long      getStaticFieldSize()     { return                staticFieldSize.getValue(this); }
@@ -267,7 +267,7 @@
   public boolean   getIsMarkedDependent()   { return                isMarkedDependent.getValue(this) != 0; }
   public long      getVtableLen()           { return                vtableLen.getValue(this); }
   public long      getItableLen()           { return                itableLen.getValue(this); }
-  public Symbol    getGenericSignature()    { return (Symbol)       genericSignature.getValue(this); }
+  public Symbol    getGenericSignature()    { return getSymbol(genericSignature); }
   public long      majorVersion()           { return                majorVersion.getValue(this); }
   public long      minorVersion()           { return                minorVersion.getValue(this); }
 
@@ -308,12 +308,12 @@
           if (ioff != 0) {
              // only look at classes that are already loaded
              // since we are looking for the flags for our self.
-             Oop classInfo = getConstants().getObjAt(ioff);
+             ConstantPool.CPSlot classInfo = getConstants().getSlotAt(ioff);
              Symbol name = null;
-             if (classInfo instanceof Klass) {
-                name = ((Klass) classInfo).getName();
-             } else if (classInfo instanceof Symbol) {
-                name = (Symbol) classInfo;
+             if (classInfo.isOop()) {
+               name = ((Klass) classInfo.getOop()).getName();
+             } else if (classInfo.isMetaData()) {
+               name = classInfo.getSymbol();
              } else {
                 throw new RuntimeException("should not reach here");
              }
@@ -358,12 +358,12 @@
          // 'ioff' can be zero.
          // refer to JVM spec. section 4.7.5.
          if (ioff != 0) {
-            Oop iclassInfo = getConstants().getObjAt(ioff);
+            ConstantPool.CPSlot iclassInfo = getConstants().getSlotAt(ioff);
             Symbol innerName = null;
-            if (iclassInfo instanceof Klass) {
-               innerName = ((Klass) iclassInfo).getName();
-            } else if (iclassInfo instanceof Symbol) {
-               innerName = (Symbol) iclassInfo;
+            if (iclassInfo.isOop()) {
+              innerName = ((Klass) iclassInfo.getOop()).getName();
+            } else if (iclassInfo.isMetaData()) {
+              innerName = iclassInfo.getSymbol();
             } else {
                throw new RuntimeException("should not reach here");
             }
@@ -387,12 +387,12 @@
                   }
                }
             } else {
-               Oop oclassInfo = getConstants().getObjAt(ooff);
+               ConstantPool.CPSlot oclassInfo = getConstants().getSlotAt(ooff);
                Symbol outerName = null;
-               if (oclassInfo instanceof Klass) {
-                  outerName = ((Klass) oclassInfo).getName();
-               } else if (oclassInfo instanceof Symbol) {
-                  outerName = (Symbol) oclassInfo;
+               if (oclassInfo.isOop()) {
+                 outerName = ((Klass) oclassInfo.getOop()).getName();
+               } else if (oclassInfo.isMetaData()) {
+                 outerName = oclassInfo.getSymbol();
                } else {
                   throw new RuntimeException("should not reach here");
                }
@@ -450,7 +450,6 @@
       visitor.doOop(classLoader, true);
       visitor.doOop(protectionDomain, true);
       visitor.doOop(signers, true);
-      visitor.doOop(sourceFileName, true);
       visitor.doOop(innerClasses, true);
       visitor.doCInt(nonstaticFieldSize, true);
       visitor.doCInt(staticFieldSize, true);
@@ -467,7 +466,7 @@
     for (int index = 0; index < length; index += NEXT_OFFSET) {
       short accessFlags    = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
       short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
-      FieldType   type   = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
+      FieldType   type   = new FieldType(getConstants().getSymbolAt(signatureIndex));
       AccessFlags access = new AccessFlags(accessFlags);
       if (access.isStatic()) {
         visitField(visitor, type, index);
@@ -490,7 +489,7 @@
       short accessFlags    = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
       short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
 
-      FieldType   type   = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
+      FieldType   type   = new FieldType(getConstants().getSymbolAt(signatureIndex));
       AccessFlags access = new AccessFlags(accessFlags);
       if (!access.isStatic()) {
         visitField(visitor, type, index);
@@ -787,7 +786,7 @@
   private Field newField(int index) {
     TypeArray fields = getFields();
     short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
-    FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
+    FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex));
     if (type.isOop()) {
      if (VM.getVM().isCompressedOopsEnabled()) {
         return new NarrowOopField(this, index);
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java	Wed Feb 16 13:47:20 2011 +0100
@@ -53,7 +53,7 @@
     javaMirror   = new OopField(type.getOopField("_java_mirror"), Oop.getHeaderSize());
     superField   = new OopField(type.getOopField("_super"), Oop.getHeaderSize());
     layoutHelper = new IntField(type.getJIntField("_layout_helper"), Oop.getHeaderSize());
-    name         = new OopField(type.getOopField("_name"), Oop.getHeaderSize());
+    name         = type.getAddressField("_name");
     accessFlags  = new CIntField(type.getCIntegerField("_access_flags"), Oop.getHeaderSize());
     subklass     = new OopField(type.getOopField("_subklass"), Oop.getHeaderSize());
     nextSibling  = new OopField(type.getOopField("_next_sibling"), Oop.getHeaderSize());
@@ -83,18 +83,26 @@
   private static OopField  javaMirror;
   private static OopField  superField;
   private static IntField layoutHelper;
-  private static OopField  name;
+  private static AddressField  name;
   private static CIntField accessFlags;
   private static OopField  subklass;
   private static OopField  nextSibling;
   private static CIntField allocCount;
 
+  private Address getValue(AddressField field) {
+    return getHandle().getAddressAt(field.getOffset() + Oop.getHeaderSize());
+  }
+
+  protected Symbol getSymbol(AddressField field) {
+    return Symbol.create(getHandle().getAddressAt(field.getOffset() + Oop.getHeaderSize()));
+  }
+
   // Accessors for declared fields
   public Instance getJavaMirror()       { return (Instance) javaMirror.getValue(this);   }
   public Klass    getSuper()            { return (Klass)    superField.getValue(this);   }
   public Klass    getJavaSuper()        { return null;  }
   public int      getLayoutHelper()     { return (int)           layoutHelper.getValue(this); }
-  public Symbol   getName()             { return (Symbol)   name.getValue(this);         }
+  public Symbol   getName()             { return getSymbol(name); }
   public long     getAccessFlags()      { return            accessFlags.getValue(this);  }
   // Convenience routine
   public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags());      }
@@ -162,7 +170,7 @@
       visitor.doOop(javaMirror, true);
       visitor.doOop(superField, true);
       visitor.doInt(layoutHelper, true);
-      visitor.doOop(name, true);
+      // visitor.doOop(name, true);
       visitor.doCInt(accessFlags, true);
       visitor.doOop(subklass, true);
       visitor.doOop(nextSibling, true);
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java	Wed Feb 16 13:47:20 2011 +0100
@@ -196,11 +196,11 @@
   public Address      getFromCompiledCodeEntryPoint() { return fromCompiledCodeEntryPointField.getValue(this); }
   */
   // Accessors
-  public Symbol  getName()          { return (Symbol) getConstants().getObjAt(getNameIndex());         }
-  public Symbol  getSignature()     { return (Symbol) getConstants().getObjAt(getSignatureIndex());    }
+  public Symbol  getName()          { return getConstants().getSymbolAt(getNameIndex());         }
+  public Symbol  getSignature()     { return getConstants().getSymbolAt(getSignatureIndex());    }
   public Symbol  getGenericSignature() {
      long index = getGenericSignatureIndex();
-     return (index != 0L) ? (Symbol) getConstants().getObjAt(index) : null;
+     return (index != 0L) ? getConstants().getSymbolAt(index) : null;
   }
 
   // Method holder (the Klass holding this method)
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java	Wed Feb 16 13:47:20 2011 +0100
@@ -47,7 +47,6 @@
     DEBUG = System.getProperty("sun.jvm.hotspot.oops.ObjectHeap.DEBUG") != null;
   }
 
-  private OopHandle              symbolKlassHandle;
   private OopHandle              methodKlassHandle;
   private OopHandle              constMethodKlassHandle;
   private OopHandle              methodDataKlassHandle;
@@ -68,7 +67,6 @@
   private OopHandle              arrayKlassKlassHandle;
   private OopHandle              compiledICHolderKlassHandle;
 
-  private SymbolKlass            symbolKlassObj;
   private MethodKlass            methodKlassObj;
   private ConstMethodKlass       constMethodKlassObj;
   private MethodDataKlass        methodDataKlassObj;
@@ -93,9 +91,6 @@
     // Lookup the roots in the object hierarchy.
     Type universeType = db.lookupType("Universe");
 
-    symbolKlassHandle         = universeType.getOopField("_symbolKlassObj").getValue();
-    symbolKlassObj            = new SymbolKlass(symbolKlassHandle, this);
-
     methodKlassHandle         = universeType.getOopField("_methodKlassObj").getValue();
     methodKlassObj            = new MethodKlass(methodKlassHandle, this);
 
@@ -199,7 +194,6 @@
   public long getDoubleSize()  { return doubleSize;  }
 
   // Accessors for well-known system classes (from Universe)
-  public SymbolKlass            getSymbolKlassObj()            { return symbolKlassObj; }
   public MethodKlass            getMethodKlassObj()            { return methodKlassObj; }
   public ConstMethodKlass       getConstMethodKlassObj()       { return constMethodKlassObj; }
   public MethodDataKlass        getMethodDataKlassObj()        { return methodDataKlassObj; }
@@ -337,7 +331,6 @@
     // First check if handle is one of the root objects
     if (handle.equals(methodKlassHandle))              return getMethodKlassObj();
     if (handle.equals(constMethodKlassHandle))         return getConstMethodKlassObj();
-    if (handle.equals(symbolKlassHandle))              return getSymbolKlassObj();
     if (handle.equals(constantPoolKlassHandle))        return getConstantPoolKlassObj();
     if (handle.equals(constantPoolCacheKlassHandle))   return getConstantPoolCacheKlassObj();
     if (handle.equals(instanceKlassKlassHandle))       return getInstanceKlassKlassObj();
@@ -363,7 +356,6 @@
     if (klass != null) {
       if (klass.equals(methodKlassHandle))              return new Method(handle, this);
       if (klass.equals(constMethodKlassHandle))         return new ConstMethod(handle, this);
-      if (klass.equals(symbolKlassHandle))              return new Symbol(handle, this);
       if (klass.equals(constantPoolKlassHandle))        return new ConstantPool(handle, this);
       if (klass.equals(constantPoolCacheKlassHandle))   return new ConstantPoolCache(handle, this);
       if (!VM.getVM().isCore()) {
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/Symbol.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Symbol.java	Wed Feb 16 13:47:20 2011 +0100
@@ -34,7 +34,7 @@
 // A Symbol is a canonicalized string.
 // All Symbols reside in global symbolTable.
 
-public class Symbol extends Oop {
+public class Symbol extends VMObject {
   static {
     VM.registerVMInitializedObserver(new Observer() {
         public void update(Observable o, Object data) {
@@ -44,9 +44,10 @@
   }
 
   private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
-    Type type  = db.lookupType("symbolOopDesc");
-    length     = new CIntField(type.getCIntegerField("_length"), 0);
+    Type type  = db.lookupType("Symbol");
+    length     = type.getCIntegerField("_length");
     baseOffset = type.getField("_body").getOffset();
+    idHash = type.getCIntegerField("_identity_hash");
   }
 
   // Format:
@@ -55,8 +56,15 @@
   //   [length] byte size of uft8 string
   //   ..body..
 
-  Symbol(OopHandle handle, ObjectHeap heap) {
-    super(handle, heap);
+  public static Symbol create(Address addr) {
+    if (addr == null) {
+      return null;
+    }
+    return new Symbol(addr);
+  }
+
+  Symbol(Address addr) {
+    super(addr);
   }
 
   public boolean isSymbol()            { return true; }
@@ -64,15 +72,19 @@
   private static long baseOffset; // tells where the array part starts
 
   // Fields
-  private static CIntField length;
+  private static CIntegerField length;
 
   // Accessors for declared fields
-  public long   getLength() { return          length.getValue(this); }
+  public long   getLength() { return          length.getValue(this.addr); }
 
   public byte getByteAt(long index) {
-    return getHandle().getJByteAt(baseOffset + index);
+    return addr.getJByteAt(baseOffset + index);
   }
 
+  private static CIntegerField idHash;
+
+  public int identityHash() { return     (int)idHash.getValue(this.addr); }
+
   public boolean equals(byte[] modUTF8Chars) {
     int l = (int) getLength();
     if (l != modUTF8Chars.length) return false;
@@ -98,7 +110,9 @@
     // Decode the byte array and return the string.
     try {
       return readModifiedUTF8(asByteArray());
-    } catch(IOException e) {
+    } catch(Exception e) {
+      System.err.println(addr);
+      e.printStackTrace();
       return null;
     }
   }
@@ -111,28 +125,13 @@
     tty.print("#" + asString());
   }
 
-  public long getObjectSize() {
-    return alignObjectSize(baseOffset + getLength());
-  }
-
-  void iterateFields(OopVisitor visitor, boolean doVMFields) {
-    super.iterateFields(visitor, doVMFields);
-    if (doVMFields) {
-      visitor.doCInt(length, true);
-      int length = (int) getLength();
-      for (int index = 0; index < length; index++) {
-        visitor.doByte(new ByteField(new IndexableFieldIdentifier(index), baseOffset + index, false), true);
-      }
-    }
-  }
-
   /** Note: this comparison is used for vtable sorting only; it
       doesn't matter what order it defines, as long as it is a total,
-      time-invariant order Since symbolOops are in permSpace, their
+      time-invariant order Since Symbol* are in C_HEAP, their
       relative order in memory never changes, so use address
       comparison for speed. */
   public int fastCompare(Symbol other) {
-    return (int) getHandle().minus(other.getHandle());
+    return (int) addr.minus(other.addr);
   }
 
   private static String readModifiedUTF8(byte[] buf) throws IOException {
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/SymbolKlass.java	Wed Feb 16 13:38:33 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.oops;
-
-import java.io.*;
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-
-// A SymbolKlass is the klass for all Symbols
-
-public class SymbolKlass extends Klass {
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
-          initialize(VM.getVM().getTypeDataBase());
-        }
-      });
-  }
-
-  private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
-    Type type  = db.lookupType("symbolKlass");
-    headerSize = type.getSize() + Oop.getHeaderSize();
-  }
-
-  SymbolKlass(OopHandle handle, ObjectHeap heap) {
-    super(handle, heap);
-  }
-
-  private static long headerSize;
-
-  public long getObjectSize() { return alignObjectSize(headerSize); }
-
-  public void printValueOn(PrintStream tty) {
-    tty.print("SymbolKlass");
-  }
-}
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java	Wed Feb 16 13:47:20 2011 +0100
@@ -229,7 +229,7 @@
                 case JVM_CONSTANT_Class: {
                      dos.writeByte(cpConstType);
                      // Klass already resolved. ConstantPool constains klassOop.
-                     Klass refKls = (Klass) cpool.getObjAt(ci);
+                     Klass refKls = (Klass) cpool.getObjAtRaw(ci);
                      String klassName = refKls.getName().asString();
 
                      Short s = (Short) utf8ToIndex.get(klassName);
@@ -255,7 +255,7 @@
 
                 case JVM_CONSTANT_String: {
                      dos.writeByte(cpConstType);
-                     String str = OopUtilities.stringOopToString(cpool.getObjAt(ci));
+                     String str = OopUtilities.stringOopToString(cpool.getObjAtRaw(ci));
                      Short s = (Short) utf8ToIndex.get(str);
                      dos.writeShort(s.shortValue());
                      if (DEBUG) debugMessage("CP[" + ci + "] = string " + s);
--- a/agent/src/share/classes/sun/jvm/hotspot/types/Field.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/types/Field.java	Wed Feb 16 13:47:20 2011 +0100
@@ -56,7 +56,7 @@
     </PRE>
 
     FIXME: among other things, this interface is not sufficient to
-    describe fields which are themselves arrays (like symbolOop's
+    describe fields which are themselves arrays (like Symbol's
     jbyte _body[1]).  */
 public interface Field {
   /** Get the name of this field */
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Wed Feb 16 13:47:20 2011 +0100
@@ -530,7 +530,7 @@
 
             case JVM_CONSTANT_Class:
                buf.cell("JVM_CONSTANT_Class");
-               Klass klass = (Klass) cpool.getObjAt(index);
+               Klass klass = (Klass) cpool.getObjAtRaw(index);
                if (klass instanceof InstanceKlass) {
                   buf.cell(genKlassLink((InstanceKlass) klass));
                } else {
@@ -555,7 +555,7 @@
             case JVM_CONSTANT_String:
                buf.cell("JVM_CONSTANT_String");
                buf.cell("\"" +
-                 escapeHTMLSpecialChars(OopUtilities.stringOopToString(cpool.getObjAt(index))) + "\"");
+                 escapeHTMLSpecialChars(OopUtilities.stringOopToString(cpool.getObjAtRaw(index))) + "\"");
                break;
 
             case JVM_CONSTANT_Fieldref:
@@ -672,11 +672,11 @@
             buf.beginTag("ul");
             for (int exp = 0; exp < exceptions.length; exp++) {
                short cpIndex = (short) exceptions[exp].getClassCPIndex();
-               Oop obj = cpool.getObjAt(cpIndex);
-               if (obj instanceof Symbol) {
-                  buf.li(((Symbol)obj).asString().replace('/', '.'));
+               ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex);
+               if (obj.isMetaData()) {
+                 buf.li((obj.getSymbol()).asString().replace('/', '.'));
                } else {
-                  buf.li(genKlassLink((InstanceKlass)obj));
+                 buf.li(genKlassLink((InstanceKlass)obj.getOop()));
                }
             }
             buf.endTag("ul");
@@ -756,7 +756,7 @@
                              } else if (instr instanceof BytecodeLoadConstant) {
                                 BytecodeLoadConstant ldc = (BytecodeLoadConstant) instr;
                                 if (ldc.isKlassConstant()) {
-                                   Oop oop = ldc.getKlass();
+                                   Object oop = ldc.getKlass();
                                    if (oop instanceof Klass) {
                                       buf.append("<a href='");
                                       buf.append(genKlassHref((InstanceKlass) oop));
@@ -803,13 +803,13 @@
                buf.cell(Integer.toString(exceptionTable.getIntAt(e + 1)));
                buf.cell(Integer.toString(exceptionTable.getIntAt(e + 2)));
                short cpIndex = (short) exceptionTable.getIntAt(e + 3);
-               Oop obj = cpIndex == 0? null : cpool.getObjAt(cpIndex);
+               ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex);
                if (obj == null) {
                   buf.cell("Any");
-               } else if (obj instanceof Symbol) {
-                  buf.cell(((Symbol)obj).asString().replace('/', '.'));
+               } else if (obj.isMetaData()) {
+                 buf.cell(obj.getSymbol().asString().replace('/', '.'));
                } else {
-                  buf.cell(genKlassLink((InstanceKlass)obj));
+                 buf.cell(genKlassLink((InstanceKlass)obj.getOop()));
                }
                buf.endTag("tr");
             }
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java	Wed Feb 16 13:47:20 2011 +0100
@@ -40,7 +40,7 @@
 
   private static synchronized void initialize(TypeDataBase db) {
     // just to confirm that type exists
-    Type type = db.lookupType("Hashtable");
+    Type type = db.lookupType("Hashtable<intptr_t>");
   }
 
   // derived class may return Class<? extends HashtableEntry>
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/HashtableEntry.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/HashtableEntry.java	Wed Feb 16 13:47:20 2011 +0100
@@ -41,16 +41,16 @@
   }
 
   private static synchronized void initialize(TypeDataBase db) {
-    Type type = db.lookupType("HashtableEntry");
-    literalField   = type.getOopField("_literal");
+    Type type = db.lookupType("HashtableEntry<intptr_t>");
+    literalField   = type.getAddressField("_literal");
   }
 
   // Fields
-  private static OopField      literalField;
+  private static AddressField      literalField;
 
   // Accessors
-  public Oop literal() {
-    return VM.getVM().getObjectHeap().newOop(literalField.getValue(addr));
+  public Address literalValue() {
+    return literalField.getValue(addr);
   }
 
   public HashtableEntry(Address addr) {
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java	Wed Feb 16 13:38:33 2011 +0100
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java	Wed Feb 16 13:47:20 2011 +0100
@@ -740,7 +740,7 @@
         for (Iterator itr = fields.iterator(); itr.hasNext();) {
             Field field = (Field) itr.next();
             Symbol name = symTbl.probe(field.getID().getName());
-            writeObjectID(name);
+            writeSymbolID(name);
             char typeCode = (char) field.getSignature().getByteAt(0);
             int kind = signatureToHprofKind(typeCode);
             out.writeByte((byte)kind);
@@ -852,7 +852,7 @@
     private void writeSymbol(Symbol sym) throws IOException {
         byte[] buf = sym.asString().getBytes("UTF-8");
         writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE);
-        writeObjectID(sym);
+        writeSymbolID(sym);
         out.write(buf);
     }
 
@@ -869,7 +869,7 @@
                         out.writeInt(serialNum);
                         writeObjectID(clazz);
                         out.writeInt(DUMMY_STACK_TRACE_ID);
-                        writeObjectID(k.getName());
+                        writeSymbolID(k.getName());
                         serialNum++;
                     } catch (IOException exp) {
                         throw new RuntimeException(exp);
@@ -901,6 +901,10 @@
         writeObjectID(address);
     }
 
+    private void writeSymbolID(Symbol sym) throws IOException {
+        writeObjectID(getAddressValue(sym.getAddress()));
+    }
+
     private void writeObjectID(long address) throws IOException {
         if (OBJ_ID_SIZE == 4) {
             out.writeInt((int) address);
--- a/make/hotspot_version	Wed Feb 16 13:38:33 2011 +0100
+++ b/make/hotspot_version	Wed Feb 16 13:47:20 2011 +0100
@@ -33,9 +33,9 @@
 # Don't put quotes (fail windows build).
 HOTSPOT_VM_COPYRIGHT=Copyright 2011
 
-HS_MAJOR_VER=20
+HS_MAJOR_VER=21
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=06
+HS_BUILD_NUMBER=01
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7
--- a/src/cpu/sparc/vm/assembler_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/assembler_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -4104,7 +4104,7 @@
 
   ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t1);
   sub(top, t1, t1); // size of tlab's allocated portion
-  incr_allocated_bytes(t1, 0, t2);
+  incr_allocated_bytes(t1, t2, t3);
 
   // refill the tlab with an eden allocation
   bind(do_refill);
@@ -4138,19 +4138,14 @@
   delayed()->nop();
 }
 
-void MacroAssembler::incr_allocated_bytes(Register var_size_in_bytes,
-                                          int con_size_in_bytes,
-                                          Register t1) {
+void MacroAssembler::incr_allocated_bytes(RegisterOrConstant size_in_bytes,
+                                          Register t1, Register t2) {
   // Bump total bytes allocated by this thread
   assert(t1->is_global(), "must be global reg"); // so all 64 bits are saved on a context switch
-  assert_different_registers(var_size_in_bytes, t1);
+  assert_different_registers(size_in_bytes.register_or_noreg(), t1, t2);
   // v8 support has gone the way of the dodo
   ldx(G2_thread, in_bytes(JavaThread::allocated_bytes_offset()), t1);
-  if (var_size_in_bytes->is_valid()) {
-    add(t1, var_size_in_bytes, t1);
-  } else {
-    add(t1, con_size_in_bytes, t1);
-  }
+  add(t1, ensure_simm13_or_reg(size_in_bytes, t2), t1);
   stx(t1, G2_thread, in_bytes(JavaThread::allocated_bytes_offset()));
 }
 
--- a/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -823,15 +823,23 @@
   };
 
   // test if x is within signed immediate range for nbits
-  static bool is_simm(int x, int nbits) { return -( 1 << nbits-1 )  <= x   &&   x  <  ( 1 << nbits-1 ); }
+  static bool is_simm(intptr_t x, int nbits) { return -( intptr_t(1) << nbits-1 )  <= x   &&   x  <  ( intptr_t(1) << nbits-1 ); }
 
   // test if -4096 <= x <= 4095
-  static bool is_simm13(int x) { return is_simm(x, 13); }
+  static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
+
+  static bool is_in_wdisp_range(address a, address b, int nbits) {
+    intptr_t d = intptr_t(b) - intptr_t(a);
+    return is_simm(d, nbits + 2);
+  }
 
   // test if label is in simm16 range in words (wdisp16).
   bool is_in_wdisp16_range(Label& L) {
-    intptr_t d = intptr_t(pc()) - intptr_t(target(L));
-    return is_simm(d, 18);
+    return is_in_wdisp_range(target(L), pc(), 16);
+  }
+  // test if the distance between two addresses fits in simm30 range in words
+  static bool is_in_wdisp30_range(address a, address b) {
+    return is_in_wdisp_range(a, b, 30);
   }
 
   enum ASIs { // page 72, v9
@@ -1843,6 +1851,8 @@
   inline void jmp( Register s1, Register s2 );
   inline void jmp( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() );
 
+  // Check if the call target is out of wdisp30 range (relative to the code cache)
+  static inline bool is_far_target(address d);
   inline void call( address d,  relocInfo::relocType rt = relocInfo::runtime_call_type );
   inline void call( Label& L,   relocInfo::relocType rt = relocInfo::runtime_call_type );
   inline void callr( Register s1, Register s2 );
@@ -2389,7 +2399,8 @@
     Label&   slow_case                 // continuation point if fast allocation fails
   );
   void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
-  void incr_allocated_bytes(Register var_size_in_bytes, int con_size_in_bytes, Register t1);
+  void incr_allocated_bytes(RegisterOrConstant size_in_bytes,
+                            Register t1, Register t2);
 
   // interface method calling
   void lookup_interface_method(Register recv_klass,
--- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -588,10 +588,13 @@
 inline void MacroAssembler::jmp( Register s1, Register s2 ) { jmpl( s1, s2, G0 ); }
 inline void MacroAssembler::jmp( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, G0, rspec); }
 
+inline bool MacroAssembler::is_far_target(address d) {
+  return !is_in_wdisp30_range(d, CodeCache::low_bound()) || !is_in_wdisp30_range(d, CodeCache::high_bound());
+}
+
 // Call with a check to see if we need to deal with the added
 // expense of relocation and if we overflow the displacement
-// of the quick call instruction./
-// Check to see if we have to deal with relocations
+// of the quick call instruction.
 inline void MacroAssembler::call( address d, relocInfo::relocType rt ) {
 #ifdef _LP64
   intptr_t disp;
@@ -603,14 +606,12 @@
 
   // Is this address within range of the call instruction?
   // If not, use the expensive instruction sequence
-  disp = (intptr_t)d - (intptr_t)pc();
-  if ( disp != (intptr_t)(int32_t)disp ) {
+  if (is_far_target(d)) {
     relocate(rt);
     AddressLiteral dest(d);
     jumpl_to(dest, O7, O7);
-  }
-  else {
-    Assembler::call( d, rt );
+  } else {
+    Assembler::call(d, rt);
   }
 #else
   Assembler::call( d, rt );
--- a/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -129,27 +129,6 @@
 }
 
 
-// Implementation of ArrayStoreExceptionStub
-
-ArrayStoreExceptionStub::ArrayStoreExceptionStub(CodeEmitInfo* info):
-  _info(info) {
-}
-
-
-void ArrayStoreExceptionStub::emit_code(LIR_Assembler* ce) {
-  __ bind(_entry);
-  __ call(Runtime1::entry_for(Runtime1::throw_array_store_exception_id), relocInfo::runtime_call_type);
-  __ delayed()->nop();
-  ce->add_call_info_here(_info);
-  ce->verify_oop_map(_info);
-#ifdef ASSERT
-  __ should_not_reach_here();
-#endif
-}
-
-
-
-
 // Implementation of NewInstanceStub
 
 NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id) {
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2358,6 +2358,8 @@
          op->tmp3()->as_register()  == G4 &&
          op->tmp4()->as_register()  == O1 &&
          op->klass()->as_register() == G5, "must be");
+
+  LP64_ONLY( __ signx(op->len()->as_register()); )
   if (UseSlowPath ||
       (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) ||
       (!UseFastNewTypeArray   && (op->type() != T_OBJECT && op->type() != T_ARRAY))) {
--- a/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -170,11 +170,13 @@
   Register t2,                         // temp register
   Label&   slow_case                   // continuation point if fast allocation fails
 ) {
+  RegisterOrConstant size_in_bytes = var_size_in_bytes->is_valid()
+    ? RegisterOrConstant(var_size_in_bytes) : RegisterOrConstant(con_size_in_bytes);
   if (UseTLAB) {
     tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
   } else {
     eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
-    incr_allocated_bytes(var_size_in_bytes, con_size_in_bytes, t1);
+    incr_allocated_bytes(size_in_bytes, t1, t2);
   }
 }
 
--- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -343,9 +343,10 @@
   // returned.
 
   restore_live_registers(sasm);
-  __ restore();
-  __ br(Assembler::always, false, Assembler::pt, deopt_blob->unpack_with_reexecution(), relocInfo::runtime_call_type);
-  __ delayed()->nop();
+
+  AddressLiteral dest(deopt_blob->unpack_with_reexecution());
+  __ jump_to(dest, O0);
+  __ delayed()->restore();
 
   __ bind(no_deopt);
   restore_live_registers(sasm);
@@ -461,7 +462,7 @@
           // get the instance size
           __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size);
           __ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path);
-          __ incr_allocated_bytes(G1_obj_size, 0, G3_t1);
+          __ incr_allocated_bytes(G1_obj_size, G3_t1, G4_t2);
 
           __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2);
           __ verify_oop(O0_obj);
@@ -577,7 +578,7 @@
           __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size);
 
           __ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path);  // preserves G1_arr_size
-          __ incr_allocated_bytes(G1_arr_size, 0, G3_t1);
+          __ incr_allocated_bytes(G1_arr_size, G3_t1, O1_t2);
 
           __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2);
           __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset);
@@ -709,7 +710,7 @@
     case throw_array_store_exception_id:
       {
         __ set_info("throw_array_store_exception", dont_gc_arguments);
-        oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), false);
+        oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true);
       }
       break;
 
--- a/src/cpu/sparc/vm/interp_masm_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1295,16 +1295,13 @@
 // Get the method data pointer from the methodOop and set the
 // specified register to its value.
 
-void InterpreterMacroAssembler::set_method_data_pointer_offset(Register Roff) {
+void InterpreterMacroAssembler::set_method_data_pointer() {
   assert(ProfileInterpreter, "must be profiling interpreter");
   Label get_continue;
 
   ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr);
   test_method_data_pointer(get_continue);
   add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr);
-  if (Roff != noreg)
-    // Roff contains a method data index ("mdi").  It defaults to zero.
-    add(ImethodDataPtr, Roff, ImethodDataPtr);
   bind(get_continue);
 }
 
@@ -1315,10 +1312,11 @@
   Label zero_continue;
 
   // Test MDO to avoid the call if it is NULL.
-  ld_ptr(Lmethod, methodOopDesc::method_data_offset(), ImethodDataPtr);
+  ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr);
   test_method_data_pointer(zero_continue);
   call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), Lmethod, Lbcp);
-  set_method_data_pointer_offset(O0);
+  add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr);
+  add(ImethodDataPtr, O0, ImethodDataPtr);
   bind(zero_continue);
 }
 
@@ -1369,7 +1367,6 @@
 }
 
 void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count,
-                                                                Register cur_bcp,
                                                                 Register Rtmp,
                                                                 Label &profile_continue) {
   assert(ProfileInterpreter, "must be profiling interpreter");
@@ -1400,8 +1397,8 @@
   delayed()->nop();
 
   // Build it now.
-  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), cur_bcp);
-  set_method_data_pointer_offset(O0);
+  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
+  set_method_data_pointer_for_bcp();
   ba(false, profile_continue);
   delayed()->nop();
   bind(done);
--- a/src/cpu/sparc/vm/interp_masm_sparc.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/interp_masm_sparc.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -269,12 +269,11 @@
 
 #ifndef CC_INTERP
   // Interpreter profiling operations
-  void set_method_data_pointer() { set_method_data_pointer_offset(noreg); }
+  void set_method_data_pointer();
   void set_method_data_pointer_for_bcp();
-  void set_method_data_pointer_offset(Register mdi_reg);
   void test_method_data_pointer(Label& zero_continue);
   void verify_method_data_pointer();
-  void test_invocation_counter_for_mdp(Register invocation_count, Register cur_bcp, Register Rtmp, Label &profile_continue);
+  void test_invocation_counter_for_mdp(Register invocation_count, Register Rtmp, Label &profile_continue);
 
   void set_mdp_data_at(int constant, Register value);
   void increment_mdp_data_at(Address counter, Register bumped_count,
--- a/src/cpu/sparc/vm/methodHandles_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -395,7 +395,7 @@
 //
 // Generate an "entry" field for a method handle.
 // This determines how the method handle will respond to calls.
-void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) {
+void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
   // Here is the register state during an interpreted call,
   // as set up by generate_method_handle_interpreter_entry():
   // - G5: garbage temp (was MethodHandle.invoke methodOop, unused)
@@ -447,8 +447,9 @@
       // exception.  Since we use a C2I adapter to set up the
       // interpreter state, arguments are expected in compiler
       // argument registers.
-      methodHandle mh(raise_exception_method());
-      address c2i_entry = methodOopDesc::make_adapters(mh, CATCH);
+      assert(raise_exception_method(), "must be set");
+      address c2i_entry = raise_exception_method()->get_c2i_entry();
+      assert(c2i_entry, "method must be linked");
 
       __ mov(O5_savedSP, SP);  // Cut the stack back to where the caller started.
 
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -2541,7 +2541,7 @@
     in_sig_bt[i++] = bt;  // Collect remaining bits of signature
     out_sig_bt[total_c_args++] = bt;
     if( bt == T_OBJECT) {
-      symbolOop s = ss.as_symbol_or_null();
+      Symbol* s = ss.as_symbol_or_null();
       if (s == vmSymbols::java_lang_String()) {
         total_strings++;
         out_sig_bt[total_c_args-1] = T_ADDRESS;
--- a/src/cpu/sparc/vm/sparc.ad	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/sparc.ad	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 //
 // This code is free software; you can redistribute it and/or modify it
@@ -575,7 +575,11 @@
 
 int MachCallRuntimeNode::ret_addr_offset() {
 #ifdef _LP64
-  return NativeFarCall::instruction_size;  // farcall; delay slot
+  if (MacroAssembler::is_far_target(entry_point())) {
+    return NativeFarCall::instruction_size;
+  } else {
+    return NativeCall::instruction_size;
+  }
 #else
   return NativeCall::instruction_size;  // call; delay slot
 #endif
@@ -941,7 +945,7 @@
 #endif
 }
 
-void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false, bool force_far_call = false) {
+void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false) {
   // The method which records debug information at every safepoint
   // expects the call to be the first instruction in the snippet as
   // it creates a PcDesc structure which tracks the offset of a call
@@ -963,20 +967,7 @@
   int startpos = __ offset();
 #endif /* ASSERT */
 
-#ifdef _LP64
-  // Calls to the runtime or native may not be reachable from compiled code,
-  // so we generate the far call sequence on 64 bit sparc.
-  // This code sequence is relocatable to any address, even on LP64.
-  if ( force_far_call ) {
-    __ relocate(rtype);
-    AddressLiteral dest(entry_point);
-    __ jumpl_to(dest, O7, O7);
-  }
-  else
-#endif
-  {
-     __ call((address)entry_point, rtype);
-  }
+  __ call((address)entry_point, rtype);
 
   if (preserve_g2)   __ delayed()->mov(G2, L7);
   else __ delayed()->nop();
@@ -2507,7 +2498,7 @@
     // CALL directly to the runtime
     // The user of this is responsible for ensuring that R_L7 is empty (killed).
     emit_call_reloc(cbuf, $meth$$method, relocInfo::runtime_call_type,
-                    /*preserve_g2=*/true, /*force far call*/true);
+                    /*preserve_g2=*/true);
   %}
 
   enc_class preserve_SP %{
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1364,15 +1364,8 @@
       // We have decided to profile this method in the interpreter
       __ bind(profile_method);
 
-      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), Lbcp, true);
-
-#ifdef ASSERT
-      __ tst(O0);
-      __ breakpoint_trap(Assembler::notEqual);
-#endif
-
-      __ set_method_data_pointer();
-
+      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
+      __ set_method_data_pointer_for_bcp();
       __ ba(false, profile_method_continue);
       __ delayed()->nop();
     }
--- a/src/cpu/sparc/vm/templateTable_sparc.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/sparc/vm/templateTable_sparc.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1689,7 +1689,7 @@
       const Register G4_invoke_ctr = G4;
       __ increment_backedge_counter(G4_invoke_ctr, G1_scratch);
       if (ProfileInterpreter) {
-        __ test_invocation_counter_for_mdp(G4_invoke_ctr, Lbcp, G3_scratch, Lforward);
+        __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward);
         if (UseOnStackReplacement) {
           __ test_backedge_count_for_osr(O2_bumped_count, O0_cur_bcp, G3_scratch);
         }
@@ -3447,7 +3447,8 @@
     __ delayed()->nop();
 
     // bump total bytes allocated by this thread
-    __ incr_allocated_bytes(Roffset, 0, G1_scratch);
+    // RoldTopValue and RtopAddr are dead, so can use G1 and G3
+    __ incr_allocated_bytes(Roffset, G1_scratch, G3_scratch);
   }
 
   if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {
--- a/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -411,20 +411,6 @@
 }
 
 
-ArrayStoreExceptionStub::ArrayStoreExceptionStub(CodeEmitInfo* info):
-  _info(info) {
-}
-
-
-void ArrayStoreExceptionStub::emit_code(LIR_Assembler* ce) {
-  assert(__ rsp_offset() == 0, "frame size should be fixed");
-  __ bind(_entry);
-  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::throw_array_store_exception_id)));
-  ce->add_call_info_here(_info);
-  debug_only(__ should_not_reach_here());
-}
-
-
 void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
   //---------------slow case: call to native-----------------
   __ bind(_entry);
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1641,12 +1641,14 @@
 }
 
 void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
+  Register len =  op->len()->as_register();
+  LP64_ONLY( __ movslq(len, len); )
+
   if (UseSlowPath ||
       (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) ||
       (!UseFastNewTypeArray   && (op->type() != T_OBJECT && op->type() != T_ARRAY))) {
     __ jmp(*op->stub()->entry());
   } else {
-    Register len =  op->len()->as_register();
     Register tmp1 = op->tmp1()->as_register();
     Register tmp2 = op->tmp2()->as_register();
     Register tmp3 = op->tmp3()->as_register();
--- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -733,8 +733,8 @@
 
   // generate compare-and-swap; produces zero condition if swap occurs
   int value_offset = sun_misc_AtomicLongCSImpl::value_offset();
-  LIR_Opr addr = obj.result();
-  __ add(addr, LIR_OprFact::intConst(value_offset), addr);
+  LIR_Opr addr = new_pointer_register();
+  __ leal(LIR_OprFact::address(new LIR_Address(obj.result(), value_offset, T_LONG)), addr);
   LIR_Opr t1 = LIR_OprFact::illegalOpr;  // no temp needed
   LIR_Opr t2 = LIR_OprFact::illegalOpr;  // no temp needed
   __ cas_long(addr, cmp_value.result(), new_value.result(), t1, t2);
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1432,7 +1432,7 @@
       { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments);
         // tos + 0: link
         //     + 1: return address
-        oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), false);
+        oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true);
       }
       break;
 
--- a/src/cpu/x86/vm/globals_x86.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/globals_x86.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -62,7 +62,7 @@
 // due to lack of optimization caused by C++ compiler bugs
 define_pd_global(intx, StackShadowPages, SOLARIS_ONLY(20) NOT_SOLARIS(6) DEBUG_ONLY(+2));
 #else
-define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
+define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+5));
 #endif // AMD64
 
 define_pd_global(intx, PreInflateSpin,           10);
--- a/src/cpu/x86/vm/interp_masm_x86_32.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -819,7 +819,7 @@
 // Set the method data pointer for the current bcp.
 void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
   assert(ProfileInterpreter, "must be profiling interpreter");
-  Label zero_continue;
+  Label set_mdp;
   push(rax);
   push(rbx);
 
@@ -827,21 +827,17 @@
   // Test MDO to avoid the call if it is NULL.
   movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
   testptr(rax, rax);
-  jcc(Assembler::zero, zero_continue);
-
+  jcc(Assembler::zero, set_mdp);
   // rbx,: method
   // rsi: bcp
   call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, rsi);
   // rax,: mdi
-
+  // mdo is guaranteed to be non-zero here, we checked for it before the call.
   movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
-  testptr(rbx, rbx);
-  jcc(Assembler::zero, zero_continue);
   addptr(rbx, in_bytes(methodDataOopDesc::data_offset()));
-  addptr(rbx, rax);
-  movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx);
-
-  bind(zero_continue);
+  addptr(rax, rbx);
+  bind(set_mdp);
+  movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
   pop(rbx);
   pop(rax);
 }
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -855,7 +855,7 @@
 // Set the method data pointer for the current bcp.
 void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
   assert(ProfileInterpreter, "must be profiling interpreter");
-  Label zero_continue;
+  Label set_mdp;
   push(rax);
   push(rbx);
 
@@ -863,21 +863,17 @@
   // Test MDO to avoid the call if it is NULL.
   movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
   testptr(rax, rax);
-  jcc(Assembler::zero, zero_continue);
-
+  jcc(Assembler::zero, set_mdp);
   // rbx: method
   // r13: bcp
   call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, r13);
   // rax: mdi
-
+  // mdo is guaranteed to be non-zero here, we checked for it before the call.
   movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
-  testptr(rbx, rbx);
-  jcc(Assembler::zero, zero_continue);
   addptr(rbx, in_bytes(methodDataOopDesc::data_offset()));
-  addptr(rbx, rax);
-  movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx);
-
-  bind(zero_continue);
+  addptr(rax, rbx);
+  bind(set_mdp);
+  movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
   pop(rbx);
   pop(rax);
 }
--- a/src/cpu/x86/vm/methodHandles_x86.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/methodHandles_x86.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -390,7 +390,7 @@
 //
 // Generate an "entry" field for a method handle.
 // This determines how the method handle will respond to calls.
-void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) {
+void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
   // Here is the register state during an interpreted call,
   // as set up by generate_method_handle_interpreter_entry():
   // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused)
@@ -451,8 +451,9 @@
       // exception.  Since we use a C2I adapter to set up the
       // interpreter state, arguments are expected in compiler
       // argument registers.
-      methodHandle mh(raise_exception_method());
-      address c2i_entry = methodOopDesc::make_adapters(mh, CHECK);
+      assert(raise_exception_method(), "must be set");
+      address c2i_entry = raise_exception_method()->get_c2i_entry();
+      assert(c2i_entry, "method must be linked");
 
       const Register rdi_pc = rax;
       __ pop(rdi_pc);  // caller PC
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1974,7 +1974,7 @@
     in_sig_bt[i++] = bt;  // Collect remaining bits of signature
     out_sig_bt[total_c_args++] = bt;
     if( bt == T_OBJECT) {
-      symbolOop s = ss.as_symbol_or_null();
+      Symbol* s = ss.as_symbol_or_null();   // symbol is created
       if (s == vmSymbols::java_lang_String()) {
         total_strings++;
         out_sig_bt[total_c_args-1] = T_ADDRESS;
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1980,7 +1980,7 @@
     in_sig_bt[i++] = bt;  // Collect remaining bits of signature
     out_sig_bt[total_c_args++] = bt;
     if( bt == T_OBJECT) {
-      symbolOop s = ss.as_symbol_or_null();
+      Symbol* s = ss.as_symbol_or_null();   // symbol is created
       if (s == vmSymbols::java_lang_String()) {
         total_strings++;
         out_sig_bt[total_c_args-1] = T_ADDRESS;
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1367,15 +1367,9 @@
     if (ProfileInterpreter) {
       // We have decided to profile this method in the interpreter
       __ bind(profile_method);
-
-      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), rsi, true);
-
-      __ movptr(rbx, Address(rbp, method_offset));   // restore methodOop
-      __ movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
-      __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
-      __ test_method_data_pointer(rax, profile_method_continue);
-      __ addptr(rax, in_bytes(methodDataOopDesc::data_offset()));
-      __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
+      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
+      __ set_method_data_pointer_for_bcp();
+      __ get_method(rbx);
       __ jmp(profile_method_continue);
     }
     // Handle overflow of counter and compile method
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1383,20 +1383,9 @@
     if (ProfileInterpreter) {
       // We have decided to profile this method in the interpreter
       __ bind(profile_method);
-
-      __ call_VM(noreg,
-                 CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method),
-                 r13, true);
-
-      __ movptr(rbx, Address(rbp, method_offset)); // restore methodOop
-      __ movptr(rax, Address(rbx,
-                             in_bytes(methodOopDesc::method_data_offset())));
-      __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
-                rax);
-      __ test_method_data_pointer(rax, profile_method_continue);
-      __ addptr(rax, in_bytes(methodDataOopDesc::data_offset()));
-      __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
-              rax);
+      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
+      __ set_method_data_pointer_for_bcp();
+      __ get_method(rbx);
       __ jmp(profile_method_continue);
     }
     // Handle overflow of counter and compile method
--- a/src/cpu/x86/vm/templateTable_x86_32.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/templateTable_x86_32.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1665,16 +1665,9 @@
     if (ProfileInterpreter) {
       // Out-of-line code to allocate method data oop.
       __ bind(profile_method);
-      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), rsi);
+      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
       __ load_unsigned_byte(rbx, Address(rsi, 0));  // restore target bytecode
-      __ movptr(rcx, Address(rbp, method_offset));
-      __ movptr(rcx, Address(rcx, in_bytes(methodOopDesc::method_data_offset())));
-      __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rcx);
-      __ test_method_data_pointer(rcx, dispatch);
-      // offset non-null mdp by MDO::data_offset() + IR::profile_method()
-      __ addptr(rcx, in_bytes(methodDataOopDesc::data_offset()));
-      __ addptr(rcx, rax);
-      __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rcx);
+      __ set_method_data_pointer_for_bcp();
       __ jmp(dispatch);
     }
 
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1695,21 +1695,9 @@
     if (ProfileInterpreter) {
       // Out-of-line code to allocate method data oop.
       __ bind(profile_method);
-      __ call_VM(noreg,
-                 CAST_FROM_FN_PTR(address,
-                                  InterpreterRuntime::profile_method), r13);
+      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
       __ load_unsigned_byte(rbx, Address(r13, 0));  // restore target bytecode
-      __ movptr(rcx, Address(rbp, method_offset));
-      __ movptr(rcx, Address(rcx,
-                             in_bytes(methodOopDesc::method_data_offset())));
-      __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
-                rcx);
-      __ test_method_data_pointer(rcx, dispatch);
-      // offset non-null mdp by MDO::data_offset() + IR::profile_method()
-      __ addptr(rcx, in_bytes(methodDataOopDesc::data_offset()));
-      __ addptr(rcx, rax);
-      __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
-                rcx);
+      __ set_method_data_pointer_for_bcp();
       __ jmp(dispatch);
     }
 
--- a/src/os/linux/vm/os_linux.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os/linux/vm/os_linux.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1610,10 +1610,9 @@
 
 const char* os::dll_file_extension() { return ".so"; }
 
-const char* os::get_temp_directory() {
-  const char *prop = Arguments::get_property("java.io.tmpdir");
-  return prop == NULL ? "/tmp" : prop;
-}
+// This must be hard coded because it's the system's temporary
+// directory not the java application's temp directory, ala java.io.tmpdir.
+const char* os::get_temp_directory() { return "/tmp"; }
 
 static bool file_exists(const char* filename) {
   struct stat statbuf;
--- a/src/os/solaris/dtrace/generateJvmOffsets.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os/solaris/dtrace/generateJvmOffsets.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -49,7 +49,7 @@
 #include "oops/klass.hpp"
 #include "oops/methodOop.hpp"
 #include "oops/oop.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/virtualspace.hpp"
 #include "runtime/vmStructs.hpp"
 #include "utilities/accessFlags.hpp"
@@ -215,8 +215,8 @@
   GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE);
   GEN_VALUE(constMethodOopDesc_has_linenumber_table, constMethodOopDesc::_has_linenumber_table);
   GEN_OFFS(AccessFlags, _flags);
-  GEN_OFFS(symbolOopDesc, _length);
-  GEN_OFFS(symbolOopDesc, _body);
+  GEN_OFFS(Symbol, _length);
+  GEN_OFFS(Symbol, _body);
   printf("\n");
 
   GEN_OFFS(methodOopDesc, _constMethod);
--- a/src/os/solaris/dtrace/jhelper.d	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os/solaris/dtrace/jhelper.d	Wed Feb 16 13:47:20 2011 +0100
@@ -114,8 +114,8 @@
   copyin_offset(OFFSET_HeapBlockHeader_used);
   copyin_offset(OFFSET_oopDesc_metadata);
 
-  copyin_offset(OFFSET_symbolOopDesc_length);
-  copyin_offset(OFFSET_symbolOopDesc_body);
+  copyin_offset(OFFSET_Symbol_length);
+  copyin_offset(OFFSET_Symbol_body);
 
   copyin_offset(OFFSET_methodOopDesc_constMethod);
   copyin_offset(OFFSET_methodOopDesc_constants);
@@ -366,13 +366,13 @@
       this->nameIndex * sizeof (pointer) + SIZE_constantPoolOopDesc);
 
   this->nameSymbolLength = copyin_uint16(this->nameSymbol +
-      OFFSET_symbolOopDesc_length);
+      OFFSET_Symbol_length);
 
   this->signatureSymbol = copyin_ptr(this->constantPool +
       this->signatureIndex * sizeof (pointer) + SIZE_constantPoolOopDesc);
 
   this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
-      OFFSET_symbolOopDesc_length);
+      OFFSET_Symbol_length);
 
   this->klassPtr = copyin_ptr(this->constantPool +
       OFFSET_constantPoolOopDesc_pool_holder);
@@ -381,7 +381,7 @@
       OFFSET_Klass_name + SIZE_oopDesc);
 
   this->klassSymbolLength = copyin_uint16(this->klassSymbol +
-      OFFSET_symbolOopDesc_length);
+      OFFSET_Symbol_length);
 
   /*
    * Enough for three strings, plus the '.', plus the trailing '\0'.
@@ -390,7 +390,7 @@
       this->nameSymbolLength +
       this->signatureSymbolLength + 2 + 1);
 
-  copyinto(this->klassSymbol + OFFSET_symbolOopDesc_body,
+  copyinto(this->klassSymbol + OFFSET_Symbol_body,
       this->klassSymbolLength, this->result);
 
   /*
@@ -398,11 +398,11 @@
    */
   this->result[this->klassSymbolLength] = '.';
 
-  copyinto(this->nameSymbol + OFFSET_symbolOopDesc_body,
+  copyinto(this->nameSymbol + OFFSET_Symbol_body,
       this->nameSymbolLength,
       this->result + this->klassSymbolLength + 1);
 
-  copyinto(this->signatureSymbol + OFFSET_symbolOopDesc_body,
+  copyinto(this->signatureSymbol + OFFSET_Symbol_body,
       this->signatureSymbolLength,
       this->result + this->klassSymbolLength +
       this->nameSymbolLength + 1);
--- a/src/os/solaris/dtrace/libjvm_db.c	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os/solaris/dtrace/libjvm_db.c	Wed Feb 16 13:47:20 2011 +0100
@@ -524,10 +524,10 @@
   CHECK_FAIL(err);
   err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &nameSymbol);
   CHECK_FAIL(err);
-  err = ps_pread(J->P, nameSymbol + OFFSET_symbolOopDesc_length, &nameSymbolLength, 2);
+  err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
   CHECK_FAIL(err);
   nameString = (char*)calloc(nameSymbolLength + 1, 1);
-  err = ps_pread(J->P, nameSymbol + OFFSET_symbolOopDesc_body, nameString, nameSymbolLength);
+  err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
   CHECK_FAIL(err);
 
   /* To get signature string */
@@ -535,10 +535,10 @@
   CHECK_FAIL(err);
   err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &signatureSymbol);
   CHECK_FAIL(err);
-  err = ps_pread(J->P, signatureSymbol + OFFSET_symbolOopDesc_length, &signatureSymbolLength, 2);
+  err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
   CHECK_FAIL(err);
   signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
-  err = ps_pread(J->P, signatureSymbol + OFFSET_symbolOopDesc_body, signatureString, signatureSymbolLength);
+  err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
   CHECK_FAIL(err);
 
   /* To get klass string */
@@ -546,10 +546,10 @@
   CHECK_FAIL(err);
   err = read_pointer(J, klassPtr + OFFSET_Klass_name + SIZE_oopDesc, &klassSymbol);
   CHECK_FAIL(err);
-  err = ps_pread(J->P, klassSymbol + OFFSET_symbolOopDesc_length, &klassSymbolLength, 2);
+  err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
   CHECK_FAIL(err);
   klassString = (char*)calloc(klassSymbolLength + 1, 1);
-  err = ps_pread(J->P, klassSymbol + OFFSET_symbolOopDesc_body, klassString, klassSymbolLength);
+  err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
   CHECK_FAIL(err);
 
   result[0] = '\0';
--- a/src/os/solaris/vm/dtraceJSDT_solaris.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os/solaris/vm/dtraceJSDT_solaris.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -142,7 +142,7 @@
     ++strcount;
     for(int prbc = 0; prbc < provider->probe_count; ++prbc) {
       JVM_DTraceProbe* p = &(provider->probes[prbc]);
-      symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
+      Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
       // function + name + one per argument
       strcount += 2 + ArgumentCount(sig).size();
     }
@@ -178,7 +178,7 @@
       stroffs[curstr++] = string_index;
       string_index += strlen(name) + 1;
 
-      symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
+      Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
       SignatureStream ss(sig);
       for ( ; !ss.at_return_type(); ss.next()) {
         BasicType bt = ss.type();
@@ -227,7 +227,7 @@
     uint32_t argscount = 0;
     for(int prbc = 0; prbc < provider->probe_count; ++prbc) {
        JVM_DTraceProbe* p = &(provider->probes[prbc]);
-       symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
+       Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
        argscount += ArgumentCount(sig).size();
     }
     secoffs[argoffs_sec] = align_size_up(offset, alignment_for[ARG_OFFSETS]);
@@ -298,7 +298,7 @@
       strcpy(str, name);
       str += strlen(name) + 1;
 
-      symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
+      Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
       SignatureStream ss(sig);
       for ( ; !ss.at_return_type(); ss.next()) {
         BasicType bt = ss.type();
@@ -433,7 +433,7 @@
     uint8_t* par = (uint8_t*)(dof + sec->dofs_offset);
     for (int prbc = 0; prbc < provider->probe_count; ++prbc) {
       JVM_DTraceProbe* p = &(provider->probes[prbc]);
-      symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
+      Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature();
       uint8_t count = (uint8_t)ArgumentCount(sig).size();
       for (uint8_t i = 0; i < count; ++i) {
         *par++ = i;
--- a/src/os/solaris/vm/os_solaris.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os/solaris/vm/os_solaris.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1884,10 +1884,9 @@
 
 const char* os::dll_file_extension() { return ".so"; }
 
-const char* os::get_temp_directory() {
-  const char *prop = Arguments::get_property("java.io.tmpdir");
-  return prop == NULL ? "/tmp" : prop;
-}
+// This must be hard coded because it's the system's temporary
+// directory not the java application's temp directory, ala java.io.tmpdir.
+const char* os::get_temp_directory() { return "/tmp"; }
 
 static bool file_exists(const char* filename) {
   struct stat statbuf;
--- a/src/os/windows/vm/os_windows.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os/windows/vm/os_windows.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1044,9 +1044,9 @@
     return 0;
 }
 
+// This must be hard coded because it's the system's temporary
+// directory not the java application's temp directory, ala java.io.tmpdir.
 const char* os::get_temp_directory() {
-  const char *prop = Arguments::get_property("java.io.tmpdir");
-  if (prop != 0) return prop;
   static char path_buf[MAX_PATH];
   if (GetTempPath(MAX_PATH, path_buf)>0)
     return path_buf;
--- a/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,6 +54,8 @@
 inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
 inline void Atomic::dec_ptr(volatile void*     dest) { (void)add_ptr(-1, dest); }
 
+inline jlong Atomic::load(volatile jlong* src) { return *src; }
+
 inline jint     Atomic::add    (jint     add_value, volatile jint*     dest) {
   intptr_t rv;
   __asm__ volatile(
--- a/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -100,11 +100,6 @@
   return exchange_value;
 }
 
-extern "C" {
-  // defined in linux_x86.s
-  jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool);
-}
-
 #ifdef AMD64
 inline void Atomic::store    (jlong    store_value, jlong*    dest) { *dest = store_value; }
 inline void Atomic::store    (jlong    store_value, volatile jlong*    dest) { *dest = store_value; }
@@ -164,9 +159,9 @@
   return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
 }
 
-#else
-//inline void Atomic::store    (jlong    store_value, jlong*    dest) { *dest = store_value; }
-//inline void Atomic::store  (jlong    store_value, volatile jlong*    dest) { *dest = store_value; }
+inline jlong Atomic::load(volatile jlong* src) { return *src; }
+
+#else // !AMD64
 
 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
   return (intptr_t)Atomic::add((jint)add_value, (volatile jint*)dest);
@@ -189,6 +184,12 @@
   return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest);
 }
 
+extern "C" {
+  // defined in linux_x86.s
+  jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool);
+  void _Atomic_move_long(volatile jlong* src, volatile jlong* dst);
+}
+
 inline jlong    Atomic::cmpxchg    (jlong    exchange_value, volatile jlong*    dest, jlong    compare_value) {
   return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP());
 }
@@ -200,6 +201,21 @@
 inline void*    Atomic::cmpxchg_ptr(void*    exchange_value, volatile void*     dest, void*    compare_value) {
   return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
 }
+
+inline jlong Atomic::load(volatile jlong* src) {
+  volatile jlong dest;
+  _Atomic_move_long(src, &dest);
+  return dest;
+}
+
+inline void Atomic::store(jlong store_value, jlong* dest) {
+  _Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+  _Atomic_move_long((volatile jlong*)&store_value, dest);
+}
+
 #endif // AMD64
 
 #endif // OS_CPU_LINUX_X86_VM_ATOMIC_LINUX_X86_INLINE_HPP
--- a/src/os_cpu/linux_x86/vm/linux_x86_32.s	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/linux_x86/vm/linux_x86_32.s	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 # 
-# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
 	.globl _mmx_Copy_arrayof_conjoint_jshorts
 
         .globl _Atomic_cmpxchg_long
+        .globl _Atomic_move_long
 
 	.text
 
@@ -653,3 +654,15 @@
         popl     %ebx
         ret
 
+
+        # Support for jlong Atomic::load and Atomic::store.
+        # void _Atomic_move_long(volatile jlong* src, volatile jlong* dst)
+        .p2align 4,,15
+	.type    _Atomic_move_long,@function
+_Atomic_move_long:
+        movl     4(%esp), %eax   # src
+        fildll    (%eax)
+        movl     8(%esp), %eax   # dest
+        fistpll   (%eax)
+        ret
+
--- a/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 #ifndef OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP
 #define OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP
 
+#include "runtime/atomic.hpp"
 #include "runtime/orderAccess.hpp"
 #include "vm_version_x86.hpp"
 
@@ -64,11 +65,11 @@
 inline jbyte    OrderAccess::load_acquire(volatile jbyte*   p) { return *p; }
 inline jshort   OrderAccess::load_acquire(volatile jshort*  p) { return *p; }
 inline jint     OrderAccess::load_acquire(volatile jint*    p) { return *p; }
-inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { return *p; }
+inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { return Atomic::load(p); }
 inline jubyte   OrderAccess::load_acquire(volatile jubyte*  p) { return *p; }
 inline jushort  OrderAccess::load_acquire(volatile jushort* p) { return *p; }
 inline juint    OrderAccess::load_acquire(volatile juint*   p) { return *p; }
-inline julong   OrderAccess::load_acquire(volatile julong*  p) { return *p; }
+inline julong   OrderAccess::load_acquire(volatile julong*  p) { return Atomic::load((volatile jlong*)p); }
 inline jfloat   OrderAccess::load_acquire(volatile jfloat*  p) { return *p; }
 inline jdouble  OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
 
@@ -79,11 +80,11 @@
 inline void     OrderAccess::release_store(volatile jbyte*   p, jbyte   v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jshort*  p, jshort  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jint*    p, jint    v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { *p = v; }
+inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { Atomic::store(v, p); }
 inline void     OrderAccess::release_store(volatile jubyte*  p, jubyte  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
 inline void     OrderAccess::release_store(volatile juint*   p, juint   v) { *p = v; }
-inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { *p = v; }
+inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { Atomic::store((jlong)v, (volatile jlong*)p); }
 inline void     OrderAccess::release_store(volatile jfloat*  p, jfloat  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
 
@@ -178,7 +179,7 @@
                           : "0" (v), "r" (p)
                           : "memory");
 #else
-  *p = v; fence();
+  release_store(p, v); fence();
 #endif // AMD64
 }
 
--- a/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,14 +35,12 @@
 inline void Atomic::store    (jbyte    store_value, jbyte*    dest) { *dest = store_value; }
 inline void Atomic::store    (jshort   store_value, jshort*   dest) { *dest = store_value; }
 inline void Atomic::store    (jint     store_value, jint*     dest) { *dest = store_value; }
-inline void Atomic::store    (jlong    store_value, jlong*    dest) { *dest = store_value; }
 inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
 inline void Atomic::store_ptr(void*    store_value, void*     dest) { *(void**)dest = store_value; }
 
 inline void Atomic::store    (jbyte    store_value, volatile jbyte*    dest) { *dest = store_value; }
 inline void Atomic::store    (jshort   store_value, volatile jshort*   dest) { *dest = store_value; }
 inline void Atomic::store    (jint     store_value, volatile jint*     dest) { *dest = store_value; }
-inline void Atomic::store    (jlong    store_value, volatile jlong*    dest) { *dest = store_value; }
 inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
 inline void Atomic::store_ptr(void*    store_value, volatile void*     dest) { *(void* volatile *)dest = store_value; }
 
@@ -54,8 +52,49 @@
 inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
 inline void Atomic::dec_ptr(volatile void*     dest) { (void)add_ptr(-1, dest); }
 
+
+#ifdef _LP64
+
+inline void Atomic::store(jlong store_value, jlong* dest) { *dest = store_value; }
+inline void Atomic::store(jlong store_value, volatile jlong* dest) { *dest = store_value; }
 inline jlong Atomic::load(volatile jlong* src) { return *src; }
 
+#else
+
+extern "C" void _Atomic_move_long_v8(volatile jlong* src, volatile jlong* dst);
+extern "C" void _Atomic_move_long_v9(volatile jlong* src, volatile jlong* dst);
+
+inline void Atomic_move_long(volatile jlong* src, volatile jlong* dst) {
+#ifdef COMPILER2
+  // Compiler2 does not support v8, it is used only for v9.
+  assert (VM_Version::v9_instructions_work(), "only supported on v9");
+  _Atomic_move_long_v9(src, dst);
+#else
+  // The branch is cheaper then emulated LDD.
+  if (VM_Version::v9_instructions_work()) {
+    _Atomic_move_long_v9(src, dst);
+  } else {
+    _Atomic_move_long_v8(src, dst);
+  }
+#endif
+}
+
+inline jlong Atomic::load(volatile jlong* src) {
+  volatile jlong dest;
+  Atomic_move_long(src, &dest);
+  return dest;
+}
+
+inline void Atomic::store(jlong store_value, jlong* dest) {
+  Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+  Atomic_move_long((volatile jlong*)&store_value, dest);
+}
+
+#endif
+
 #ifdef _GNU_SOURCE
 
 inline jint     Atomic::add    (jint     add_value, volatile jint*     dest) {
--- a/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,11 +77,11 @@
 inline jbyte    OrderAccess::load_acquire(volatile jbyte*   p) { return *p; }
 inline jshort   OrderAccess::load_acquire(volatile jshort*  p) { return *p; }
 inline jint     OrderAccess::load_acquire(volatile jint*    p) { return *p; }
-inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { return *p; }
+inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { return Atomic::load(p); }
 inline jubyte   OrderAccess::load_acquire(volatile jubyte*  p) { return *p; }
 inline jushort  OrderAccess::load_acquire(volatile jushort* p) { return *p; }
 inline juint    OrderAccess::load_acquire(volatile juint*   p) { return *p; }
-inline julong   OrderAccess::load_acquire(volatile julong*  p) { return *p; }
+inline julong   OrderAccess::load_acquire(volatile julong*  p) { return Atomic::load((volatile jlong*)p); }
 inline jfloat   OrderAccess::load_acquire(volatile jfloat*  p) { return *p; }
 inline jdouble  OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
 
@@ -92,11 +92,11 @@
 inline void     OrderAccess::release_store(volatile jbyte*   p, jbyte   v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jshort*  p, jshort  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jint*    p, jint    v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { *p = v; }
+inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { Atomic::store(v, p); }
 inline void     OrderAccess::release_store(volatile jubyte*  p, jubyte  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
 inline void     OrderAccess::release_store(volatile juint*   p, juint   v) { *p = v; }
-inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { *p = v; }
+inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { Atomic::store((jlong)v, (volatile jlong*)p); }
 inline void     OrderAccess::release_store(volatile jfloat*  p, jfloat  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
 
@@ -120,11 +120,11 @@
 inline void     OrderAccess::release_store_fence(volatile jbyte*   p, jbyte   v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile jshort*  p, jshort  v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile jint*    p, jint    v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jlong*   p, jlong   v) { *p = v; fence(); }
+inline void     OrderAccess::release_store_fence(volatile jlong*   p, jlong   v) { release_store(p, v); fence(); }
 inline void     OrderAccess::release_store_fence(volatile jubyte*  p, jubyte  v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile juint*   p, juint   v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile julong*  p, julong  v) { *p = v; fence(); }
+inline void     OrderAccess::release_store_fence(volatile julong*  p, julong  v) { release_store(p, v); fence(); }
 inline void     OrderAccess::release_store_fence(volatile jfloat*  p, jfloat  v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
 
--- a/src/os_cpu/solaris_sparc/vm/solaris_sparc.il	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/solaris_sparc/vm/solaris_sparc.il	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 //
 // This code is free software; you can redistribute it and/or modify it
@@ -152,6 +152,39 @@
         .nonvolatile
         .end
 
+  // Support for jlong Atomic::load and Atomic::store on v8.
+  //
+  // void _Atomic_move_long_v8(volatile jlong* src, volatile jlong* dst)
+  //
+  // Arguments:
+  //      src:  O0
+  //      dest: O1
+  //
+  // Overwrites O2 and O3
+
+        .inline _Atomic_move_long_v8,2
+        .volatile
+        ldd     [%o0], %o2
+        std     %o2, [%o1]
+        .nonvolatile
+        .end
+
+  // Support for jlong Atomic::load and Atomic::store on v9.
+  //
+  // void _Atomic_move_long_v9(volatile jlong* src, volatile jlong* dst)
+  //
+  // Arguments:
+  //      src:  O0
+  //      dest: O1
+  //
+  // Overwrites O2
+
+        .inline _Atomic_move_long_v9,2
+        .volatile
+        ldx     [%o0], %o2
+        stx     %o2, [%o1]
+        .nonvolatile
+        .end
 
   // Support for jint Atomic::add(jint add_value, volatile jint* dest).
   //
--- a/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -151,14 +151,22 @@
   return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
 }
 
-extern "C" void _Atomic_load_long(volatile jlong* src, volatile jlong* dst);
+extern "C" void _Atomic_move_long(volatile jlong* src, volatile jlong* dst);
 
 inline jlong Atomic::load(volatile jlong* src) {
   volatile jlong dest;
-  _Atomic_load_long(src, &dest);
+  _Atomic_move_long(src, &dest);
   return dest;
 }
 
+inline void Atomic::store(jlong store_value, jlong* dest) {
+  _Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+  _Atomic_move_long((volatile jlong*)&store_value, dest);
+}
+
 #endif // AMD64
 
 #ifdef _GNU_SOURCE
--- a/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 #ifndef OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP
 #define OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP
 
+#include "runtime/atomic.hpp"
 #include "runtime/orderAccess.hpp"
 #include "vm_version_x86.hpp"
 
@@ -80,11 +81,11 @@
 inline jbyte    OrderAccess::load_acquire(volatile jbyte*   p) { return *p; }
 inline jshort   OrderAccess::load_acquire(volatile jshort*  p) { return *p; }
 inline jint     OrderAccess::load_acquire(volatile jint*    p) { return *p; }
-inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { return *p; }
+inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { return Atomic::load(p); }
 inline jubyte   OrderAccess::load_acquire(volatile jubyte*  p) { return *p; }
 inline jushort  OrderAccess::load_acquire(volatile jushort* p) { return *p; }
 inline juint    OrderAccess::load_acquire(volatile juint*   p) { return *p; }
-inline julong   OrderAccess::load_acquire(volatile julong*  p) { return *p; }
+inline julong   OrderAccess::load_acquire(volatile julong*  p) { return Atomic::load((volatile jlong*)p); }
 inline jfloat   OrderAccess::load_acquire(volatile jfloat*  p) { return *p; }
 inline jdouble  OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
 
@@ -95,11 +96,11 @@
 inline void     OrderAccess::release_store(volatile jbyte*   p, jbyte   v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jshort*  p, jshort  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jint*    p, jint    v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { *p = v; }
+inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { Atomic::store(v, p); }
 inline void     OrderAccess::release_store(volatile jubyte*  p, jubyte  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
 inline void     OrderAccess::release_store(volatile juint*   p, juint   v) { *p = v; }
-inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { *p = v; }
+inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { Atomic::store((jlong)v, (volatile jlong*)p); }
 inline void     OrderAccess::release_store(volatile jfloat*  p, jfloat  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
 
@@ -123,11 +124,11 @@
 inline void     OrderAccess::release_store_fence(volatile jbyte*   p, jbyte   v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile jshort*  p, jshort  v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile jint*    p, jint    v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jlong*   p, jlong   v) { *p = v; fence(); }
+inline void     OrderAccess::release_store_fence(volatile jlong*   p, jlong   v) { release_store(p, v); fence(); }
 inline void     OrderAccess::release_store_fence(volatile jubyte*  p, jubyte  v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile juint*   p, juint   v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile julong*  p, julong  v) { *p = v; fence(); }
+inline void     OrderAccess::release_store_fence(volatile julong*  p, julong  v) { release_store(p, v); fence(); }
 inline void     OrderAccess::release_store_fence(volatile jfloat*  p, jfloat  v) { *p = v; fence(); }
 inline void     OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
 
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/solaris_x86/vm/solaris_x86_32.il	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 //
 // This code is free software; you can redistribute it and/or modify it
@@ -104,8 +104,9 @@
       popl     %ebx
       .end
 
-  // Support for void Atomic::load(volatile jlong* src, volatile jlong* dest).
-      .inline _Atomic_load_long,2
+  // Support for jlong Atomic::load and Atomic::store.
+  // void _Atomic_move_long(volatile jlong* src, volatile jlong* dst)
+      .inline _Atomic_move_long,2
       movl     0(%esp), %eax   // src
       fildll    (%eax)
       movl     4(%esp), %eax   // dest
--- a/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -137,10 +137,10 @@
   return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
 }
 
+inline jlong Atomic::load(volatile jlong* src) { return *src; }
+
 #else // !AMD64
 
-//inline void Atomic::store    (jlong    store_value, jlong*    dest) { *dest = store_value; }
-//inline void Atomic::store  (jlong    store_value, volatile jlong*    dest) { *dest = store_value; }
 inline jint     Atomic::add    (jint     add_value, volatile jint*     dest) {
   int mp = os::is_MP();
   __asm {
@@ -254,6 +254,33 @@
 inline void*    Atomic::cmpxchg_ptr(void*    exchange_value, volatile void*     dest, void*    compare_value) {
   return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
 }
+
+inline jlong Atomic::load(volatile jlong* src) {
+  volatile jlong dest;
+  volatile jlong* pdest = &dest;
+  __asm {
+    mov eax, src
+    fild     qword ptr [eax]
+    mov eax, pdest
+    fistp    qword ptr [eax]
+  }
+  return dest;
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+  volatile jlong* src = &store_value;
+  __asm {
+    mov eax, src
+    fild     qword ptr [eax]
+    mov eax, dest
+    fistp    qword ptr [eax]
+  }
+}
+
+inline void Atomic::store(jlong store_value, jlong* dest) {
+  Atomic::store(store_value, (volatile jlong*)dest);
+}
+
 #endif // AMD64
 
 #pragma warning(default: 4035) // Enables warnings reporting missing return statement
--- a/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 #ifndef OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP
 #define OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP
 
+#include "runtime/atomic.hpp"
 #include "runtime/orderAccess.hpp"
 #include "vm_version_x86.hpp"
 
@@ -65,11 +66,11 @@
 inline jbyte    OrderAccess::load_acquire(volatile jbyte*   p) { return *p; }
 inline jshort   OrderAccess::load_acquire(volatile jshort*  p) { return *p; }
 inline jint     OrderAccess::load_acquire(volatile jint*    p) { return *p; }
-inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { return *p; }
+inline jlong    OrderAccess::load_acquire(volatile jlong*   p) { return Atomic::load(p); }
 inline jubyte   OrderAccess::load_acquire(volatile jubyte*  p) { return *p; }
 inline jushort  OrderAccess::load_acquire(volatile jushort* p) { return *p; }
 inline juint    OrderAccess::load_acquire(volatile juint*   p) { return *p; }
-inline julong   OrderAccess::load_acquire(volatile julong*  p) { return *p; }
+inline julong   OrderAccess::load_acquire(volatile julong*  p) { return Atomic::load((volatile jlong*)p); }
 inline jfloat   OrderAccess::load_acquire(volatile jfloat*  p) { return *p; }
 inline jdouble  OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
 
@@ -80,11 +81,11 @@
 inline void     OrderAccess::release_store(volatile jbyte*   p, jbyte   v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jshort*  p, jshort  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jint*    p, jint    v) { *p = v; }
-inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { *p = v; }
+inline void     OrderAccess::release_store(volatile jlong*   p, jlong   v) { Atomic::store(v, p); }
 inline void     OrderAccess::release_store(volatile jubyte*  p, jubyte  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
 inline void     OrderAccess::release_store(volatile juint*   p, juint   v) { *p = v; }
-inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { *p = v; }
+inline void     OrderAccess::release_store(volatile julong*  p, julong  v) { Atomic::store((jlong)v, (volatile jlong*)p); }
 inline void     OrderAccess::release_store(volatile jfloat*  p, jfloat  v) { *p = v; }
 inline void     OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
 
@@ -188,7 +189,7 @@
 #endif // AMD64
 }
 
-inline void     OrderAccess::release_store_fence(volatile jlong*   p, jlong   v) { *p = v; fence(); }
+inline void     OrderAccess::release_store_fence(volatile jlong*   p, jlong   v) { release_store(p, v); fence(); }
 
 inline void     OrderAccess::release_store_fence(volatile jubyte*  p, jubyte  v) { release_store_fence((volatile jbyte*)p,  (jbyte)v);  }
 inline void     OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); }
--- a/src/share/vm/c1/c1_Canonicalizer.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_Canonicalizer.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -898,4 +898,4 @@
 void Canonicalizer::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {}
 void Canonicalizer::do_ProfileCall(ProfileCall* x) {}
 void Canonicalizer::do_ProfileInvoke(ProfileInvoke* x) {}
-
+void Canonicalizer::do_RuntimeCall(RuntimeCall* x) {}
--- a/src/share/vm/c1/c1_Canonicalizer.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_Canonicalizer.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -102,6 +102,7 @@
   virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x);
   virtual void do_ProfileCall    (ProfileCall*     x);
   virtual void do_ProfileInvoke  (ProfileInvoke*   x);
+  virtual void do_RuntimeCall    (RuntimeCall*     x);
 };
 
 #endif // SHARE_VM_C1_C1_CANONICALIZER_HPP
--- a/src/share/vm/c1/c1_CodeStubs.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_CodeStubs.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -476,18 +476,12 @@
 
 
 
-class ArrayStoreExceptionStub: public CodeStub {
+class ArrayStoreExceptionStub: public SimpleExceptionStub {
  private:
   CodeEmitInfo* _info;
 
  public:
-  ArrayStoreExceptionStub(CodeEmitInfo* info);
-  virtual void emit_code(LIR_Assembler* emit);
-  virtual CodeEmitInfo* info() const             { return _info; }
-  virtual bool is_exception_throw_stub() const   { return true; }
-  virtual void visit(LIR_OpVisitState* visitor) {
-    visitor->do_slow_case(_info);
-  }
+  ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(Runtime1::throw_array_store_exception_id, obj, info) {}
 #ifndef PRODUCT
   virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); }
 #endif // PRODUCT
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -319,24 +319,24 @@
 
       case Bytecodes::_tableswitch: {
         // set block for each case
-        Bytecode_tableswitch *switch_ = Bytecode_tableswitch_at(s.cur_bcp());
-        int l = switch_->length();
+        Bytecode_tableswitch sw(&s);
+        int l = sw.length();
         for (int i = 0; i < l; i++) {
-          make_block_at(cur_bci + switch_->dest_offset_at(i), current);
+          make_block_at(cur_bci + sw.dest_offset_at(i), current);
         }
-        make_block_at(cur_bci + switch_->default_offset(), current);
+        make_block_at(cur_bci + sw.default_offset(), current);
         current = NULL;
         break;
       }
 
       case Bytecodes::_lookupswitch: {
         // set block for each case
-        Bytecode_lookupswitch *switch_ = Bytecode_lookupswitch_at(s.cur_bcp());
-        int l = switch_->number_of_pairs();
+        Bytecode_lookupswitch sw(&s);
+        int l = sw.number_of_pairs();
         for (int i = 0; i < l; i++) {
-          make_block_at(cur_bci + switch_->pair_at(i)->offset(), current);
+          make_block_at(cur_bci + sw.pair_at(i).offset(), current);
         }
-        make_block_at(cur_bci + switch_->default_offset(), current);
+        make_block_at(cur_bci + sw.default_offset(), current);
         current = NULL;
         break;
       }
@@ -1275,15 +1275,15 @@
 
 
 void GraphBuilder::table_switch() {
-  Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(method()->code() + bci());
-  const int l = switch_->length();
+  Bytecode_tableswitch sw(stream());
+  const int l = sw.length();
   if (CanonicalizeNodes && l == 1) {
     // total of 2 successors => use If instead of switch
     // Note: This code should go into the canonicalizer as soon as it can
     //       can handle canonicalized forms that contain more than one node.
-    Value key = append(new Constant(new IntConstant(switch_->low_key())));
-    BlockBegin* tsux = block_at(bci() + switch_->dest_offset_at(0));
-    BlockBegin* fsux = block_at(bci() + switch_->default_offset());
+    Value key = append(new Constant(new IntConstant(sw.low_key())));
+    BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0));
+    BlockBegin* fsux = block_at(bci() + sw.default_offset());
     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
     ValueStack* state_before = is_bb ? copy_state_before() : NULL;
     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
@@ -1293,29 +1293,29 @@
     int i;
     bool has_bb = false;
     for (i = 0; i < l; i++) {
-      sux->at_put(i, block_at(bci() + switch_->dest_offset_at(i)));
-      if (switch_->dest_offset_at(i) < 0) has_bb = true;
+      sux->at_put(i, block_at(bci() + sw.dest_offset_at(i)));
+      if (sw.dest_offset_at(i) < 0) has_bb = true;
     }
     // add default successor
-    sux->at_put(i, block_at(bci() + switch_->default_offset()));
+    sux->at_put(i, block_at(bci() + sw.default_offset()));
     ValueStack* state_before = has_bb ? copy_state_before() : NULL;
-    append(new TableSwitch(ipop(), sux, switch_->low_key(), state_before, has_bb));
+    append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb));
   }
 }
 
 
 void GraphBuilder::lookup_switch() {
-  Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(method()->code() + bci());
-  const int l = switch_->number_of_pairs();
+  Bytecode_lookupswitch sw(stream());
+  const int l = sw.number_of_pairs();
   if (CanonicalizeNodes && l == 1) {
     // total of 2 successors => use If instead of switch
     // Note: This code should go into the canonicalizer as soon as it can
     //       can handle canonicalized forms that contain more than one node.
     // simplify to If
-    LookupswitchPair* pair = switch_->pair_at(0);
-    Value key = append(new Constant(new IntConstant(pair->match())));
-    BlockBegin* tsux = block_at(bci() + pair->offset());
-    BlockBegin* fsux = block_at(bci() + switch_->default_offset());
+    LookupswitchPair pair = sw.pair_at(0);
+    Value key = append(new Constant(new IntConstant(pair.match())));
+    BlockBegin* tsux = block_at(bci() + pair.offset());
+    BlockBegin* fsux = block_at(bci() + sw.default_offset());
     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
     ValueStack* state_before = is_bb ? copy_state_before() : NULL;
     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
@@ -1326,13 +1326,13 @@
     int i;
     bool has_bb = false;
     for (i = 0; i < l; i++) {
-      LookupswitchPair* pair = switch_->pair_at(i);
-      if (pair->offset() < 0) has_bb = true;
-      sux->at_put(i, block_at(bci() + pair->offset()));
-      keys->at_put(i, pair->match());
+      LookupswitchPair pair = sw.pair_at(i);
+      if (pair.offset() < 0) has_bb = true;
+      sux->at_put(i, block_at(bci() + pair.offset()));
+      keys->at_put(i, pair.match());
     }
     // add default successor
-    sux->at_put(i, block_at(bci() + switch_->default_offset()));
+    sux->at_put(i, block_at(bci() + sw.default_offset()));
     ValueStack* state_before = has_bb ? copy_state_before() : NULL;
     append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb));
   }
@@ -1396,6 +1396,13 @@
   if (continuation() != NULL) {
     assert(!method()->is_synchronized() || InlineSynchronizedMethods, "can not inline synchronized methods yet");
 
+    if (compilation()->env()->dtrace_method_probes()) {
+      // Report exit from inline methods
+      Values* args = new Values(1);
+      args->push(append(new Constant(new ObjectConstant(method()))));
+      append(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args));
+    }
+
     // If the inlined method is synchronized, the monitor must be
     // released before we jump to the continuation block.
     if (method()->is_synchronized()) {
@@ -3301,6 +3308,13 @@
   Value exception = append_with_bci(new ExceptionObject(), SynchronizationEntryBCI);
   assert(exception->is_pinned(), "must be");
 
+  if (compilation()->env()->dtrace_method_probes()) {
+    // Report exit from inline methods
+    Values* args = new Values(1);
+    args->push(append(new Constant(new ObjectConstant(method()))));
+    append(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args));
+  }
+
   int bci = SynchronizationEntryBCI;
   if (lock) {
     assert(state()->locks_size() > 0 && state()->lock_at(state()->locks_size() - 1) == lock, "lock is missing");
@@ -3486,6 +3500,11 @@
     inline_sync_entry(lock, sync_handler);
   }
 
+  if (compilation()->env()->dtrace_method_probes()) {
+    Values* args = new Values(1);
+    args->push(append(new Constant(new ObjectConstant(method()))));
+    append(new RuntimeCall(voidType, "dtrace_method_entry", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), args));
+  }
 
   BlockBegin* callee_start_block = block_at(0);
   if (callee_start_block != NULL) {
--- a/src/share/vm/c1/c1_Instruction.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_Instruction.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -106,6 +106,7 @@
 class         UnsafePrefetchWrite;
 class   ProfileCall;
 class   ProfileInvoke;
+class   RuntimeCall;
 
 // A Value is a reference to the instruction creating the value
 typedef Instruction* Value;
@@ -202,6 +203,7 @@
   virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) = 0;
   virtual void do_ProfileCall    (ProfileCall*     x) = 0;
   virtual void do_ProfileInvoke  (ProfileInvoke*   x) = 0;
+  virtual void do_RuntimeCall    (RuntimeCall*     x) = 0;
 };
 
 
@@ -2267,6 +2269,38 @@
   virtual void input_values_do(ValueVisitor* f)   { if (_recv != NULL) f->visit(&_recv); }
 };
 
+
+// Call some C runtime function that doesn't safepoint,
+// optionally passing the current thread as the first argument.
+LEAF(RuntimeCall, Instruction)
+ private:
+  const char* _entry_name;
+  address     _entry;
+  Values*     _args;
+  bool        _pass_thread;  // Pass the JavaThread* as an implicit first argument
+
+ public:
+  RuntimeCall(ValueType* type, const char* entry_name, address entry, Values* args, bool pass_thread = true)
+    : Instruction(type)
+    , _entry(entry)
+    , _args(args)
+    , _entry_name(entry_name)
+    , _pass_thread(pass_thread) {
+    ASSERT_VALUES
+    pin();
+  }
+
+  const char* entry_name() const  { return _entry_name; }
+  address entry() const           { return _entry; }
+  int number_of_arguments() const { return _args->length(); }
+  Value argument_at(int i) const  { return _args->at(i); }
+  bool pass_thread() const        { return _pass_thread; }
+
+  virtual void input_values_do(ValueVisitor* f)   {
+    for (int i = 0; i < _args->length(); i++) f->visit(_args->adr_at(i));
+  }
+};
+
 // Use to trip invocation counter of an inlined method
 
 LEAF(ProfileInvoke, Instruction)
--- a/src/share/vm/c1/c1_InstructionPrinter.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_InstructionPrinter.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -841,4 +841,13 @@
 
 }
 
+void InstructionPrinter::do_RuntimeCall(RuntimeCall* x) {
+  output()->print("call_rt %s(", x->entry_name());
+  for (int i = 0; i < x->number_of_arguments(); i++) {
+    if (i > 0) output()->print(", ");
+    print_value(x->argument_at(i));
+  }
+  output()->put(')');
+}
+
 #endif // PRODUCT
--- a/src/share/vm/c1/c1_InstructionPrinter.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_InstructionPrinter.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -131,6 +131,7 @@
   virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x);
   virtual void do_ProfileCall    (ProfileCall*     x);
   virtual void do_ProfileInvoke  (ProfileInvoke*   x);
+  virtual void do_RuntimeCall    (RuntimeCall*     x);
 };
 #endif // PRODUCT
 
--- a/src/share/vm/c1/c1_LIR.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_LIR.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -396,7 +396,7 @@
   , _should_profile(false)
 {
   if (code == lir_store_check) {
-    _stub = new ArrayStoreExceptionStub(info_for_exception);
+    _stub = new ArrayStoreExceptionStub(object, info_for_exception);
     assert(info_for_exception != NULL, "store_check throws exceptions");
   } else {
     ShouldNotReachHere();
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1990,9 +1990,8 @@
 
   LIR_Opr reg = reg = rlock_result(x, x->basic_type());
 
+  get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile());
   if (x->is_volatile() && os::is_MP()) __ membar_acquire();
-  get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile());
-  if (x->is_volatile() && os::is_MP()) __ membar();
 }
 
 
@@ -2014,6 +2013,7 @@
 
   if (x->is_volatile() && os::is_MP()) __ membar_release();
   put_Object_unsafe(src.result(), off.result(), data.result(), type, x->is_volatile());
+  if (x->is_volatile() && os::is_MP()) __ membar();
 }
 
 
@@ -2741,6 +2741,31 @@
   }
 }
 
+void LIRGenerator::do_RuntimeCall(RuntimeCall* x) {
+  LIR_OprList* args = new LIR_OprList(x->number_of_arguments());
+  BasicTypeList* signature = new BasicTypeList(x->number_of_arguments());
+
+  if (x->pass_thread()) {
+    signature->append(T_ADDRESS);
+    args->append(getThreadPointer());
+  }
+
+  for (int i = 0; i < x->number_of_arguments(); i++) {
+    Value a = x->argument_at(i);
+    LIRItem* item = new LIRItem(a, this);
+    item->load_item();
+    args->append(item->result());
+    signature->append(as_BasicType(a->type()));
+  }
+
+  LIR_Opr result = call_runtime(signature, args, x->entry(), x->type(), NULL);
+  if (x->type() == voidType) {
+    set_no_result(x);
+  } else {
+    __ move(result, rlock_result(x));
+  }
+}
+
 LIR_Opr LIRGenerator::call_runtime(Value arg1, address entry, ValueType* result_type, CodeEmitInfo* info) {
   LIRItemList args(1);
   LIRItem value(arg1, this);
--- a/src/share/vm/c1/c1_LIRGenerator.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_LIRGenerator.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -522,6 +522,7 @@
   virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x);
   virtual void do_ProfileCall    (ProfileCall*     x);
   virtual void do_ProfileInvoke  (ProfileInvoke*   x);
+  virtual void do_RuntimeCall    (RuntimeCall*     x);
 };
 
 
--- a/src/share/vm/c1/c1_Optimizer.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_Optimizer.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -496,6 +496,7 @@
   void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x);
   void do_ProfileCall    (ProfileCall*     x);
   void do_ProfileInvoke  (ProfileInvoke*   x);
+  void do_RuntimeCall    (RuntimeCall*     x);
 };
 
 
@@ -664,6 +665,7 @@
 void NullCheckVisitor::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {}
 void NullCheckVisitor::do_ProfileCall    (ProfileCall*     x) { nce()->clear_last_explicit_null_check(); }
 void NullCheckVisitor::do_ProfileInvoke  (ProfileInvoke*   x) {}
+void NullCheckVisitor::do_RuntimeCall    (RuntimeCall*     x) {}
 
 
 void NullCheckEliminator::visit(Value* p) {
--- a/src/share/vm/c1/c1_Runtime1.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -346,8 +346,10 @@
 JRT_END
 
 
-JRT_ENTRY(void, Runtime1::throw_array_store_exception(JavaThread* thread))
-  THROW(vmSymbolHandles::java_lang_ArrayStoreException());
+JRT_ENTRY(void, Runtime1::throw_array_store_exception(JavaThread* thread, oopDesc* obj))
+  ResourceMark rm(thread);
+  const char* klass_name = Klass::cast(obj->klass())->external_name();
+  SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArrayStoreException(), klass_name);
 JRT_END
 
 
@@ -376,7 +378,7 @@
   if (branch_bci != InvocationEntryBci) {
     // Compute desination bci
     address pc = method()->code_base() + branch_bci;
-    Bytecodes::Code branch = Bytecodes::code_at(pc, method());
+    Bytecodes::Code branch = Bytecodes::code_at(method(), pc);
     int offset = 0;
     switch (branch) {
       case Bytecodes::_if_icmplt: case Bytecodes::_iflt:
@@ -699,14 +701,14 @@
 
 
 static klassOop resolve_field_return_klass(methodHandle caller, int bci, TRAPS) {
-  Bytecode_field* field_access = Bytecode_field_at(caller, bci);
+  Bytecode_field field_access(caller, bci);
   // This can be static or non-static field access
-  Bytecodes::Code code       = field_access->code();
+  Bytecodes::Code code       = field_access.code();
 
   // We must load class, initialize class and resolvethe field
   FieldAccessInfo result; // initialize class if needed
   constantPoolHandle constants(THREAD, caller->constants());
-  LinkResolver::resolve_field(result, constants, field_access->index(), Bytecodes::java_code(code), false, CHECK_NULL);
+  LinkResolver::resolve_field(result, constants, field_access.index(), Bytecodes::java_code(code), false, CHECK_NULL);
   return result.klass()();
 }
 
@@ -807,7 +809,7 @@
 
   Events::log("patch_code @ " INTPTR_FORMAT , caller_frame.pc());
 
-  Bytecodes::Code code = Bytecode_at(caller_method->bcp_from(bci))->java_code();
+  Bytecodes::Code code = caller_method()->java_code_at(bci);
 
 #ifndef PRODUCT
   // this is used by assertions in the access_field_patching_id
@@ -819,11 +821,11 @@
   Handle load_klass(THREAD, NULL);                // oop needed by load_klass_patching code
   if (stub_id == Runtime1::access_field_patching_id) {
 
-    Bytecode_field* field_access = Bytecode_field_at(caller_method, bci);
+    Bytecode_field field_access(caller_method, bci);
     FieldAccessInfo result; // initialize class if needed
-    Bytecodes::Code code = field_access->code();
+    Bytecodes::Code code = field_access.code();
     constantPoolHandle constants(THREAD, caller_method->constants());
-    LinkResolver::resolve_field(result, constants, field_access->index(), Bytecodes::java_code(code), false, CHECK);
+    LinkResolver::resolve_field(result, constants, field_access.index(), Bytecodes::java_code(code), false, CHECK);
     patch_field_offset = result.field_offset();
 
     // If we're patching a field which is volatile then at compile it
@@ -851,36 +853,36 @@
         }
         break;
       case Bytecodes::_new:
-        { Bytecode_new* bnew = Bytecode_new_at(caller_method->bcp_from(bci));
-          k = caller_method->constants()->klass_at(bnew->index(), CHECK);
+        { Bytecode_new bnew(caller_method(), caller_method->bcp_from(bci));
+          k = caller_method->constants()->klass_at(bnew.index(), CHECK);
         }
         break;
       case Bytecodes::_multianewarray:
-        { Bytecode_multianewarray* mna = Bytecode_multianewarray_at(caller_method->bcp_from(bci));
-          k = caller_method->constants()->klass_at(mna->index(), CHECK);
+        { Bytecode_multianewarray mna(caller_method(), caller_method->bcp_from(bci));
+          k = caller_method->constants()->klass_at(mna.index(), CHECK);
         }
         break;
       case Bytecodes::_instanceof:
-        { Bytecode_instanceof* io = Bytecode_instanceof_at(caller_method->bcp_from(bci));
-          k = caller_method->constants()->klass_at(io->index(), CHECK);
+        { Bytecode_instanceof io(caller_method(), caller_method->bcp_from(bci));
+          k = caller_method->constants()->klass_at(io.index(), CHECK);
         }
         break;
       case Bytecodes::_checkcast:
-        { Bytecode_checkcast* cc = Bytecode_checkcast_at(caller_method->bcp_from(bci));
-          k = caller_method->constants()->klass_at(cc->index(), CHECK);
+        { Bytecode_checkcast cc(caller_method(), caller_method->bcp_from(bci));
+          k = caller_method->constants()->klass_at(cc.index(), CHECK);
         }
         break;
       case Bytecodes::_anewarray:
-        { Bytecode_anewarray* anew = Bytecode_anewarray_at(caller_method->bcp_from(bci));
-          klassOop ek = caller_method->constants()->klass_at(anew->index(), CHECK);
+        { Bytecode_anewarray anew(caller_method(), caller_method->bcp_from(bci));
+          klassOop ek = caller_method->constants()->klass_at(anew.index(), CHECK);
           k = Klass::cast(ek)->array_klass(CHECK);
         }
         break;
       case Bytecodes::_ldc:
       case Bytecodes::_ldc_w:
         {
-          Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method, bci);
-          k = cc->resolve_constant(CHECK);
+          Bytecode_loadconstant cc(caller_method, bci);
+          k = cc.resolve_constant(CHECK);
           assert(k != NULL && !k->is_klass(), "must be class mirror or other Java constant");
         }
         break;
--- a/src/share/vm/c1/c1_Runtime1.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_Runtime1.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -154,9 +154,9 @@
   static void throw_index_exception(JavaThread* thread, int index);
   static void throw_div0_exception(JavaThread* thread);
   static void throw_null_pointer_exception(JavaThread* thread);
-  static void throw_class_cast_exception(JavaThread* thread, oopDesc* obect);
+  static void throw_class_cast_exception(JavaThread* thread, oopDesc* object);
   static void throw_incompatible_class_change_error(JavaThread* thread);
-  static void throw_array_store_exception(JavaThread* thread);
+  static void throw_array_store_exception(JavaThread* thread, oopDesc* object);
 
   static void monitorenter(JavaThread* thread, oopDesc* obj, BasicObjectLock* lock);
   static void monitorexit (JavaThread* thread, BasicObjectLock* lock);
--- a/src/share/vm/c1/c1_ValueMap.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/c1/c1_ValueMap.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -192,11 +192,12 @@
   void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
   void do_RoundFP        (RoundFP*         x) { /* nothing to do */ }
   void do_UnsafeGetRaw   (UnsafeGetRaw*    x) { /* nothing to do */ }
-  void do_ProfileInvoke  (ProfileInvoke*   x) { /* nothing to do */ };
   void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }
   void do_UnsafePrefetchRead (UnsafePrefetchRead*  x) { /* nothing to do */ }
   void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }
   void do_ProfileCall    (ProfileCall*     x) { /* nothing to do */ }
+  void do_ProfileInvoke  (ProfileInvoke*   x) { /* nothing to do */ };
+  void do_RuntimeCall    (RuntimeCall*     x) { /* nothing to do */ };
 };
 
 
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -233,6 +233,10 @@
 
   // compute size of arguments
   int arg_size = target->arg_size();
+  if (code == Bytecodes::_invokedynamic) {
+    assert(!target->is_static(), "receiver explicit in method");
+    arg_size--;  // implicit, not really on stack
+  }
   if (!target->is_loaded() && code == Bytecodes::_invokestatic) {
     arg_size--;
   }
@@ -250,6 +254,10 @@
     ArgumentMap arg = state._stack[i];
     skip_callee = !is_argument(arg) || !is_arg_stack(arg) || (directly_recursive && arg.is_singleton(i - arg_base));
   }
+  // For now we conservatively skip invokedynamic.
+  if (code == Bytecodes::_invokedynamic) {
+    skip_callee = true;
+  }
   if (skip_callee) {
     TRACE_BCEA(3, tty->print_cr("[EA] skipping method %s::%s", holder->name()->as_utf8(), target->name()->as_utf8()));
     for (i = 0; i < arg_size; i++) {
@@ -761,15 +769,15 @@
       case Bytecodes::_tableswitch:
         {
           state.spop();
-          Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(s.cur_bcp());
-          int len = switch_->length();
+          Bytecode_tableswitch sw(&s);
+          int len = sw.length();
           int dest_bci;
           for (int i = 0; i < len; i++) {
-            dest_bci = s.cur_bci() + switch_->dest_offset_at(i);
+            dest_bci = s.cur_bci() + sw.dest_offset_at(i);
             assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
             successors.push(_methodBlocks->block_containing(dest_bci));
           }
-          dest_bci = s.cur_bci() + switch_->default_offset();
+          dest_bci = s.cur_bci() + sw.default_offset();
           assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
           successors.push(_methodBlocks->block_containing(dest_bci));
           assert(s.next_bci() == limit_bci, "branch must end block");
@@ -779,15 +787,15 @@
       case Bytecodes::_lookupswitch:
         {
           state.spop();
-          Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(s.cur_bcp());
-          int len = switch_->number_of_pairs();
+          Bytecode_lookupswitch sw(&s);
+          int len = sw.number_of_pairs();
           int dest_bci;
           for (int i = 0; i < len; i++) {
-            dest_bci = s.cur_bci() + switch_->pair_at(i)->offset();
+            dest_bci = s.cur_bci() + sw.pair_at(i).offset();
             assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
             successors.push(_methodBlocks->block_containing(dest_bci));
           }
-          dest_bci = s.cur_bci() + switch_->default_offset();
+          dest_bci = s.cur_bci() + sw.default_offset();
           assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
           successors.push(_methodBlocks->block_containing(dest_bci));
           fall_through = false;
--- a/src/share/vm/ci/ciClassList.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciClassList.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -60,7 +60,6 @@
 class    ciKlass;
 class     ciInstanceKlass;
 class     ciMethodKlass;
-class     ciSymbolKlass;
 class     ciArrayKlass;
 class       ciObjArrayKlass;
 class       ciTypeArrayKlass;
@@ -112,7 +111,6 @@
 friend class ciKlass;                  \
 friend class ciInstanceKlass;          \
 friend class ciMethodKlass;            \
-friend class ciSymbolKlass;            \
 friend class ciArrayKlass;             \
 friend class ciObjArrayKlass;          \
 friend class ciTypeArrayKlass;         \
--- a/src/share/vm/ci/ciEnv.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciEnv.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -68,7 +68,6 @@
 
 ciObject*              ciEnv::_null_object_instance;
 ciMethodKlass*         ciEnv::_method_klass_instance;
-ciSymbolKlass*         ciEnv::_symbol_klass_instance;
 ciKlassKlass*          ciEnv::_klass_klass_instance;
 ciInstanceKlassKlass*  ciEnv::_instance_klass_klass_instance;
 ciTypeArrayKlassKlass* ciEnv::_type_array_klass_klass_instance;
@@ -203,6 +202,7 @@
 ciEnv::~ciEnv() {
   _factory->cleanup();
   CompilerThread* current_thread = CompilerThread::current();
+  _factory->remove_symbols();
   current_thread->set_env(NULL);
 }
 
@@ -235,7 +235,7 @@
 
 // ------------------------------------------------------------------
 // helper for lazy exception creation
-ciInstance* ciEnv::get_or_create_exception(jobject& handle, symbolHandle name) {
+ciInstance* ciEnv::get_or_create_exception(jobject& handle, Symbol* name) {
   VM_ENTRY_MARK;
   if (handle == NULL) {
     // Cf. universe.cpp, creation of Universe::_null_ptr_exception_instance.
@@ -262,7 +262,7 @@
   if (_ArrayIndexOutOfBoundsException_instance == NULL) {
     _ArrayIndexOutOfBoundsException_instance
           = get_or_create_exception(_ArrayIndexOutOfBoundsException_handle,
-          vmSymbolHandles::java_lang_ArrayIndexOutOfBoundsException());
+          vmSymbols::java_lang_ArrayIndexOutOfBoundsException());
   }
   return _ArrayIndexOutOfBoundsException_instance;
 }
@@ -270,7 +270,7 @@
   if (_ArrayStoreException_instance == NULL) {
     _ArrayStoreException_instance
           = get_or_create_exception(_ArrayStoreException_handle,
-          vmSymbolHandles::java_lang_ArrayStoreException());
+          vmSymbols::java_lang_ArrayStoreException());
   }
   return _ArrayStoreException_instance;
 }
@@ -278,7 +278,7 @@
   if (_ClassCastException_instance == NULL) {
     _ClassCastException_instance
           = get_or_create_exception(_ClassCastException_handle,
-          vmSymbolHandles::java_lang_ClassCastException());
+          vmSymbols::java_lang_ClassCastException());
   }
   return _ClassCastException_instance;
 }
@@ -378,14 +378,16 @@
   EXCEPTION_CONTEXT;
 
   // Now we need to check the SystemDictionary
-  symbolHandle sym(THREAD, name->get_symbolOop());
+  Symbol* sym = name->get_symbol();
   if (sym->byte_at(0) == 'L' &&
     sym->byte_at(sym->utf8_length()-1) == ';') {
     // This is a name from a signature.  Strip off the trimmings.
-    sym = oopFactory::new_symbol_handle(sym->as_utf8()+1,
-                                        sym->utf8_length()-2,
-                                        KILL_COMPILE_ON_FATAL_(_unloaded_ciinstance_klass));
-    name = get_object(sym())->as_symbol();
+    // Call recursive to keep scope of strippedsym.
+    TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1,
+                    sym->utf8_length()-2,
+                    KILL_COMPILE_ON_FATAL_(_unloaded_ciinstance_klass));
+    ciSymbol* strippedname = get_symbol(strippedsym);
+    return get_klass_by_name_impl(accessing_klass, strippedname, require_local);
   }
 
   // Check for prior unloaded klass.  The SystemDictionary's answers
@@ -410,15 +412,15 @@
   } else {
     fail_type = _unloaded_ciinstance_klass;
   }
-  klassOop found_klass;
+  KlassHandle found_klass;
   if (!require_local) {
-    found_klass =
-      SystemDictionary::find_constrained_instance_or_array_klass(sym, loader,
-                                                                 KILL_COMPILE_ON_FATAL_(fail_type));
+    klassOop kls = SystemDictionary::find_constrained_instance_or_array_klass(
+        sym, loader, KILL_COMPILE_ON_FATAL_(fail_type));
+    found_klass = KlassHandle(THREAD, kls);
   } else {
-    found_klass =
-      SystemDictionary::find_instance_or_array_klass(sym, loader, domain,
-                                                     KILL_COMPILE_ON_FATAL_(fail_type));
+    klassOop kls = SystemDictionary::find_instance_or_array_klass(
+        sym, loader, domain, KILL_COMPILE_ON_FATAL_(fail_type));
+    found_klass = KlassHandle(THREAD, kls);
   }
 
   // If we fail to find an array klass, look again for its element type.
@@ -431,13 +433,14 @@
       (sym->byte_at(1) == '[' || sym->byte_at(1) == 'L')) {
     // We have an unloaded array.
     // Build it on the fly if the element class exists.
-    symbolOop elem_sym = oopFactory::new_symbol(sym->as_utf8()+1,
-                                                sym->utf8_length()-1,
-                                                KILL_COMPILE_ON_FATAL_(fail_type));
+    TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1,
+                                                 sym->utf8_length()-1,
+                                                 KILL_COMPILE_ON_FATAL_(fail_type));
+
     // Get element ciKlass recursively.
     ciKlass* elem_klass =
       get_klass_by_name_impl(accessing_klass,
-                             get_object(elem_sym)->as_symbol(),
+                             get_symbol(elem_sym),
                              require_local);
     if (elem_klass != NULL && elem_klass->is_loaded()) {
       // Now make an array for it
@@ -445,9 +448,9 @@
     }
   }
 
-  if (found_klass != NULL) {
+  if (found_klass() != NULL) {
     // Found it.  Build a CI handle.
-    return get_object(found_klass)->as_klass();
+    return get_object(found_klass())->as_klass();
   }
 
   if (require_local)  return NULL;
@@ -476,7 +479,7 @@
                                         ciInstanceKlass* accessor) {
   EXCEPTION_CONTEXT;
   KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index));
-  symbolHandle klass_name;
+  Symbol* klass_name = NULL;
   if (klass.is_null()) {
     // The klass has not been inserted into the constant pool.
     // Try to look it up by name.
@@ -491,10 +494,10 @@
         // very recently.
         klass = KlassHandle(THREAD, cpool->resolved_klass_at(index));
       } else if (tag.is_symbol()) {
-        klass_name = symbolHandle(THREAD, cpool->symbol_at(index));
+        klass_name = cpool->symbol_at(index);
       } else {
         assert(cpool->tag_at(index).is_unresolved_klass(), "wrong tag");
-        klass_name = symbolHandle(THREAD, cpool->unresolved_klass_at(index));
+        klass_name = cpool->unresolved_klass_at(index);
       }
     }
   }
@@ -502,7 +505,7 @@
   if (klass.is_null()) {
     // Not found in constant pool.  Use the name to do the lookup.
     ciKlass* k = get_klass_by_name_impl(accessor,
-                                        get_object(klass_name())->as_symbol(),
+                                        get_symbol(klass_name),
                                         false);
     // Calculate accessibility the hard way.
     if (!k->is_loaded()) {
@@ -520,7 +523,7 @@
 
   // Check for prior unloaded klass.  The SystemDictionary's answers
   // can vary over time but the compiler needs consistency.
-  ciSymbol* name = get_object(klass()->klass_part()->name())->as_symbol();
+  ciSymbol* name = get_symbol(klass()->klass_part()->name());
   ciKlass* unloaded_klass = check_get_unloaded_klass(accessor, name);
   if (unloaded_klass != NULL) {
     is_accessible = false;
@@ -606,7 +609,7 @@
     return ciConstant(T_OBJECT, ciobj);
   } else if (tag.is_method_type()) {
     // must execute Java code to link this CP entry into cache[i].f1
-    ciSymbol* signature = get_object(cpool->method_type_signature_at(index))->as_symbol();
+    ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index));
     ciObject* ciobj = get_unloaded_method_type_constant(signature);
     return ciConstant(T_OBJECT, ciobj);
   } else if (tag.is_method_handle()) {
@@ -614,8 +617,8 @@
     int ref_kind        = cpool->method_handle_ref_kind_at(index);
     int callee_index    = cpool->method_handle_klass_index_at(index);
     ciKlass* callee     = get_klass_by_index_impl(cpool, callee_index, ignore_will_link, accessor);
-    ciSymbol* name      = get_object(cpool->method_handle_name_ref_at(index))->as_symbol();
-    ciSymbol* signature = get_object(cpool->method_handle_signature_ref_at(index))->as_symbol();
+    ciSymbol* name      = get_symbol(cpool->method_handle_name_ref_at(index));
+    ciSymbol* signature = get_symbol(cpool->method_handle_signature_ref_at(index));
     ciObject* ciobj     = get_unloaded_method_handle_constant(callee, name, signature, ref_kind);
     return ciConstant(T_OBJECT, ciobj);
   } else {
@@ -675,33 +678,31 @@
 // name, signature, and bytecode.
 methodOop ciEnv::lookup_method(instanceKlass*  accessor,
                                instanceKlass*  holder,
-                               symbolOop       name,
-                               symbolOop       sig,
+                               Symbol*       name,
+                               Symbol*       sig,
                                Bytecodes::Code bc) {
   EXCEPTION_CONTEXT;
   KlassHandle h_accessor(THREAD, accessor);
   KlassHandle h_holder(THREAD, holder);
-  symbolHandle h_name(THREAD, name);
-  symbolHandle h_sig(THREAD, sig);
   LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
   methodHandle dest_method;
   switch (bc) {
   case Bytecodes::_invokestatic:
     dest_method =
-      LinkResolver::resolve_static_call_or_null(h_holder, h_name, h_sig, h_accessor);
+      LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor);
     break;
   case Bytecodes::_invokespecial:
     dest_method =
-      LinkResolver::resolve_special_call_or_null(h_holder, h_name, h_sig, h_accessor);
+      LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor);
     break;
   case Bytecodes::_invokeinterface:
     dest_method =
-      LinkResolver::linktime_resolve_interface_method_or_null(h_holder, h_name, h_sig,
+      LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig,
                                                               h_accessor, true);
     break;
   case Bytecodes::_invokevirtual:
     dest_method =
-      LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, h_name, h_sig,
+      LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig,
                                                             h_accessor, true);
     break;
   default: ShouldNotReachHere();
@@ -722,8 +723,8 @@
   ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
 
   // Get the method's name and signature.
-  symbolOop name_sym = cpool->name_ref_at(index);
-  symbolOop sig_sym  = cpool->signature_ref_at(index);
+  Symbol* name_sym = cpool->name_ref_at(index);
+  Symbol* sig_sym  = cpool->signature_ref_at(index);
 
   if (holder_is_accessible) { // Our declared holder is loaded.
     instanceKlass* lookup = declared_holder->get_instanceKlass();
@@ -739,8 +740,8 @@
   // lookup.
 
   return get_unloaded_method(declared_holder,
-                             get_object(name_sym)->as_symbol(),
-                             get_object(sig_sym)->as_symbol());
+                             get_symbol(name_sym),
+                             get_symbol(sig_sym));
 }
 
 
@@ -760,7 +761,7 @@
   // compiler, but it is simpler to stop the code path here with an unlinked method.
   if (!is_resolved) {
     ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass();
-    ciSymbol*        sig_sym  = get_object(cpool->signature_ref_at(index))->as_symbol();
+    ciSymbol*        sig_sym  = get_symbol(cpool->signature_ref_at(index));
     return get_unloaded_method(mh_klass, ciSymbol::invokeExact_name(), sig_sym);
   }
 
--- a/src/share/vm/ci/ciEnv.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciEnv.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -79,7 +79,6 @@
   // Distinguished instances of certain ciObjects..
   static ciObject*              _null_object_instance;
   static ciMethodKlass*         _method_klass_instance;
-  static ciSymbolKlass*         _symbol_klass_instance;
   static ciKlassKlass*          _klass_klass_instance;
   static ciInstanceKlassKlass*  _instance_klass_klass_instance;
   static ciTypeArrayKlassKlass* _type_array_klass_klass_instance;
@@ -164,8 +163,8 @@
                                       klassOop resolved_klassOop);
   methodOop  lookup_method(instanceKlass*  accessor,
                            instanceKlass*  holder,
-                           symbolOop       name,
-                           symbolOop       sig,
+                           Symbol*         name,
+                           Symbol*         sig,
                            Bytecodes::Code bc);
 
   public:
@@ -180,9 +179,18 @@
   }
   private:
 
+  ciSymbol* get_symbol(Symbol* o) {
+    if (o == NULL) {
+      ShouldNotReachHere();
+      return NULL;
+    } else {
+      return _factory->get_symbol(o);
+    }
+  }
+
   ciMethod* get_method_from_handle(jobject method);
 
-  ciInstance* get_or_create_exception(jobject& handle, symbolHandle name);
+  ciInstance* get_or_create_exception(jobject& handle, Symbol* name);
 
   // Get a ciMethod representing either an unfound method or
   // a method with an unloaded holder.  Ensures uniqueness of
--- a/src/share/vm/ci/ciField.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciField.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -79,15 +79,15 @@
   constantPoolHandle cpool(thread, klass->get_instanceKlass()->constants());
 
   // Get the field's name, signature, and type.
-  symbolHandle name  (thread, cpool->name_ref_at(index));
-  _name = ciEnv::current(thread)->get_object(name())->as_symbol();
+  Symbol* name  = cpool->name_ref_at(index);
+  _name = ciEnv::current(thread)->get_symbol(name);
 
   int nt_index = cpool->name_and_type_ref_index_at(index);
   int sig_index = cpool->signature_ref_index_at(nt_index);
-  symbolHandle signature (thread, cpool->symbol_at(sig_index));
-  _signature = ciEnv::current(thread)->get_object(signature())->as_symbol();
+  Symbol* signature = cpool->symbol_at(sig_index);
+  _signature = ciEnv::current(thread)->get_symbol(signature);
 
-  BasicType field_type = FieldType::basic_type(signature());
+  BasicType field_type = FieldType::basic_type(signature);
 
   // If the field is a pointer type, get the klass of the
   // field.
@@ -100,7 +100,7 @@
     _type = ciType::make(field_type);
   }
 
-  _name = (ciSymbol*)ciEnv::current(thread)->get_object(name());
+  _name = (ciSymbol*)ciEnv::current(thread)->get_symbol(name);
 
   // Get the field's declared holder.
   //
@@ -130,7 +130,7 @@
   // Perform the field lookup.
   fieldDescriptor field_desc;
   klassOop canonical_holder =
-    loaded_decl_holder->find_field(name(), signature(), &field_desc);
+    loaded_decl_holder->find_field(name, signature, &field_desc);
   if (canonical_holder == NULL) {
     // Field lookup failed.  Will be detected by will_link.
     _holder = declared_holder;
@@ -150,8 +150,8 @@
 
   // Get the field's name, signature, and type.
   ciEnv* env = CURRENT_ENV;
-  _name = env->get_object(fd->name())->as_symbol();
-  _signature = env->get_object(fd->signature())->as_symbol();
+  _name = env->get_symbol(fd->name());
+  _signature = env->get_symbol(fd->signature());
 
   BasicType field_type = fd->field_type();
 
--- a/src/share/vm/ci/ciInstanceKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciInstanceKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -379,7 +379,7 @@
   VM_ENTRY_MARK;
   instanceKlass* k = get_instanceKlass();
   fieldDescriptor fd;
-  klassOop def = k->find_field(name->get_symbolOop(), signature->get_symbolOop(), is_static, &fd);
+  klassOop def = k->find_field(name->get_symbol(), signature->get_symbol(), is_static, &fd);
   if (def == NULL) {
     return NULL;
   }
@@ -540,8 +540,8 @@
 ciMethod* ciInstanceKlass::find_method(ciSymbol* name, ciSymbol* signature) {
   VM_ENTRY_MARK;
   instanceKlass* k = get_instanceKlass();
-  symbolOop name_sym = name->get_symbolOop();
-  symbolOop sig_sym= signature->get_symbolOop();
+  Symbol* name_sym = name->get_symbol();
+  Symbol* sig_sym= signature->get_symbol();
 
   methodOop m = k->find_method(name_sym, sig_sym);
   if (m == NULL)  return NULL;
--- a/src/share/vm/ci/ciKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -39,9 +39,9 @@
   assert(get_oop()->is_klass(), "wrong type");
   Klass* k = get_Klass();
   _layout_helper = k->layout_helper();
-  symbolOop klass_name = k->name();
+  Symbol* klass_name = k->name();
   assert(klass_name != NULL, "wrong ciKlass constructor");
-  _name = CURRENT_ENV->get_object(klass_name)->as_symbol();
+  _name = CURRENT_ENV->get_symbol(klass_name);
 }
 
 // ------------------------------------------------------------------
--- a/src/share/vm/ci/ciMethod.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciMethod.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -122,9 +122,9 @@
 
   // generating _signature may allow GC and therefore move m.
   // These fields are always filled in.
-  _name = env->get_object(h_m()->name())->as_symbol();
+  _name = env->get_symbol(h_m()->name());
   _holder = env->get_object(h_m()->method_holder())->as_instance_klass();
-  ciSymbol* sig_symbol = env->get_object(h_m()->signature())->as_symbol();
+  ciSymbol* sig_symbol = env->get_symbol(h_m()->signature());
   _signature = new (env->arena()) ciSignature(_holder, sig_symbol);
   _method_data = NULL;
   // Take a snapshot of these values, so they will be commensurate with the MDO.
@@ -649,8 +649,8 @@
    KlassHandle caller_klass (THREAD, caller->get_klassOop());
    KlassHandle h_recv       (THREAD, exact_receiver->get_klassOop());
    KlassHandle h_resolved   (THREAD, holder()->get_klassOop());
-   symbolHandle h_name      (THREAD, name()->get_symbolOop());
-   symbolHandle h_signature (THREAD, signature()->get_symbolOop());
+   Symbol* h_name      = name()->get_symbol();
+   Symbol* h_signature = signature()->get_symbol();
 
    methodHandle m;
    // Only do exact lookup if receiver klass has been linked.  Otherwise,
@@ -702,8 +702,8 @@
 
      KlassHandle caller_klass (THREAD, caller->get_klassOop());
      KlassHandle h_recv       (THREAD, receiver->get_klassOop());
-     symbolHandle h_name      (THREAD, name()->get_symbolOop());
-     symbolHandle h_signature (THREAD, signature()->get_symbolOop());
+     Symbol* h_name = name()->get_symbol();
+     Symbol* h_signature = signature()->get_symbol();
 
      vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, h_recv, h_name, h_signature, caller_klass);
      if (vtable_index == methodOopDesc::nonvirtual_vtable_index) {
--- a/src/share/vm/ci/ciMethod.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciMethod.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -144,7 +144,7 @@
 
   Bytecodes::Code java_code_at_bci(int bci) {
     address bcp = code() + bci;
-    return Bytecodes::java_code_at(bcp);
+    return Bytecodes::java_code_at(NULL, bcp);
   }
   BCEscapeAnalyzer  *get_bcea();
   ciMethodBlocks    *get_method_blocks();
--- a/src/share/vm/ci/ciMethodBlocks.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciMethodBlocks.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -175,15 +175,15 @@
       case Bytecodes::_tableswitch :
         {
           cur_block->set_control_bci(bci);
-          Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(s.cur_bcp());
-          int len = switch_->length();
+          Bytecode_tableswitch sw(&s);
+          int len = sw.length();
           ciBlock *dest;
           int dest_bci;
           for (int i = 0; i < len; i++) {
-            dest_bci = s.cur_bci() + switch_->dest_offset_at(i);
+            dest_bci = s.cur_bci() + sw.dest_offset_at(i);
             dest = make_block_at(dest_bci);
           }
-          dest_bci = s.cur_bci() + switch_->default_offset();
+          dest_bci = s.cur_bci() + sw.default_offset();
           make_block_at(dest_bci);
           if (s.next_bci() < limit_bci) {
             dest = make_block_at(s.next_bci());
@@ -194,15 +194,15 @@
       case Bytecodes::_lookupswitch:
         {
           cur_block->set_control_bci(bci);
-          Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(s.cur_bcp());
-          int len = switch_->number_of_pairs();
+          Bytecode_lookupswitch sw(&s);
+          int len = sw.number_of_pairs();
           ciBlock *dest;
           int dest_bci;
           for (int i = 0; i < len; i++) {
-            dest_bci = s.cur_bci() + switch_->pair_at(i)->offset();
+            dest_bci = s.cur_bci() + sw.pair_at(i).offset();
             dest = make_block_at(dest_bci);
           }
-          dest_bci = s.cur_bci() + switch_->default_offset();
+          dest_bci = s.cur_bci() + sw.default_offset();
           dest = make_block_at(dest_bci);
           if (s.next_bci() < limit_bci) {
             dest = make_block_at(s.next_bci());
--- a/src/share/vm/ci/ciMethodHandle.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciMethodHandle.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,11 +38,12 @@
 // Return an adapter for this MethodHandle.
 ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
   VM_ENTRY_MARK;
-
   Handle h(get_oop());
   methodHandle callee(_callee->get_methodOop());
-  MethodHandleCompiler mhc(h, callee, is_invokedynamic, THREAD);
-  methodHandle m = mhc.compile(CHECK_NULL);
+  // We catch all exceptions here that could happen in the method
+  // handle compiler and stop the VM.
+  MethodHandleCompiler mhc(h, callee, is_invokedynamic, CATCH);
+  methodHandle m = mhc.compile(CATCH);
   return CURRENT_ENV->get_object(m())->as_method();
 }
 
--- a/src/share/vm/ci/ciObjArrayKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciObjArrayKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -110,7 +110,7 @@
   EXCEPTION_CONTEXT;
   int element_len = element_name->utf8_length();
 
-  symbolOop base_name_sym = element_name->get_symbolOop();
+  Symbol* base_name_sym = element_name->get_symbol();
   char* name;
 
   if (base_name_sym->byte_at(0) == '[' ||
--- a/src/share/vm/ci/ciObject.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciObject.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -276,10 +276,6 @@
     assert(is_type_array_klass(), "bad cast");
     return (ciTypeArrayKlass*)this;
   }
-  ciSymbolKlass*           as_symbol_klass() {
-    assert(is_symbol_klass(), "bad cast");
-    return (ciSymbolKlass*)this;
-  }
   ciKlassKlass*            as_klass_klass() {
     assert(is_klass_klass(), "bad cast");
     return (ciKlassKlass*)this;
--- a/src/share/vm/ci/ciObjectFactory.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciObjectFactory.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -38,7 +38,6 @@
 #include "ci/ciObjArrayKlassKlass.hpp"
 #include "ci/ciObjectFactory.hpp"
 #include "ci/ciSymbol.hpp"
-#include "ci/ciSymbolKlass.hpp"
 #include "ci/ciTypeArray.hpp"
 #include "ci/ciTypeArrayKlass.hpp"
 #include "ci/ciTypeArrayKlassKlass.hpp"
@@ -98,6 +97,8 @@
   _unloaded_instances = new (arena) GrowableArray<ciInstance*>(arena, 4, 0, NULL);
   _return_addresses =
     new (arena) GrowableArray<ciReturnAddress*>(arena, 8, 0, NULL);
+
+  _symbols = new (arena) GrowableArray<ciSymbol*>(arena, 100, 0, NULL);
 }
 
 void ciObjectFactory::cleanup() {
@@ -135,19 +136,19 @@
     // Create the shared symbols, but not in _shared_ci_objects.
     int i;
     for (i = vmSymbols::FIRST_SID; i < vmSymbols::SID_LIMIT; i++) {
-      symbolHandle sym_handle = vmSymbolHandles::symbol_handle_at((vmSymbols::SID) i);
-      assert(vmSymbols::find_sid(sym_handle()) == i, "1-1 mapping");
-      ciSymbol* sym = new (_arena) ciSymbol(sym_handle, (vmSymbols::SID) i);
+      Symbol* vmsym = vmSymbols::symbol_at((vmSymbols::SID) i);
+      assert(vmSymbols::find_sid(vmsym) == i, "1-1 mapping");
+      ciSymbol* sym = new (_arena) ciSymbol(vmsym, (vmSymbols::SID) i);
       init_ident_of(sym);
       _shared_ci_symbols[i] = sym;
     }
 #ifdef ASSERT
     for (i = vmSymbols::FIRST_SID; i < vmSymbols::SID_LIMIT; i++) {
-      symbolHandle sym_handle = vmSymbolHandles::symbol_handle_at((vmSymbols::SID) i);
+      Symbol* vmsym = vmSymbols::symbol_at((vmSymbols::SID) i);
       ciSymbol* sym = vm_symbol_at((vmSymbols::SID) i);
-      assert(sym->get_oop() == sym_handle(), "oop must match");
+      assert(sym->get_symbol() == vmsym, "oop must match");
     }
-    assert(ciSymbol::void_class_signature()->get_oop() == vmSymbols::void_class_signature(), "spot check");
+    assert(ciSymbol::void_class_signature()->get_symbol() == vmSymbols::void_class_signature(), "spot check");
 #endif
   }
 
@@ -165,8 +166,6 @@
   init_ident_of(ciEnv::_null_object_instance);
   ciEnv::_method_klass_instance =
     get(Universe::methodKlassObj())->as_method_klass();
-  ciEnv::_symbol_klass_instance =
-    get(Universe::symbolKlassObj())->as_symbol_klass();
   ciEnv::_klass_klass_instance =
     get(Universe::klassKlassObj())->as_klass_klass();
   ciEnv::_instance_klass_klass_instance =
@@ -196,7 +195,7 @@
     }
   }
 
-  ciEnv::_unloaded_cisymbol = (ciSymbol*) ciObjectFactory::get(vmSymbols::dummy_symbol_oop());
+  ciEnv::_unloaded_cisymbol = ciObjectFactory::get_symbol(vmSymbols::dummy_symbol());
   // Create dummy instanceKlass and objArrayKlass object and assign them idents
   ciEnv::_unloaded_ciinstance_klass = new (_arena) ciInstanceKlass(ciEnv::_unloaded_cisymbol, NULL, NULL);
   init_ident_of(ciEnv::_unloaded_ciinstance_klass);
@@ -226,6 +225,30 @@
   _shared_ci_objects = _ci_objects;
 }
 
+
+ciSymbol* ciObjectFactory::get_symbol(Symbol* key) {
+  vmSymbols::SID sid = vmSymbols::find_sid(key);
+  if (sid != vmSymbols::NO_SID) {
+    // do not pollute the main cache with it
+    return vm_symbol_at(sid);
+  }
+
+  assert(vmSymbols::find_sid(key) == vmSymbols::NO_SID, "");
+  ciSymbol* s = new (arena()) ciSymbol(key, vmSymbols::NO_SID);
+  _symbols->push(s);
+  return s;
+}
+
+// Decrement the refcount when done on symbols referenced by this compilation.
+void ciObjectFactory::remove_symbols() {
+  for (int i = 0; i < _symbols->length(); i++) {
+    ciSymbol* s = _symbols->at(i);
+    s->get_symbol()->decrement_refcount();
+  }
+  // Since _symbols is resource allocated we're not allowed to delete it
+  // but it'll go away just the same.
+}
+
 // ------------------------------------------------------------------
 // ciObjectFactory::get
 //
@@ -263,15 +286,6 @@
       return bucket->object();
     }
 
-    // Check in the shared symbol area before putting it in the list.
-    if (key->is_symbol()) {
-      vmSymbols::SID sid = vmSymbols::find_sid((symbolOop)key);
-      if (sid != vmSymbols::NO_SID) {
-        // do not pollute the main cache with it
-        return vm_symbol_at(sid);
-      }
-    }
-
     // The ciObject does not yet exist.  Create it and insert it
     // into the cache.
     Handle keyHandle(key);
@@ -305,11 +319,7 @@
 ciObject* ciObjectFactory::create_new_object(oop o) {
   EXCEPTION_CONTEXT;
 
-  if (o->is_symbol()) {
-    symbolHandle h_o(THREAD, (symbolOop)o);
-    assert(vmSymbols::find_sid(h_o()) == vmSymbols::NO_SID, "");
-    return new (arena()) ciSymbol(h_o, vmSymbols::NO_SID);
-  } else if (o->is_klass()) {
+  if (o->is_klass()) {
     KlassHandle h_k(THREAD, (klassOop)o);
     Klass* k = ((klassOop)o)->klass_part();
     if (k->oop_is_instance()) {
@@ -320,8 +330,6 @@
       return new (arena()) ciTypeArrayKlass(h_k);
     } else if (k->oop_is_method()) {
       return new (arena()) ciMethodKlass(h_k);
-    } else if (k->oop_is_symbol()) {
-      return new (arena()) ciSymbolKlass(h_k);
     } else if (k->oop_is_klass()) {
       if (k->oop_is_objArrayKlass()) {
         return new (arena()) ciObjArrayKlassKlass(h_k);
@@ -434,22 +442,20 @@
   // unloaded instanceKlass.  Deal with both.
   if (name->byte_at(0) == '[') {
     // Decompose the name.'
-    jint dimension = 0;
-    symbolOop element_name = NULL;
-    BasicType element_type= FieldType::get_array_info(name->get_symbolOop(),
-                                                      &dimension,
-                                                      &element_name,
-                                                      THREAD);
+    FieldArrayInfo fd;
+    BasicType element_type = FieldType::get_array_info(name->get_symbol(),
+                                                       fd, THREAD);
     if (HAS_PENDING_EXCEPTION) {
       CLEAR_PENDING_EXCEPTION;
       CURRENT_THREAD_ENV->record_out_of_memory_failure();
       return ciEnv::_unloaded_ciobjarrayklass;
     }
+    int dimension = fd.dimension();
     assert(element_type != T_ARRAY, "unsuccessful decomposition");
     ciKlass* element_klass = NULL;
     if (element_type == T_OBJECT) {
       ciEnv *env = CURRENT_THREAD_ENV;
-      ciSymbol* ci_name = env->get_object(element_name)->as_symbol();
+      ciSymbol* ci_name = env->get_symbol(fd.object_key());
       element_klass =
         env->get_klass_by_name(accessing_klass, ci_name, false)->as_instance_klass();
     } else {
@@ -581,6 +587,10 @@
   obj->set_ident(_next_ident++);
 }
 
+void ciObjectFactory::init_ident_of(ciSymbol* obj) {
+  obj->set_ident(_next_ident++);
+}
+
 
 // ------------------------------------------------------------------
 // ciObjectFactory::find
--- a/src/share/vm/ci/ciObjectFactory.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciObjectFactory.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -48,6 +48,7 @@
   GrowableArray<ciKlass*>* _unloaded_klasses;
   GrowableArray<ciInstance*>* _unloaded_instances;
   GrowableArray<ciReturnAddress*>* _return_addresses;
+  GrowableArray<ciSymbol*>* _symbols;  // keep list of symbols created
   int                       _next_ident;
 
 public:
@@ -76,6 +77,7 @@
   void insert_non_perm(NonPermObject* &where, oop key, ciObject* obj);
 
   void init_ident_of(ciObject* obj);
+  void init_ident_of(ciSymbol* obj);
 
   Arena* arena() { return _arena; }
 
@@ -88,6 +90,7 @@
 
   static void initialize();
   void init_shared_objects();
+  void remove_symbols();
 
   ciObjectFactory(Arena* arena, int expected_size);
 
@@ -96,6 +99,8 @@
   // Get the ciObject corresponding to some oop.
   ciObject* get(oop key);
 
+  ciSymbol* get_symbol(Symbol* key);
+
   // Get the ciSymbol corresponding to one of the vmSymbols.
   static ciSymbol* vm_symbol_at(int index);
 
--- a/src/share/vm/ci/ciSignature.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciSignature.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -47,7 +47,8 @@
 
   int size = 0;
   int count = 0;
-  symbolHandle sh (THREAD, symbol->get_symbolOop());
+  ResourceMark rm(THREAD);
+  Symbol* sh = symbol->get_symbol();
   SignatureStream ss(sh);
   for (; ; ss.next()) {
     // Process one element of the signature
@@ -55,14 +56,14 @@
     if (!ss.is_object()) {
       type = ciType::make(ss.type());
     } else {
-      symbolOop name = ss.as_symbol(THREAD);
+      Symbol* name = ss.as_symbol(THREAD);
       if (HAS_PENDING_EXCEPTION) {
         type = ss.is_array() ? (ciType*)ciEnv::unloaded_ciobjarrayklass()
           : (ciType*)ciEnv::unloaded_ciinstance_klass();
         env->record_out_of_memory_failure();
         CLEAR_PENDING_EXCEPTION;
       } else {
-        ciSymbol* klass_name = env->get_object(name)->as_symbol();
+        ciSymbol* klass_name = env->get_symbol(name);
         type = env->get_klass_by_name_impl(_accessing_klass, klass_name, false);
       }
     }
--- a/src/share/vm/ci/ciSignature.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciSignature.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -48,7 +48,7 @@
 
   void get_all_klasses();
 
-  symbolOop get_symbolOop() const                { return _symbol->get_symbolOop(); }
+  Symbol* get_symbol() const                     { return _symbol->get_symbol(); }
 
 public:
   ciSymbol* as_symbol() const                    { return _symbol; }
--- a/src/share/vm/ci/ciStreams.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciStreams.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,8 +78,8 @@
     else { assert(!is_wide(), "must not be a wide instruction"); }
   }
 
-  Bytecode* bytecode() const { return Bytecode_at(_bc_start); }
-  Bytecode* next_bytecode() const { return Bytecode_at(_pc); }
+  Bytecode bytecode() const { return Bytecode(this, _bc_start); }
+  Bytecode next_bytecode() const { return Bytecode(this, _pc); }
 
 public:
   // End-Of-Bytecodes
@@ -151,11 +151,11 @@
   bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
 
   int get_index_u1() const {
-    return bytecode()->get_index_u1(cur_bc_raw());
+    return bytecode().get_index_u1(cur_bc_raw());
   }
 
   int get_index_u1_cpcache() const {
-    return bytecode()->get_index_u1_cpcache(cur_bc_raw());
+    return bytecode().get_index_u1_cpcache(cur_bc_raw());
   }
 
   // Get a byte index following this bytecode.
@@ -169,29 +169,29 @@
 
   // Get 2-byte index (byte swapping depending on which bytecode)
   int get_index_u2(bool is_wide = false) const {
-    return bytecode()->get_index_u2(cur_bc_raw(), is_wide);
+    return bytecode().get_index_u2(cur_bc_raw(), is_wide);
   }
 
   // Get 2-byte index in native byte order.  (Rewriter::rewrite makes these.)
   int get_index_u2_cpcache() const {
-    return bytecode()->get_index_u2_cpcache(cur_bc_raw());
+    return bytecode().get_index_u2_cpcache(cur_bc_raw());
   }
 
   // Get 4-byte index, for invokedynamic.
   int get_index_u4() const {
-    return bytecode()->get_index_u4(cur_bc_raw());
+    return bytecode().get_index_u4(cur_bc_raw());
   }
 
   bool has_index_u4() const {
-    return bytecode()->has_index_u4(cur_bc_raw());
+    return bytecode().has_index_u4(cur_bc_raw());
   }
 
   // Get dimensions byte (multinewarray)
   int get_dimensions() const { return *(unsigned char*)(_pc-1); }
 
   // Sign-extended index byte/short, no widening
-  int get_constant_u1()                     const { return bytecode()->get_constant_u1(instruction_size()-1, cur_bc_raw()); }
-  int get_constant_u2(bool is_wide = false) const { return bytecode()->get_constant_u2(instruction_size()-2, cur_bc_raw(), is_wide); }
+  int get_constant_u1()                     const { return bytecode().get_constant_u1(instruction_size()-1, cur_bc_raw()); }
+  int get_constant_u2(bool is_wide = false) const { return bytecode().get_constant_u2(instruction_size()-2, cur_bc_raw(), is_wide); }
 
   // Get a byte signed constant for "iinc".  Invalid for other bytecodes.
   // If prefixed with a wide bytecode, get a wide constant
@@ -199,18 +199,18 @@
 
   // 2-byte branch offset from current pc
   int get_dest() const {
-    return cur_bci() + bytecode()->get_offset_s2(cur_bc_raw());
+    return cur_bci() + bytecode().get_offset_s2(cur_bc_raw());
   }
 
   // 2-byte branch offset from next pc
   int next_get_dest() const {
     assert(_pc < _end, "");
-    return next_bci() + next_bytecode()->get_offset_s2(Bytecodes::_ifeq);
+    return next_bci() + next_bytecode().get_offset_s2(Bytecodes::_ifeq);
   }
 
   // 4-byte branch offset from current pc
   int get_far_dest() const {
-    return cur_bci() + bytecode()->get_offset_s4(cur_bc_raw());
+    return cur_bci() + bytecode().get_offset_s4(cur_bc_raw());
   }
 
   // For a lookup or switch table, return target destination
@@ -407,4 +407,11 @@
   }
 };
 
+
+
+// Implementation for declarations in bytecode.hpp
+Bytecode::Bytecode(const ciBytecodeStream* stream, address bcp): _bcp(bcp != NULL ? bcp : stream->cur_bcp()), _code(Bytecodes::code_at(NULL, addr_at(0))) {}
+Bytecode_lookupswitch::Bytecode_lookupswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); }
+Bytecode_tableswitch::Bytecode_tableswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); }
+
 #endif // SHARE_VM_CI_CISTREAMS_HPP
--- a/src/share/vm/ci/ciSymbol.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciSymbol.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -30,23 +30,27 @@
 // ------------------------------------------------------------------
 // ciSymbol::ciSymbol
 //
-// Preallocated handle variant.  Used with handles from vmSymboHandles.
-ciSymbol::ciSymbol(symbolHandle h_s, vmSymbols::SID sid)
-  : ciObject(h_s), _sid(sid)
+// Preallocated symbol variant.  Used with symbols from vmSymbols.
+ciSymbol::ciSymbol(Symbol* s, vmSymbols::SID sid)
+  : _symbol(s), _sid(sid)
 {
+  assert(_symbol != NULL, "adding null symbol");
+  _symbol->increment_refcount();  // increment ref count
   assert(sid_ok(), "must be in vmSymbols");
 }
 
 // Normal case for non-famous symbols.
-ciSymbol::ciSymbol(symbolOop s)
-  : ciObject(s), _sid(vmSymbols::NO_SID)
+ciSymbol::ciSymbol(Symbol* s)
+  : _symbol(s), _sid(vmSymbols::NO_SID)
 {
+  assert(_symbol != NULL, "adding null symbol");
+  _symbol->increment_refcount();  // increment ref count
   assert(sid_ok(), "must not be in vmSymbols");
 }
 
 // ciSymbol
 //
-// This class represents a symbolOop in the HotSpot virtual
+// This class represents a Symbol* in the HotSpot virtual
 // machine.
 
 // ------------------------------------------------------------------
@@ -55,20 +59,20 @@
 // The text of the symbol as a null-terminated C string.
 const char* ciSymbol::as_utf8() {
   VM_QUICK_ENTRY_MARK;
-  symbolOop s = get_symbolOop();
+  Symbol* s = get_symbol();
   return s->as_utf8();
 }
 
 // ------------------------------------------------------------------
 // ciSymbol::base
-jbyte* ciSymbol::base() {
-  GUARDED_VM_ENTRY(return get_symbolOop()->base();)
+const jbyte* ciSymbol::base() {
+  GUARDED_VM_ENTRY(return get_symbol()->base();)
 }
 
 // ------------------------------------------------------------------
 // ciSymbol::byte_at
 int ciSymbol::byte_at(int i) {
-  GUARDED_VM_ENTRY(return get_symbolOop()->byte_at(i);)
+  GUARDED_VM_ENTRY(return get_symbol()->byte_at(i);)
 }
 
 // ------------------------------------------------------------------
@@ -76,7 +80,7 @@
 //
 // Tests if the symbol starts with the given prefix.
 bool ciSymbol::starts_with(const char* prefix, int len) const {
-  GUARDED_VM_ENTRY(return get_symbolOop()->starts_with(prefix, len);)
+  GUARDED_VM_ENTRY(return get_symbol()->starts_with(prefix, len);)
 }
 
 // ------------------------------------------------------------------
@@ -84,13 +88,13 @@
 //
 // Determines where the symbol contains the given substring.
 int ciSymbol::index_of_at(int i, const char* str, int len) const {
-  GUARDED_VM_ENTRY(return get_symbolOop()->index_of_at(i, str, len);)
+  GUARDED_VM_ENTRY(return get_symbol()->index_of_at(i, str, len);)
 }
 
 // ------------------------------------------------------------------
 // ciSymbol::utf8_length
 int ciSymbol::utf8_length() {
-  GUARDED_VM_ENTRY(return get_symbolOop()->utf8_length();)
+  GUARDED_VM_ENTRY(return get_symbol()->utf8_length();)
 }
 
 // ------------------------------------------------------------------
@@ -107,7 +111,7 @@
 //
 // Print the value of this symbol on an outputStream
 void ciSymbol::print_symbol_on(outputStream *st) {
-  GUARDED_VM_ENTRY(get_symbolOop()->print_symbol_on(st);)
+  GUARDED_VM_ENTRY(get_symbol()->print_symbol_on(st);)
 }
 
 // ------------------------------------------------------------------
@@ -116,15 +120,13 @@
 // Make a ciSymbol from a C string (implementation).
 ciSymbol* ciSymbol::make_impl(const char* s) {
   EXCEPTION_CONTEXT;
-  // For some reason, oopFactory::new_symbol doesn't declare its
-  // char* argument as const.
-  symbolOop sym = oopFactory::new_symbol((char*)s, (int)strlen(s), THREAD);
+  TempNewSymbol sym = SymbolTable::new_symbol(s, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     CURRENT_THREAD_ENV->record_out_of_memory_failure();
     return ciEnv::_unloaded_cisymbol;
   }
-  return CURRENT_THREAD_ENV->get_object(sym)->as_symbol();
+  return CURRENT_THREAD_ENV->get_symbol(sym);
 }
 
 // ------------------------------------------------------------------
--- a/src/share/vm/ci/ciSymbol.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciSymbol.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -28,15 +28,18 @@
 #include "ci/ciObject.hpp"
 #include "ci/ciObjectFactory.hpp"
 #include "classfile/vmSymbols.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 
 // ciSymbol
 //
-// This class represents a symbolOop in the HotSpot virtual
+// This class represents a Symbol* in the HotSpot virtual
 // machine.
-class ciSymbol : public ciObject {
+class ciSymbol : public ResourceObj {
+  Symbol* _symbol;
+  uint _ident;
+
   CI_PACKAGE_ACCESS
-  // These friends all make direct use of get_symbolOop:
+  // These friends all make direct use of get_symbol:
   friend class ciEnv;
   friend class ciInstanceKlass;
   friend class ciSignature;
@@ -45,10 +48,12 @@
 
 private:
   const vmSymbols::SID _sid;
-  DEBUG_ONLY( bool sid_ok() { return vmSymbols::find_sid(get_symbolOop()) == _sid; } )
+  DEBUG_ONLY( bool sid_ok() { return vmSymbols::find_sid(get_symbol()) == _sid; } )
 
-  ciSymbol(symbolOop s);  // normal case, for symbols not mentioned in vmSymbols
-  ciSymbol(symbolHandle s, vmSymbols::SID sid);   // for use with vmSymbolHandles
+  ciSymbol(Symbol* s);  // normal case, for symbols not mentioned in vmSymbols
+  ciSymbol(Symbol* s, vmSymbols::SID sid);   // for use with vmSymbols
+
+  Symbol* get_symbol() const { return _symbol; }
 
 public:
   symbolOop get_symbolOop() const { return (symbolOop)get_oop(); }
@@ -58,13 +63,17 @@
 
   void print_impl(outputStream* st);
 
-  // This is public in symbolOop but private here, because the base can move:
-  jbyte*      base();
+  // This is public in Symbol* but private here, because the base can move:
+  const jbyte* base();
 
   // Make a ciSymbol from a C string (implementation).
   static ciSymbol* make_impl(const char* s);
 
+  void set_ident(uint id) { _ident = id; }
 public:
+  // A number unique to this object.
+  uint ident() { return _ident; }
+
   // The enumeration ID from vmSymbols, or vmSymbols::NO_SID if none.
   vmSymbols::SID sid() const { return _sid; }
 
@@ -81,9 +90,6 @@
   // Determines where the symbol contains the given substring.
   int index_of_at(int i, const char* str, int len) const;
 
-  // What kind of ciObject is this?
-  bool is_symbol() { return true; }
-
   void print_symbol_on(outputStream* st);
   void print_symbol() {
     print_symbol_on(tty);
@@ -98,6 +104,13 @@
   static ciSymbol* name() { return ciObjectFactory::vm_symbol_at(vmSymbols::VM_SYMBOL_ENUM_NAME(name)); }
   VM_SYMBOLS_DO(CI_SYMBOL_DECLARE, CI_SYMBOL_DECLARE)
 #undef CI_SYMBOL_DECLARE
+
+  void print() {
+    _symbol->print();
+  }
+
+  // Are two ciSymbols equal?
+  bool equals(ciSymbol* obj) { return this->_symbol == obj->get_symbol(); }
 };
 
 #endif // SHARE_VM_CI_CISYMBOL_HPP
--- a/src/share/vm/ci/ciSymbolKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "ci/ciSymbolKlass.hpp"
-#include "ci/ciUtilities.hpp"
-
-// ciSymbolKlass
-//
-// This class represents a klassOop in the HotSpot virtual machine
-// whose Klass part is a symbolKlass.
-
-// ------------------------------------------------------------------
-// ciSymbolKlass::instance
-//
-// Return the distinguished instance of this class
-ciSymbolKlass* ciSymbolKlass::make() {
-  return CURRENT_ENV->_symbol_klass_instance;
-}
--- a/src/share/vm/ci/ciSymbolKlass.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_CI_CISYMBOLKLASS_HPP
-#define SHARE_VM_CI_CISYMBOLKLASS_HPP
-
-#include "ci/ciKlass.hpp"
-#include "ci/ciSymbol.hpp"
-
-// ciSymbolKlass
-//
-// This class represents a klassOop in the HotSpot virtual machine
-// whose Klass part in a symbolKlass.  Although, in the VM
-// Klass hierarchy, symbolKlass is a direct subclass of typeArrayKlass,
-// we do not model this relationship in the ciObject hierarchy -- the
-// subclassing is used to share implementation and is not of note
-// to compiler writers.
-class ciSymbolKlass : public ciKlass {
-  CI_PACKAGE_ACCESS
-
-protected:
-  ciSymbolKlass(KlassHandle h_k)
-    : ciKlass(h_k, ciSymbol::make("unique_symbolKlass")) {
-    assert(get_Klass()->oop_is_symbol(), "wrong type");
-  }
-
-  symbolKlass* get_symbolKlass() { return (symbolKlass*)get_Klass(); }
-
-  const char* type_string() { return "ciSymbolKlass"; }
-
-public:
-  // What kind of ciObject is this?
-  bool is_symbol_klass() { return true; }
-
-  // Return the distinguished ciSymbolKlass instance.
-  static ciSymbolKlass* make();
-};
-
-#endif // SHARE_VM_CI_CISYMBOLKLASS_HPP
--- a/src/share/vm/ci/ciTypeFlow.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/ciTypeFlow.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1698,18 +1698,17 @@
         break;
 
       case Bytecodes::_tableswitch:  {
-        Bytecode_tableswitch *tableswitch =
-          Bytecode_tableswitch_at(str->cur_bcp());
+        Bytecode_tableswitch tableswitch(str);
 
-        int len = tableswitch->length();
+        int len = tableswitch.length();
         _successors =
           new (arena) GrowableArray<Block*>(arena, len+1, 0, NULL);
-        int bci = current_bci + tableswitch->default_offset();
+        int bci = current_bci + tableswitch.default_offset();
         Block* block = analyzer->block_at(bci, jsrs);
         assert(_successors->length() == SWITCH_DEFAULT, "");
         _successors->append(block);
         while (--len >= 0) {
-          int bci = current_bci + tableswitch->dest_offset_at(len);
+          int bci = current_bci + tableswitch.dest_offset_at(len);
           block = analyzer->block_at(bci, jsrs);
           assert(_successors->length() >= SWITCH_CASES, "");
           _successors->append_if_missing(block);
@@ -1718,19 +1717,18 @@
       }
 
       case Bytecodes::_lookupswitch: {
-        Bytecode_lookupswitch *lookupswitch =
-          Bytecode_lookupswitch_at(str->cur_bcp());
+        Bytecode_lookupswitch lookupswitch(str);
 
-        int npairs = lookupswitch->number_of_pairs();
+        int npairs = lookupswitch.number_of_pairs();
         _successors =
           new (arena) GrowableArray<Block*>(arena, npairs+1, 0, NULL);
-        int bci = current_bci + lookupswitch->default_offset();
+        int bci = current_bci + lookupswitch.default_offset();
         Block* block = analyzer->block_at(bci, jsrs);
         assert(_successors->length() == SWITCH_DEFAULT, "");
         _successors->append(block);
         while(--npairs >= 0) {
-          LookupswitchPair *pair = lookupswitch->pair_at(npairs);
-          int bci = current_bci + pair->offset();
+          LookupswitchPair pair = lookupswitch.pair_at(npairs);
+          int bci = current_bci + pair.offset();
           Block* block = analyzer->block_at(bci, jsrs);
           assert(_successors->length() >= SWITCH_CASES, "");
           _successors->append_if_missing(block);
--- a/src/share/vm/ci/compilerInterface.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/ci/compilerInterface.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -49,7 +49,6 @@
 #include "ci/ciSignature.hpp"
 #include "ci/ciStreams.hpp"
 #include "ci/ciSymbol.hpp"
-#include "ci/ciSymbolKlass.hpp"
 #include "ci/ciTypeArray.hpp"
 #include "ci/ciTypeArrayKlass.hpp"
 #include "ci/ciTypeArrayKlassKlass.hpp"
--- a/src/share/vm/classfile/classFileError.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/classFileError.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,25 +31,25 @@
 
 void ClassFileParser::classfile_parse_error(const char* msg, TRAPS) {
     ResourceMark rm(THREAD);
-    Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbolHandles::java_lang_ClassFormatError(),
+    Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(),
                        msg, _class_name->as_C_string());
 }
 
 void ClassFileParser::classfile_parse_error(const char* msg, int index, TRAPS) {
     ResourceMark rm(THREAD);
-    Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbolHandles::java_lang_ClassFormatError(),
+    Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(),
                        msg, index, _class_name->as_C_string());
 }
 
 void ClassFileParser::classfile_parse_error(const char* msg, const char *name, TRAPS) {
     ResourceMark rm(THREAD);
-    Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbolHandles::java_lang_ClassFormatError(),
+    Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(),
                        msg, name, _class_name->as_C_string());
 }
 
 void ClassFileParser::classfile_parse_error(const char* msg, int index, const char *name, TRAPS) {
     ResourceMark rm(THREAD);
-    Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbolHandles::java_lang_ClassFormatError(),
+    Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(),
                        msg, index, name, _class_name->as_C_string());
 }
 
@@ -57,7 +57,7 @@
   ResourceMark rm(THREAD);
   Exceptions::fthrow(
     THREAD_AND_LOCATION,
-    vmSymbolHandles::java_lang_ClassFormatError(),
+    vmSymbols::java_lang_ClassFormatError(),
     "StackMapTable format error: %s", msg
   );
 }
--- a/src/share/vm/classfile/classFileParser.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/classFileParser.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -41,7 +41,7 @@
 #include "oops/klassOop.hpp"
 #include "oops/klassVtable.hpp"
 #include "oops/methodOop.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/perfData.hpp"
@@ -267,14 +267,14 @@
           }
 
           unsigned int hash;
-          symbolOop result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash);
+          Symbol* result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash);
           if (result == NULL) {
             names[names_count] = (char*)utf8_buffer;
             lengths[names_count] = utf8_length;
             indices[names_count] = index;
             hashValues[names_count++] = hash;
             if (names_count == SymbolTable::symbol_alloc_batch_size) {
-              oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
+              SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
               names_count = 0;
             }
           } else {
@@ -291,7 +291,7 @@
 
   // Allocate the remaining symbols
   if (names_count > 0) {
-    oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
+    SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
   }
 
   // Copy _current pointer of local copy back to stream().
@@ -301,6 +301,23 @@
   cfs0->set_current(cfs1.current());
 }
 
+// This class unreferences constant pool symbols if an error has occurred
+// while parsing the class before it is assigned into the class.
+// If it gets an error after that it is unloaded and the constant pool will
+// be cleaned up then.
+class ConstantPoolCleaner : public StackObj {
+  constantPoolHandle _cphandle;
+  bool               _in_error;
+ public:
+  ConstantPoolCleaner(constantPoolHandle cp) : _cphandle(cp), _in_error(true) {}
+  ~ConstantPoolCleaner() {
+    if (_in_error && _cphandle.not_null()) {
+      _cphandle->unreference_symbols();
+    }
+  }
+  void set_in_error(bool clean) { _in_error = clean; }
+};
+
 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
 
 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
@@ -319,6 +336,7 @@
   constantPoolHandle cp (THREAD, constant_pool);
 
   cp->set_partially_loaded();    // Enables heap verify to work on partial constantPoolOops
+  ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up.
 
   // parsing constant pool entries
   parse_constant_pool_entries(cp, length, CHECK_(nullHandle));
@@ -411,7 +429,7 @@
               cp->tag_at(string_index).is_utf8(),
             "Invalid constant pool index %u in class file %s",
             string_index, CHECK_(nullHandle));
-          symbolOop sym = cp->symbol_at(string_index);
+          Symbol* sym = cp->symbol_at(string_index);
           cp->unresolved_string_at_put(index, sym);
         }
         break;
@@ -526,6 +544,7 @@
   }
 
   if (!_need_verify) {
+    cp_in_error.set_in_error(false);
     return cp;
   }
 
@@ -535,7 +554,7 @@
     jbyte tag = cp->tag_at(index).value();
     switch (tag) {
       case JVM_CONSTANT_UnresolvedClass: {
-        symbolHandle class_name(THREAD, cp->unresolved_klass_at(index));
+        Symbol*  class_name = cp->unresolved_klass_at(index);
         // check the name, even if _cp_patches will overwrite it
         verify_legal_class_name(class_name, CHECK_(nullHandle));
         break;
@@ -544,8 +563,8 @@
         if (_need_verify && _major_version >= JAVA_7_VERSION) {
           int sig_index = cp->signature_ref_index_at(index);
           int name_index = cp->name_ref_index_at(index);
-          symbolHandle name(THREAD, cp->symbol_at(name_index));
-          symbolHandle sig(THREAD, cp->symbol_at(sig_index));
+          Symbol*  name = cp->symbol_at(name_index);
+          Symbol*  sig = cp->symbol_at(sig_index);
           if (sig->byte_at(0) == JVM_SIGNATURE_FUNC) {
             verify_legal_method_signature(name, sig, CHECK_(nullHandle));
           } else {
@@ -562,8 +581,8 @@
         int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index);
         // already verified to be utf8
         int signature_ref_index = cp->signature_ref_index_at(name_and_type_ref_index);
-        symbolHandle name(THREAD, cp->symbol_at(name_ref_index));
-        symbolHandle signature(THREAD, cp->symbol_at(signature_ref_index));
+        Symbol*  name = cp->symbol_at(name_ref_index);
+        Symbol*  signature = cp->symbol_at(signature_ref_index);
         if (tag == JVM_CONSTANT_Fieldref) {
           verify_legal_field_name(name, CHECK_(nullHandle));
           if (_need_verify && _major_version >= JAVA_7_VERSION) {
@@ -590,11 +609,11 @@
           }
           if (tag == JVM_CONSTANT_Methodref) {
             // 4509014: If a class method name begins with '<', it must be "<init>".
-            assert(!name.is_null(), "method name in constant pool is null");
+            assert(name != NULL, "method name in constant pool is null");
             unsigned int name_len = name->utf8_length();
             assert(name_len > 0, "bad method name");  // already verified as legal name
             if (name->byte_at(0) == '<') {
-              if (name() != vmSymbols::object_initializer_name()) {
+              if (name != vmSymbols::object_initializer_name()) {
                 classfile_parse_error(
                   "Bad method name at constant pool index %u in class file %s",
                   name_ref_index, CHECK_(nullHandle));
@@ -615,15 +634,15 @@
           {
             int name_and_type_ref_index = cp->name_and_type_ref_index_at(ref_index);
             int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index);
-            symbolHandle name(THREAD, cp->symbol_at(name_ref_index));
+            Symbol*  name = cp->symbol_at(name_ref_index);
             if (ref_kind == JVM_REF_newInvokeSpecial) {
-              if (name() != vmSymbols::object_initializer_name()) {
+              if (name != vmSymbols::object_initializer_name()) {
                 classfile_parse_error(
                   "Bad constructor name at constant pool index %u in class file %s",
                   name_ref_index, CHECK_(nullHandle));
               }
             } else {
-              if (name() == vmSymbols::object_initializer_name()) {
+              if (name == vmSymbols::object_initializer_name()) {
                 classfile_parse_error(
                   "Bad method name at constant pool index %u in class file %s",
                   name_ref_index, CHECK_(nullHandle));
@@ -636,14 +655,18 @@
         break;
       }
       case JVM_CONSTANT_MethodType: {
-        symbolHandle no_name = vmSymbolHandles::type_name(); // place holder
-        symbolHandle signature(THREAD, cp->method_type_signature_at(index));
+        Symbol* no_name = vmSymbols::type_name(); // place holder
+        Symbol*  signature = cp->method_type_signature_at(index);
         verify_legal_method_signature(no_name, signature, CHECK_(nullHandle));
         break;
       }
+      case JVM_CONSTANT_Utf8: {
+        assert(cp->symbol_at(index)->refcount() != 0, "count corrupted");
+      }
     }  // end of switch
   }  // end of for
 
+  cp_in_error.set_in_error(false);
   return cp;
 }
 
@@ -665,8 +688,8 @@
       guarantee_property(java_lang_String::is_instance(patch()),
                          "Illegal class patch at %d in class file %s",
                          index, CHECK);
-      symbolHandle name = java_lang_String::as_symbol(patch(), CHECK);
-      cp->unresolved_klass_at_put(index, name());
+      Symbol* name = java_lang_String::as_symbol(patch(), CHECK);
+      cp->unresolved_klass_at_put(index, name);
     }
     break;
 
@@ -717,15 +740,15 @@
 
 class NameSigHash: public ResourceObj {
  public:
-  symbolOop     _name;       // name
-  symbolOop     _sig;        // signature
+  Symbol*       _name;       // name
+  Symbol*       _sig;        // signature
   NameSigHash*  _next;       // Next entry in hash table
 };
 
 
 #define HASH_ROW_SIZE 256
 
-unsigned int hash(symbolOop name, symbolOop sig) {
+unsigned int hash(Symbol* name, Symbol* sig) {
   unsigned int raw_hash = 0;
   raw_hash += ((unsigned int)(uintptr_t)name) >> (LogHeapWordSize + 2);
   raw_hash += ((unsigned int)(uintptr_t)sig) >> LogHeapWordSize;
@@ -742,8 +765,8 @@
 // Return true if no duplicate is found. And name/sig is added as a new entry in table.
 // The old format checker uses heap sort to find duplicates.
 // NOTE: caller should guarantee that GC doesn't happen during the life cycle
-// of table since we don't expect symbolOop's to move.
-bool put_after_lookup(symbolOop name, symbolOop sig, NameSigHash** table) {
+// of table since we don't expect Symbol*'s to move.
+bool put_after_lookup(Symbol* name, Symbol* sig, NameSigHash** table) {
   assert(name != NULL, "name in constant pool is NULL");
 
   // First lookup for duplicates
@@ -773,7 +796,7 @@
                                                  int length,
                                                  Handle class_loader,
                                                  Handle protection_domain,
-                                                 symbolHandle class_name,
+                                                 Symbol* class_name,
                                                  TRAPS) {
   ClassFileStream* cfs = stream();
   assert(length > 0, "only called for length>0");
@@ -793,7 +816,7 @@
     if (cp->tag_at(interface_index).is_klass()) {
       interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index));
     } else {
-      symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index));
+      Symbol*  unresolved_klass  = cp->klass_name_at(interface_index);
 
       // Don't need to check legal name because it's checked when parsing constant pool.
       // But need to make sure it's not an array type.
@@ -830,7 +853,7 @@
     debug_only(No_Safepoint_Verifier nsv;)
     for (index = 0; index < length; index++) {
       klassOop k = (klassOop)interfaces->obj_at(index);
-      symbolOop name = instanceKlass::cast(k)->name();
+      Symbol* name = instanceKlass::cast(k)->name();
       // If no duplicates, add (name, NULL) in hashtable interface_names.
       if (!put_after_lookup(name, NULL, interface_names)) {
         dup = true;
@@ -908,7 +931,7 @@
                    "Invalid field attribute index %u in class file %s",
                    attribute_name_index,
                    CHECK);
-    symbolOop attribute_name = cp->symbol_at(attribute_name_index);
+    Symbol* attribute_name = cp->symbol_at(attribute_name_index);
     if (is_static && attribute_name == vmSymbols::tag_constant_value()) {
       // ignore if non-static
       if (constantvalue_index != 0) {
@@ -1031,7 +1054,7 @@
       valid_cp_range(name_index, cp_size) && cp->tag_at(name_index).is_utf8(),
       "Invalid constant pool index %u for field name in class file %s",
       name_index, CHECK_(nullHandle));
-    symbolHandle name(THREAD, cp->symbol_at(name_index));
+    Symbol*  name = cp->symbol_at(name_index);
     verify_legal_field_name(name, CHECK_(nullHandle));
 
     u2 signature_index = cfs->get_u2_fast();
@@ -1040,7 +1063,7 @@
         cp->tag_at(signature_index).is_utf8(),
       "Invalid constant pool index %u for field signature in class file %s",
       signature_index, CHECK_(nullHandle));
-    symbolHandle sig(THREAD, cp->symbol_at(signature_index));
+    Symbol*  sig = cp->symbol_at(signature_index);
     verify_legal_field_signature(name, sig, CHECK_(nullHandle));
 
     u2 constantvalue_index = 0;
@@ -1166,9 +1189,9 @@
       debug_only(No_Safepoint_Verifier nsv;)
       for (int i = 0; i < length*instanceKlass::next_offset; i += instanceKlass::next_offset) {
         int name_index = fields->ushort_at(i + instanceKlass::name_index_offset);
-        symbolOop name = cp->symbol_at(name_index);
+        Symbol* name = cp->symbol_at(name_index);
         int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset);
-        symbolOop sig = cp->symbol_at(sig_index);
+        Symbol* sig = cp->symbol_at(sig_index);
         // If no duplicates, add name/signature in hashtable names_and_sigs.
         if (!put_after_lookup(name, sig, names_and_sigs)) {
           dup = true;
@@ -1422,16 +1445,16 @@
         "Signature index %u in %s has bad constant type in class file %s",
         descriptor_index, tbl_name, CHECK_NULL);
 
-      symbolHandle name(THREAD, cp->symbol_at(name_index));
-      symbolHandle sig(THREAD, cp->symbol_at(descriptor_index));
+      Symbol*  name = cp->symbol_at(name_index);
+      Symbol*  sig = cp->symbol_at(descriptor_index);
       verify_legal_field_name(name, CHECK_NULL);
       u2 extra_slot = 0;
       if (!isLVTT) {
         verify_legal_field_signature(name, sig, CHECK_NULL);
 
         // 4894874: check special cases for double and long local variables
-        if (sig() == vmSymbols::type_signature(T_DOUBLE) ||
-            sig() == vmSymbols::type_signature(T_LONG)) {
+        if (sig == vmSymbols::type_signature(T_DOUBLE) ||
+            sig == vmSymbols::type_signature(T_LONG)) {
           extra_slot = 1;
         }
       }
@@ -1539,7 +1562,7 @@
 }
 
 void ClassFileParser::throwIllegalSignature(
-    const char* type, symbolHandle name, symbolHandle sig, TRAPS) {
+    const char* type, Symbol* name, Symbol* sig, TRAPS) {
   ResourceMark rm(THREAD);
   Exceptions::fthrow(THREAD_AND_LOCATION,
       vmSymbols::java_lang_ClassFormatError(),
@@ -1580,7 +1603,7 @@
       cp->tag_at(name_index).is_utf8(),
     "Illegal constant pool index %u for method name in class file %s",
     name_index, CHECK_(nullHandle));
-  symbolHandle name(THREAD, cp->symbol_at(name_index));
+  Symbol*  name = cp->symbol_at(name_index);
   verify_legal_method_name(name, CHECK_(nullHandle));
 
   u2 signature_index = cfs->get_u2_fast();
@@ -1589,7 +1612,7 @@
       cp->tag_at(signature_index).is_utf8(),
     "Illegal constant pool index %u for method signature in class file %s",
     signature_index, CHECK_(nullHandle));
-  symbolHandle signature(THREAD, cp->symbol_at(signature_index));
+  Symbol*  signature = cp->symbol_at(signature_index);
 
   AccessFlags access_flags;
   if (name == vmSymbols::class_initializer_name()) {
@@ -1660,7 +1683,7 @@
       "Invalid method attribute name index %u in class file %s",
       method_attribute_name_index, CHECK_(nullHandle));
 
-    symbolOop method_attribute_name = cp->symbol_at(method_attribute_name_index);
+    Symbol* method_attribute_name = cp->symbol_at(method_attribute_name_index);
     if (method_attribute_name == vmSymbols::tag_code()) {
       // Parse Code attribute
       if (_need_verify) {
@@ -2057,16 +2080,16 @@
                                                      0,
                                                      CHECK_(nullHandle));
 
-  if (name() == vmSymbols::finalize_method_name() &&
-      signature() == vmSymbols::void_method_signature()) {
+  if (name == vmSymbols::finalize_method_name() &&
+      signature == vmSymbols::void_method_signature()) {
     if (m->is_empty_method()) {
       _has_empty_finalizer = true;
     } else {
       _has_finalizer = true;
     }
   }
-  if (name() == vmSymbols::object_initializer_name() &&
-      signature() == vmSymbols::void_method_signature() &&
+  if (name == vmSymbols::object_initializer_name() &&
+      signature == vmSymbols::void_method_signature() &&
       m->is_vanilla_constructor()) {
     _has_vanilla_constructor = true;
   }
@@ -2193,7 +2216,7 @@
     }
   }
   // Sort method array by ascending method name (for faster lookups & vtable construction)
-  // Note that the ordering is not alphabetical, see symbolOopDesc::fast_compare
+  // Note that the ordering is not alphabetical, see Symbol::fast_compare
   methodOopDesc::sort_methods(methods(),
                               methods_annotations(),
                               methods_parameter_annotations(),
@@ -2242,9 +2265,10 @@
   if (JvmtiExport::can_get_source_debug_extension()) {
     // Optimistically assume that only 1 byte UTF format is used
     // (common case)
-    symbolOop sde_symbol = oopFactory::new_symbol((char*)sde_buffer,
-                                                  length, CHECK);
+    TempNewSymbol sde_symbol = SymbolTable::new_symbol((const char*)sde_buffer, length, CHECK);
     k->set_source_debug_extension(sde_symbol);
+    // Note that set_source_debug_extension() increments the reference count
+    // for its copy of the Symbol*, so use a TempNewSymbol here.
   }
   // Got utf8 string, set stream position forward
   cfs->skip_u1(length, CHECK);
@@ -2440,7 +2464,7 @@
         cp->tag_at(attribute_name_index).is_utf8(),
       "Attribute name has bad constant pool index %u in class file %s",
       attribute_name_index, CHECK);
-    symbolOop tag = cp->symbol_at(attribute_name_index);
+    Symbol* tag = cp->symbol_at(attribute_name_index);
     if (tag == vmSymbols::tag_source_file()) {
       // Check for SourceFile tag
       if (_need_verify) {
@@ -2607,7 +2631,7 @@
       case T_OBJECT:
         {
           #ifdef ASSERT
-          symbolOop sym = oopFactory::new_symbol("Ljava/lang/String;", CHECK);
+          TempNewSymbol sym = SymbolTable::new_symbol("Ljava/lang/String;", CHECK);
           assert(fd->signature() == sym, "just checking");
           #endif
           oop string = fd->string_initial_value(CHECK);
@@ -2650,8 +2674,8 @@
     (*fields_ptr)()->ushort_at(i + instanceKlass::name_index_offset);
     int sig_index  =
       (*fields_ptr)()->ushort_at(i + instanceKlass::signature_index_offset);
-    symbolOop f_name = cp->symbol_at(name_index);
-    symbolOop f_sig  = cp->symbol_at(sig_index);
+    Symbol* f_name = cp->symbol_at(name_index);
+    Symbol* f_sig  = cp->symbol_at(sig_index);
     if (f_sig == vmSymbols::reference_signature() && reference_index == 0) {
       // Save the index for reference signature for later use.
       // The fake discovered field does not entries in the
@@ -2805,9 +2829,8 @@
     int name_index = fields->ushort_at(i + instanceKlass::name_index_offset);
     int sig_index  = fields->ushort_at(i + instanceKlass::signature_index_offset);
     int acc_flags  = fields->ushort_at(i + instanceKlass::access_flags_offset);
-    symbolOop f_name = cp->symbol_at(name_index);
-    symbolOop f_sig  = cp->symbol_at(sig_index);
-
+    Symbol* f_name = cp->symbol_at(name_index);
+    Symbol* f_sig  = cp->symbol_at(sig_index);
     if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) {
       if (f_sig == vmSymbols::machine_word_signature()) {
         // If the signature of vmentry is already changed, we're done.
@@ -2841,12 +2864,12 @@
 }
 
 
-instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
+instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
                                                     Handle class_loader,
                                                     Handle protection_domain,
                                                     KlassHandle host_klass,
                                                     GrowableArray<Handle>* cp_patches,
-                                                    symbolHandle& parsed_name,
+                                                    TempNewSymbol& parsed_name,
                                                     bool verify,
                                                     TRAPS) {
   // So that JVMTI can cache class file in the state before retransformable agents
@@ -2899,7 +2922,7 @@
   cfs->set_verify(_need_verify);
 
   // Save the class file name for easier error message printing.
-  _class_name = name.not_null()? name : vmSymbolHandles::unknown_class_name();
+  _class_name = (name != NULL) ? name : vmSymbols::unknown_class_name();
 
   cfs->guarantee_more(8, CHECK_(nullHandle));  // magic, major, minor
   // Magic value
@@ -2914,10 +2937,10 @@
 
   // Check version numbers - we check this even with verifier off
   if (!is_supported_version(major_version, minor_version)) {
-    if (name.is_null()) {
+    if (name == NULL) {
       Exceptions::fthrow(
         THREAD_AND_LOCATION,
-        vmSymbolHandles::java_lang_UnsupportedClassVersionError(),
+        vmSymbols::java_lang_UnsupportedClassVersionError(),
         "Unsupported major.minor version %u.%u",
         major_version,
         minor_version);
@@ -2925,7 +2948,7 @@
       ResourceMark rm(THREAD);
       Exceptions::fthrow(
         THREAD_AND_LOCATION,
-        vmSymbolHandles::java_lang_UnsupportedClassVersionError(),
+        vmSymbols::java_lang_UnsupportedClassVersionError(),
         "%s : Unsupported major.minor version %u.%u",
         name->as_C_string(),
         major_version,
@@ -2944,6 +2967,8 @@
 
   // Constant pool
   constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle));
+  ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up.
+
   int cp_size = cp->length();
 
   cfs->guarantee_more(8, CHECK_(nullHandle));  // flags, this_class, super_class, infs_len
@@ -2968,12 +2993,15 @@
     "Invalid this class index %u in constant pool in class file %s",
     this_class_index, CHECK_(nullHandle));
 
-  symbolHandle class_name (THREAD, cp->unresolved_klass_at(this_class_index));
-  assert(class_name.not_null(), "class_name can't be null");
+  Symbol*  class_name  = cp->unresolved_klass_at(this_class_index);
+  assert(class_name != NULL, "class_name can't be null");
 
   // It's important to set parsed_name *before* resolving the super class.
   // (it's used for cleanup by the caller if parsing fails)
   parsed_name = class_name;
+  // parsed_name is returned and can be used if there's an error, so add to
+  // its reference count.  Caller will decrement the refcount.
+  parsed_name->increment_refcount();
 
   // Update _class_name which could be null previously to be class_name
   _class_name = class_name;
@@ -2993,11 +3021,11 @@
   { HandleMark hm(THREAD);
 
     // Checks if name in class file matches requested name
-    if (name.not_null() && class_name() != name()) {
+    if (name != NULL && class_name != name) {
       ResourceMark rm(THREAD);
       Exceptions::fthrow(
         THREAD_AND_LOCATION,
-        vmSymbolHandles::java_lang_NoClassDefFoundError(),
+        vmSymbols::java_lang_NoClassDefFoundError(),
         "%s (wrong name: %s)",
         name->as_C_string(),
         class_name->as_C_string()
@@ -3006,14 +3034,14 @@
     }
 
     if (TraceClassLoadingPreorder) {
-      tty->print("[Loading %s", name()->as_klass_external_name());
+      tty->print("[Loading %s", name->as_klass_external_name());
       if (cfs->source() != NULL) tty->print(" from %s", cfs->source());
       tty->print_cr("]");
     }
 
     u2 super_class_index = cfs->get_u2_fast();
     if (super_class_index == 0) {
-      check_property(class_name() == vmSymbols::java_lang_Object(),
+      check_property(class_name == vmSymbols::java_lang_Object(),
                      "Invalid superclass index %u in class file %s",
                      super_class_index,
                      CHECK_(nullHandle));
@@ -3075,11 +3103,11 @@
 
     // We check super class after class file is parsed and format is checked
     if (super_class_index > 0 && super_klass.is_null()) {
-      symbolHandle sk (THREAD, cp->klass_name_at(super_class_index));
+      Symbol*  sk  = cp->klass_name_at(super_class_index);
       if (access_flags.is_interface()) {
         // Before attempting to resolve the superclass, check for class format
         // errors not checked yet.
-        guarantee_property(sk() == vmSymbols::java_lang_Object(),
+        guarantee_property(sk == vmSymbols::java_lang_Object(),
                            "Interfaces must have java.lang.Object as superclass in class file %s",
                            CHECK_(nullHandle));
       }
@@ -3100,7 +3128,7 @@
         ResourceMark rm(THREAD);
         Exceptions::fthrow(
           THREAD_AND_LOCATION,
-          vmSymbolHandles::java_lang_IncompatibleClassChangeError(),
+          vmSymbols::java_lang_IncompatibleClassChangeError(),
           "class %s has interface %s as super class",
           class_name->as_klass_external_name(),
           super_klass->external_name()
@@ -3193,18 +3221,18 @@
     next_nonstatic_field_offset = first_nonstatic_field_offset;
 
     // Add fake fields for java.lang.Class instances (also see below)
-    if (class_name() == vmSymbols::java_lang_Class() && class_loader.is_null()) {
+    if (class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) {
       java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle));
     }
 
     // adjust the vmentry field declaration in java.dyn.MethodHandle
-    if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) {
+    if (EnableMethodHandles && class_name == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) {
       java_dyn_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle));
     }
 
     // Add a fake "discovered" field if it is not present
     // for compatibility with earlier jdk's.
-    if (class_name() == vmSymbols::java_lang_ref_Reference()
+    if (class_name == vmSymbols::java_lang_ref_Reference()
       && class_loader.is_null()) {
       java_lang_ref_Reference_fix_pre(&fields, cp, &fac, CHECK_(nullHandle));
     }
@@ -3236,7 +3264,7 @@
 
     // Add fake fields for java.lang.Class instances (also see above).
     // FieldsAllocationStyle and CompactFields values will be reset to default.
-    if(class_name() == vmSymbols::java_lang_Class() && class_loader.is_null()) {
+    if(class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) {
       java_lang_Class_fix_post(&next_nonstatic_field_offset);
       nonstatic_oop_offsets[0] = first_nonstatic_field_offset;
       const uint fake_oop_count = (next_nonstatic_field_offset -
@@ -3279,22 +3307,22 @@
     // (see in JavaClasses::compute_hard_coded_offsets()).
     // Use default fields allocation order for them.
     if( (allocation_style != 0 || compact_fields ) && class_loader.is_null() &&
-        (class_name() == vmSymbols::java_lang_AssertionStatusDirectives() ||
-         class_name() == vmSymbols::java_lang_Class() ||
-         class_name() == vmSymbols::java_lang_ClassLoader() ||
-         class_name() == vmSymbols::java_lang_ref_Reference() ||
-         class_name() == vmSymbols::java_lang_ref_SoftReference() ||
-         class_name() == vmSymbols::java_lang_StackTraceElement() ||
-         class_name() == vmSymbols::java_lang_String() ||
-         class_name() == vmSymbols::java_lang_Throwable() ||
-         class_name() == vmSymbols::java_lang_Boolean() ||
-         class_name() == vmSymbols::java_lang_Character() ||
-         class_name() == vmSymbols::java_lang_Float() ||
-         class_name() == vmSymbols::java_lang_Double() ||
-         class_name() == vmSymbols::java_lang_Byte() ||
-         class_name() == vmSymbols::java_lang_Short() ||
-         class_name() == vmSymbols::java_lang_Integer() ||
-         class_name() == vmSymbols::java_lang_Long())) {
+        (class_name == vmSymbols::java_lang_AssertionStatusDirectives() ||
+         class_name == vmSymbols::java_lang_Class() ||
+         class_name == vmSymbols::java_lang_ClassLoader() ||
+         class_name == vmSymbols::java_lang_ref_Reference() ||
+         class_name == vmSymbols::java_lang_ref_SoftReference() ||
+         class_name == vmSymbols::java_lang_StackTraceElement() ||
+         class_name == vmSymbols::java_lang_String() ||
+         class_name == vmSymbols::java_lang_Throwable() ||
+         class_name == vmSymbols::java_lang_Boolean() ||
+         class_name == vmSymbols::java_lang_Character() ||
+         class_name == vmSymbols::java_lang_Float() ||
+         class_name == vmSymbols::java_lang_Double() ||
+         class_name == vmSymbols::java_lang_Byte() ||
+         class_name == vmSymbols::java_lang_Short() ||
+         class_name == vmSymbols::java_lang_Integer() ||
+         class_name == vmSymbols::java_lang_Long())) {
       allocation_style = 0;     // Allocate oops first
       compact_fields   = false; // Don't compact fields
     }
@@ -3543,6 +3571,7 @@
     this_klass->set_has_nonstatic_fields(has_nonstatic_fields);
     this_klass->set_static_oop_field_size(fac.static_oop_count);
     cp->set_pool_holder(this_klass());
+    error_handler.set_in_error(false);   // turn off error handler for cp
     this_klass->set_constants(cp());
     this_klass->set_local_interfaces(local_interfaces());
     this_klass->set_fields(fields());
@@ -3935,7 +3964,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_IllegalAccessError(),
+      vmSymbols::java_lang_IllegalAccessError(),
       "class %s cannot access its superclass %s",
       this_klass->external_name(),
       instanceKlass::cast(super)->external_name()
@@ -3955,7 +3984,7 @@
       ResourceMark rm(THREAD);
       Exceptions::fthrow(
         THREAD_AND_LOCATION,
-        vmSymbolHandles::java_lang_IllegalAccessError(),
+        vmSymbols::java_lang_IllegalAccessError(),
         "class %s cannot access its superinterface %s",
         this_klass->external_name(),
         instanceKlass::cast(k)->external_name()
@@ -3979,8 +4008,8 @@
         (!m->is_static()) &&
         (m->name() != vmSymbols::object_initializer_name())) {
 
-      symbolOop name = m->name();
-      symbolOop signature = m->signature();
+      Symbol* name = m->name();
+      Symbol* signature = m->signature();
       klassOop k = this_klass->super();
       methodOop super_m = NULL;
       while (k != NULL) {
@@ -4003,7 +4032,7 @@
             ResourceMark rm(THREAD);
             Exceptions::fthrow(
               THREAD_AND_LOCATION,
-              vmSymbolHandles::java_lang_VerifyError(),
+              vmSymbols::java_lang_VerifyError(),
               "class %s overrides final method %s.%s",
               this_klass->external_name(),
               name->as_C_string(),
@@ -4037,7 +4066,7 @@
       ResourceMark rm(THREAD);
       Exceptions::fthrow(
         THREAD_AND_LOCATION,
-        vmSymbolHandles::java_lang_VerifyError(),
+        vmSymbols::java_lang_VerifyError(),
         "Illegal static method %s in interface %s",
         m->name()->as_C_string(),
         this_klass->external_name()
@@ -4067,7 +4096,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_ClassFormatError(),
+      vmSymbols::java_lang_ClassFormatError(),
       "Illegal class modifiers in class %s: 0x%X",
       _class_name->as_C_string(), flags
     );
@@ -4127,7 +4156,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_ClassFormatError(),
+      vmSymbols::java_lang_ClassFormatError(),
       "Illegal field modifiers in class %s: 0x%X",
       _class_name->as_C_string(), flags);
     return;
@@ -4135,7 +4164,7 @@
 }
 
 void ClassFileParser::verify_legal_method_modifiers(
-    jint flags, bool is_interface, symbolHandle name, TRAPS) {
+    jint flags, bool is_interface, Symbol* name, TRAPS) {
   if (!_need_verify) { return; }
 
   const bool is_public       = (flags & JVM_ACC_PUBLIC)       != 0;
@@ -4180,7 +4209,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_ClassFormatError(),
+      vmSymbols::java_lang_ClassFormatError(),
       "Method %s in class %s has illegal modifiers: 0x%X",
       name->as_C_string(), _class_name->as_C_string(), flags);
     return;
@@ -4251,7 +4280,7 @@
 }
 
 // Checks if name is a legal class name.
-void ClassFileParser::verify_legal_class_name(symbolHandle name, TRAPS) {
+void ClassFileParser::verify_legal_class_name(Symbol* name, TRAPS) {
   if (!_need_verify || _relax_verify) { return; }
 
   char buf[fixed_buffer_size];
@@ -4281,7 +4310,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_ClassFormatError(),
+      vmSymbols::java_lang_ClassFormatError(),
       "Illegal class name \"%s\" in class file %s", bytes,
       _class_name->as_C_string()
     );
@@ -4290,7 +4319,7 @@
 }
 
 // Checks if name is a legal field name.
-void ClassFileParser::verify_legal_field_name(symbolHandle name, TRAPS) {
+void ClassFileParser::verify_legal_field_name(Symbol* name, TRAPS) {
   if (!_need_verify || _relax_verify) { return; }
 
   char buf[fixed_buffer_size];
@@ -4314,7 +4343,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_ClassFormatError(),
+      vmSymbols::java_lang_ClassFormatError(),
       "Illegal field name \"%s\" in class %s", bytes,
       _class_name->as_C_string()
     );
@@ -4323,10 +4352,10 @@
 }
 
 // Checks if name is a legal method name.
-void ClassFileParser::verify_legal_method_name(symbolHandle name, TRAPS) {
+void ClassFileParser::verify_legal_method_name(Symbol* name, TRAPS) {
   if (!_need_verify || _relax_verify) { return; }
 
-  assert(!name.is_null(), "method name is null");
+  assert(name != NULL, "method name is null");
   char buf[fixed_buffer_size];
   char* bytes = name->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size);
   unsigned int length = name->utf8_length();
@@ -4351,7 +4380,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_ClassFormatError(),
+      vmSymbols::java_lang_ClassFormatError(),
       "Illegal method name \"%s\" in class %s", bytes,
       _class_name->as_C_string()
     );
@@ -4361,7 +4390,7 @@
 
 
 // Checks if signature is a legal field signature.
-void ClassFileParser::verify_legal_field_signature(symbolHandle name, symbolHandle signature, TRAPS) {
+void ClassFileParser::verify_legal_field_signature(Symbol* name, Symbol* signature, TRAPS) {
   if (!_need_verify) { return; }
 
   char buf[fixed_buffer_size];
@@ -4376,7 +4405,7 @@
 
 // Checks if signature is a legal method signature.
 // Returns number of parameters
-int ClassFileParser::verify_legal_method_signature(symbolHandle name, symbolHandle signature, TRAPS) {
+int ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signature, TRAPS) {
   if (!_need_verify) {
     // make sure caller's args_size will be less than 0 even for non-static
     // method so it will be recomputed in compute_size_of_parameters().
@@ -4508,8 +4537,8 @@
       // public static boolean isJavaIdentifierStart(char ch);
       JavaCalls::call_static(&result,
                              klass,
-                             vmSymbolHandles::isJavaIdentifierStart_name(),
-                             vmSymbolHandles::int_bool_signature(),
+                             vmSymbols::isJavaIdentifierStart_name(),
+                             vmSymbols::int_bool_signature(),
                              &args,
                              THREAD);
 
@@ -4525,8 +4554,8 @@
         // public static boolean isJavaIdentifierPart(char ch);
         JavaCalls::call_static(&result,
                                klass,
-                               vmSymbolHandles::isJavaIdentifierPart_name(),
-                               vmSymbolHandles::int_bool_signature(),
+                               vmSymbols::isJavaIdentifierPart_name(),
+                               vmSymbols::int_bool_signature(),
                                &args,
                                THREAD);
 
--- a/src/share/vm/classfile/classFileParser.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/classFileParser.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -32,6 +32,7 @@
 #include "runtime/handles.inline.hpp"
 #include "utilities/accessFlags.hpp"
 
+class TempNewSymbol;
 // Parser for for .class files
 //
 // The bytes describing the class file structure is read from a Stream object
@@ -42,7 +43,7 @@
   bool _relax_verify;
   u2   _major_version;
   u2   _minor_version;
-  symbolHandle _class_name;
+  Symbol* _class_name;
   KlassHandle _host_klass;
   GrowableArray<Handle>* _cp_patches; // overrides for CP entries
 
@@ -73,7 +74,7 @@
                                   int length,
                                   Handle class_loader,
                                   Handle protection_domain,
-                                  symbolHandle class_name,
+                                  Symbol* class_name,
                                   TRAPS);
 
   // Field parsing
@@ -209,21 +210,21 @@
   }
 
   void throwIllegalSignature(
-      const char* type, symbolHandle name, symbolHandle sig, TRAPS);
+      const char* type, Symbol* name, Symbol* sig, TRAPS);
 
   bool is_supported_version(u2 major, u2 minor);
   bool has_illegal_visibility(jint flags);
 
   void verify_constantvalue(int constantvalue_index, int signature_index, constantPoolHandle cp, TRAPS);
   void verify_legal_utf8(const unsigned char* buffer, int length, TRAPS);
-  void verify_legal_class_name(symbolHandle name, TRAPS);
-  void verify_legal_field_name(symbolHandle name, TRAPS);
-  void verify_legal_method_name(symbolHandle name, TRAPS);
-  void verify_legal_field_signature(symbolHandle fieldname, symbolHandle signature, TRAPS);
-  int  verify_legal_method_signature(symbolHandle methodname, symbolHandle signature, TRAPS);
+  void verify_legal_class_name(Symbol* name, TRAPS);
+  void verify_legal_field_name(Symbol* name, TRAPS);
+  void verify_legal_method_name(Symbol* name, TRAPS);
+  void verify_legal_field_signature(Symbol* fieldname, Symbol* signature, TRAPS);
+  int  verify_legal_method_signature(Symbol* methodname, Symbol* signature, TRAPS);
   void verify_legal_class_modifiers(jint flags, TRAPS);
   void verify_legal_field_modifiers(jint flags, bool is_interface, TRAPS);
-  void verify_legal_method_modifiers(jint flags, bool is_interface, symbolHandle name, TRAPS);
+  void verify_legal_method_modifiers(jint flags, bool is_interface, Symbol* name, TRAPS);
   bool verify_unqualified_name(char* name, unsigned int length, int type);
   char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
   char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
@@ -272,21 +273,21 @@
   //
   // "parsed_name" is updated by this method, and is the name found
   // while parsing the stream.
-  instanceKlassHandle parseClassFile(symbolHandle name,
+  instanceKlassHandle parseClassFile(Symbol* name,
                                      Handle class_loader,
                                      Handle protection_domain,
-                                     symbolHandle& parsed_name,
+                                     TempNewSymbol& parsed_name,
                                      bool verify,
                                      TRAPS) {
     KlassHandle no_host_klass;
     return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, verify, THREAD);
   }
-  instanceKlassHandle parseClassFile(symbolHandle name,
+  instanceKlassHandle parseClassFile(Symbol* name,
                                      Handle class_loader,
                                      Handle protection_domain,
                                      KlassHandle host_klass,
                                      GrowableArray<Handle>* cp_patches,
-                                     symbolHandle& parsed_name,
+                                     TempNewSymbol& parsed_name,
                                      bool verify,
                                      TRAPS);
 
--- a/src/share/vm/classfile/classLoader.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/classLoader.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -41,7 +41,7 @@
 #include "oops/instanceKlass.hpp"
 #include "oops/instanceRefKlass.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jvm_misc.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/compilationPolicy.hpp"
@@ -752,11 +752,7 @@
     }
   }
   if (*top + n + sizeof(intptr_t) >= end) {
-    warning("\nThe shared miscellaneous data space is not large "
-            "enough to \npreload requested classes.  Use "
-            "-XX:SharedMiscDataSize= to increase \nthe initial "
-            "size of the miscellaneous data space.\n");
-    exit(2);
+    report_out_of_shared_space(SharedMiscData);
   }
 
   // Copy the table data (the strings) to the shared space.
@@ -875,9 +871,9 @@
 }
 
 
-instanceKlassHandle ClassLoader::load_classfile(symbolHandle h_name, TRAPS) {
+instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
   ResourceMark rm(THREAD);
-  EventMark m("loading class " INTPTR_FORMAT, (address)h_name());
+  EventMark m("loading class " INTPTR_FORMAT, (address)h_name);
   ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
 
   stringStream st;
@@ -912,7 +908,7 @@
     ClassFileParser parser(stream);
     Handle class_loader;
     Handle protection_domain;
-    symbolHandle parsed_name;
+    TempNewSymbol parsed_name = NULL;
     instanceKlassHandle result = parser.parseClassFile(h_name,
                                                        class_loader,
                                                        protection_domain,
@@ -1308,7 +1304,7 @@
       if (_compile_the_world_counter > CompileTheWorldStopAt) return;
 
       // Construct name without extension
-      symbolHandle sym = oopFactory::new_symbol_handle(buffer, CHECK);
+      TempNewSymbol sym = SymbolTable::new_symbol(buffer, CHECK);
       // Use loader to load and initialize class
       klassOop ik = SystemDictionary::resolve_or_null(sym, loader, Handle(), THREAD);
       instanceKlassHandle k (THREAD, ik);
@@ -1382,3 +1378,61 @@
 }
 
 #endif //PRODUCT
+
+// Please keep following two functions at end of this file. With them placed at top or in middle of the file,
+// they could get inlined by agressive compiler, an unknown trick, see bug 6966589.
+void PerfClassTraceTime::initialize() {
+  if (!UsePerfData) return;
+
+  if (_eventp != NULL) {
+    // increment the event counter
+    _eventp->inc();
+  }
+
+  // stop the current active thread-local timer to measure inclusive time
+  _prev_active_event = -1;
+  for (int i=0; i < EVENT_TYPE_COUNT; i++) {
+     if (_timers[i].is_active()) {
+       assert(_prev_active_event == -1, "should have only one active timer");
+       _prev_active_event = i;
+       _timers[i].stop();
+     }
+  }
+
+  if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) {
+    // start the inclusive timer if not recursively called
+    _t.start();
+  }
+
+  // start thread-local timer of the given event type
+   if (!_timers[_event_type].is_active()) {
+    _timers[_event_type].start();
+  }
+}
+
+PerfClassTraceTime::~PerfClassTraceTime() {
+  if (!UsePerfData) return;
+
+  // stop the thread-local timer as the event completes
+  // and resume the thread-local timer of the event next on the stack
+  _timers[_event_type].stop();
+  jlong selftime = _timers[_event_type].ticks();
+
+  if (_prev_active_event >= 0) {
+    _timers[_prev_active_event].start();
+  }
+
+  if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return;
+
+  // increment the counters only on the leaf call
+  _t.stop();
+  _timep->inc(_t.ticks());
+  if (_selftimep != NULL) {
+    _selftimep->inc(selftime);
+  }
+  // add all class loading related event selftime to the accumulated time counter
+  ClassLoader::perf_accumulated_time()->inc(selftime);
+
+  // reset the timer
+  _timers[_event_type].reset();
+}
--- a/src/share/vm/classfile/classLoader.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/classLoader.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -280,7 +280,7 @@
   }
 
   // Load individual .class file
-  static instanceKlassHandle load_classfile(symbolHandle h_name, TRAPS);
+  static instanceKlassHandle load_classfile(Symbol* h_name, TRAPS);
 
   // If the specified package has been loaded by the system, then returns
   // the name of the directory or ZIP file that the package was loaded from.
@@ -356,111 +356,57 @@
 // (i.e. only one event type) are active at a time even multiple PerfClassTraceTime
 // instances have been created as multiple events are happening.
 class PerfClassTraceTime {
-  public:
-    enum {
-       CLASS_LOAD   = 0,
-       PARSE_CLASS  = 1,
-       CLASS_LINK   = 2,
-       CLASS_VERIFY = 3,
-       CLASS_CLINIT = 4,
-       DEFINE_CLASS = 5,
-       EVENT_TYPE_COUNT = 6
-    };
-  protected:
-    // _t tracks time from initialization to destruction of this timer instance
-    // including time for all other event types, and recursive calls of this type.
-    // When a timer is called recursively, the elapsedTimer _t would not be used.
-    elapsedTimer     _t;
-    PerfLongCounter* _timep;
-    PerfLongCounter* _selftimep;
-    PerfLongCounter* _eventp;
-    // pointer to thread-local recursion counter and timer array
-    // The thread_local timers track cumulative time for specific event types
-    // exclusive of time for other event types, but including recursive calls
-    // of the same type.
-    int*             _recursion_counters;
-    elapsedTimer*    _timers;
-    int              _event_type;
-    int              _prev_active_event;
-
-  public:
-
-    inline PerfClassTraceTime(PerfLongCounter* timep,     /* counter incremented with inclusive time */
-                              PerfLongCounter* selftimep, /* counter incremented with exclusive time */
-                              PerfLongCounter* eventp,    /* event counter */
-                              int* recursion_counters,    /* thread-local recursion counter array */
-                              elapsedTimer* timers,       /* thread-local timer array */
-                              int type                    /* event type */ ) :
-        _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) {
-      initialize();
-    }
-
-    inline PerfClassTraceTime(PerfLongCounter* timep,     /* counter incremented with inclusive time */
-                              elapsedTimer* timers,       /* thread-local timer array */
-                              int type                    /* event type */ ) :
-        _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) {
-      initialize();
-    }
-
-    void initialize() {
-      if (!UsePerfData) return;
+ public:
+  enum {
+    CLASS_LOAD   = 0,
+    PARSE_CLASS  = 1,
+    CLASS_LINK   = 2,
+    CLASS_VERIFY = 3,
+    CLASS_CLINIT = 4,
+    DEFINE_CLASS = 5,
+    EVENT_TYPE_COUNT = 6
+  };
+ protected:
+  // _t tracks time from initialization to destruction of this timer instance
+  // including time for all other event types, and recursive calls of this type.
+  // When a timer is called recursively, the elapsedTimer _t would not be used.
+  elapsedTimer     _t;
+  PerfLongCounter* _timep;
+  PerfLongCounter* _selftimep;
+  PerfLongCounter* _eventp;
+  // pointer to thread-local recursion counter and timer array
+  // The thread_local timers track cumulative time for specific event types
+  // exclusive of time for other event types, but including recursive calls
+  // of the same type.
+  int*             _recursion_counters;
+  elapsedTimer*    _timers;
+  int              _event_type;
+  int              _prev_active_event;
 
-      if (_eventp != NULL) {
-        // increment the event counter
-        _eventp->inc();
-      }
+ public:
 
-      // stop the current active thread-local timer to measure inclusive time
-      _prev_active_event = -1;
-      for (int i=0; i < EVENT_TYPE_COUNT; i++) {
-         if (_timers[i].is_active()) {
-           assert(_prev_active_event == -1, "should have only one active timer");
-           _prev_active_event = i;
-           _timers[i].stop();
-         }
-      }
-
-      if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) {
-        // start the inclusive timer if not recursively called
-        _t.start();
-      }
-
-      // start thread-local timer of the given event type
-      if (!_timers[_event_type].is_active()) {
-        _timers[_event_type].start();
-      }
-    }
+  inline PerfClassTraceTime(PerfLongCounter* timep,     /* counter incremented with inclusive time */
+                            PerfLongCounter* selftimep, /* counter incremented with exclusive time */
+                            PerfLongCounter* eventp,    /* event counter */
+                            int* recursion_counters,    /* thread-local recursion counter array */
+                            elapsedTimer* timers,       /* thread-local timer array */
+                            int type                    /* event type */ ) :
+      _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) {
+    initialize();
+  }
 
-    inline void suspend() { _t.stop(); _timers[_event_type].stop(); }
-    inline void resume()  { _t.start(); _timers[_event_type].start(); }
-
-    ~PerfClassTraceTime() {
-      if (!UsePerfData) return;
-
-      // stop the thread-local timer as the event completes
-      // and resume the thread-local timer of the event next on the stack
-      _timers[_event_type].stop();
-      jlong selftime = _timers[_event_type].ticks();
-
-      if (_prev_active_event >= 0) {
-        _timers[_prev_active_event].start();
-      }
+  inline PerfClassTraceTime(PerfLongCounter* timep,     /* counter incremented with inclusive time */
+                            elapsedTimer* timers,       /* thread-local timer array */
+                            int type                    /* event type */ ) :
+      _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) {
+    initialize();
+  }
 
-      if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return;
+  inline void suspend() { _t.stop(); _timers[_event_type].stop(); }
+  inline void resume()  { _t.start(); _timers[_event_type].start(); }
 
-      // increment the counters only on the leaf call
-      _t.stop();
-      _timep->inc(_t.ticks());
-      if (_selftimep != NULL) {
-        _selftimep->inc(selftime);
-      }
-      // add all class loading related event selftime to the accumulated time counter
-      ClassLoader::perf_accumulated_time()->inc(selftime);
-
-      // reset the timer
-      _timers[_event_type].reset();
-    }
+  ~PerfClassTraceTime();
+  void initialize();
 };
 
-
 #endif // SHARE_VM_CLASSFILE_CLASSLOADER_HPP
--- a/src/share/vm/classfile/dictionary.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/dictionary.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -36,7 +36,7 @@
 
 
 Dictionary::Dictionary(int table_size)
-  : TwoOopHashtable(table_size, sizeof(DictionaryEntry)) {
+  : TwoOopHashtable<klassOop>(table_size, sizeof(DictionaryEntry)) {
   _current_class_index = 0;
   _current_class_entry = NULL;
 };
@@ -45,7 +45,7 @@
 
 Dictionary::Dictionary(int table_size, HashtableBucket* t,
                        int number_of_entries)
-  : TwoOopHashtable(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
+  : TwoOopHashtable<klassOop>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
   _current_class_index = 0;
   _current_class_entry = NULL;
 };
@@ -54,7 +54,7 @@
 DictionaryEntry* Dictionary::new_entry(unsigned int hash, klassOop klass,
                                        oop loader) {
   DictionaryEntry* entry;
-  entry = (DictionaryEntry*)Hashtable::new_entry(hash, klass);
+  entry = (DictionaryEntry*)Hashtable<klassOop>::new_entry(hash, klass);
   entry->set_loader(loader);
   entry->set_pd_set(NULL);
   return entry;
@@ -62,7 +62,7 @@
 
 
 DictionaryEntry* Dictionary::new_entry() {
-  DictionaryEntry* entry = (DictionaryEntry*)Hashtable::new_entry(0L, NULL);
+  DictionaryEntry* entry = (DictionaryEntry*)Hashtable<klassOop>::new_entry(0L, NULL);
   entry->set_loader(NULL);
   entry->set_pd_set(NULL);
   return entry;
@@ -76,7 +76,7 @@
     entry->set_pd_set(to_delete->next());
     delete to_delete;
   }
-  Hashtable::free_entry(entry);
+  Hashtable<klassOop>::free_entry(entry);
 }
 
 
@@ -298,7 +298,7 @@
     for (DictionaryEntry *probe = bucket(index);
                           probe != NULL;
                           probe = probe->next()) {
-      oop e = probe->klass();
+      klassOop e = probe->klass();
       oop class_loader = probe->loader();
       if (is_strongly_reachable(class_loader, e)) {
         blk->do_oop((oop*)probe->klass_addr());
@@ -421,11 +421,11 @@
 // also cast to volatile;  we do this to ensure store order is maintained
 // by the compilers.
 
-void Dictionary::add_klass(symbolHandle class_name, Handle class_loader,
+void Dictionary::add_klass(Symbol* class_name, Handle class_loader,
                            KlassHandle obj) {
   assert_locked_or_safepoint(SystemDictionary_lock);
   assert(obj() != NULL, "adding NULL obj");
-  assert(Klass::cast(obj())->name() == class_name(), "sanity check on name");
+  assert(Klass::cast(obj())->name() == class_name, "sanity check on name");
 
   unsigned int hash = compute_hash(class_name, class_loader);
   int index = hash_to_index(hash);
@@ -444,15 +444,14 @@
 // Callers should be aware that an entry could be added just after
 // _buckets[index] is read here, so the caller will not see the new entry.
 DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
-                                       symbolHandle class_name,
+                                       Symbol* class_name,
                                        Handle class_loader) {
-  symbolOop name_ = class_name();
-  oop loader_ = class_loader();
+  oop loader = class_loader();
   debug_only(_lookup_count++);
   for (DictionaryEntry* entry = bucket(index);
                         entry != NULL;
                         entry = entry->next()) {
-    if (entry->hash() == hash && entry->equals(name_, loader_)) {
+    if (entry->hash() == hash && entry->equals(class_name, loader)) {
       return entry;
     }
     debug_only(_lookup_length++);
@@ -461,7 +460,7 @@
 }
 
 
-klassOop Dictionary::find(int index, unsigned int hash, symbolHandle name,
+klassOop Dictionary::find(int index, unsigned int hash, Symbol* name,
                           Handle loader, Handle protection_domain, TRAPS) {
   DictionaryEntry* entry = get_entry(index, hash, name, loader);
   if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) {
@@ -473,7 +472,7 @@
 
 
 klassOop Dictionary::find_class(int index, unsigned int hash,
-                                symbolHandle name, Handle loader) {
+                                Symbol* name, Handle loader) {
   assert_locked_or_safepoint(SystemDictionary_lock);
   assert (index == index_for(name, loader), "incorrect index?");
 
@@ -486,7 +485,7 @@
 // that table is static.
 
 klassOop Dictionary::find_shared_class(int index, unsigned int hash,
-                                       symbolHandle name) {
+                                       Symbol* name) {
   assert (index == index_for(name, Handle()), "incorrect index?");
 
   DictionaryEntry* entry = get_entry(index, hash, name, Handle());
@@ -498,7 +497,7 @@
                                        instanceKlassHandle klass,
                                        Handle loader, Handle protection_domain,
                                        TRAPS) {
-  symbolHandle klass_name(THREAD, klass->name());
+  Symbol*  klass_name = klass->name();
   DictionaryEntry* entry = get_entry(index, hash, klass_name, loader);
 
   assert(entry != NULL,"entry must be present, we just created it");
@@ -513,7 +512,7 @@
 
 
 bool Dictionary::is_valid_protection_domain(int index, unsigned int hash,
-                                            symbolHandle name,
+                                            Symbol* name,
                                             Handle loader,
                                             Handle protection_domain) {
   DictionaryEntry* entry = get_entry(index, hash, name, loader);
@@ -545,7 +544,7 @@
     DictionaryEntry* p = master_list;
     master_list = master_list->next();
     p->set_next(NULL);
-    symbolHandle class_name (thread, instanceKlass::cast((klassOop)(p->klass()))->name());
+    Symbol* class_name = instanceKlass::cast((klassOop)(p->klass()))->name();
     unsigned int hash = compute_hash(class_name, Handle(thread, p->loader()));
     int index = hash_to_index(hash);
     p->set_hash(hash);
@@ -555,22 +554,22 @@
 }
 
 SymbolPropertyTable::SymbolPropertyTable(int table_size)
-  : Hashtable(table_size, sizeof(SymbolPropertyEntry))
+  : Hashtable<Symbol*>(table_size, sizeof(SymbolPropertyEntry))
 {
 }
 SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t,
                                          int number_of_entries)
-  : Hashtable(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
+  : Hashtable<Symbol*>(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
 {
 }
 
 
 SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash,
-                                                     symbolHandle sym,
+                                                     Symbol* sym,
                                                      intptr_t sym_mode) {
   assert(index == index_for(sym, sym_mode), "incorrect index?");
   for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
-    if (p->hash() == hash && p->symbol() == sym() && p->symbol_mode() == sym_mode) {
+    if (p->hash() == hash && p->symbol() == sym && p->symbol_mode() == sym_mode) {
       return p;
     }
   }
@@ -579,13 +578,13 @@
 
 
 SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash,
-                                                    symbolHandle sym, intptr_t sym_mode) {
+                                                    Symbol* sym, intptr_t sym_mode) {
   assert_locked_or_safepoint(SystemDictionary_lock);
   assert(index == index_for(sym, sym_mode), "incorrect index?");
   assert(find_entry(index, hash, sym, sym_mode) == NULL, "no double entry");
 
-  SymbolPropertyEntry* p = new_entry(hash, sym(), sym_mode);
-  Hashtable::add_entry(index, p);
+  SymbolPropertyEntry* p = new_entry(hash, sym, sym_mode);
+  Hashtable<Symbol*>::add_entry(index, p);
   return p;
 }
 
@@ -593,7 +592,6 @@
 void SymbolPropertyTable::oops_do(OopClosure* f) {
   for (int index = 0; index < table_size(); index++) {
     for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
-      f->do_oop((oop*) p->symbol_addr());
       if (p->property_oop() != NULL) {
         f->do_oop(p->property_oop_addr());
       }
--- a/src/share/vm/classfile/dictionary.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/dictionary.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -36,7 +36,7 @@
 // The data structure for the system dictionary (and the shared system
 // dictionary).
 
-class Dictionary : public TwoOopHashtable {
+class Dictionary : public TwoOopHashtable<klassOop> {
   friend class VMStructs;
 private:
   // current iteration index.
@@ -45,19 +45,19 @@
   static DictionaryEntry*       _current_class_entry;
 
   DictionaryEntry* get_entry(int index, unsigned int hash,
-                             symbolHandle name, Handle loader);
+                             Symbol* name, Handle loader);
 
   DictionaryEntry* bucket(int i) {
-    return (DictionaryEntry*)Hashtable::bucket(i);
+    return (DictionaryEntry*)Hashtable<klassOop>::bucket(i);
   }
 
   // The following method is not MT-safe and must be done under lock.
   DictionaryEntry** bucket_addr(int i) {
-    return (DictionaryEntry**)Hashtable::bucket_addr(i);
+    return (DictionaryEntry**)Hashtable<klassOop>::bucket_addr(i);
   }
 
   void add_entry(int index, DictionaryEntry* new_entry) {
-    Hashtable::add_entry(index, (HashtableEntry*)new_entry);
+    Hashtable<klassOop>::add_entry(index, (HashtableEntry<oop>*)new_entry);
   }
 
 
@@ -71,12 +71,12 @@
 
   void free_entry(DictionaryEntry* entry);
 
-  void add_klass(symbolHandle class_name, Handle class_loader,KlassHandle obj);
+  void add_klass(Symbol* class_name, Handle class_loader,KlassHandle obj);
 
   klassOop find_class(int index, unsigned int hash,
-                      symbolHandle name, Handle loader);
+                      Symbol* name, Handle loader);
 
-  klassOop find_shared_class(int index, unsigned int hash, symbolHandle name);
+  klassOop find_shared_class(int index, unsigned int hash, Symbol* name);
 
   // Compiler support
   klassOop try_get_next_class();
@@ -95,7 +95,7 @@
 
   // Classes loaded by the bootstrap loader are always strongly reachable.
   // If we're not doing class unloading, all classes are strongly reachable.
-  static bool is_strongly_reachable(oop class_loader, oop klass) {
+  static bool is_strongly_reachable(oop class_loader, klassOop klass) {
     assert (klass != NULL, "should have non-null klass");
     return (class_loader == NULL || !ClassUnloading);
   }
@@ -105,10 +105,10 @@
   bool do_unloading(BoolObjectClosure* is_alive);
 
   // Protection domains
-  klassOop find(int index, unsigned int hash, symbolHandle name,
+  klassOop find(int index, unsigned int hash, Symbol* name,
                 Handle loader, Handle protection_domain, TRAPS);
   bool is_valid_protection_domain(int index, unsigned int hash,
-                                  symbolHandle name, Handle class_loader,
+                                  Symbol* name, Handle class_loader,
                                   Handle protection_domain);
   void add_protection_domain(int index, unsigned int hash,
                              instanceKlassHandle klass, Handle loader,
@@ -147,7 +147,7 @@
 // An entry in the system dictionary, this describes a class as
 // { klassOop, loader, protection_domain }.
 
-class DictionaryEntry : public HashtableEntry {
+class DictionaryEntry : public HashtableEntry<klassOop> {
   friend class VMStructs;
  private:
   // Contains the set of approved protection domains that can access
@@ -166,11 +166,11 @@
   klassOop* klass_addr() { return (klassOop*)literal_addr(); }
 
   DictionaryEntry* next() const {
-    return (DictionaryEntry*)HashtableEntry::next();
+    return (DictionaryEntry*)HashtableEntry<klassOop>::next();
   }
 
   DictionaryEntry** next_addr() {
-    return (DictionaryEntry**)HashtableEntry::next_addr();
+    return (DictionaryEntry**)HashtableEntry<klassOop>::next_addr();
   }
 
   oop loader() const { return _loader; }
@@ -209,7 +209,7 @@
     }
   }
 
-  bool equals(symbolOop class_name, oop class_loader) const {
+  bool equals(Symbol* class_name, oop class_loader) const {
     klassOop klass = (klassOop)literal();
     return (instanceKlass::cast(klass)->name() == class_name &&
             _loader == class_loader);
@@ -226,9 +226,9 @@
   }
 };
 
-// Entry in a SymbolPropertyTable, mapping a single symbolOop
+// Entry in a SymbolPropertyTable, mapping a single Symbol*
 // to a managed and an unmanaged pointer.
-class SymbolPropertyEntry : public HashtableEntry {
+class SymbolPropertyEntry : public HashtableEntry<Symbol*> {
   friend class VMStructs;
  private:
   intptr_t _symbol_mode;  // secondary key
@@ -236,7 +236,7 @@
   address _property_data;
 
  public:
-  symbolOop symbol() const          { return (symbolOop) literal(); }
+  Symbol* symbol() const            { return literal(); }
 
   intptr_t symbol_mode() const      { return _symbol_mode; }
   void set_symbol_mode(intptr_t m)  { _symbol_mode = m; }
@@ -248,14 +248,13 @@
   void set_property_data(address p) { _property_data = p; }
 
   SymbolPropertyEntry* next() const {
-    return (SymbolPropertyEntry*)HashtableEntry::next();
+    return (SymbolPropertyEntry*)HashtableEntry<Symbol*>::next();
   }
 
   SymbolPropertyEntry** next_addr() {
-    return (SymbolPropertyEntry**)HashtableEntry::next_addr();
+    return (SymbolPropertyEntry**)HashtableEntry<Symbol*>::next_addr();
   }
 
-  oop* symbol_addr()                { return literal_addr(); }
   oop* property_oop_addr()          { return &_property_oop; }
 
   void print_on(outputStream* st) const {
@@ -279,16 +278,16 @@
 // A system-internal mapping of symbols to pointers, both managed
 // and unmanaged.  Used to record the auto-generation of each method
 // MethodHandle.invoke(S)T, for all signatures (S)T.
-class SymbolPropertyTable : public Hashtable {
+class SymbolPropertyTable : public Hashtable<Symbol*> {
   friend class VMStructs;
 private:
   SymbolPropertyEntry* bucket(int i) {
-    return (SymbolPropertyEntry*) Hashtable::bucket(i);
+    return (SymbolPropertyEntry*) Hashtable<Symbol*>::bucket(i);
   }
 
   // The following method is not MT-safe and must be done under lock.
   SymbolPropertyEntry** bucket_addr(int i) {
-    return (SymbolPropertyEntry**) Hashtable::bucket_addr(i);
+    return (SymbolPropertyEntry**) Hashtable<Symbol*>::bucket_addr(i);
   }
 
   void add_entry(int index, SymbolPropertyEntry* new_entry) {
@@ -298,8 +297,10 @@
     ShouldNotReachHere();
   }
 
-  SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol, intptr_t symbol_mode) {
-    SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol);
+  SymbolPropertyEntry* new_entry(unsigned int hash, Symbol* symbol, intptr_t symbol_mode) {
+    SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable<Symbol*>::new_entry(hash, symbol);
+    // Hashtable with Symbol* literal must increment and decrement refcount.
+    symbol->increment_refcount();
     entry->set_symbol_mode(symbol_mode);
     entry->set_property_oop(NULL);
     entry->set_property_data(NULL);
@@ -311,23 +312,25 @@
   SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries);
 
   void free_entry(SymbolPropertyEntry* entry) {
-    Hashtable::free_entry(entry);
+    // decrement Symbol refcount here because hashtable doesn't.
+    entry->literal()->decrement_refcount();
+    Hashtable<Symbol*>::free_entry(entry);
   }
 
-  unsigned int compute_hash(symbolHandle sym, intptr_t symbol_mode) {
+  unsigned int compute_hash(Symbol* sym, intptr_t symbol_mode) {
     // Use the regular identity_hash.
-    return Hashtable::compute_hash(sym) ^ symbol_mode;
+    return Hashtable<Symbol*>::compute_hash(sym) ^ symbol_mode;
   }
 
-  int index_for(symbolHandle name, intptr_t symbol_mode) {
+  int index_for(Symbol* name, intptr_t symbol_mode) {
     return hash_to_index(compute_hash(name, symbol_mode));
   }
 
   // need not be locked; no state change
-  SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode);
+  SymbolPropertyEntry* find_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode);
 
   // must be done under SystemDictionary_lock
-  SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode);
+  SymbolPropertyEntry* add_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode);
 
   // GC support
   void oops_do(OopClosure* f);
@@ -343,6 +346,4 @@
 #endif
   void verify();
 };
-
-
 #endif // SHARE_VM_CLASSFILE_DICTIONARY_HPP
--- a/src/share/vm/classfile/javaAssertions.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/javaAssertions.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -93,7 +93,7 @@
 }
 
 oop JavaAssertions::createAssertionStatusDirectives(TRAPS) {
-  symbolHandle asd_sym = vmSymbolHandles::java_lang_AssertionStatusDirectives();
+  Symbol* asd_sym = vmSymbols::java_lang_AssertionStatusDirectives();
   klassOop k = SystemDictionary::resolve_or_fail(asd_sym, true, CHECK_NULL);
   instanceKlassHandle asd_klass (THREAD, k);
   asd_klass->initialize(CHECK_NULL);
--- a/src/share/vm/classfile/javaClasses.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/javaClasses.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -36,7 +36,7 @@
 #include "oops/klass.hpp"
 #include "oops/klassOop.hpp"
 #include "oops/methodOop.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayOop.hpp"
 #include "runtime/fieldDescriptor.hpp"
 #include "runtime/handles.inline.hpp"
@@ -57,7 +57,7 @@
 #endif
 
 static bool find_field(instanceKlass* ik,
-                       symbolOop name_symbol, symbolOop signature_symbol,
+                       Symbol* name_symbol, Symbol* signature_symbol,
                        fieldDescriptor* fd,
                        bool allow_super = false) {
   if (allow_super)
@@ -69,7 +69,7 @@
 // Helpful routine for computing field offsets at run time rather than hardcoding them
 static void
 compute_offset(int &dest_offset,
-               klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol,
+               klassOop klass_oop, Symbol* name_symbol, Symbol* signature_symbol,
                bool allow_super = false) {
   fieldDescriptor fd;
   instanceKlass* ik = instanceKlass::cast(klass_oop);
@@ -84,7 +84,7 @@
 // Same as above but for "optional" offsets that might not be present in certain JDK versions
 static void
 compute_optional_offset(int& dest_offset,
-                        klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol,
+                        klassOop klass_oop, Symbol* name_symbol, Symbol* signature_symbol,
                         bool allow_super = false) {
   fieldDescriptor fd;
   instanceKlass* ik = instanceKlass::cast(klass_oop);
@@ -164,7 +164,7 @@
   return h_obj();
 }
 
-Handle java_lang_String::create_from_symbol(symbolHandle symbol, TRAPS) {
+Handle java_lang_String::create_from_symbol(Symbol* symbol, TRAPS) {
   int length = UTF8::unicode_length((char*)symbol->bytes(), symbol->utf8_length());
   Handle h_obj = basic_create(length, false, CHECK_NH);
   if (length > 0) {
@@ -278,17 +278,17 @@
   return result;
 }
 
-symbolHandle java_lang_String::as_symbol(Handle java_string, TRAPS) {
+Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) {
   oop          obj    = java_string();
   typeArrayOop value  = java_lang_String::value(obj);
   int          offset = java_lang_String::offset(obj);
   int          length = java_lang_String::length(obj);
   jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
-  symbolOop sym = SymbolTable::lookup_unicode(base, length, THREAD);
-  return symbolHandle(THREAD, sym);
+  Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD);
+  return sym;
 }
 
-symbolOop java_lang_String::as_symbol_or_null(oop java_string) {
+Symbol* java_lang_String::as_symbol_or_null(oop java_string) {
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
@@ -437,7 +437,7 @@
 
 void java_lang_Class::print_signature(oop java_class, outputStream* st) {
   assert(java_lang_Class::is_instance(java_class), "must be a Class object");
-  symbolOop name = NULL;
+  Symbol* name = NULL;
   bool is_instance = false;
   if (is_primitive(java_class)) {
     name = vmSymbols::type_signature(primitive_type(java_class));
@@ -455,25 +455,32 @@
   if (is_instance)  st->print(";");
 }
 
-symbolOop java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, TRAPS) {
+Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, TRAPS) {
   assert(java_lang_Class::is_instance(java_class), "must be a Class object");
-  symbolOop name = NULL;
+  Symbol* name;
   if (is_primitive(java_class)) {
-    return vmSymbols::type_signature(primitive_type(java_class));
+    name = vmSymbols::type_signature(primitive_type(java_class));
+    // Because this can create a new symbol, the caller has to decrement
+    // the refcount, so make adjustment here and below for symbols returned
+    // that are not created or incremented due to a successful lookup.
+    name->increment_refcount();
   } else {
     klassOop k = as_klassOop(java_class);
     if (!Klass::cast(k)->oop_is_instance()) {
-      return Klass::cast(k)->name();
+      name = Klass::cast(k)->name();
+      name->increment_refcount();
     } else {
       ResourceMark rm;
       const char* sigstr = Klass::cast(k)->signature_name();
       int         siglen = (int) strlen(sigstr);
-      if (!intern_if_not_found)
-        return SymbolTable::probe(sigstr, siglen);
-      else
-        return oopFactory::new_symbol(sigstr, siglen, THREAD);
+      if (!intern_if_not_found) {
+        name = SymbolTable::probe(sigstr, siglen);
+      } else {
+        name = SymbolTable::new_symbol(sigstr, siglen, THREAD);
+      }
     }
   }
+  return name;
 }
 
 
@@ -1022,8 +1029,8 @@
       JavaCalls::call_virtual(&result,
                               stream,
                               KlassHandle(THREAD, stream->klass()),
-                              vmSymbolHandles::println_name(),
-                              vmSymbolHandles::char_array_void_signature(),
+                              vmSymbols::println_name(),
+                              vmSymbols::char_array_void_signature(),
                               arg,
                               THREAD);
     }
@@ -1077,8 +1084,8 @@
       JavaCalls::call_virtual(&result,
                               h_throwable,
                               KlassHandle(THREAD, h_throwable->klass()),
-                              vmSymbolHandles::getCause_name(),
-                              vmSymbolHandles::void_throwable_signature(),
+                              vmSymbols::getCause_name(),
+                              vmSymbols::void_throwable_signature(),
                               THREAD);
       // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM.
       if (HAS_PENDING_EXCEPTION) {
@@ -1516,7 +1523,7 @@
   oop methodname = StringTable::intern(method->name(), CHECK_0);
   java_lang_StackTraceElement::set_methodName(element(), methodname);
   // Fill in source file name
-  symbolOop source = instanceKlass::cast(method->method_holder())->source_file_name();
+  Symbol* source = instanceKlass::cast(method->method_holder())->source_file_name();
   oop filename = StringTable::intern(source, CHECK_0);
   java_lang_StackTraceElement::set_fileName(element(), filename);
   // File in source line number
@@ -1732,7 +1739,7 @@
 
 Handle java_lang_reflect_Constructor::create(TRAPS) {
   assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
-  symbolHandle name = vmSymbolHandles::java_lang_reflect_Constructor();
+  Symbol* name = vmSymbols::java_lang_reflect_Constructor();
   klassOop k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH);
   instanceKlassHandle klass (THREAD, k);
   // Ensure it is initialized
@@ -1854,7 +1861,7 @@
 
 Handle java_lang_reflect_Field::create(TRAPS) {
   assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
-  symbolHandle name = vmSymbolHandles::java_lang_reflect_Field();
+  Symbol* name = vmSymbols::java_lang_reflect_Field();
   klassOop k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH);
   instanceKlassHandle klass (THREAD, k);
   // Ensure it is initialized
@@ -2422,16 +2429,19 @@
   java_lang_Class::print_signature(rtype(mt), st);
 }
 
-symbolOop java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) {
+Symbol* java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) {
   ResourceMark rm;
   stringStream buffer(128);
   print_signature(mt, &buffer);
   const char* sigstr =       buffer.base();
   int         siglen = (int) buffer.size();
-  if (!intern_if_not_found)
-    return SymbolTable::probe(sigstr, siglen);
-  else
-    return oopFactory::new_symbol(sigstr, siglen, THREAD);
+  Symbol *name;
+  if (!intern_if_not_found) {
+    name = SymbolTable::probe(sigstr, siglen);
+  } else {
+    name = SymbolTable::new_symbol(sigstr, siglen, THREAD);
+  }
+  return name;
 }
 
 oop java_dyn_MethodType::rtype(oop mt) {
@@ -2908,13 +2918,12 @@
 bool JavaClasses::check_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) {
   EXCEPTION_MARK;
   fieldDescriptor fd;
-  symbolHandle klass_sym = oopFactory::new_symbol_handle(klass_name, CATCH);
+  TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH);
   klassOop k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH);
   instanceKlassHandle h_klass (THREAD, k);
-  //instanceKlassHandle h_klass(klass);
-  symbolHandle f_name = oopFactory::new_symbol_handle(field_name, CATCH);
-  symbolHandle f_sig  = oopFactory::new_symbol_handle(field_sig, CATCH);
-  if (!h_klass->find_local_field(f_name(), f_sig(), &fd)) {
+  TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH);
+  TempNewSymbol f_sig  = SymbolTable::new_symbol(field_sig, CATCH);
+  if (!h_klass->find_local_field(f_name, f_sig, &fd)) {
     tty->print_cr("Nonstatic field %s.%s not found", klass_name, field_name);
     return false;
   }
@@ -2935,12 +2944,12 @@
 bool JavaClasses::check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) {
   EXCEPTION_MARK;
   fieldDescriptor fd;
-  symbolHandle klass_sym = oopFactory::new_symbol_handle(klass_name, CATCH);
+  TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH);
   klassOop k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH);
   instanceKlassHandle h_klass (THREAD, k);
-  symbolHandle f_name = oopFactory::new_symbol_handle(field_name, CATCH);
-  symbolHandle f_sig  = oopFactory::new_symbol_handle(field_sig, CATCH);
-  if (!h_klass->find_local_field(f_name(), f_sig(), &fd)) {
+  TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH);
+  TempNewSymbol f_sig  = SymbolTable::new_symbol(field_sig, CATCH);
+  if (!h_klass->find_local_field(f_name, f_sig, &fd)) {
     tty->print_cr("Static field %s.%s not found", klass_name, field_name);
     return false;
   }
@@ -2960,12 +2969,12 @@
 bool JavaClasses::check_constant(const char *klass_name, int hardcoded_constant, const char *field_name, const char* field_sig) {
   EXCEPTION_MARK;
   fieldDescriptor fd;
-  symbolHandle klass_sym = oopFactory::new_symbol_handle(klass_name, CATCH);
+  TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH);
   klassOop k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH);
   instanceKlassHandle h_klass (THREAD, k);
-  symbolHandle f_name = oopFactory::new_symbol_handle(field_name, CATCH);
-  symbolHandle f_sig  = oopFactory::new_symbol_handle(field_sig, CATCH);
-  if (!h_klass->find_local_field(f_name(), f_sig(), &fd)) {
+  TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH);
+  TempNewSymbol f_sig  = SymbolTable::new_symbol(field_sig, CATCH);
+  if (!h_klass->find_local_field(f_name, f_sig, &fd)) {
     tty->print_cr("Static field %s.%s not found", klass_name, field_name);
     return false;
   }
--- a/src/share/vm/classfile/javaClasses.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/javaClasses.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -78,7 +78,7 @@
   static oop    create_oop_from_unicode(jchar* unicode, int len, TRAPS);
   static Handle create_from_str(const char* utf8_str, TRAPS);
   static oop    create_oop_from_str(const char* utf8_str, TRAPS);
-  static Handle create_from_symbol(symbolHandle symbol, TRAPS);
+  static Handle create_from_symbol(Symbol* symbol, TRAPS);
   static Handle create_from_platform_dependent_str(const char* str, TRAPS);
   static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS);
 
@@ -116,8 +116,8 @@
   static Handle internalize_classname(Handle java_string, TRAPS) { return char_converter(java_string, '.', '/', THREAD); }
 
   // Conversion
-  static symbolHandle as_symbol(Handle java_string, TRAPS);
-  static symbolOop as_symbol_or_null(oop java_string);
+  static Symbol* as_symbol(Handle java_string, TRAPS);
+  static Symbol* as_symbol_or_null(oop java_string);
 
   // Testers
   static bool is_instance(oop obj) {
@@ -167,7 +167,7 @@
     (*reference_klass) = KlassHandle(refk_oop);
     return result;
   }
-  static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS);
+  static Symbol* as_signature(oop java_class, bool intern_if_not_found, TRAPS);
   static void print_signature(oop java_class, outputStream *st);
   // Testing
   static bool is_instance(oop obj) {
@@ -1039,7 +1039,7 @@
   static oop            ptype(oop mt, int index);
   static int            ptype_count(oop mt);
 
-  static symbolOop      as_signature(oop mt, bool intern_if_not_found, TRAPS);
+  static Symbol*        as_signature(oop mt, bool intern_if_not_found, TRAPS);
   static void           print_signature(oop mt, outputStream* st);
 
   static bool is_instance(oop obj) {
--- a/src/share/vm/classfile/loaderConstraints.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/loaderConstraints.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,28 +31,33 @@
 #include "utilities/hashtable.inline.hpp"
 
 LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
-  : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {};
+  : Hashtable<klassOop>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
 
 
 LoaderConstraintEntry* LoaderConstraintTable::new_entry(
-                                 unsigned int hash, symbolOop name,
+                                 unsigned int hash, Symbol* name,
                                  klassOop klass, int num_loaders,
                                  int max_loaders) {
   LoaderConstraintEntry* entry;
-  entry = (LoaderConstraintEntry*)Hashtable::new_entry(hash, klass);
+  entry = (LoaderConstraintEntry*)Hashtable<klassOop>::new_entry(hash, klass);
   entry->set_name(name);
   entry->set_num_loaders(num_loaders);
   entry->set_max_loaders(max_loaders);
   return entry;
 }
 
+void LoaderConstraintTable::free_entry(LoaderConstraintEntry *entry) {
+  // decrement name refcount before freeing
+  entry->name()->decrement_refcount();
+  Hashtable<klassOop>::free_entry(entry);
+}
+
 
 void LoaderConstraintTable::oops_do(OopClosure* f) {
   for (int index = 0; index < table_size(); index++) {
     for (LoaderConstraintEntry* probe = bucket(index);
                                 probe != NULL;
                                 probe = probe->next()) {
-      f->do_oop((oop*)(probe->name_addr()));
       if (probe->klass() != NULL) {
         f->do_oop((oop*)probe->klass_addr());
       }
@@ -65,27 +70,13 @@
   }
 }
 
-// We must keep the symbolOop used in the name alive.  We'll use the
-// loaders to decide if a particular entry can be purged.
-void LoaderConstraintTable::always_strong_classes_do(OopClosure* blk) {
-  // We must keep the symbolOop used in the name alive.
-  for (int cindex = 0; cindex < table_size(); cindex++) {
-    for (LoaderConstraintEntry* lc_probe = bucket(cindex);
-                                lc_probe != NULL;
-                                lc_probe = lc_probe->next()) {
-      assert (lc_probe->name() != NULL,  "corrupted loader constraint table");
-      blk->do_oop((oop*)lc_probe->name_addr());
-    }
-  }
-}
-
 
 // The loaderConstraintTable must always be accessed with the
 // SystemDictionary lock held. This is true even for readers as
 // entries in the table could be being dynamically resized.
 
 LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
-                                    symbolHandle name, Handle loader) {
+                                    Symbol* name, Handle loader) {
 
   unsigned int hash = compute_hash(name);
   int index = hash_to_index(hash);
@@ -93,7 +84,7 @@
   while (*pp) {
     LoaderConstraintEntry* p = *pp;
     if (p->hash() == hash) {
-      if (p->name() == name()) {
+      if (p->name() == name) {
         for (int i = p->num_loaders() - 1; i >= 0; i--) {
           if (p->loader(i) == loader()) {
             return pp;
@@ -177,7 +168,6 @@
         free_entry(probe);
       } else {
 #ifdef ASSERT
-        assert(is_alive->do_object_b(probe->name()), "name should be live");
         if (probe->klass() != NULL) {
           assert(is_alive->do_object_b(probe->klass()), "klass should be live");
         }
@@ -194,7 +184,7 @@
   }
 }
 
-bool LoaderConstraintTable::add_entry(symbolHandle class_name,
+bool LoaderConstraintTable::add_entry(Symbol* class_name,
                                       klassOop klass1, Handle class_loader1,
                                       klassOop klass2, Handle class_loader2) {
   int failure_code = 0; // encode different reasons for failing
@@ -233,7 +223,7 @@
         unsigned int hash = compute_hash(class_name);
         int index = hash_to_index(hash);
         LoaderConstraintEntry* p;
-        p = new_entry(hash, class_name(), klass, 2, 2);
+        p = new_entry(hash, class_name, klass, 2, 2);
         p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2));
         p->set_loader(0, class_loader1());
         p->set_loader(1, class_loader2());
@@ -244,7 +234,7 @@
           ResourceMark rm;
           tty->print("[Adding new constraint for name: %s, loader[0]: %s,"
                      " loader[1]: %s ]\n",
-                     class_name()->as_C_string(),
+                     class_name->as_C_string(),
                      SystemDictionary::loader_name(class_loader1()),
                      SystemDictionary::loader_name(class_loader2())
                      );
@@ -257,7 +247,7 @@
             ResourceMark rm;
             tty->print("[Setting class object in existing constraint for"
                        " name: %s and loader %s ]\n",
-                       class_name()->as_C_string(),
+                       class_name->as_C_string(),
                        SystemDictionary::loader_name(class_loader1())
                        );
           }
@@ -288,7 +278,7 @@
     }
     tty->print("[Failed to add constraint for name: %s, loader[0]: %s,"
                " loader[1]: %s, Reason: %s ]\n",
-               class_name()->as_C_string(),
+               class_name->as_C_string(),
                SystemDictionary::loader_name(class_loader1()),
                SystemDictionary::loader_name(class_loader2()),
                reason
@@ -303,14 +293,14 @@
 // violated
 bool LoaderConstraintTable::check_or_update(instanceKlassHandle k,
                                                    Handle loader,
-                                                   symbolHandle name) {
+                                                   Symbol* name) {
   LoaderConstraintEntry* p = *(find_loader_constraint(name, loader));
   if (p && p->klass() != NULL && p->klass() != k()) {
     if (TraceLoaderConstraints) {
       ResourceMark rm;
       tty->print("[Constraint check failed for name %s, loader %s: "
                  "the presented class object differs from that stored ]\n",
-                 name()->as_C_string(),
+                 name->as_C_string(),
                  SystemDictionary::loader_name(loader()));
     }
     return false;
@@ -321,7 +311,7 @@
         ResourceMark rm;
         tty->print("[Updating constraint for name %s, loader %s, "
                    "by setting class object ]\n",
-                   name()->as_C_string(),
+                   name->as_C_string(),
                    SystemDictionary::loader_name(loader()));
       }
     }
@@ -329,7 +319,7 @@
   }
 }
 
-klassOop LoaderConstraintTable::find_constrained_klass(symbolHandle name,
+klassOop LoaderConstraintTable::find_constrained_klass(Symbol* name,
                                                        Handle loader) {
   LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
   if (p != NULL && p->klass() != NULL)
@@ -442,11 +432,10 @@
     for (LoaderConstraintEntry* probe = bucket(cindex);
                                 probe != NULL;
                                 probe = probe->next()) {
-      guarantee(probe->name()->is_symbol(), "should be symbol");
       if (probe->klass() != NULL) {
         instanceKlass* ik = instanceKlass::cast(probe->klass());
         guarantee(ik->name() == probe->name(), "name should match");
-        symbolHandle name (thread, ik->name());
+        Symbol* name = ik->name();
         Handle loader(thread, ik->class_loader());
         unsigned int d_hash = dictionary->compute_hash(name, loader);
         int d_index = dictionary->hash_to_index(d_hash);
--- a/src/share/vm/classfile/loaderConstraints.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/loaderConstraints.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,7 +31,7 @@
 
 class LoaderConstraintEntry;
 
-class LoaderConstraintTable : public Hashtable {
+class LoaderConstraintTable : public Hashtable<klassOop> {
   friend class VMStructs;
 private:
 
@@ -40,39 +40,39 @@
     _nof_buckets            = 1009                     // number of buckets in hash table
   };
 
-  LoaderConstraintEntry** find_loader_constraint(symbolHandle name,
+  LoaderConstraintEntry** find_loader_constraint(Symbol* name,
                                                  Handle loader);
 
 public:
 
   LoaderConstraintTable(int nof_buckets);
 
-  LoaderConstraintEntry* new_entry(unsigned int hash, symbolOop name,
+  LoaderConstraintEntry* new_entry(unsigned int hash, Symbol* name,
                                    klassOop klass, int num_loaders,
                                    int max_loaders);
+  void free_entry(LoaderConstraintEntry *entry);
 
   LoaderConstraintEntry* bucket(int i) {
-    return (LoaderConstraintEntry*)Hashtable::bucket(i);
+    return (LoaderConstraintEntry*)Hashtable<klassOop>::bucket(i);
   }
 
   LoaderConstraintEntry** bucket_addr(int i) {
-    return (LoaderConstraintEntry**)Hashtable::bucket_addr(i);
+    return (LoaderConstraintEntry**)Hashtable<klassOop>::bucket_addr(i);
   }
 
   // GC support
   void oops_do(OopClosure* f);
-  void always_strong_classes_do(OopClosure* blk);
 
   // Check class loader constraints
-  bool add_entry(symbolHandle name, klassOop klass1, Handle loader1,
+  bool add_entry(Symbol* name, klassOop klass1, Handle loader1,
                                     klassOop klass2, Handle loader2);
 
   // Note:  The main entry point for this module is via SystemDictionary.
-  // SystemDictionary::check_signature_loaders(symbolHandle signature,
+  // SystemDictionary::check_signature_loaders(Symbol* signature,
   //                                           Handle loader1, Handle loader2,
   //                                           bool is_method, TRAPS)
 
-  klassOop find_constrained_klass(symbolHandle name, Handle loader);
+  klassOop find_constrained_klass(Symbol* name, Handle loader);
 
   // Class loader constraints
 
@@ -83,7 +83,7 @@
                                 LoaderConstraintEntry** pp2, klassOop klass);
 
   bool check_or_update(instanceKlassHandle k, Handle loader,
-                              symbolHandle name);
+                              Symbol* name);
 
 
   void purge_loader_constraints(BoolObjectClosure* is_alive);
@@ -94,34 +94,36 @@
 #endif
 };
 
-class LoaderConstraintEntry : public HashtableEntry {
+class LoaderConstraintEntry : public HashtableEntry<klassOop> {
   friend class VMStructs;
 private:
-  symbolOop              _name;                   // class name
+  Symbol*                _name;                   // class name
   int                    _num_loaders;
   int                    _max_loaders;
   oop*                   _loaders;                // initiating loaders
 
 public:
 
-  klassOop klass() { return (klassOop)literal(); }
-  klassOop* klass_addr() { return (klassOop*)literal_addr(); }
+  klassOop klass() { return literal(); }
+  klassOop* klass_addr() { return literal_addr(); }
   void set_klass(klassOop k) { set_literal(k); }
 
   LoaderConstraintEntry* next() {
-    return (LoaderConstraintEntry*)HashtableEntry::next();
+    return (LoaderConstraintEntry*)HashtableEntry<klassOop>::next();
   }
 
   LoaderConstraintEntry** next_addr() {
-    return (LoaderConstraintEntry**)HashtableEntry::next_addr();
+    return (LoaderConstraintEntry**)HashtableEntry<klassOop>::next_addr();
   }
   void set_next(LoaderConstraintEntry* next) {
-    HashtableEntry::set_next(next);
+    HashtableEntry<klassOop>::set_next(next);
   }
 
-  symbolOop name() { return _name; }
-  symbolOop* name_addr() { return &_name; }
-  void set_name(symbolOop name) { _name = name; }
+  Symbol* name() { return _name; }
+  void set_name(Symbol* name) {
+    _name = name;
+    if (name != NULL) name->increment_refcount();
+  }
 
   int num_loaders() { return _num_loaders; }
   void set_num_loaders(int i) { _num_loaders = i; }
--- a/src/share/vm/classfile/placeholders.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/placeholders.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,10 +31,12 @@
 
 // Placeholder methods
 
-PlaceholderEntry* PlaceholderTable::new_entry(int hash, symbolOop name,
+PlaceholderEntry* PlaceholderTable::new_entry(int hash, Symbol* name,
                                               oop loader, bool havesupername,
-                                              symbolOop supername) {
-  PlaceholderEntry* entry = (PlaceholderEntry*)Hashtable::new_entry(hash, name);
+                                              Symbol* supername) {
+  PlaceholderEntry* entry = (PlaceholderEntry*)Hashtable<Symbol*>::new_entry(hash, name);
+  // Hashtable with Symbol* literal must increment and decrement refcount.
+  name->increment_refcount();
   entry->set_loader(loader);
   entry->set_havesupername(havesupername);
   entry->set_supername(supername);
@@ -46,33 +48,40 @@
   return entry;
 }
 
+void PlaceholderTable::free_entry(PlaceholderEntry* entry) {
+  // decrement Symbol refcount here because Hashtable doesn't.
+  entry->literal()->decrement_refcount();
+  if (entry->supername() != NULL) entry->supername()->decrement_refcount();
+  Hashtable<Symbol*>::free_entry(entry);
+}
+
 
 // Placeholder objects represent classes currently being loaded.
 // All threads examining the placeholder table must hold the
 // SystemDictionary_lock, so we don't need special precautions
 // on store ordering here.
 void PlaceholderTable::add_entry(int index, unsigned int hash,
-                                 symbolHandle class_name, Handle class_loader,
-                                 bool havesupername, symbolHandle supername){
+                                 Symbol* class_name, Handle class_loader,
+                                 bool havesupername, Symbol* supername){
   assert_locked_or_safepoint(SystemDictionary_lock);
-  assert(!class_name.is_null(), "adding NULL obj");
+  assert(class_name != NULL, "adding NULL obj");
 
   // Both readers and writers are locked so it's safe to just
   // create the placeholder and insert it in the list without a membar.
-  PlaceholderEntry* entry = new_entry(hash, class_name(), class_loader(), havesupername, supername());
+  PlaceholderEntry* entry = new_entry(hash, class_name, class_loader(), havesupername, supername);
   add_entry(index, entry);
 }
 
 
 // Remove a placeholder object.
 void PlaceholderTable::remove_entry(int index, unsigned int hash,
-                                    symbolHandle class_name,
+                                    Symbol* class_name,
                                     Handle class_loader) {
   assert_locked_or_safepoint(SystemDictionary_lock);
   PlaceholderEntry** p = bucket_addr(index);
   while (*p) {
     PlaceholderEntry *probe = *p;
-    if (probe->hash() == hash && probe->equals(class_name(), class_loader())) {
+    if (probe->hash() == hash && probe->equals(class_name, class_loader())) {
       // Delete entry
       *p = probe->next();
       free_entry(probe);
@@ -83,29 +92,28 @@
 }
 
 PlaceholderEntry* PlaceholderTable::get_entry(int index, unsigned int hash,
-                                       symbolHandle class_name,
+                                       Symbol* class_name,
                                        Handle class_loader) {
   assert_locked_or_safepoint(SystemDictionary_lock);
 
-  symbolOop class_name_ = class_name();
   oop class_loader_ = class_loader();
 
   for (PlaceholderEntry *place_probe = bucket(index);
                          place_probe != NULL;
                          place_probe = place_probe->next()) {
     if (place_probe->hash() == hash &&
-        place_probe->equals(class_name_, class_loader_)) {
+        place_probe->equals(class_name, class_loader_)) {
       return place_probe;
     }
   }
   return NULL;
 }
 
-symbolOop PlaceholderTable::find_entry(int index, unsigned int hash,
-                                       symbolHandle class_name,
+Symbol* PlaceholderTable::find_entry(int index, unsigned int hash,
+                                       Symbol* class_name,
                                        Handle class_loader) {
   PlaceholderEntry* probe = get_entry(index, hash, class_name, class_loader);
-  return (probe? probe->klass(): symbolOop(NULL));
+  return (probe? probe->klassname(): (Symbol*)NULL);
 }
 
   // find_and_add returns probe pointer - old or new
@@ -113,7 +121,7 @@
   // If entry exists, reuse entry
   // For both, push SeenThread for classloadAction
   // if havesupername: this is used for circularity for instanceklass loading
-PlaceholderEntry* PlaceholderTable::find_and_add(int index, unsigned int hash, symbolHandle name, Handle loader, classloadAction action, symbolHandle supername, Thread* thread) {
+PlaceholderEntry* PlaceholderTable::find_and_add(int index, unsigned int hash, Symbol* name, Handle loader, classloadAction action, Symbol* supername, Thread* thread) {
   PlaceholderEntry* probe = get_entry(index, hash, name, loader);
   if (probe == NULL) {
     // Nothing found, add place holder
@@ -122,7 +130,7 @@
   } else {
     if (action == LOAD_SUPER) {
       probe->set_havesupername(true);
-      probe->set_supername(supername());
+      probe->set_supername(supername);
     }
   }
   if (probe) probe->add_seen_thread(thread, action);
@@ -145,7 +153,7 @@
 // Therefore - must always check SD first
 // Ignores the case where entry is not found
 void PlaceholderTable::find_and_remove(int index, unsigned int hash,
-                       symbolHandle name, Handle loader, Thread* thread) {
+                       Symbol* name, Handle loader, Thread* thread) {
     assert_locked_or_safepoint(SystemDictionary_lock);
     PlaceholderEntry *probe = get_entry(index, hash, name, loader);
     if (probe != NULL) {
@@ -158,7 +166,7 @@
   }
 
 PlaceholderTable::PlaceholderTable(int table_size)
-    : TwoOopHashtable(table_size, sizeof(PlaceholderEntry)) {
+    : TwoOopHashtable<Symbol*>(table_size, sizeof(PlaceholderEntry)) {
 }
 
 
@@ -174,26 +182,22 @@
 
 
 void PlaceholderEntry::oops_do(OopClosure* blk) {
-  assert(klass() != NULL, "should have a non-null klass");
-  blk->do_oop((oop*)klass_addr());
+  assert(klassname() != NULL, "should have a non-null klass");
   if (_loader != NULL) {
     blk->do_oop(loader_addr());
   }
-  if (_supername != NULL) {
-    blk->do_oop((oop*)supername_addr());
-  }
   if (_instanceKlass != NULL) {
     blk->do_oop((oop*)instanceKlass_addr());
   }
 }
 
 // do all entries in the placeholder table
-void PlaceholderTable::entries_do(void f(symbolOop, oop)) {
+void PlaceholderTable::entries_do(void f(Symbol*, oop)) {
   for (int index = 0; index < table_size(); index++) {
     for (PlaceholderEntry* probe = bucket(index);
                            probe != NULL;
                            probe = probe->next()) {
-      f(probe->klass(), probe->loader());
+      f(probe->klassname(), probe->loader());
     }
   }
 }
@@ -202,7 +206,7 @@
 #ifndef PRODUCT
 // Note, doesn't append a cr
 void PlaceholderEntry::print() const {
-  klass()->print_value();
+  klassname()->print_value();
   if (loader() != NULL) {
     tty->print(", loader ");
     loader()->print_value();
@@ -238,7 +242,6 @@
   guarantee(instanceKlass() == NULL
             || Klass::cast(instanceKlass())->oop_is_instance(),
             "checking type of instanceKlass result");
-  klass()->verify();
 }
 
 void PlaceholderTable::verify() {
--- a/src/share/vm/classfile/placeholders.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/placeholders.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -34,35 +34,36 @@
 // being loaded, as well as arrays of primitives.
 //
 
-class PlaceholderTable : public TwoOopHashtable {
+class PlaceholderTable : public TwoOopHashtable<Symbol*> {
   friend class VMStructs;
 
 public:
   PlaceholderTable(int table_size);
 
-  PlaceholderEntry* new_entry(int hash, symbolOop name, oop loader, bool havesupername, symbolOop supername);
+  PlaceholderEntry* new_entry(int hash, Symbol* name, oop loader, bool havesupername, Symbol* supername);
+  void free_entry(PlaceholderEntry* entry);
 
   PlaceholderEntry* bucket(int i) {
-    return (PlaceholderEntry*)Hashtable::bucket(i);
+    return (PlaceholderEntry*)Hashtable<Symbol*>::bucket(i);
   }
 
   PlaceholderEntry** bucket_addr(int i) {
-    return (PlaceholderEntry**)Hashtable::bucket_addr(i);
+    return (PlaceholderEntry**)Hashtable<Symbol*>::bucket_addr(i);
   }
 
   void add_entry(int index, PlaceholderEntry* new_entry) {
-    Hashtable::add_entry(index, (HashtableEntry*)new_entry);
+    Hashtable<Symbol*>::add_entry(index, (HashtableEntry<Symbol*>*)new_entry);
   }
 
-  void add_entry(int index, unsigned int hash, symbolHandle name,
-                Handle loader, bool havesupername, symbolHandle supername);
+  void add_entry(int index, unsigned int hash, Symbol* name,
+                Handle loader, bool havesupername, Symbol* supername);
 
-// This returns a symbolOop to match type for SystemDictionary
-  symbolOop find_entry(int index, unsigned int hash,
-                       symbolHandle name, Handle loader);
+  // This returns a Symbol* to match type for SystemDictionary
+  Symbol* find_entry(int index, unsigned int hash,
+                       Symbol* name, Handle loader);
 
   PlaceholderEntry* get_entry(int index, unsigned int hash,
-                       symbolHandle name, Handle loader);
+                       Symbol* name, Handle loader);
 
 // caller to create a placeholder entry must enumerate an action
 // caller claims ownership of that action
@@ -84,22 +85,22 @@
   // If no entry exists, add a placeholder entry and push SeenThread
   // If entry exists, reuse entry and push SeenThread for classloadAction
   PlaceholderEntry* find_and_add(int index, unsigned int hash,
-                                 symbolHandle name, Handle loader,
-                                 classloadAction action, symbolHandle supername,
+                                 Symbol* name, Handle loader,
+                                 classloadAction action, Symbol* supername,
                                  Thread* thread);
 
   void remove_entry(int index, unsigned int hash,
-                    symbolHandle name, Handle loader);
+                    Symbol* name, Handle loader);
 
 // Remove placeholder information
   void find_and_remove(int index, unsigned int hash,
-                       symbolHandle name, Handle loader, Thread* thread);
+                       Symbol* name, Handle loader, Thread* thread);
 
   // GC support.
   void oops_do(OopClosure* f);
 
   // JVMTI support
-  void entries_do(void f(symbolOop, oop));
+  void entries_do(void f(Symbol*, oop));
 
 #ifndef PRODUCT
   void print();
@@ -151,14 +152,14 @@
 // on store ordering here.
 // The system dictionary is the only user of this class.
 
-class PlaceholderEntry : public HashtableEntry {
+class PlaceholderEntry : public HashtableEntry<Symbol*> {
   friend class VMStructs;
 
 
  private:
   oop               _loader;        // initiating loader
   bool              _havesupername; // distinguish between null supername, and unknown
-  symbolOop         _supername;
+  Symbol*           _supername;
   Thread*           _definer;       // owner of define token
   klassOop          _instanceKlass; // instanceKlass from successful define
   SeenThread*       _superThreadQ;  // doubly-linked queue of Threads loading a superclass for this class
@@ -173,8 +174,7 @@
 
  public:
   // Simple accessors, used only by SystemDictionary
-  symbolOop          klass()               const { return (symbolOop)literal(); }
-  symbolOop*         klass_addr()          { return (symbolOop*)literal_addr(); }
+  Symbol*            klassname()           const { return literal(); }
 
   oop                loader()              const { return _loader; }
   void               set_loader(oop loader) { _loader = loader; }
@@ -183,9 +183,11 @@
   bool               havesupername()       const { return _havesupername; }
   void               set_havesupername(bool havesupername) { _havesupername = havesupername; }
 
-  symbolOop          supername()           const { return _supername; }
-  void               set_supername(symbolOop supername) { _supername = supername; }
-  symbolOop*         supername_addr()      { return &_supername; }
+  Symbol*            supername()           const { return _supername; }
+  void               set_supername(Symbol* supername) {
+    _supername = supername;
+    if (_supername != NULL) _supername->increment_refcount();
+  }
 
   Thread*            definer()             const {return _definer; }
   void               set_definer(Thread* definer) { _definer = definer; }
@@ -204,17 +206,17 @@
   void               set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }
 
   PlaceholderEntry* next() const {
-    return (PlaceholderEntry*)HashtableEntry::next();
+    return (PlaceholderEntry*)HashtableEntry<Symbol*>::next();
   }
 
   PlaceholderEntry** next_addr() {
-    return (PlaceholderEntry**)HashtableEntry::next_addr();
+    return (PlaceholderEntry**)HashtableEntry<Symbol*>::next_addr();
   }
 
   // Test for equality
   // Entries are unique for class/classloader name pair
-  bool equals(symbolOop class_name, oop class_loader) const {
-    return (klass() == class_name && loader() == class_loader);
+  bool equals(Symbol* class_name, oop class_loader) const {
+    return (klassname() == class_name && loader() == class_loader);
   }
 
   SeenThread* actionToQueue(PlaceholderTable::classloadAction action) {
--- a/src/share/vm/classfile/resolutionErrors.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/resolutionErrors.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -32,12 +32,12 @@
 
 // add new entry to the table
 void ResolutionErrorTable::add_entry(int index, unsigned int hash,
-                                     constantPoolHandle pool, int cp_index, symbolHandle error)
+                                     constantPoolHandle pool, int cp_index, Symbol* error)
 {
   assert_locked_or_safepoint(SystemDictionary_lock);
-  assert(!pool.is_null() && !error.is_null(), "adding NULL obj");
+  assert(!pool.is_null() && error != NULL, "adding NULL obj");
 
-  ResolutionErrorEntry* entry = new_entry(hash, pool(), cp_index, error());
+  ResolutionErrorEntry* entry = new_entry(hash, pool(), cp_index, error);
   add_entry(index, entry);
 }
 
@@ -57,20 +57,35 @@
   return NULL;
 }
 
+void ResolutionErrorEntry::set_error(Symbol* e) {
+  assert(e == NULL || _error == NULL, "cannot reset error");
+  _error = e;
+  if (_error != NULL) _error->increment_refcount();
+}
+
 // create new error entry
 ResolutionErrorEntry* ResolutionErrorTable::new_entry(int hash, constantPoolOop pool,
-                                                      int cp_index, symbolOop error)
+                                                      int cp_index, Symbol* error)
 {
-  ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable::new_entry(hash, pool);
+  ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<constantPoolOop>::new_entry(hash, pool);
   entry->set_cp_index(cp_index);
+  NOT_PRODUCT(entry->set_error(NULL);)
   entry->set_error(error);
 
   return entry;
 }
 
+void ResolutionErrorTable::free_entry(ResolutionErrorEntry *entry) {
+  // decrement error refcount
+  assert(entry->error() != NULL, "error should be set");
+  entry->error()->decrement_refcount();
+  Hashtable<constantPoolOop>::free_entry(entry);
+}
+
+
 // create resolution error table
 ResolutionErrorTable::ResolutionErrorTable(int table_size)
-    : Hashtable(table_size, sizeof(ResolutionErrorEntry)) {
+    : Hashtable<constantPoolOop>(table_size, sizeof(ResolutionErrorEntry)) {
 }
 
 // GC support
@@ -80,7 +95,7 @@
                            probe != NULL;
                            probe = probe->next()) {
       assert(probe->pool() != (constantPoolOop)NULL, "resolution error table is corrupt");
-      assert(probe->error() != (symbolOop)NULL, "resolution error table is corrupt");
+      assert(probe->error() != (Symbol*)NULL, "resolution error table is corrupt");
       probe->oops_do(f);
     }
   }
@@ -89,20 +104,6 @@
 // GC support
 void ResolutionErrorEntry::oops_do(OopClosure* blk) {
   blk->do_oop((oop*)pool_addr());
-  blk->do_oop((oop*)error_addr());
-}
-
-// We must keep the symbolOop used in the error alive. The constantPoolOop will
-// decide when the entry can be purged.
-void ResolutionErrorTable::always_strong_classes_do(OopClosure* blk) {
-  for (int i = 0; i < table_size(); i++) {
-    for (ResolutionErrorEntry* probe = bucket(i);
-                           probe != NULL;
-                           probe = probe->next()) {
-      assert(probe->error() != (symbolOop)NULL, "resolution error table is corrupt");
-      blk->do_oop((oop*)probe->error_addr());
-    }
-  }
 }
 
 // Remove unloaded entries from the table
--- a/src/share/vm/classfile/resolutionErrors.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/resolutionErrors.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -33,27 +33,28 @@
 // ResolutionError objects are used to record errors encountered during
 // constant pool resolution (JVMS 5.4.3).
 
-class ResolutionErrorTable : public Hashtable {
+class ResolutionErrorTable : public Hashtable<constantPoolOop> {
 
 public:
   ResolutionErrorTable(int table_size);
 
-  ResolutionErrorEntry* new_entry(int hash, constantPoolOop pool, int cp_index, symbolOop error);
+  ResolutionErrorEntry* new_entry(int hash, constantPoolOop pool, int cp_index, Symbol* error);
+  void free_entry(ResolutionErrorEntry *entry);
 
   ResolutionErrorEntry* bucket(int i) {
-    return (ResolutionErrorEntry*)Hashtable::bucket(i);
+    return (ResolutionErrorEntry*)Hashtable<constantPoolOop>::bucket(i);
   }
 
   ResolutionErrorEntry** bucket_addr(int i) {
-    return (ResolutionErrorEntry**)Hashtable::bucket_addr(i);
+    return (ResolutionErrorEntry**)Hashtable<constantPoolOop>::bucket_addr(i);
   }
 
   void add_entry(int index, ResolutionErrorEntry* new_entry) {
-    Hashtable::add_entry(index, (HashtableEntry*)new_entry);
+    Hashtable<constantPoolOop>::add_entry(index, (HashtableEntry<constantPoolOop>*)new_entry);
   }
 
   void add_entry(int index, unsigned int hash,
-                 constantPoolHandle pool, int which, symbolHandle error);
+                 constantPoolHandle pool, int which, Symbol* error);
 
 
   // find error given the constant pool and constant pool index
@@ -68,18 +69,15 @@
   // purges unloaded entries from the table
   void purge_resolution_errors(BoolObjectClosure* is_alive);
 
-  // this table keeps symbolOops alive
-  void always_strong_classes_do(OopClosure* blk);
-
   // GC support.
   void oops_do(OopClosure* f);
 };
 
 
-class ResolutionErrorEntry : public HashtableEntry {
+class ResolutionErrorEntry : public HashtableEntry<constantPoolOop> {
  private:
   int               _cp_index;
-  symbolOop         _error;
+  Symbol*           _error;
 
  public:
   constantPoolOop    pool() const               { return (constantPoolOop)literal(); }
@@ -88,16 +86,15 @@
   int                cp_index() const           { return _cp_index; }
   void               set_cp_index(int cp_index) { _cp_index = cp_index; }
 
-  symbolOop          error() const              { return _error; }
-  void               set_error(symbolOop e)     { _error = e; }
-  symbolOop*         error_addr()               { return &_error; }
+  Symbol*            error() const              { return _error; }
+  void               set_error(Symbol* e);
 
   ResolutionErrorEntry* next() const {
-    return (ResolutionErrorEntry*)HashtableEntry::next();
+    return (ResolutionErrorEntry*)HashtableEntry<constantPoolOop>::next();
   }
 
   ResolutionErrorEntry** next_addr() {
-    return (ResolutionErrorEntry**)HashtableEntry::next_addr();
+    return (ResolutionErrorEntry**)HashtableEntry<constantPoolOop>::next_addr();
   }
 
   // GC support
--- a/src/share/vm/classfile/stackMapFrame.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/stackMapFrame.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -27,7 +27,7 @@
 #include "classfile/verifier.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 #include "utilities/globalDefinitions.hpp"
 
@@ -90,8 +90,7 @@
 
 VerificationType StackMapFrame::set_locals_from_arg(
     const methodHandle m, VerificationType thisKlass, TRAPS) {
-  symbolHandle signature(THREAD, m->signature());
-  SignatureStream ss(signature);
+  SignatureStream ss(m->signature());
   int init_local_num = 0;
   if (!m->is_static()) {
     init_local_num++;
@@ -118,8 +117,14 @@
     case T_OBJECT:
     case T_ARRAY:
     {
-      symbolOop sig = ss.as_symbol(CHECK_(VerificationType::bogus_type()));
-      return VerificationType::reference_type(symbolHandle(THREAD, sig));
+      Symbol* sig = ss.as_symbol(CHECK_(VerificationType::bogus_type()));
+      // Create another symbol to save as signature stream unreferences
+      // this symbol.
+      Symbol* sig_copy =
+        verifier()->create_temporary_symbol(sig, 0, sig->utf8_length(),
+                                 CHECK_(VerificationType::bogus_type()));
+      assert(sig_copy == sig, "symbols don't match");
+      return VerificationType::reference_type(sig_copy);
     }
     case T_INT:     return VerificationType::integer_type();
     case T_BYTE:    return VerificationType::byte_type();
@@ -157,7 +162,7 @@
     VerificationType* from, VerificationType* to, int32_t len, TRAPS) const {
   for (int32_t i = 0; i < len; i++) {
     bool subtype = to[i].is_assignable_from(
-      from[i], verifier()->current_class(), THREAD);
+      from[i], verifier(), THREAD);
     if (!subtype) {
       return false;
     }
@@ -187,7 +192,7 @@
   }
   VerificationType top = _stack[--_stack_size];
   bool subtype = type.is_assignable_from(
-    top, verifier()->current_class(), CHECK_(VerificationType::bogus_type()));
+    top, verifier(), CHECK_(VerificationType::bogus_type()));
   if (!subtype) {
     verifier()->verify_error(_offset, "Bad type on operand stack");
     return VerificationType::bogus_type();
@@ -203,7 +208,7 @@
     return VerificationType::bogus_type();
   }
   bool subtype = type.is_assignable_from(_locals[index],
-    verifier()->current_class(), CHECK_(VerificationType::bogus_type()));
+    verifier(), CHECK_(VerificationType::bogus_type()));
   if (!subtype) {
     verifier()->verify_error(_offset, "Bad local variable type");
     return VerificationType::bogus_type();
@@ -221,9 +226,9 @@
     return;
   }
   bool subtype1 = type1.is_assignable_from(
-    _locals[index], verifier()->current_class(), CHECK);
+    _locals[index], verifier(), CHECK);
   bool subtype2 = type2.is_assignable_from(
-    _locals[index+1], verifier()->current_class(), CHECK);
+    _locals[index+1], verifier(), CHECK);
   if (!subtype1 || !subtype2) {
     verifier()->verify_error(_offset, "Bad local variable type");
     return;
--- a/src/share/vm/classfile/stackMapFrame.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/stackMapFrame.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -177,8 +177,7 @@
     if (_stack_size != 0) {
       VerificationType top = _stack[_stack_size - 1];
       bool subtype = type.is_assignable_from(
-        top, verifier()->current_class(),
-        CHECK_(VerificationType::bogus_type()));
+        top, verifier(), CHECK_(VerificationType::bogus_type()));
       if (subtype) {
         _stack_size --;
         NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
@@ -194,11 +193,9 @@
     assert(type2.is_long() || type2.is_double(), "must be long/double_2");
     if (_stack_size >= 2) {
       VerificationType top1 = _stack[_stack_size - 1];
-      bool subtype1 = type1.is_assignable_from(
-        top1, verifier()->current_class(), CHECK);
+      bool subtype1 = type1.is_assignable_from(top1, verifier(), CHECK);
       VerificationType top2 = _stack[_stack_size - 2];
-      bool subtype2 = type2.is_assignable_from(
-        top2, verifier()->current_class(), CHECK);
+      bool subtype2 = type2.is_assignable_from(top2, verifier(), CHECK);
       if (subtype1 && subtype2) {
         _stack_size -= 2;
         NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
--- a/src/share/vm/classfile/stackMapTable.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/stackMapTable.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -184,8 +184,7 @@
       _stream->stackmap_format_error("bad class index", THREAD);
       return VerificationType::bogus_type();
     }
-    return VerificationType::reference_type(
-      symbolHandle(THREAD, _cp->klass_name_at(class_index)));
+    return VerificationType::reference_type(_cp->klass_name_at(class_index));
   }
   if (tag == ITEM_UninitializedThis) {
     if (flags != NULL) {
--- a/src/share/vm/classfile/symbolTable.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/symbolTable.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,7 +31,6 @@
 #include "memory/gcLocker.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.inline2.hpp"
-#include "oops/symbolKlass.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "utilities/hashtable.inline.hpp"
 
@@ -39,14 +38,97 @@
 
 SymbolTable* SymbolTable::_the_table = NULL;
 
+Symbol* SymbolTable::allocate_symbol(const u1* name, int len, TRAPS) {
+  // Don't allow symbols to be created which cannot fit in a Symbol*.
+  if (len > Symbol::max_length()) {
+    THROW_MSG_0(vmSymbols::java_lang_InternalError(),
+                "name is too long to represent");
+  }
+  Symbol* sym = new (len) Symbol(name, len);
+  assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
+  return sym;
+}
+
+bool SymbolTable::allocate_symbols(int names_count, const u1** names,
+                                   int* lengths, Symbol** syms, TRAPS) {
+  for (int i = 0; i< names_count; i++) {
+    if (lengths[i] > Symbol::max_length()) {
+      THROW_MSG_0(vmSymbols::java_lang_InternalError(),
+                  "name is too long to represent");
+    }
+  }
+
+  for (int i = 0; i< names_count; i++) {
+    int len = lengths[i];
+    syms[i] = new (len) Symbol(names[i], len);
+    assert(syms[i] != NULL, "new should call vm_exit_out_of_memory if "
+                            "C_HEAP is exhausted");
+  }
+  return true;
+}
+
+// Call function for all symbols in the symbol table.
+void SymbolTable::symbols_do(SymbolClosure *cl) {
+  const int n = the_table()->table_size();
+  for (int i = 0; i < n; i++) {
+    for (HashtableEntry<Symbol*>* p = the_table()->bucket(i);
+         p != NULL;
+         p = p->next()) {
+      cl->do_symbol(p->literal_addr());
+    }
+  }
+}
+
+int SymbolTable::symbols_removed = 0;
+int SymbolTable::symbols_counted = 0;
+
+// Remove unreferenced symbols from the symbol table
+// This is done late during GC.  This doesn't use the hash table unlink because
+// it assumes that the literals are oops.
+void SymbolTable::unlink() {
+  int removed = 0;
+  int total = 0;
+  int memory_total = 0;
+  for (int i = 0; i < the_table()->table_size(); ++i) {
+    for (HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i); *p != NULL; ) {
+      HashtableEntry<Symbol*>* entry = *p;
+      if (entry->is_shared()) {
+        break;
+      }
+      Symbol* s = entry->literal();
+      memory_total += s->object_size();
+      total++;
+      assert(s != NULL, "just checking");
+      // If reference count is zero, remove.
+      if (s->refcount() == 0) {
+        delete s;
+        removed++;
+        *p = entry->next();
+        the_table()->free_entry(entry);
+      } else {
+        p = entry->next_addr();
+      }
+    }
+  }
+  symbols_removed += removed;
+  symbols_counted += total;
+  if (PrintGCDetails) {
+    gclog_or_tty->print(" [Symbols=%d size=%dK] ", total,
+                        (memory_total*HeapWordSize)/1024);
+  }
+}
+
+
 // Lookup a symbol in a bucket.
 
-symbolOop SymbolTable::lookup(int index, const char* name,
+Symbol* SymbolTable::lookup(int index, const char* name,
                               int len, unsigned int hash) {
-  for (HashtableEntry* e = bucket(index); e != NULL; e = e->next()) {
+  for (HashtableEntry<Symbol*>* e = bucket(index); e != NULL; e = e->next()) {
     if (e->hash() == hash) {
-      symbolOop sym = symbolOop(e->literal());
+      Symbol* sym = e->literal();
       if (sym->equals(name, len)) {
+        // something is referencing this symbol now.
+        sym->increment_refcount();
         return sym;
       }
     }
@@ -62,11 +144,11 @@
 // entries in the symbol table during normal execution (only during
 // safepoints).
 
-symbolOop SymbolTable::lookup(const char* name, int len, TRAPS) {
+Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) {
   unsigned int hashValue = hash_symbol(name, len);
   int index = the_table()->hash_to_index(hashValue);
 
-  symbolOop s = the_table()->lookup(index, name, len, hashValue);
+  Symbol* s = the_table()->lookup(index, name, len, hashValue);
 
   // Found
   if (s != NULL) return s;
@@ -75,7 +157,7 @@
   return the_table()->basic_add(index, (u1*)name, len, hashValue, CHECK_NULL);
 }
 
-symbolOop SymbolTable::lookup(symbolHandle sym, int begin, int end, TRAPS) {
+Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
   char* buffer;
   int index, len;
   unsigned int hashValue;
@@ -87,7 +169,7 @@
     len = end - begin;
     hashValue = hash_symbol(name, len);
     index = the_table()->hash_to_index(hashValue);
-    symbolOop s = the_table()->lookup(index, name, len, hashValue);
+    Symbol* s = the_table()->lookup(index, name, len, hashValue);
 
     // Found
     if (s != NULL) return s;
@@ -111,18 +193,19 @@
   return the_table()->basic_add(index, (u1*)buffer, len, hashValue, CHECK_NULL);
 }
 
-symbolOop SymbolTable::lookup_only(const char* name, int len,
+Symbol* SymbolTable::lookup_only(const char* name, int len,
                                    unsigned int& hash) {
   hash = hash_symbol(name, len);
   int index = the_table()->hash_to_index(hash);
 
-  return the_table()->lookup(index, name, len, hash);
+  Symbol* s = the_table()->lookup(index, name, len, hash);
+  return s;
 }
 
 // Suggestion: Push unicode-based lookup all the way into the hashing
 // and probing logic, so there is no need for convert_to_utf8 until
-// an actual new symbolOop is created.
-symbolOop SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) {
+// an actual new Symbol* is created.
+Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) {
   int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
   char stack_buf[128];
   if (utf8_length < (int) sizeof(stack_buf)) {
@@ -137,7 +220,7 @@
   }
 }
 
-symbolOop SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length,
+Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length,
                                            unsigned int& hash) {
   int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
   char stack_buf[128];
@@ -163,25 +246,23 @@
     // do it the hard way
     for (int i=0; i<names_count; i++) {
       int index = table->hash_to_index(hashValues[i]);
-      symbolOop sym = table->basic_add(index, (u1*)names[i], lengths[i],
+      Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i],
                                        hashValues[i], CHECK);
       cp->symbol_at_put(cp_indices[i], sym);
     }
   }
 }
 
-symbolOop SymbolTable::basic_add(int index, u1 *name, int len,
+Symbol* SymbolTable::basic_add(int index, u1 *name, int len,
                                  unsigned int hashValue, TRAPS) {
   assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
          "proposed name of symbol must be stable");
 
   // We assume that lookup() has been called already, that it failed,
   // and symbol was not found.  We create the symbol here.
-  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
-  symbolOop s_oop = sk->allocate_symbol(name, len, CHECK_NULL);
-  symbolHandle sym (THREAD, s_oop);
+  Symbol* sym = allocate_symbol(name, len, CHECK_NULL);
 
-  // Allocation must be done before grapping the SymbolTable_lock lock
+  // Allocation must be done before grabbing the SymbolTable_lock lock
   MutexLocker ml(SymbolTable_lock, THREAD);
 
   assert(sym->equals((char*)name, len), "symbol must be properly initialized");
@@ -189,51 +270,51 @@
   // Since look-up was done lock-free, we need to check if another
   // thread beat us in the race to insert the symbol.
 
-  symbolOop test = lookup(index, (char*)name, len, hashValue);
+  Symbol* test = lookup(index, (char*)name, len, hashValue);
   if (test != NULL) {
     // A race occurred and another thread introduced the symbol, this one
     // will be dropped and collected.
+    delete sym;
+    assert(test->refcount() != 0, "lookup should have incremented the count");
     return test;
   }
 
-  HashtableEntry* entry = new_entry(hashValue, sym());
+  HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym);
+  sym->increment_refcount();
   add_entry(index, entry);
-  return sym();
+  return sym;
 }
 
 bool SymbolTable::basic_add(constantPoolHandle cp, int names_count,
                             const char** names, int* lengths,
                             int* cp_indices, unsigned int* hashValues,
                             TRAPS) {
-  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
-  symbolOop sym_oops[symbol_alloc_batch_size];
-  bool allocated = sk->allocate_symbols(names_count, names, lengths,
-                                        sym_oops, CHECK_false);
+  Symbol* syms[symbol_alloc_batch_size];
+  bool allocated = allocate_symbols(names_count, (const u1**)names, lengths,
+                                    syms, CHECK_false);
   if (!allocated) {
     return false;
   }
-  symbolHandle syms[symbol_alloc_batch_size];
-  int i;
-  for (i=0; i<names_count; i++) {
-    syms[i] = symbolHandle(THREAD, sym_oops[i]);
-  }
 
   // Allocation must be done before grabbing the SymbolTable_lock lock
   MutexLocker ml(SymbolTable_lock, THREAD);
 
-  for (i=0; i<names_count; i++) {
+  for (int i=0; i<names_count; i++) {
     assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized");
     // Since look-up was done lock-free, we need to check if another
     // thread beat us in the race to insert the symbol.
     int index = hash_to_index(hashValues[i]);
-    symbolOop test = lookup(index, names[i], lengths[i], hashValues[i]);
+    Symbol* test = lookup(index, names[i], lengths[i], hashValues[i]);
     if (test != NULL) {
       // A race occurred and another thread introduced the symbol, this one
       // will be dropped and collected. Use test instead.
       cp->symbol_at_put(cp_indices[i], test);
+      assert(test->refcount() != 0, "lookup should have incremented the count");
+      delete syms[i];
     } else {
-      symbolOop sym = syms[i]();
-      HashtableEntry* entry = new_entry(hashValues[i], sym);
+      Symbol* sym = syms[i];
+      HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym);
+      sym->increment_refcount();  // increment refcount in external hashtable
       add_entry(index, entry);
       cp->symbol_at_put(cp_indices[i], sym);
     }
@@ -245,12 +326,10 @@
 
 void SymbolTable::verify() {
   for (int i = 0; i < the_table()->table_size(); ++i) {
-    HashtableEntry* p = the_table()->bucket(i);
+    HashtableEntry<Symbol*>* p = the_table()->bucket(i);
     for ( ; p != NULL; p = p->next()) {
-      symbolOop s = symbolOop(p->literal());
+      Symbol* s = (Symbol*)(p->literal());
       guarantee(s != NULL, "symbol is NULL");
-      s->verify();
-      guarantee(s->is_perm(), "symbol not in permspace");
       unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length());
       guarantee(p->hash() == h, "broken hash in symbol table entry");
       guarantee(the_table()->hash_to_index(h) == i,
@@ -279,10 +358,14 @@
   int total = 0;
   int max_symbols = 0;
   int out_of_range = 0;
+  int memory_total = 0;
+  int count = 0;
   for (i = 0; i < the_table()->table_size(); i++) {
-    HashtableEntry* p = the_table()->bucket(i);
+    HashtableEntry<Symbol*>* p = the_table()->bucket(i);
     for ( ; p != NULL; p = p->next()) {
-      int counter = symbolOop(p->literal())->utf8_length();
+      memory_total += p->literal()->object_size();
+      count++;
+      int counter = p->literal()->utf8_length();
       total += counter;
       if (counter < results_length) {
         results[counter]++;
@@ -293,6 +376,17 @@
     }
   }
   tty->print_cr("Symbol Table:");
+  tty->print_cr("Total number of symbols  %5d", count);
+  tty->print_cr("Total size in memory     %5dK",
+          (memory_total*HeapWordSize)/1024);
+  tty->print_cr("Total counted            %5d", symbols_counted);
+  tty->print_cr("Total removed            %5d", symbols_removed);
+  if (symbols_counted > 0) {
+    tty->print_cr("Percent removed          %3.2f",
+          ((float)symbols_removed/(float)symbols_counted)* 100);
+  }
+  tty->print_cr("Reference counts         %5d", Symbol::_total_count);
+  tty->print_cr("Histogram of symbol length:");
   tty->print_cr("%8s %5d", "Total  ", total);
   tty->print_cr("%8s %5d", "Maximum", max_symbols);
   tty->print_cr("%8s %3.2f", "Average",
@@ -304,22 +398,41 @@
       tty->print_cr("%6d %10d", i, results[i]);
     }
   }
-  int line_length = 70;
-  tty->print_cr("%s %30s", " Length", "Number chains that length");
-  for (i = 0; i < results_length; i++) {
-    if (results[i] > 0) {
-      tty->print("%4d", i);
-      for (j = 0; (j < results[i]) && (j < line_length);  j++) {
-        tty->print("%1s", "*");
+  if (Verbose) {
+    int line_length = 70;
+    tty->print_cr("%s %30s", " Length", "Number chains that length");
+    for (i = 0; i < results_length; i++) {
+      if (results[i] > 0) {
+        tty->print("%4d", i);
+        for (j = 0; (j < results[i]) && (j < line_length);  j++) {
+          tty->print("%1s", "*");
+        }
+        if (j == line_length) {
+          tty->print("%1s", "+");
+        }
+        tty->cr();
       }
-      if (j == line_length) {
-        tty->print("%1s", "+");
+    }
+  }
+  tty->print_cr(" %s %d: %d\n", "Number chains longer than",
+                    results_length, out_of_range);
+}
+
+void SymbolTable::print() {
+  for (int i = 0; i < the_table()->table_size(); ++i) {
+    HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i);
+    HashtableEntry<Symbol*>* entry = the_table()->bucket(i);
+    if (entry != NULL) {
+      while (entry != NULL) {
+        tty->print(PTR_FORMAT " ", entry->literal());
+        entry->literal()->print();
+        tty->print(" %d", entry->literal()->refcount());
+        p = entry->next_addr();
+        entry = (HashtableEntry<Symbol*>*)HashtableEntry<Symbol*>::make_ptr(*p);
       }
       tty->cr();
     }
   }
-  tty->print_cr(" %s %d: %d\n", "Number chains longer than",
-                    results_length, out_of_range);
 }
 
 #endif // PRODUCT
@@ -396,7 +509,7 @@
 
 oop StringTable::lookup(int index, jchar* name,
                         int len, unsigned int hash) {
-  for (HashtableEntry* l = bucket(index); l != NULL; l = l->next()) {
+  for (HashtableEntry<oop>* l = bucket(index); l != NULL; l = l->next()) {
     if (l->hash() == hash) {
       if (java_lang_String::equals(l->literal(), name, len)) {
         return l->literal();
@@ -436,13 +549,13 @@
     return test;
   }
 
-  HashtableEntry* entry = new_entry(hashValue, string());
+  HashtableEntry<oop>* entry = new_entry(hashValue, string());
   add_entry(index, entry);
   return string();
 }
 
 
-oop StringTable::lookup(symbolOop symbol) {
+oop StringTable::lookup(Symbol* symbol) {
   ResourceMark rm;
   int length;
   jchar* chars = symbol->as_unicode(length);
@@ -466,7 +579,7 @@
                                 hashValue, CHECK_NULL);
 }
 
-oop StringTable::intern(symbolOop symbol, TRAPS) {
+oop StringTable::intern(Symbol* symbol, TRAPS) {
   if (symbol == NULL) return NULL;
   ResourceMark rm(THREAD);
   int length;
@@ -500,9 +613,50 @@
   return result;
 }
 
+void StringTable::unlink(BoolObjectClosure* is_alive) {
+  // Readers of the table are unlocked, so we should only be removing
+  // entries at a safepoint.
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  for (int i = 0; i < the_table()->table_size(); ++i) {
+    for (HashtableEntry<oop>** p = the_table()->bucket_addr(i); *p != NULL; ) {
+      HashtableEntry<oop>* entry = *p;
+      if (entry->is_shared()) {
+        break;
+      }
+      assert(entry->literal() != NULL, "just checking");
+      if (is_alive->do_object_b(entry->literal())) {
+        p = entry->next_addr();
+      } else {
+        *p = entry->next();
+        the_table()->free_entry(entry);
+      }
+    }
+  }
+}
+
+void StringTable::oops_do(OopClosure* f) {
+  for (int i = 0; i < the_table()->table_size(); ++i) {
+    HashtableEntry<oop>** p = the_table()->bucket_addr(i);
+    HashtableEntry<oop>* entry = the_table()->bucket(i);
+    while (entry != NULL) {
+      f->do_oop((oop*)entry->literal_addr());
+
+      // Did the closure remove the literal from the table?
+      if (entry->literal() == NULL) {
+        assert(!entry->is_shared(), "immutable hashtable entry?");
+        *p = entry->next();
+        the_table()->free_entry(entry);
+      } else {
+        p = entry->next_addr();
+      }
+      entry = (HashtableEntry<oop>*)HashtableEntry<oop>::make_ptr(*p);
+    }
+  }
+}
+
 void StringTable::verify() {
   for (int i = 0; i < the_table()->table_size(); ++i) {
-    HashtableEntry* p = the_table()->bucket(i);
+    HashtableEntry<oop>* p = the_table()->bucket(i);
     for ( ; p != NULL; p = p->next()) {
       oop s = p->literal();
       guarantee(s != NULL, "interned string is NULL");
--- a/src/share/vm/classfile/symbolTable.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/symbolTable.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -26,11 +26,11 @@
 #define SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
 
 #include "memory/allocation.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "utilities/hashtable.hpp"
 
-// The symbol table holds all symbolOops and corresponding interned strings.
-// symbolOops and literal strings should be canonicalized.
+// The symbol table holds all Symbol*s and corresponding interned strings.
+// Symbol*s and literal strings should be canonicalized.
 //
 // The interned strings are created lazily.
 //
@@ -42,32 +42,76 @@
 class BoolObjectClosure;
 
 
-class SymbolTable : public Hashtable {
+// Class to hold a newly created or referenced Symbol* temporarily in scope.
+// new_symbol() and lookup() will create a Symbol* if not already in the
+// symbol table and add to the symbol's reference count.
+// probe() and lookup_only() will increment the refcount if symbol is found.
+class TempNewSymbol : public StackObj {
+  Symbol* _temp;
+
+ public:
+  TempNewSymbol() : _temp(NULL) {}
+  // Creating or looking up a symbol increments the symbol's reference count
+  TempNewSymbol(Symbol *s) : _temp(s) {}
+
+  // Operator= increments reference count.
+  void operator=(const TempNewSymbol &s) {
+    _temp = s._temp;
+    if (_temp !=NULL) _temp->increment_refcount();
+  }
+
+  // Decrement reference counter so it can go away if it's unique
+  ~TempNewSymbol() { if (_temp != NULL) _temp->decrement_refcount(); }
+
+  // Operators so they can be used like Symbols
+  Symbol* operator -> () const                   { return _temp; }
+  bool    operator == (Symbol* o) const          { return _temp == o; }
+  // Sneaky conversion function
+  operator Symbol*()                             { return _temp; }
+};
+
+class SymbolTable : public Hashtable<Symbol*> {
   friend class VMStructs;
+  friend class ClassFileParser;
 
 private:
   // The symbol table
   static SymbolTable* _the_table;
 
+  // For statistics
+  static int symbols_removed;
+  static int symbols_counted;
+
+  Symbol* allocate_symbol(const u1* name, int len, TRAPS);   // Assumes no characters larger than 0x7F
+  bool allocate_symbols(int names_count, const u1** names, int* lengths, Symbol** syms, TRAPS);
+
   // Adding elements
-  symbolOop basic_add(int index, u1* name, int len,
+  Symbol* basic_add(int index, u1* name, int len,
                       unsigned int hashValue, TRAPS);
   bool basic_add(constantPoolHandle cp, int names_count,
                  const char** names, int* lengths, int* cp_indices,
                  unsigned int* hashValues, TRAPS);
 
+  static void new_symbols(constantPoolHandle cp, int names_count,
+                          const char** name, int* lengths,
+                          int* cp_indices, unsigned int* hashValues,
+                          TRAPS) {
+    add(cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
+  }
+
+
   // Table size
   enum {
     symbol_table_size = 20011
   };
 
-  symbolOop lookup(int index, const char* name, int len, unsigned int hash);
+  Symbol* lookup(int index, const char* name, int len, unsigned int hash);
 
   SymbolTable()
-    : Hashtable(symbol_table_size, sizeof (HashtableEntry)) {}
+    : Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>)) {}
 
   SymbolTable(HashtableBucket* t, int number_of_entries)
-    : Hashtable(symbol_table_size, sizeof (HashtableEntry), t,
+    : Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>), t,
                 number_of_entries) {}
 
 
@@ -92,66 +136,76 @@
     _the_table = new SymbolTable(t, number_of_entries);
   }
 
-  static symbolOop lookup(const char* name, int len, TRAPS);
+  static Symbol* lookup(const char* name, int len, TRAPS);
   // lookup only, won't add. Also calculate hash.
-  static symbolOop lookup_only(const char* name, int len, unsigned int& hash);
+  static Symbol* lookup_only(const char* name, int len, unsigned int& hash);
   // Only copy to C string to be added if lookup failed.
-  static symbolOop lookup(symbolHandle sym, int begin, int end, TRAPS);
+  static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS);
+
+  static void release(Symbol* sym);
 
   // jchar (utf16) version of lookups
-  static symbolOop lookup_unicode(const jchar* name, int len, TRAPS);
-  static symbolOop lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
+  static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
+  static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
 
   static void add(constantPoolHandle cp, int names_count,
                   const char** names, int* lengths, int* cp_indices,
                   unsigned int* hashValues, TRAPS);
 
-  // GC support
-  //   Delete pointers to otherwise-unreachable objects.
-  static void unlink(BoolObjectClosure* cl) {
-    the_table()->Hashtable::unlink(cl);
+  // Release any dead symbols
+  static void unlink();
+
+  // iterate over symbols
+  static void symbols_do(SymbolClosure *cl);
+
+  // Symbol creation
+  static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) {
+    assert(utf8_buffer != NULL, "just checking");
+    return lookup(utf8_buffer, length, THREAD);
   }
-
-  // Invoke "f->do_oop" on the locations of all oops in the table.
-  static void oops_do(OopClosure* f) {
-    the_table()->Hashtable::oops_do(f);
+  static Symbol*       new_symbol(const char* name, TRAPS) {
+    return new_symbol(name, (int)strlen(name), THREAD);
+  }
+  static Symbol*       new_symbol(const Symbol* sym, int begin, int end, TRAPS) {
+    assert(begin <= end && end <= sym->utf8_length(), "just checking");
+    return lookup(sym, begin, end, THREAD);
   }
 
   // Symbol lookup
-  static symbolOop lookup(int index, const char* name, int len, TRAPS);
+  static Symbol* lookup(int index, const char* name, int len, TRAPS);
 
   // Needed for preloading classes in signatures when compiling.
   // Returns the symbol is already present in symbol table, otherwise
   // NULL.  NO ALLOCATION IS GUARANTEED!
-  static symbolOop probe(const char* name, int len) {
+  static Symbol* probe(const char* name, int len) {
     unsigned int ignore_hash;
     return lookup_only(name, len, ignore_hash);
   }
-  static symbolOop probe_unicode(const jchar* name, int len) {
+  static Symbol* probe_unicode(const jchar* name, int len) {
     unsigned int ignore_hash;
     return lookup_only_unicode(name, len, ignore_hash);
   }
 
   // Histogram
   static void print_histogram()     PRODUCT_RETURN;
+  static void print()     PRODUCT_RETURN;
 
   // Debugging
   static void verify();
 
   // Sharing
   static void copy_buckets(char** top, char*end) {
-    the_table()->Hashtable::copy_buckets(top, end);
+    the_table()->Hashtable<Symbol*>::copy_buckets(top, end);
   }
   static void copy_table(char** top, char*end) {
-    the_table()->Hashtable::copy_table(top, end);
+    the_table()->Hashtable<Symbol*>::copy_table(top, end);
   }
   static void reverse(void* boundary = NULL) {
-    ((Hashtable*)the_table())->reverse(boundary);
+    the_table()->Hashtable<Symbol*>::reverse(boundary);
   }
 };
 
-
-class StringTable : public Hashtable {
+class StringTable : public Hashtable<oop> {
   friend class VMStructs;
 
 private:
@@ -169,10 +223,10 @@
 
   oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
 
-  StringTable() : Hashtable(string_table_size, sizeof (HashtableEntry)) {}
+  StringTable() : Hashtable<oop>(string_table_size, sizeof (HashtableEntry<oop>)) {}
 
   StringTable(HashtableBucket* t, int number_of_entries)
-    : Hashtable(string_table_size, sizeof (HashtableEntry), t,
+    : Hashtable<oop>(string_table_size, sizeof (HashtableEntry<oop>), t,
                 number_of_entries) {}
 
 public:
@@ -192,26 +246,20 @@
     _the_table = new StringTable(t, number_of_entries);
   }
 
-
   static int hash_string(jchar* s, int len);
 
-
   // GC support
   //   Delete pointers to otherwise-unreachable objects.
-  static void unlink(BoolObjectClosure* cl) {
-    the_table()->Hashtable::unlink(cl);
-  }
+  static void unlink(BoolObjectClosure* cl);
 
   // Invoke "f->do_oop" on the locations of all oops in the table.
-  static void oops_do(OopClosure* f) {
-    the_table()->Hashtable::oops_do(f);
-  }
+  static void oops_do(OopClosure* f);
 
   // Probing
-  static oop lookup(symbolOop symbol);
+  static oop lookup(Symbol* symbol);
 
   // Interning
-  static oop intern(symbolOop symbol, TRAPS);
+  static oop intern(Symbol* symbol, TRAPS);
   static oop intern(oop string, TRAPS);
   static oop intern(const char *utf8_string, TRAPS);
 
@@ -220,13 +268,13 @@
 
   // Sharing
   static void copy_buckets(char** top, char*end) {
-    the_table()->Hashtable::copy_buckets(top, end);
+    the_table()->Hashtable<oop>::copy_buckets(top, end);
   }
   static void copy_table(char** top, char*end) {
-    the_table()->Hashtable::copy_table(top, end);
+    the_table()->Hashtable<oop>::copy_table(top, end);
   }
   static void reverse() {
-    ((BasicHashtable*)the_table())->reverse();
+    the_table()->Hashtable<oop>::reverse();
   }
 };
 
--- a/src/share/vm/classfile/systemDictionary.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/systemDictionary.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -93,8 +93,8 @@
   JavaValue result(T_OBJECT);
   JavaCalls::call_static(&result,
                          KlassHandle(THREAD, WK_KLASS(ClassLoader_klass)),
-                         vmSymbolHandles::getSystemClassLoader_name(),
-                         vmSymbolHandles::void_classloader_signature(),
+                         vmSymbols::getSystemClassLoader_name(),
+                         vmSymbols::void_classloader_signature(),
                          CHECK);
 
   _java_system_loader = (oop)result.get_jobject();
@@ -107,8 +107,8 @@
 #ifdef ASSERT
 
 // return true if class_name contains no '.' (internal format is '/')
-bool SystemDictionary::is_internal_format(symbolHandle class_name) {
-  if (class_name.not_null()) {
+bool SystemDictionary::is_internal_format(Symbol* class_name) {
+  if (class_name != NULL) {
     ResourceMark rm;
     char* name = class_name->as_C_string();
     return strchr(name, '.') == NULL;
@@ -141,7 +141,7 @@
 
 // Forwards to resolve_or_null
 
-klassOop SystemDictionary::resolve_or_fail(symbolHandle class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS) {
+klassOop SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS) {
   klassOop klass = resolve_or_null(class_name, class_loader, protection_domain, THREAD);
   if (HAS_PENDING_EXCEPTION || klass == NULL) {
     KlassHandle k_h(THREAD, klass);
@@ -151,7 +151,7 @@
   return klass;
 }
 
-klassOop SystemDictionary::handle_resolution_exception(symbolHandle class_name, Handle class_loader, Handle protection_domain, bool throw_error, KlassHandle klass_h, TRAPS) {
+klassOop SystemDictionary::handle_resolution_exception(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, KlassHandle klass_h, TRAPS) {
   if (HAS_PENDING_EXCEPTION) {
     // If we have a pending exception we forward it to the caller, unless throw_error is true,
     // in which case we have to check whether the pending exception is a ClassNotFoundException,
@@ -180,7 +180,7 @@
 }
 
 
-klassOop SystemDictionary::resolve_or_fail(symbolHandle class_name,
+klassOop SystemDictionary::resolve_or_fail(Symbol* class_name,
                                            bool throw_error, TRAPS)
 {
   return resolve_or_fail(class_name, Handle(), Handle(), throw_error, THREAD);
@@ -189,49 +189,50 @@
 
 // Forwards to resolve_instance_class_or_null
 
-klassOop SystemDictionary::resolve_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS) {
+klassOop SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) {
   // (tw) May we do this?
-  // assert(!THREAD->is_Compiler_thread(), "Can not load classes with the Compiler thread");
-  if (FieldType::is_array(class_name())) {
+  //assert(!THREAD->is_Compiler_thread(), "Can not load classes with the Compiler thread");
+  if (FieldType::is_array(class_name)) {
     return resolve_array_class_or_null(class_name, class_loader, protection_domain, CHECK_NULL);
+  } else if (FieldType::is_obj(class_name)) {
+    ResourceMark rm(THREAD);
+    // Ignore wrapping L and ;.
+    TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1,
+                                   class_name->utf8_length() - 2, CHECK_NULL);
+    return resolve_instance_class_or_null(name, class_loader, protection_domain, CHECK_NULL);
   } else {
     return resolve_instance_class_or_null(class_name, class_loader, protection_domain, CHECK_NULL);
   }
 }
 
-klassOop SystemDictionary::resolve_or_null(symbolHandle class_name, TRAPS) {
+klassOop SystemDictionary::resolve_or_null(Symbol* class_name, TRAPS) {
   return resolve_or_null(class_name, Handle(), Handle(), THREAD);
 }
 
 // Forwards to resolve_instance_class_or_null
 
-klassOop SystemDictionary::resolve_array_class_or_null(symbolHandle class_name,
+klassOop SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
                                                        Handle class_loader,
                                                        Handle protection_domain,
                                                        TRAPS) {
-  assert(FieldType::is_array(class_name()), "must be array");
-  jint dimension;
-  symbolOop object_key;
+  assert(FieldType::is_array(class_name), "must be array");
   klassOop k = NULL;
-  // dimension and object_key are assigned as a side-effect of this call
-  BasicType t = FieldType::get_array_info(class_name(),
-                                          &dimension,
-                                          &object_key,
-                                          CHECK_NULL);
-
+  FieldArrayInfo fd;
+  // dimension and object_key in FieldArrayInfo are assigned as a side-effect
+  // of this call
+  BasicType t = FieldType::get_array_info(class_name, fd, CHECK_NULL);
   if (t == T_OBJECT) {
-    symbolHandle h_key(THREAD, object_key);
     // naked oop "k" is OK here -- we assign back into it
-    k = SystemDictionary::resolve_instance_class_or_null(h_key,
+    k = SystemDictionary::resolve_instance_class_or_null(fd.object_key(),
                                                          class_loader,
                                                          protection_domain,
                                                          CHECK_NULL);
     if (k != NULL) {
-      k = Klass::cast(k)->array_klass(dimension, CHECK_NULL);
+      k = Klass::cast(k)->array_klass(fd.dimension(), CHECK_NULL);
     }
   } else {
     k = Universe::typeArrayKlassObj(t);
-    k = typeArrayKlass::cast(k)->array_klass(dimension, CHECK_NULL);
+    k = typeArrayKlass::cast(k)->array_klass(fd.dimension(), CHECK_NULL);
   }
   return k;
 }
@@ -272,8 +273,8 @@
 // Must be called, even if superclass is null, since this is
 // where the placeholder entry is created which claims this
 // thread is loading this class/classloader.
-klassOop SystemDictionary::resolve_super_or_fail(symbolHandle child_name,
-                                                 symbolHandle class_name,
+klassOop SystemDictionary::resolve_super_or_fail(Symbol* child_name,
+                                                 Symbol* class_name,
                                                  Handle class_loader,
                                                  Handle protection_domain,
                                                  bool is_superclass,
@@ -282,7 +283,7 @@
   // Try to get one of the well-known klasses.
   // They are trusted, and do not participate in circularities.
   if (LinkWellKnownClasses) {
-    klassOop k = find_well_known_klass(class_name());
+    klassOop k = find_well_known_klass(class_name);
     if (k != NULL) {
       return k;
     }
@@ -324,7 +325,7 @@
     if ((childk != NULL ) && (is_superclass) &&
        ((quicksuperk = instanceKlass::cast(childk)->super()) != NULL) &&
 
-         ((Klass::cast(quicksuperk)->name() == class_name()) &&
+         ((Klass::cast(quicksuperk)->name() == class_name) &&
             (Klass::cast(quicksuperk)->class_loader()  == class_loader()))) {
            return quicksuperk;
     } else {
@@ -343,7 +344,7 @@
   }
 
 // java.lang.Object should have been found above
-  assert(class_name() != NULL, "null super class for resolving");
+  assert(class_name != NULL, "null super class for resolving");
   // Resolve the super class or interface, check results on return
   klassOop superk = NULL;
   superk = SystemDictionary::resolve_or_null(class_name,
@@ -393,8 +394,8 @@
   JavaCalls::call_special(&result,
                          class_loader,
                          system_loader,
-                         vmSymbolHandles::checkPackageAccess_name(),
-                         vmSymbolHandles::class_protectiondomain_signature(),
+                         vmSymbols::checkPackageAccess_name(),
+                         vmSymbols::class_protectiondomain_signature(),
                          Handle(THREAD, klass->java_mirror()),
                          protection_domain,
                          THREAD);
@@ -415,7 +416,7 @@
   {
     // We recalculate the entry here -- we've called out to java since
     // the last time it was calculated.
-    symbolHandle kn(THREAD, klass->name());
+    Symbol*  kn = klass->name();
     unsigned int d_hash = dictionary()->compute_hash(kn, class_loader);
     int d_index = dictionary()->hash_to_index(d_hash);
 
@@ -490,7 +491,7 @@
 // and we are done,
 // If return null klassOop and no pending exception, the caller must load the class
 instanceKlassHandle SystemDictionary::handle_parallel_super_load(
-    symbolHandle name, symbolHandle superclassname, Handle class_loader,
+    Symbol* name, Symbol* superclassname, Handle class_loader,
     Handle protection_domain, Handle lockObject, TRAPS) {
 
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
@@ -579,17 +580,9 @@
 }
 
 
-klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS) {
-  assert(class_name.not_null() && !FieldType::is_array(class_name()), "invalid class name");
-  // First check to see if we should remove wrapping L and ;
-  symbolHandle name;
-  if (FieldType::is_obj(class_name())) {
-    ResourceMark rm(THREAD);
-    // Ignore wrapping L and ;.
-    name = oopFactory::new_symbol_handle(class_name()->as_C_string() + 1, class_name()->utf8_length() - 2, CHECK_NULL);
-  } else {
-    name = class_name;
-  }
+klassOop SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle class_loader, Handle protection_domain, TRAPS) {
+  assert(name != NULL && !FieldType::is_array(name) &&
+         !FieldType::is_obj(name), "invalid class name");
 
   // UseNewReflection
   // Fix for 4474172; see evaluation for more details
@@ -633,7 +626,7 @@
   bool havesupername = false;
   instanceKlassHandle k;
   PlaceholderEntry* placeholder;
-  symbolHandle superclassname;
+  Symbol* superclassname = NULL;
 
   {
     MutexLocker mu(SystemDictionary_lock, THREAD);
@@ -647,7 +640,7 @@
       if (placeholder && placeholder->super_load_in_progress()) {
          super_load_in_progress = true;
          if (placeholder->havesupername() == true) {
-           superclassname = symbolHandle(THREAD, placeholder->supername());
+           superclassname = placeholder->supername();
            havesupername = true;
          }
       }
@@ -692,7 +685,6 @@
     //    No performance benefit and no deadlock issues.
     // case 5. parallelCapable user level classloaders - without objectLocker
     //    Allow parallel classloading of a class/classloader pair
-    symbolHandle nullsymbolHandle;
     bool throw_circularity_error = false;
     {
       MutexLocker mu(SystemDictionary_lock, THREAD);
@@ -734,7 +726,7 @@
       // LOAD_INSTANCE in parallel
       // add placeholder entry even if error - callers will remove on error
       if (!throw_circularity_error && !class_has_been_loaded) {
-        PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, name, class_loader, PlaceholderTable::LOAD_INSTANCE, nullsymbolHandle, THREAD);
+        PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, name, class_loader, PlaceholderTable::LOAD_INSTANCE, NULL, THREAD);
         // For class loaders that do not acquire the classloader object lock,
         // if they did not catch another thread holding LOAD_INSTANCE,
         // need a check analogous to the acquire ObjectLocker/find_class
@@ -838,7 +830,7 @@
   {
     Handle loader (THREAD, k->class_loader());
     MutexLocker mu(SystemDictionary_lock, THREAD);
-    oop kk = find_class_or_placeholder(name, loader);
+    oop kk = find_class(name, loader);
     assert(kk == k(), "should be present in dictionary");
   }
 #endif
@@ -881,7 +873,7 @@
 // _dictionary->bucket(index) is read here, so the caller will not see
 // the new entry.
 
-klassOop SystemDictionary::find(symbolHandle class_name,
+klassOop SystemDictionary::find(Symbol* class_name,
                                 Handle class_loader,
                                 Handle protection_domain,
                                 TRAPS) {
@@ -911,37 +903,34 @@
 
 // Look for a loaded instance or array klass by name.  Do not do any loading.
 // return NULL in case of error.
-klassOop SystemDictionary::find_instance_or_array_klass(symbolHandle class_name,
+klassOop SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
                                                         Handle class_loader,
                                                         Handle protection_domain,
                                                         TRAPS) {
   klassOop k = NULL;
-  assert(class_name() != NULL, "class name must be non NULL");
+  assert(class_name != NULL, "class name must be non NULL");
 
   // Try to get one of the well-known klasses.
   if (LinkWellKnownClasses) {
-    k = find_well_known_klass(class_name());
+    k = find_well_known_klass(class_name);
     if (k != NULL) {
       return k;
     }
   }
 
-  if (FieldType::is_array(class_name())) {
+  if (FieldType::is_array(class_name)) {
     // The name refers to an array.  Parse the name.
-    jint dimension;
-    symbolOop object_key;
-
-    // dimension and object_key are assigned as a side-effect of this call
-    BasicType t = FieldType::get_array_info(class_name(), &dimension,
-                                            &object_key, CHECK_(NULL));
+    // dimension and object_key in FieldArrayInfo are assigned as a
+    // side-effect of this call
+    FieldArrayInfo fd;
+    BasicType t = FieldType::get_array_info(class_name, fd, CHECK_(NULL));
     if (t != T_OBJECT) {
       k = Universe::typeArrayKlassObj(t);
     } else {
-      symbolHandle h_key(THREAD, object_key);
-      k = SystemDictionary::find(h_key, class_loader, protection_domain, THREAD);
+      k = SystemDictionary::find(fd.object_key(), class_loader, protection_domain, THREAD);
     }
     if (k != NULL) {
-      k = Klass::cast(k)->array_klass_or_null(dimension);
+      k = Klass::cast(k)->array_klass_or_null(fd.dimension());
     }
   } else {
     k = find(class_name, class_loader, protection_domain, THREAD);
@@ -950,7 +939,7 @@
 }
 
 // Quick range check for names of well-known classes:
-static symbolOop wk_klass_name_limits[2] = {NULL, NULL};
+static Symbol* wk_klass_name_limits[2] = {NULL, NULL};
 
 #ifndef PRODUCT
 static int find_wkk_calls, find_wkk_probes, find_wkk_wins;
@@ -958,7 +947,7 @@
 //  => 60% hit after limit guard, 25% total win rate
 #endif
 
-klassOop SystemDictionary::find_well_known_klass(symbolOop class_name) {
+klassOop SystemDictionary::find_well_known_klass(Symbol* class_name) {
   // A bounds-check on class_name will quickly get a negative result.
   NOT_PRODUCT(find_wkk_calls++);
   if (class_name >= wk_klass_name_limits[0] &&
@@ -984,14 +973,14 @@
 // Note: this method is much like resolve_from_stream, but
 // updates no supplemental data structures.
 // TODO consolidate the two methods with a helper routine?
-klassOop SystemDictionary::parse_stream(symbolHandle class_name,
+klassOop SystemDictionary::parse_stream(Symbol* class_name,
                                         Handle class_loader,
                                         Handle protection_domain,
                                         ClassFileStream* st,
                                         KlassHandle host_klass,
                                         GrowableArray<Handle>* cp_patches,
                                         TRAPS) {
-  symbolHandle parsed_name;
+  TempNewSymbol parsed_name = NULL;
 
   // Parse the stream. Note that we do this even though this klass might
   // already be present in the SystemDictionary, otherwise we would not
@@ -1012,13 +1001,12 @@
                                                              true,
                                                              THREAD);
 
-
   // We don't redefine the class, so we just need to clean up whether there
   // was an error or not (don't want to modify any system dictionary
   // data structures).
   // Parsed name could be null if we threw an error before we got far
   // enough along to parse it -- in that case, there is nothing to clean up.
-  if (!parsed_name.is_null()) {
+  if (parsed_name != NULL) {
     unsigned int p_hash = placeholders()->compute_hash(parsed_name,
                                                        class_loader);
     int p_index = placeholders()->hash_to_index(p_hash);
@@ -1061,7 +1049,7 @@
 // Note: class_name can be NULL. In that case we do not know the name of
 // the class until we have parsed the stream.
 
-klassOop SystemDictionary::resolve_from_stream(symbolHandle class_name,
+klassOop SystemDictionary::resolve_from_stream(Symbol* class_name,
                                                Handle class_loader,
                                                Handle protection_domain,
                                                ClassFileStream* st,
@@ -1080,7 +1068,7 @@
   check_loader_lock_contention(lockObject, THREAD);
   ObjectLocker ol(lockObject, THREAD, DoObjectLock);
 
-  symbolHandle parsed_name;
+  TempNewSymbol parsed_name = NULL;
 
   // Parse the stream. Note that we do this even though this klass might
   // already be present in the SystemDictionary, otherwise we would not
@@ -1102,7 +1090,7 @@
   const char* pkg = "java/";
   if (!HAS_PENDING_EXCEPTION &&
       !class_loader.is_null() &&
-      !parsed_name.is_null() &&
+      parsed_name != NULL &&
       !strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
     // It is illegal to define classes in the "java." package from
     // JVM_DefineClass or jni_DefineClass unless you're the bootclassloader
@@ -1122,9 +1110,8 @@
   }
 
   if (!HAS_PENDING_EXCEPTION) {
-    assert(!parsed_name.is_null(), "Sanity");
-    assert(class_name.is_null() || class_name() == parsed_name(),
-           "name mismatch");
+    assert(parsed_name != NULL, "Sanity");
+    assert(class_name == NULL || class_name == parsed_name, "name mismatch");
     // Verification prevents us from creating names with dots in them, this
     // asserts that that's the case.
     assert(is_internal_format(parsed_name),
@@ -1145,7 +1132,7 @@
   // must make sure parsed_name is valid first (it won't be if we had
   // a format error before the class was parsed far enough to
   // find the name).
-  if (HAS_PENDING_EXCEPTION && !parsed_name.is_null()) {
+  if (HAS_PENDING_EXCEPTION && parsed_name != NULL) {
     unsigned int p_hash = placeholders()->compute_hash(parsed_name,
                                                        class_loader);
     int p_index = placeholders()->hash_to_index(p_hash);
@@ -1161,16 +1148,16 @@
   // SystemDictionary; this is only done on success
   debug_only( {
     if (!HAS_PENDING_EXCEPTION) {
-      assert(!parsed_name.is_null(), "parsed_name is still null?");
-      symbolHandle h_name   (THREAD, k->name());
+      assert(parsed_name != NULL, "parsed_name is still null?");
+      Symbol*  h_name    = k->name();
       Handle h_loader (THREAD, k->class_loader());
 
       MutexLocker mu(SystemDictionary_lock, THREAD);
 
-      oop check = find_class_or_placeholder(parsed_name, class_loader);
+      klassOop check = find_class(parsed_name, class_loader);
       assert(check == k(), "should be present in the dictionary");
 
-      oop check2 = find_class_or_placeholder(h_name, h_loader);
+      klassOop check2 = find_class(h_name, h_loader);
       assert(check == check2, "name inconsistancy in SystemDictionary");
     }
   } );
@@ -1190,7 +1177,7 @@
 // If there is a shared dictionary, then find the entry for the
 // given shared system class, if any.
 
-klassOop SystemDictionary::find_shared_class(symbolHandle class_name) {
+klassOop SystemDictionary::find_shared_class(Symbol* class_name) {
   if (shared_dictionary() != NULL) {
     unsigned int d_hash = dictionary()->compute_hash(class_name, Handle());
     int d_index = dictionary()->hash_to_index(d_hash);
@@ -1208,7 +1195,7 @@
 // object hierarchy until loaded.]
 
 instanceKlassHandle SystemDictionary::load_shared_class(
-                 symbolHandle class_name, Handle class_loader, TRAPS) {
+                 Symbol* class_name, Handle class_loader, TRAPS) {
   instanceKlassHandle ik (THREAD, find_shared_class(class_name));
   return load_shared_class(ik, class_loader, THREAD);
 }
@@ -1223,14 +1210,14 @@
   assert(class_loader.is_null(), "non-null classloader for shared class?");
   if (ik.not_null()) {
     instanceKlassHandle nh = instanceKlassHandle(); // null Handle
-    symbolHandle class_name(THREAD, ik->name());
+    Symbol*  class_name = ik->name();
 
     // Found the class, now load the superclass and interfaces.  If they
     // are shared, add them to the main system dictionary and reset
     // their hierarchy references (supers, subs, and interfaces).
 
     if (ik->super() != NULL) {
-      symbolHandle cn(THREAD, ik->super()->klass_part()->name());
+      Symbol*  cn = ik->super()->klass_part()->name();
       resolve_super_or_fail(class_name, cn,
                             class_loader, Handle(), true, CHECK_(nh));
     }
@@ -1244,7 +1231,7 @@
       // interfaces' instanceKlass's C++ vtbls haven't been
       // reinitialized yet (they will be once the interface classes
       // are loaded)
-      symbolHandle name (THREAD, k->klass_part()->name());
+      Symbol*  name  = k->klass_part()->name();
       resolve_super_or_fail(class_name, name, class_loader, Handle(), false, CHECK_(nh));
     }
 
@@ -1291,7 +1278,7 @@
 // Note that with delegation class loaders all classes in another loader will
 // first try to call this so it'd better be fast!!
 static instanceKlassHandle download_and_retry_class_load(
-                                                    symbolHandle class_name,
+                                                    Symbol* class_name,
                                                     TRAPS) {
 
   klassOop dlm = SystemDictionary::sun_jkernel_DownloadManager_klass();
@@ -1314,8 +1301,8 @@
     // public static String getBootClassPathEntryForClass(String className);
     JavaCalls::call_static(&result,
                        KlassHandle(THREAD, dlm),
-                       vmSymbolHandles::getBootClassPathEntryForClass_name(),
-                       vmSymbolHandles::string_string_signature(),
+                       vmSymbols::getBootClassPathEntryForClass_name(),
+                       vmSymbols::string_string_signature(),
                        class_string,
                        CHECK_(nk));
 
@@ -1345,7 +1332,7 @@
 #endif // KERNEL
 
 
-instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_name, Handle class_loader, TRAPS) {
+instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
   if (class_loader.is_null()) {
 
@@ -1420,16 +1407,16 @@
       JavaCalls::call_special(&result,
                               class_loader,
                               spec_klass,
-                              vmSymbolHandles::loadClassInternal_name(),
-                              vmSymbolHandles::string_class_signature(),
+                              vmSymbols::loadClassInternal_name(),
+                              vmSymbols::string_class_signature(),
                               string,
                               CHECK_(nh));
     } else {
       JavaCalls::call_virtual(&result,
                               class_loader,
                               spec_klass,
-                              vmSymbolHandles::loadClass_name(),
-                              vmSymbolHandles::string_class_signature(),
+                              vmSymbols::loadClass_name(),
+                              vmSymbols::string_class_signature(),
                               string,
                               CHECK_(nh));
     }
@@ -1445,7 +1432,7 @@
       // For user defined Java class loaders, check that the name returned is
       // the same as that requested.  This check is done for the bootstrap
       // loader when parsing the class file.
-      if (class_name() == k->name()) {
+      if (class_name == k->name()) {
         return k;
       }
     }
@@ -1478,7 +1465,7 @@
   // classloader lock held
   // Parallel classloaders will call find_or_define_instance_class
   // which will require a token to perform the define class
-  symbolHandle name_h(THREAD, k->name());
+  Symbol*  name_h = k->name();
   unsigned int d_hash = dictionary()->compute_hash(name_h, class_loader_h);
   int d_index = dictionary()->hash_to_index(d_hash);
   check_constraints(d_index, d_hash, k, class_loader_h, true, CHECK);
@@ -1537,10 +1524,10 @@
 // findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they
 // potentially waste time reading and parsing the bytestream.
 // Note: VM callers should ensure consistency of k/class_name,class_loader
-instanceKlassHandle SystemDictionary::find_or_define_instance_class(symbolHandle class_name, Handle class_loader, instanceKlassHandle k, TRAPS) {
+instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader, instanceKlassHandle k, TRAPS) {
 
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
-  symbolHandle name_h(THREAD, k->name()); // passed in class_name may be null
+  Symbol*  name_h = k->name(); // passed in class_name may be null
 
   unsigned int d_hash = dictionary()->compute_hash(name_h, class_loader);
   int d_index = dictionary()->hash_to_index(d_hash);
@@ -1561,8 +1548,7 @@
     }
 
     // Acquire define token for this class/classloader
-    symbolHandle nullsymbolHandle;
-    probe = placeholders()->find_and_add(p_index, p_hash, name_h, class_loader, PlaceholderTable::DEFINE_CLASS, nullsymbolHandle, THREAD);
+    probe = placeholders()->find_and_add(p_index, p_hash, name_h, class_loader, PlaceholderTable::DEFINE_CLASS, NULL, THREAD);
     // Wait if another thread defining in parallel
     // All threads wait - even those that will throw duplicate class: otherwise
     // caller is surprised by LinkageError: duplicate, but findLoadedClass fails
@@ -1654,7 +1640,7 @@
 // Lookup
 
 klassOop SystemDictionary::find_class(int index, unsigned int hash,
-                                      symbolHandle class_name,
+                                      Symbol* class_name,
                                       Handle class_loader) {
   assert_locked_or_safepoint(SystemDictionary_lock);
   assert (index == dictionary()->index_for(class_name, class_loader),
@@ -1666,18 +1652,17 @@
 
 
 // Basic find on classes in the midst of being loaded
-symbolOop SystemDictionary::find_placeholder(int index, unsigned int hash,
-                                             symbolHandle class_name,
-                                             Handle class_loader) {
+Symbol* SystemDictionary::find_placeholder(Symbol* class_name,
+                                           Handle class_loader) {
   assert_locked_or_safepoint(SystemDictionary_lock);
-
-  return placeholders()->find_entry(index, hash, class_name, class_loader);
+  unsigned int p_hash = placeholders()->compute_hash(class_name, class_loader);
+  int p_index = placeholders()->hash_to_index(p_hash);
+  return placeholders()->find_entry(p_index, p_hash, class_name, class_loader);
 }
 
 
 // Used for assertions and verification only
-oop SystemDictionary::find_class_or_placeholder(symbolHandle class_name,
-                                                Handle class_loader) {
+klassOop SystemDictionary::find_class(Symbol* class_name, Handle class_loader) {
   #ifndef ASSERT
   guarantee(VerifyBeforeGC   ||
             VerifyDuringGC   ||
@@ -1685,22 +1670,11 @@
             VerifyAfterGC, "too expensive");
   #endif
   assert_locked_or_safepoint(SystemDictionary_lock);
-  symbolOop class_name_ = class_name();
-  oop class_loader_ = class_loader();
 
   // First look in the loaded class array
   unsigned int d_hash = dictionary()->compute_hash(class_name, class_loader);
   int d_index = dictionary()->hash_to_index(d_hash);
-  oop lookup = find_class(d_index, d_hash, class_name, class_loader);
-
-  if (lookup == NULL) {
-    // Next try the placeholders
-    unsigned int p_hash = placeholders()->compute_hash(class_name,class_loader);
-    int p_index = placeholders()->hash_to_index(p_hash);
-    lookup = find_placeholder(p_index, p_hash, class_name, class_loader);
-  }
-
-  return lookup;
+  return find_class(d_index, d_hash, class_name, class_loader);
 }
 
 
@@ -1758,12 +1732,6 @@
 
   // Visit extra methods
   invoke_method_table()->oops_do(blk);
-
-  // Loader constraints. We must keep the symbolOop used in the name alive.
-  constraints()->always_strong_classes_do(blk);
-
-  // Resolution errors keep the symbolOop for the error alive
-  resolution_errors()->always_strong_classes_do(blk);
 }
 
 
@@ -1809,9 +1777,6 @@
 
 
 void SystemDictionary::preloaded_oops_do(OopClosure* f) {
-  f->do_oop((oop*) &wk_klass_name_limits[0]);
-  f->do_oop((oop*) &wk_klass_name_limits[1]);
-
   for (int k = (int)FIRST_WKID; k < (int)WKID_LIMIT; k++) {
     f->do_oop((oop*) &_well_known_klasses[k]);
   }
@@ -1863,7 +1828,7 @@
   dictionary()->classes_do(f, CHECK);
 }
 
-void SystemDictionary::placeholders_do(void f(symbolOop, oop)) {
+void SystemDictionary::placeholders_do(void f(Symbol*, oop)) {
   placeholders()->entries_do(f);
 }
 
@@ -1883,7 +1848,7 @@
   // class is loaded.
   klassOop aos = _abstract_ownable_synchronizer_klass;
   if (aos == NULL) {
-    klassOop k = resolve_or_fail(vmSymbolHandles::java_util_concurrent_locks_AbstractOwnableSynchronizer(), true, CHECK);
+    klassOop k = resolve_or_fail(vmSymbols::java_util_concurrent_locks_AbstractOwnableSynchronizer(), true, CHECK);
     // Force a fence to prevent any read before the write completes
     OrderAccess::fence();
     _abstract_ownable_synchronizer_klass = k;
@@ -1925,7 +1890,7 @@
   assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
   int  info = wk_init_info[id - FIRST_WKID];
   int  sid  = (info >> CEIL_LG_OPTION_LIMIT);
-  symbolHandle symbol = vmSymbolHandles::symbol_handle_at((vmSymbols::SID)sid);
+  Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
   klassOop*    klassp = &_well_known_klasses[id];
   bool must_load = (init_opt < SystemDictionary::Opt);
   bool try_load  = true;
@@ -1955,7 +1920,7 @@
     initialize_wk_klass((WKID)id, opt, CHECK);
 
     // Update limits, so find_well_known_klass can be very fast:
-    symbolOop s = vmSymbols::symbol_at((vmSymbols::SID)sid);
+    Symbol* s = vmSymbols::symbol_at((vmSymbols::SID)sid);
     if (wk_klass_name_limits[1] == NULL) {
       wk_klass_name_limits[0] = wk_klass_name_limits[1] = s;
     } else if (wk_klass_name_limits[1] < s) {
@@ -2082,7 +2047,7 @@
                                          TRAPS) {
   const char *linkage_error = NULL;
   {
-    symbolHandle name (THREAD, k->name());
+    Symbol*  name  = k->name();
     MutexLocker mu(SystemDictionary_lock, THREAD);
 
     klassOop check = find_class(d_index, d_hash, name, class_loader);
@@ -2103,10 +2068,8 @@
     }
 
 #ifdef ASSERT
-    unsigned int p_hash = placeholders()->compute_hash(name, class_loader);
-    int p_index = placeholders()->hash_to_index(p_hash);
-    symbolOop ph_check = find_placeholder(p_index, p_hash, name, class_loader);
-    assert(ph_check == NULL || ph_check == name(), "invalid symbol");
+    Symbol* ph_check = find_placeholder(name, class_loader);
+    assert(ph_check == NULL || ph_check == name, "invalid symbol");
 #endif
 
     if (linkage_error == NULL) {
@@ -2142,7 +2105,7 @@
                                          TRAPS) {
   // Compile_lock prevents systemDictionary updates during compilations
   assert_locked_or_safepoint(Compile_lock);
-  symbolHandle name (THREAD, k->name());
+  Symbol*  name  = k->name();
 
   {
   MutexLocker mu1(SystemDictionary_lock, THREAD);
@@ -2182,7 +2145,7 @@
 // while only one thread can define a class at one time, multiple
 // classes can resolve the superclass for a class at one time,
 // and the placeholder is used to track that
-//  symbolOop ph_check = find_placeholder(p_index, p_hash, name, class_loader);
+//  Symbol* ph_check = find_placeholder(name, class_loader);
 //  assert (ph_check == NULL, "should not have a placeholder entry");
 #endif
     SystemDictionary_lock->notify_all();
@@ -2191,7 +2154,7 @@
 
 
 klassOop SystemDictionary::find_constrained_instance_or_array_klass(
-                    symbolHandle class_name, Handle class_loader, TRAPS) {
+                    Symbol* class_name, Handle class_loader, TRAPS) {
 
   // First see if it has been loaded directly.
   // Force the protection domain to be null.  (This removes protection checks.)
@@ -2204,23 +2167,20 @@
   // Now look to see if it has been loaded elsewhere, and is subject to
   // a loader constraint that would require this loader to return the
   // klass that is already loaded.
-  if (FieldType::is_array(class_name())) {
+  if (FieldType::is_array(class_name)) {
     // For array classes, their klassOops are not kept in the
     // constraint table. The element klassOops are.
-    jint dimension;
-    symbolOop object_key;
-    BasicType t = FieldType::get_array_info(class_name(), &dimension,
-                                            &object_key, CHECK_(NULL));
+    FieldArrayInfo fd;
+    BasicType t = FieldType::get_array_info(class_name, fd, CHECK_(NULL));
     if (t != T_OBJECT) {
       klass = Universe::typeArrayKlassObj(t);
     } else {
-      symbolHandle elem_name(THREAD, object_key);
       MutexLocker mu(SystemDictionary_lock, THREAD);
-      klass = constraints()->find_constrained_klass(elem_name, class_loader);
+      klass = constraints()->find_constrained_klass(fd.object_key(), class_loader);
     }
     // If element class already loaded, allocate array klass
     if (klass != NULL) {
-      klass = Klass::cast(klass)->array_klass_or_null(dimension);
+      klass = Klass::cast(klass)->array_klass_or_null(fd.dimension());
     }
   } else {
     MutexLocker mu(SystemDictionary_lock, THREAD);
@@ -2232,25 +2192,23 @@
 }
 
 
-bool SystemDictionary::add_loader_constraint(symbolHandle class_name,
+bool SystemDictionary::add_loader_constraint(Symbol* class_name,
                                              Handle class_loader1,
                                              Handle class_loader2,
                                              Thread* THREAD) {
-  symbolHandle constraint_name;
-  if (!FieldType::is_array(class_name())) {
+  Symbol* constraint_name = NULL;
+  if (!FieldType::is_array(class_name)) {
     constraint_name = class_name;
   } else {
     // For array classes, their klassOops are not kept in the
     // constraint table. The element classes are.
-    jint dimension;
-    symbolOop object_key;
-    BasicType t = FieldType::get_array_info(class_name(), &dimension,
-                                            &object_key, CHECK_(false));
+    FieldArrayInfo fd;
+    BasicType t = FieldType::get_array_info(class_name, fd, CHECK_(false));
     // primitive types always pass
     if (t != T_OBJECT) {
       return true;
     } else {
-      constraint_name = symbolHandle(THREAD, object_key);
+      constraint_name = fd.object_key();
     }
   }
   unsigned int d_hash1 = dictionary()->compute_hash(constraint_name, class_loader1);
@@ -2273,7 +2231,7 @@
 
 // Add entry to resolution error table to record the error when the first
 // attempt to resolve a reference to a class has failed.
-void SystemDictionary::add_resolution_error(constantPoolHandle pool, int which, symbolHandle error) {
+void SystemDictionary::add_resolution_error(constantPoolHandle pool, int which, Symbol* error) {
   unsigned int hash = resolution_errors()->compute_hash(pool, which);
   int index = resolution_errors()->hash_to_index(hash);
   {
@@ -2283,13 +2241,13 @@
 }
 
 // Lookup resolution error table. Returns error if found, otherwise NULL.
-symbolOop SystemDictionary::find_resolution_error(constantPoolHandle pool, int which) {
+Symbol* SystemDictionary::find_resolution_error(constantPoolHandle pool, int which) {
   unsigned int hash = resolution_errors()->compute_hash(pool, which);
   int index = resolution_errors()->hash_to_index(hash);
   {
     MutexLocker ml(SystemDictionary_lock, Thread::current());
     ResolutionErrorEntry* entry = resolution_errors()->find_entry(index, hash, pool, which);
-    return (entry != NULL) ? entry->error() : (symbolOop)NULL;
+    return (entry != NULL) ? entry->error() : (Symbol*)NULL;
   }
 }
 
@@ -2345,7 +2303,7 @@
 // NULL if no constraint failed. The returned C string needs cleaning up
 // with a ResourceMark in the caller.  No exception except OOME is thrown.
 // Arrays are not added to the loader constraint table, their elements are.
-char* SystemDictionary::check_signature_loaders(symbolHandle signature,
+char* SystemDictionary::check_signature_loaders(Symbol* signature,
                                                Handle loader1, Handle loader2,
                                                bool is_method, TRAPS)  {
   // Nothing to do if loaders are the same.
@@ -2353,13 +2311,14 @@
     return NULL;
   }
 
+  ResourceMark rm(THREAD);
   SignatureStream sig_strm(signature, is_method);
   while (!sig_strm.is_done()) {
     if (sig_strm.is_object()) {
-      symbolOop s = sig_strm.as_symbol(CHECK_NULL);
-      symbolHandle sig (THREAD, s);
+      Symbol* s = sig_strm.as_symbol(CHECK_NULL);
+      Symbol*  sig  = s;
       if (!add_loader_constraint(sig, loader1, loader2, THREAD)) {
-        return sig()->as_C_string();
+        return sig->as_C_string();
       }
     }
     sig_strm.next();
@@ -2368,12 +2327,12 @@
 }
 
 
-methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name,
-                                                      symbolHandle signature,
+methodOop SystemDictionary::find_method_handle_invoke(Symbol* name,
+                                                      Symbol* signature,
                                                       KlassHandle accessing_klass,
                                                       TRAPS) {
   if (!EnableMethodHandles)  return NULL;
-  vmSymbols::SID name_id = vmSymbols::find_sid(name());
+  vmSymbols::SID name_id = vmSymbols::find_sid(name);
   assert(name_id != vmSymbols::NO_SID, "must be a known name");
   unsigned int hash  = invoke_method_table()->compute_hash(signature, name_id);
   int          index = invoke_method_table()->hash_to_index(hash);
@@ -2387,7 +2346,7 @@
     //  return NULL;              // do not attempt from within compiler
     bool for_invokeGeneric = (name_id == vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name));
     bool found_on_bcp = false;
-    Handle mt = find_method_handle_type(signature(), accessing_klass,
+    Handle mt = find_method_handle_type(signature, accessing_klass,
                                         for_invokeGeneric,
                                         found_on_bcp, CHECK_NULL);
     KlassHandle  mh_klass = SystemDictionaryHandles::MethodHandle_klass();
@@ -2418,7 +2377,7 @@
 // signature, as interpreted relative to the given class loader.
 // Because of class loader constraints, all method handle usage must be
 // consistent with this loader.
-Handle SystemDictionary::find_method_handle_type(symbolHandle signature,
+Handle SystemDictionary::find_method_handle_type(Symbol* signature,
                                                  KlassHandle accessing_klass,
                                                  bool for_invokeGeneric,
                                                  bool& return_bcp_flag,
@@ -2426,11 +2385,12 @@
   Handle class_loader, protection_domain;
   bool is_on_bcp = true;  // keep this true as long as we can materialize from the boot classloader
   Handle empty;
-  int npts = ArgumentCount(signature()).size();
+  int npts = ArgumentCount(signature).size();
   objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty));
   int arg = 0;
   Handle rt;                            // the return type from the signature
-  for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {
+  ResourceMark rm(THREAD);
+  for (SignatureStream ss(signature); !ss.is_done(); ss.next()) {
     oop mirror = NULL;
     if (is_on_bcp) {
       mirror = ss.as_java_mirror(class_loader, protection_domain,
@@ -2502,17 +2462,18 @@
 Handle SystemDictionary::link_method_handle_constant(KlassHandle caller,
                                                      int ref_kind, //e.g., JVM_REF_invokeVirtual
                                                      KlassHandle callee,
-                                                     symbolHandle name_sym,
-                                                     symbolHandle signature,
+                                                     Symbol* name_sym,
+                                                     Symbol* signature,
                                                      TRAPS) {
   Handle empty;
-  Handle name = java_lang_String::create_from_symbol(name_sym(), CHECK_(empty));
+  Handle name = java_lang_String::create_from_symbol(name_sym, CHECK_(empty));
   Handle type;
   if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') {
     bool ignore_is_on_bcp = false;
     type = find_method_handle_type(signature, caller, false, ignore_is_on_bcp, CHECK_(empty));
   } else {
-    SignatureStream ss(signature(), false);
+    ResourceMark rm(THREAD);
+    SignatureStream ss(signature, false);
     if (!ss.is_done()) {
       oop mirror = ss.as_java_mirror(caller->class_loader(), caller->protection_domain(),
                                      SignatureStream::NCDFError, CHECK_(empty));
@@ -2544,7 +2505,7 @@
 // Ask Java code to find or construct a java.dyn.CallSite for the given
 // name and signature, as interpreted relative to the given class loader.
 Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method,
-                                                symbolHandle name,
+                                                Symbol* name,
                                                 methodHandle signature_invoker,
                                                 Handle info,
                                                 methodHandle caller_method,
@@ -2559,7 +2520,7 @@
   MethodHandles::init_MemberName(caller_mname(), caller_method());
 
   // call sun.dyn.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos)
-  oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle!
+  oop name_str_oop = StringTable::intern(name, CHECK_(empty)); // not a handle!
   JavaCallArguments args(Handle(THREAD, bootstrap_method()));
   args.push_oop(name_str_oop);
   args.push_oop(signature_invoker->method_handle_type());
@@ -2742,16 +2703,20 @@
 
 
 void SystemDictionary::verify_obj_klass_present(Handle obj,
-                                                symbolHandle class_name,
+                                                Symbol* class_name,
                                                 Handle class_loader) {
   GCMutexLocker mu(SystemDictionary_lock);
-  oop probe = find_class_or_placeholder(class_name, class_loader);
+  Symbol* name;
+
+  klassOop probe = find_class(class_name, class_loader);
   if (probe == NULL) {
     probe = SystemDictionary::find_shared_class(class_name);
+    if (probe == NULL) {
+      name = find_placeholder(class_name, class_loader);
+    }
   }
-  guarantee(probe != NULL &&
-            (!probe->is_klass() || probe == obj()),
-                     "Loaded klasses should be in SystemDictionary");
+  guarantee(probe != NULL || name != NULL,
+            "Loaded klasses should be in SystemDictionary");
 }
 
 #ifndef PRODUCT
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,14 +28,14 @@
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
 #include "oops/objArrayOop.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/java.hpp"
 #include "runtime/reflectionUtils.hpp"
 #include "utilities/hashtable.hpp"
 
 // The system dictionary stores all loaded classes and maps:
 //
-//   [class name,class loader] -> class   i.e.  [symbolOop,oop] -> klassOop
+//   [class name,class loader] -> class   i.e.  [Symbol*,oop] -> klassOop
 //
 // Classes are loaded lazily. The default VM class loader is
 // represented as NULL.
@@ -172,6 +172,8 @@
                                                                               \
   template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
                                                                               \
+  template(sun_misc_PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt)       \
+                                                                              \
   /* Preload boxing klasses */                                                \
   template(Boolean_klass,                java_lang_Boolean,              Pre) \
   template(Character_klass,              java_lang_Character,            Pre) \
@@ -257,26 +259,26 @@
   // throw_error flag.  For most uses the throw_error argument should be set
   // to true.
 
-  static klassOop resolve_or_fail(symbolHandle class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS);
+  static klassOop resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS);
   // Convenient call for null loader and protection domain.
-  static klassOop resolve_or_fail(symbolHandle class_name, bool throw_error, TRAPS);
+  static klassOop resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS);
 private:
   // handle error translation for resolve_or_null results
-  static klassOop handle_resolution_exception(symbolHandle class_name, Handle class_loader, Handle protection_domain, bool throw_error, KlassHandle klass_h, TRAPS);
+  static klassOop handle_resolution_exception(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, KlassHandle klass_h, TRAPS);
 
 public:
 
   // Returns a class with a given class name and class loader.
   // Loads the class if needed. If not found NULL is returned.
-  static klassOop resolve_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
+  static klassOop resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS);
   // Version with null loader and protection domain
-  static klassOop resolve_or_null(symbolHandle class_name, TRAPS);
+  static klassOop resolve_or_null(Symbol* class_name, TRAPS);
 
   // Resolve a superclass or superinterface. Called from ClassFileParser,
   // parse_interfaces, resolve_instance_class_or_null, load_shared_class
   // "child_name" is the class whose super class or interface is being resolved.
-  static klassOop resolve_super_or_fail(symbolHandle child_name,
-                                        symbolHandle class_name,
+  static klassOop resolve_super_or_fail(Symbol* child_name,
+                                        Symbol* class_name,
                                         Handle class_loader,
                                         Handle protection_domain,
                                         bool is_superclass,
@@ -284,7 +286,7 @@
 
   // Parse new stream. This won't update the system dictionary or
   // class hierarchy, simply parse the stream. Used by JVMTI RedefineClasses.
-  static klassOop parse_stream(symbolHandle class_name,
+  static klassOop parse_stream(Symbol* class_name,
                                Handle class_loader,
                                Handle protection_domain,
                                ClassFileStream* st,
@@ -292,7 +294,7 @@
     KlassHandle nullHandle;
     return parse_stream(class_name, class_loader, protection_domain, st, nullHandle, NULL, THREAD);
   }
-  static klassOop parse_stream(symbolHandle class_name,
+  static klassOop parse_stream(Symbol* class_name,
                                Handle class_loader,
                                Handle protection_domain,
                                ClassFileStream* st,
@@ -301,23 +303,23 @@
                                TRAPS);
 
   // Resolve from stream (called by jni_DefineClass and JVM_DefineClass)
-  static klassOop resolve_from_stream(symbolHandle class_name, Handle class_loader,
+  static klassOop resolve_from_stream(Symbol* class_name, Handle class_loader,
                                       Handle protection_domain,
                                       ClassFileStream* st, bool verify, TRAPS);
 
   // Lookup an already loaded class. If not found NULL is returned.
-  static klassOop find(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
+  static klassOop find(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS);
 
   // Lookup an already loaded instance or array class.
   // Do not make any queries to class loaders; consult only the cache.
   // If not found NULL is returned.
-  static klassOop find_instance_or_array_klass(symbolHandle class_name,
+  static klassOop find_instance_or_array_klass(Symbol* class_name,
                                                Handle class_loader,
                                                Handle protection_domain,
                                                TRAPS);
 
   // If the given name is known to vmSymbols, return the well-know klass:
-  static klassOop find_well_known_klass(symbolOop class_name);
+  static klassOop find_well_known_klass(Symbol* class_name);
 
   // Lookup an instance or array class that has already been loaded
   // either into the given class loader, or else into another class
@@ -340,7 +342,7 @@
   // satisfied, and it is safe for classes in the given class loader
   // to manipulate strongly-typed values of the found class, subject
   // to local linkage and access checks.
-  static klassOop find_constrained_instance_or_array_klass(symbolHandle class_name,
+  static klassOop find_constrained_instance_or_array_klass(Symbol* class_name,
                                                            Handle class_loader,
                                                            TRAPS);
 
@@ -355,7 +357,7 @@
   //   (added for helpers that use HandleMarks and ResourceMarks)
   static void classes_do(void f(klassOop, oop, TRAPS), TRAPS);
   // All entries in the placeholder table and their class loaders
-  static void placeholders_do(void f(symbolOop, oop));
+  static void placeholders_do(void f(Symbol*, oop));
 
   // Iterate over all methods in all klasses in dictionary
   static void methods_do(void f(methodOop));
@@ -414,12 +416,12 @@
   static void verify();
 
 #ifdef ASSERT
-  static bool is_internal_format(symbolHandle class_name);
+  static bool is_internal_format(Symbol* class_name);
 #endif
 
   // Verify class is in dictionary
   static void verify_obj_klass_present(Handle obj,
-                                       symbolHandle class_name,
+                                       Symbol* class_name,
                                        Handle class_loader);
 
   // Initialization
@@ -500,19 +502,19 @@
   // Note:  java_lang_Class::primitive_type is the inverse of java_mirror
 
   // Check class loader constraints
-  static bool add_loader_constraint(symbolHandle name, Handle loader1,
+  static bool add_loader_constraint(Symbol* name, Handle loader1,
                                     Handle loader2, TRAPS);
-  static char* check_signature_loaders(symbolHandle signature, Handle loader1,
+  static char* check_signature_loaders(Symbol* signature, Handle loader1,
                                        Handle loader2, bool is_method, TRAPS);
 
   // JSR 292
   // find the java.dyn.MethodHandles::invoke method for a given signature
-  static methodOop find_method_handle_invoke(symbolHandle name,
-                                             symbolHandle signature,
+  static methodOop find_method_handle_invoke(Symbol* name,
+                                             Symbol* signature,
                                              KlassHandle accessing_klass,
                                              TRAPS);
   // ask Java to compute a java.dyn.MethodType object for a given signature
-  static Handle    find_method_handle_type(symbolHandle signature,
+  static Handle    find_method_handle_type(Symbol* signature,
                                            KlassHandle accessing_klass,
                                            bool for_invokeGeneric,
                                            bool& return_bcp_flag,
@@ -521,13 +523,13 @@
   static Handle    link_method_handle_constant(KlassHandle caller,
                                                int ref_kind, //e.g., JVM_REF_invokeVirtual
                                                KlassHandle callee,
-                                               symbolHandle name,
-                                               symbolHandle signature,
+                                               Symbol* name,
+                                               Symbol* signature,
                                                TRAPS);
   // ask Java to create a dynamic call site, while linking an invokedynamic op
   static Handle    make_dynamic_call_site(Handle bootstrap_method,
                                           // Callee information:
-                                          symbolHandle name,
+                                          Symbol* name,
                                           methodHandle signature_invoker,
                                           Handle info,
                                           // Caller information:
@@ -550,8 +552,8 @@
 
   // Record the error when the first attempt to resolve a reference from a constant
   // pool entry to a class fails.
-  static void add_resolution_error(constantPoolHandle pool, int which, symbolHandle error);
-  static symbolOop find_resolution_error(constantPoolHandle pool, int which);
+  static void add_resolution_error(constantPoolHandle pool, int which, Symbol* error);
+  static Symbol* find_resolution_error(constantPoolHandle pool, int which);
 
  private:
 
@@ -611,29 +613,29 @@
   static SymbolPropertyTable* invoke_method_table() { return _invoke_method_table; }
 
   // Basic loading operations
-  static klassOop resolve_instance_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
-  static klassOop resolve_array_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
-  static instanceKlassHandle handle_parallel_super_load(symbolHandle class_name, symbolHandle supername, Handle class_loader, Handle protection_domain, Handle lockObject, TRAPS);
+  static klassOop resolve_instance_class_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS);
+  static klassOop resolve_array_class_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS);
+  static instanceKlassHandle handle_parallel_super_load(Symbol* class_name, Symbol* supername, Handle class_loader, Handle protection_domain, Handle lockObject, TRAPS);
   // Wait on SystemDictionary_lock; unlocks lockObject before
   // waiting; relocks lockObject with correct recursion count
   // after waiting, but before reentering SystemDictionary_lock
   // to preserve lock order semantics.
   static void double_lock_wait(Handle lockObject, TRAPS);
   static void define_instance_class(instanceKlassHandle k, TRAPS);
-  static instanceKlassHandle find_or_define_instance_class(symbolHandle class_name,
+  static instanceKlassHandle find_or_define_instance_class(Symbol* class_name,
                                                 Handle class_loader,
                                                 instanceKlassHandle k, TRAPS);
-  static instanceKlassHandle load_shared_class(symbolHandle class_name,
+  static instanceKlassHandle load_shared_class(Symbol* class_name,
                                                Handle class_loader, TRAPS);
   static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
                                                Handle class_loader, TRAPS);
-  static instanceKlassHandle load_instance_class(symbolHandle class_name, Handle class_loader, TRAPS);
+  static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
   static Handle compute_loader_lock_object(Handle class_loader, TRAPS);
   static void check_loader_lock_contention(Handle loader_lock, TRAPS);
   static bool is_parallelCapable(Handle class_loader);
   static bool is_parallelDefine(Handle class_loader);
 
-  static klassOop find_shared_class(symbolHandle class_name);
+  static klassOop find_shared_class(Symbol* class_name);
 
   // Setup link to hierarchy
   static void add_to_hierarchy(instanceKlassHandle k, TRAPS);
@@ -644,34 +646,29 @@
 
   // Basic find on loaded classes
   static klassOop find_class(int index, unsigned int hash,
-                             symbolHandle name, Handle loader);
+                             Symbol* name, Handle loader);
+  static klassOop find_class(Symbol* class_name, Handle class_loader);
 
   // Basic find on classes in the midst of being loaded
-  static symbolOop find_placeholder(int index, unsigned int hash,
-                                    symbolHandle name, Handle loader);
-
-  // Basic find operation of loaded classes and classes in the midst
-  // of loading;  used for assertions and verification only.
-  static oop find_class_or_placeholder(symbolHandle class_name,
-                                       Handle class_loader);
+  static Symbol* find_placeholder(Symbol* name, Handle loader);
 
   // Updating entry in dictionary
   // Add a completely loaded class
-  static void add_klass(int index, symbolHandle class_name,
+  static void add_klass(int index, Symbol* class_name,
                         Handle class_loader, KlassHandle obj);
 
   // Add a placeholder for a class being loaded
   static void add_placeholder(int index,
-                              symbolHandle class_name,
+                              Symbol* class_name,
                               Handle class_loader);
   static void remove_placeholder(int index,
-                                 symbolHandle class_name,
+                                 Symbol* class_name,
                                  Handle class_loader);
 
   // Performs cleanups after resolve_super_or_fail. This typically needs
   // to be called on failure.
   // Won't throw, but can block.
-  static void resolution_cleanups(symbolHandle class_name,
+  static void resolution_cleanups(Symbol* class_name,
                                   Handle class_loader,
                                   TRAPS);
 
@@ -701,7 +698,6 @@
   static bool _has_checkPackageAccess;
 };
 
-// Cf. vmSymbols vs. vmSymbolHandles
 class SystemDictionaryHandles : AllStatic {
 public:
   #define WK_KLASS_HANDLE_DECLARE(name, ignore_symbol, option) \
--- a/src/share/vm/classfile/verificationType.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/verificationType.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/verificationType.hpp"
+#include "classfile/verifier.hpp"
 
 VerificationType VerificationType::from_tag(u1 tag) {
   switch (tag) {
@@ -41,7 +42,8 @@
 }
 
 bool VerificationType::is_reference_assignable_from(
-    const VerificationType& from, instanceKlassHandle context, TRAPS) const {
+    const VerificationType& from, ClassVerifier* context, TRAPS) const {
+  instanceKlassHandle klass = context->current_class();
   if (from.is_null()) {
     // null is assignable to any reference
     return true;
@@ -56,8 +58,8 @@
       return true;
     }
     klassOop obj = SystemDictionary::resolve_or_fail(
-        name_handle(), Handle(THREAD, context->class_loader()),
-        Handle(THREAD, context->protection_domain()), true, CHECK_false);
+        name(), Handle(THREAD, klass->class_loader()),
+        Handle(THREAD, klass->protection_domain()), true, CHECK_false);
     KlassHandle this_class(THREAD, obj);
 
     if (this_class->is_interface()) {
@@ -66,13 +68,13 @@
       return true;
     } else if (from.is_object()) {
       klassOop from_class = SystemDictionary::resolve_or_fail(
-          from.name_handle(), Handle(THREAD, context->class_loader()),
-          Handle(THREAD, context->protection_domain()), true, CHECK_false);
+          from.name(), Handle(THREAD, klass->class_loader()),
+          Handle(THREAD, klass->protection_domain()), true, CHECK_false);
       return instanceKlass::cast(from_class)->is_subclass_of(this_class());
     }
   } else if (is_array() && from.is_array()) {
-    VerificationType comp_this = get_component(CHECK_false);
-    VerificationType comp_from = from.get_component(CHECK_false);
+    VerificationType comp_this = get_component(context, CHECK_false);
+    VerificationType comp_from = from.get_component(context, CHECK_false);
     if (!comp_this.is_bogus() && !comp_from.is_bogus()) {
       return comp_this.is_assignable_from(comp_from, context, CHECK_false);
     }
@@ -80,9 +82,9 @@
   return false;
 }
 
-VerificationType VerificationType::get_component(TRAPS) const {
+VerificationType VerificationType::get_component(ClassVerifier *context, TRAPS) const {
   assert(is_array() && name()->utf8_length() >= 2, "Must be a valid array");
-  symbolOop component;
+  Symbol* component;
   switch (name()->byte_at(1)) {
     case 'Z': return VerificationType(Boolean);
     case 'B': return VerificationType(Byte);
@@ -93,12 +95,12 @@
     case 'F': return VerificationType(Float);
     case 'D': return VerificationType(Double);
     case '[':
-      component = SymbolTable::lookup(
+      component = context->create_temporary_symbol(
         name(), 1, name()->utf8_length(),
         CHECK_(VerificationType::bogus_type()));
       return VerificationType::reference_type(component);
     case 'L':
-      component = SymbolTable::lookup(
+      component = context->create_temporary_symbol(
         name(), 2, name()->utf8_length() - 1,
         CHECK_(VerificationType::bogus_type()));
       return VerificationType::reference_type(component);
--- a/src/share/vm/classfile/verificationType.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/verificationType.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -29,7 +29,7 @@
 #include "memory/allocation.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/signature.hpp"
 
@@ -47,6 +47,8 @@
   ITEM_Bogus = (uint)-1
 };
 
+class ClassVerifier;
+
 class VerificationType VALUE_OBJ_CLASS_SPEC {
   private:
     // Least significant bits of _handle are always 0, so we use these as
@@ -56,7 +58,7 @@
     // will catch this and we'll have to add a descriminator tag to this
     // structure.
     union {
-      symbolOop* _handle;
+      Symbol*   _sym;
       uintptr_t _data;
     } _u;
 
@@ -73,7 +75,7 @@
       TypeMask           = 0x00000003,
 
       // Topmost types encoding
-      Reference          = 0x0,        // _handle contains the name
+      Reference          = 0x0,        // _sym contains the name
       Primitive          = 0x1,        // see below for primitive list
       Uninitialized      = 0x2,        // 0x00ffff00 contains bci
       TypeQuery          = 0x3,        // Meta-types used for category testing
@@ -85,7 +87,7 @@
       Category2_2ndFlag  = 0x04,       // Second word of a two-word value
 
       // special reference values
-      Null               = 0x00000000, // A reference with a 0 handle is null
+      Null               = 0x00000000, // A reference with a 0 sym is null
 
       // Primitives categories (the second byte determines the category)
       Category1          = (Category1Flag     << 1 * BitsPerByte) | Primitive,
@@ -152,17 +154,14 @@
   static VerificationType category2_2nd_check()
     { return VerificationType(Category2_2ndQuery); }
 
-  // For reference types, store the actual oop* handle
-  static VerificationType reference_type(symbolHandle sh) {
-      assert(((uintptr_t)sh.raw_value() & 0x3) == 0, "Oops must be aligned");
+  // For reference types, store the actual Symbol
+  static VerificationType reference_type(Symbol* sh) {
+      assert(((uintptr_t)sh & 0x3) == 0, "Oops must be aligned");
       // If the above assert fails in the future because oop* isn't aligned,
       // then this type encoding system will have to change to have a tag value
       // to descriminate between oops and primitives.
-      return VerificationType((uintptr_t)((symbolOop*)sh.raw_value()));
+      return VerificationType((uintptr_t)sh);
   }
-  static VerificationType reference_type(symbolOop s, TRAPS)
-    { return reference_type(symbolHandle(THREAD, s)); }
-
   static VerificationType uninitialized_type(u2 bci)
     { return VerificationType(bci << 1 * BitsPerByte | Uninitialized); }
   static VerificationType uninitialized_this_type()
@@ -242,13 +241,9 @@
     return ((_u._data & BciMask) >> 1 * BitsPerByte);
   }
 
-  symbolHandle name_handle() const {
+  Symbol* name() const {
     assert(is_reference() && !is_null(), "Must be a non-null reference");
-    return symbolHandle(_u._handle, true);
-  }
-  symbolOop name() const {
-    assert(is_reference() && !is_null(), "Must be a non-null reference");
-    return *(_u._handle);
+    return _u._sym;
   }
 
   bool equals(const VerificationType& t) const {
@@ -269,7 +264,7 @@
   // is assignable to another.  Returns true if one can assign 'from' to
   // this.
   bool is_assignable_from(
-      const VerificationType& from, instanceKlassHandle context, TRAPS) const {
+      const VerificationType& from, ClassVerifier* context, TRAPS) const {
     if (equals(from) || is_bogus()) {
       return true;
     } else {
@@ -298,7 +293,7 @@
     }
   }
 
-  VerificationType get_component(TRAPS) const;
+  VerificationType get_component(ClassVerifier* context, TRAPS) const;
 
   int dimensions() const {
     assert(is_array(), "Must be an array");
@@ -312,7 +307,7 @@
  private:
 
   bool is_reference_assignable_from(
-    const VerificationType&, instanceKlassHandle, TRAPS) const;
+    const VerificationType&, ClassVerifier*, TRAPS) const;
 };
 
 #endif // SHARE_VM_CLASSFILE_VERIFICATIONTYPE_HPP
--- a/src/share/vm/classfile/verifier.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/verifier.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -98,10 +98,10 @@
 }
 
 bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool should_verify_class, TRAPS) {
+  HandleMark hm;
   ResourceMark rm(THREAD);
-  HandleMark hm;
 
-  symbolHandle exception_name;
+  Symbol* exception_name = NULL;
   const size_t message_buffer_len = klass->name()->utf8_length() + 1024;
   char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
 
@@ -141,7 +141,7 @@
         tty->print("Verification for %s has", klassName);
         tty->print_cr(" exception pending %s ",
           instanceKlass::cast(PENDING_EXCEPTION->klass())->external_name());
-      } else if (!exception_name.is_null()) {
+      } else if (exception_name != NULL) {
         tty->print_cr("Verification for %s failed", klassName);
       }
       tty->print_cr("End class verification for: %s", klassName);
@@ -150,7 +150,7 @@
 
   if (HAS_PENDING_EXCEPTION) {
     return false; // use the existing exception
-  } else if (exception_name.is_null()) {
+  } else if (exception_name == NULL) {
     return true; // verifcation succeeded
   } else { // VerifyError or ClassFormatError to be created and thrown
     ResourceMark rm(THREAD);
@@ -172,7 +172,7 @@
 }
 
 bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) {
-  symbolOop name = klass->name();
+  Symbol* name = klass->name();
   klassOop refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass();
 
   return (should_verify_for(klass->class_loader(), should_verify_class) &&
@@ -202,7 +202,7 @@
   );
 }
 
-symbolHandle Verifier::inference_verify(
+Symbol* Verifier::inference_verify(
     instanceKlassHandle klass, char* message, size_t message_len, TRAPS) {
   JavaThread* thread = (JavaThread*)THREAD;
   JNIEnv *env = thread->jni_environment();
@@ -245,18 +245,17 @@
   // These numbers are chosen so that VerifyClassCodes interface doesn't need
   // to be changed (still return jboolean (unsigned char)), and result is
   // 1 when verification is passed.
-  symbolHandle nh(NULL);
   if (result == 0) {
     return vmSymbols::java_lang_VerifyError();
   } else if (result == 1) {
-    return nh; // verified.
+    return NULL; // verified.
   } else if (result == 2) {
-    THROW_MSG_(vmSymbols::java_lang_OutOfMemoryError(), message, nh);
+    THROW_MSG_(vmSymbols::java_lang_OutOfMemoryError(), message, NULL);
   } else if (result == 3) {
     return vmSymbols::java_lang_ClassFormatError();
   } else {
     ShouldNotReachHere();
-    return nh;
+    return NULL;
   }
 }
 
@@ -266,12 +265,19 @@
 
 ClassVerifier::ClassVerifier(
     instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS)
-    : _thread(THREAD), _exception_type(symbolHandle()), _message(msg),
+    : _thread(THREAD), _exception_type(NULL), _message(msg),
       _message_buffer_len(msg_len), _klass(klass) {
   _this_type = VerificationType::reference_type(klass->name());
+  // Create list to hold symbols in reference area.
+  _symbols = new GrowableArray<Symbol*>(100, 0, NULL);
 }
 
 ClassVerifier::~ClassVerifier() {
+  // Decrement the reference count for any symbols created.
+  for (int i = 0; i < _symbols->length(); i++) {
+    Symbol* s = _symbols->at(i);
+    s->decrement_refcount();
+  }
 }
 
 VerificationType ClassVerifier::object_type() const {
@@ -308,7 +314,6 @@
 }
 
 void ClassVerifier::verify_method(methodHandle m, TRAPS) {
-  ResourceMark rm(THREAD);
   _method = m;   // initialize _method
   if (_verify_verbose) {
     tty->print_cr("Verifying method %s", m->name_and_sig_as_C_string());
@@ -615,7 +620,7 @@
               VerificationType::null_type(), CHECK_VERIFY(this));
           } else {
             VerificationType component =
-              atype.get_component(CHECK_VERIFY(this));
+              atype.get_component(this, CHECK_VERIFY(this));
             current_frame.push_stack(component, CHECK_VERIFY(this));
           }
           no_control_flow = false; break;
@@ -1386,7 +1391,7 @@
         VerificationType throwable =
           VerificationType::reference_type(vmSymbols::java_lang_Throwable());
         bool is_subclass = throwable.is_assignable_from(
-          catch_type, current_class(), CHECK_VERIFY(this));
+          catch_type, this, CHECK_VERIFY(this));
         if (!is_subclass) {
           // 4286534: should throw VerifyError according to recent spec change
           verify_error(
@@ -1473,8 +1478,6 @@
       if(bci >= start_pc && bci < end_pc) {
         u1 flags = current_frame->flags();
         if (this_uninit) {  flags |= FLAG_THIS_UNINIT; }
-
-        ResourceMark rm(THREAD);
         StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags);
         if (catch_type_index != 0) {
           // We know that this index refers to a subclass of Throwable
@@ -1575,7 +1578,7 @@
   va_end(va);
 }
 
-klassOop ClassVerifier::load_class(symbolHandle name, TRAPS) {
+klassOop ClassVerifier::load_class(Symbol* name, TRAPS) {
   // Get current loader and protection domain first.
   oop loader = current_class()->class_loader();
   oop protection_domain = current_class()->protection_domain();
@@ -1587,8 +1590,8 @@
 
 bool ClassVerifier::is_protected_access(instanceKlassHandle this_class,
                                         klassOop target_class,
-                                        symbolOop field_name,
-                                        symbolOop field_sig,
+                                        Symbol* field_name,
+                                        Symbol* field_sig,
                                         bool is_method) {
   No_Safepoint_Verifier nosafepoint;
 
@@ -1736,7 +1739,7 @@
 }
 
 bool ClassVerifier::name_in_supers(
-    symbolOop ref_name, instanceKlassHandle current) {
+    Symbol* ref_name, instanceKlassHandle current) {
   klassOop super = current->super();
   while (super != NULL) {
     if (super->klass_part()->name() == ref_name) {
@@ -1755,8 +1758,8 @@
   verify_cp_type(index, cp, 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this));
 
   // Get field name and signature
-  symbolHandle field_name = symbolHandle(THREAD, cp->name_ref_at(index));
-  symbolHandle field_sig = symbolHandle(THREAD, cp->signature_ref_at(index));
+  Symbol* field_name = cp->name_ref_at(index);
+  Symbol* field_sig = cp->signature_ref_at(index);
 
   if (!SignatureVerifier::is_valid_type_signature(field_sig)) {
     class_format_error(
@@ -1823,11 +1826,11 @@
       fieldDescriptor fd;
       if (stack_object_type == VerificationType::uninitialized_this_type() &&
           target_class_type.equals(current_type()) &&
-          _klass->find_local_field(field_name(), field_sig(), &fd)) {
+          _klass->find_local_field(field_name, field_sig, &fd)) {
         stack_object_type = current_type();
       }
       is_assignable = target_class_type.is_assignable_from(
-        stack_object_type, current_class(), CHECK_VERIFY(this));
+        stack_object_type, this, CHECK_VERIFY(this));
       if (!is_assignable) {
         verify_error(bci, "Bad type on operand stack in putfield");
         return;
@@ -1836,9 +1839,9 @@
     check_protected: {
       if (_this_type == stack_object_type)
         break; // stack_object_type must be assignable to _current_class_type
-      symbolHandle ref_class_name = symbolHandle(THREAD,
-        cp->klass_name_at(cp->klass_ref_index_at(index)));
-      if (!name_in_supers(ref_class_name(), current_class()))
+      Symbol* ref_class_name =
+        cp->klass_name_at(cp->klass_ref_index_at(index));
+      if (!name_in_supers(ref_class_name, current_class()))
         // stack_object_type must be assignable to _current_class_type since:
         // 1. stack_object_type must be assignable to ref_class.
         // 2. ref_class must be _current_class or a subclass of it. It can't
@@ -1846,12 +1849,12 @@
         break;
 
       klassOop ref_class_oop = load_class(ref_class_name, CHECK);
-      if (is_protected_access(current_class(), ref_class_oop, field_name(),
-                              field_sig(), false)) {
+      if (is_protected_access(current_class(), ref_class_oop, field_name,
+                              field_sig, false)) {
         // It's protected access, check if stack object is assignable to
         // current class.
         is_assignable = current_type().is_assignable_from(
-          stack_object_type, current_class(), CHECK_VERIFY(this));
+          stack_object_type, this, CHECK_VERIFY(this));
         if (!is_assignable) {
           verify_error(bci, "Bad access to protected data in getfield");
           return;
@@ -1911,7 +1914,7 @@
       instanceKlassHandle mh(THREAD, m->method_holder());
       if (m->is_protected() && !mh->is_same_class_package(_klass())) {
         bool assignable = current_type().is_assignable_from(
-          objectref_type, current_class(), CHECK_VERIFY(this));
+          objectref_type, this, CHECK_VERIFY(this));
         if (!assignable) {
           verify_error(bci, "Bad access to protected <init> method");
           return;
@@ -1941,8 +1944,8 @@
   verify_cp_type(index, cp, types, CHECK_VERIFY(this));
 
   // Get method name and signature
-  symbolHandle method_name(THREAD, cp->name_ref_at(index));
-  symbolHandle method_sig(THREAD, cp->signature_ref_at(index));
+  Symbol* method_name = cp->name_ref_at(index);
+  Symbol* method_sig = cp->signature_ref_at(index);
 
   if (!SignatureVerifier::is_valid_method_signature(method_sig)) {
     class_format_error(
@@ -2035,7 +2038,7 @@
   if (method_name->byte_at(0) == '<') {
     // Make sure <init> can only be invoked by invokespecial
     if (opcode != Bytecodes::_invokespecial ||
-        method_name() != vmSymbols::object_initializer_name()) {
+        method_name != vmSymbols::object_initializer_name()) {
       verify_error(bci, "Illegal call to internal method");
       return;
     }
@@ -2044,7 +2047,7 @@
              && !ref_class_type.equals(VerificationType::reference_type(
                   current_class()->super()->klass_part()->name()))) {
     bool subtype = ref_class_type.is_assignable_from(
-      current_type(), current_class(), CHECK_VERIFY(this));
+      current_type(), this, CHECK_VERIFY(this));
     if (!subtype) {
       verify_error(bci, "Bad invokespecial instruction: "
           "current class isn't assignable to reference class.");
@@ -2058,7 +2061,7 @@
   // Check objectref on operand stack
   if (opcode != Bytecodes::_invokestatic &&
       opcode != Bytecodes::_invokedynamic) {
-    if (method_name() == vmSymbols::object_initializer_name()) {  // <init> method
+    if (method_name == vmSymbols::object_initializer_name()) {  // <init> method
       verify_invoke_init(bcs, ref_class_type, current_frame,
         code_length, this_uninit, cp, CHECK_VERIFY(this));
     } else {   // other methods
@@ -2070,22 +2073,22 @@
           current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this));
         if (current_type() != stack_object_type) {
           assert(cp->cache() == NULL, "not rewritten yet");
-          symbolHandle ref_class_name = symbolHandle(THREAD,
-            cp->klass_name_at(cp->klass_ref_index_at(index)));
+          Symbol* ref_class_name =
+            cp->klass_name_at(cp->klass_ref_index_at(index));
           // See the comments in verify_field_instructions() for
           // the rationale behind this.
-          if (name_in_supers(ref_class_name(), current_class())) {
+          if (name_in_supers(ref_class_name, current_class())) {
             klassOop ref_class = load_class(ref_class_name, CHECK);
             if (is_protected_access(
-                  _klass, ref_class, method_name(), method_sig(), true)) {
+                  _klass, ref_class, method_name, method_sig, true)) {
               // It's protected access, check if stack object is
               // assignable to current class.
               bool is_assignable = current_type().is_assignable_from(
-                stack_object_type, current_class(), CHECK_VERIFY(this));
+                stack_object_type, this, CHECK_VERIFY(this));
               if (!is_assignable) {
                 if (ref_class_type.name() == vmSymbols::java_lang_Object()
                     && stack_object_type.is_array()
-                    && method_name() == vmSymbols::clone_name()) {
+                    && method_name == vmSymbols::clone_name()) {
                   // Special case: arrays pretend to implement public Object
                   // clone().
                 } else {
@@ -2105,7 +2108,7 @@
   }
   // Push the result type.
   if (sig_stream.type() != T_VOID) {
-    if (method_name() == vmSymbols::object_initializer_name()) {
+    if (method_name == vmSymbols::object_initializer_name()) {
       // <init> method must have a void return type
       verify_error(bci, "Return type must be void in <init> method");
       return;
@@ -2130,7 +2133,7 @@
   }
 
   // from_bt[index] contains the array signature which has a length of 2
-  symbolHandle sig = oopFactory::new_symbol_handle(
+  Symbol* sig = create_temporary_symbol(
     from_bt[index], 2, CHECK_(VerificationType::bogus_type()));
   return VerificationType::reference_type(sig);
 }
@@ -2143,7 +2146,6 @@
 
   VerificationType component_type =
     cp_index_to_type(index, cp, CHECK_VERIFY(this));
-  ResourceMark rm(THREAD);
   int length;
   char* arr_sig_str;
   if (component_type.is_array()) {     // it's an array
@@ -2163,7 +2165,7 @@
     strncpy(&arr_sig_str[2], component_name, length - 2);
     arr_sig_str[length - 1] = ';';
   }
-  symbolHandle arr_sig = oopFactory::new_symbol_handle(
+  Symbol* arr_sig = create_temporary_symbol(
     arr_sig_str, length, CHECK_VERIFY(this));
   VerificationType new_array_type = VerificationType::reference_type(arr_sig);
   current_frame->push_stack(new_array_type, CHECK_VERIFY(this));
@@ -2256,9 +2258,25 @@
     verify_error(bci, "Method expects a return value");
     return;
   }
-  bool match = return_type.is_assignable_from(type, _klass, CHECK_VERIFY(this));
+  bool match = return_type.is_assignable_from(type, this, CHECK_VERIFY(this));
   if (!match) {
     verify_error(bci, "Bad return type");
     return;
   }
 }
+
+// The verifier creates symbols which are substrings of Symbols.
+// These are stored in the verifier until the end of verification so that
+// they can be reference counted.
+Symbol* ClassVerifier::create_temporary_symbol(const Symbol *s, int begin,
+                                               int end, TRAPS) {
+  Symbol* sym = SymbolTable::new_symbol(s, begin, end, CHECK_NULL);
+  _symbols->push(sym);
+  return sym;
+}
+
+Symbol* ClassVerifier::create_temporary_symbol(const char *s, int length, TRAPS) {
+  Symbol* sym = SymbolTable::new_symbol(s, length, CHECK_NULL);
+  _symbols->push(sym);
+  return sym;
+}
--- a/src/share/vm/classfile/verifier.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/verifier.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -59,7 +59,7 @@
 
  private:
   static bool is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class);
-  static symbolHandle inference_verify(
+  static Symbol* inference_verify(
     instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS);
 };
 
@@ -69,8 +69,8 @@
 
 // Summary of verifier's memory usage:
 // StackMapTable is stack allocated.
-// StackMapFrame are resource allocated. There is one ResourceMark
-// for each method.
+// StackMapFrame are resource allocated. There is only one ResourceMark
+// for each class verification, which is created at the top level.
 // There is one mutable StackMapFrame (current_frame) which is updated
 // by abstract bytecode interpretation. frame_in_exception_handler() returns
 // a frame that has a mutable one-item stack (ready for pushing the
@@ -80,8 +80,6 @@
 // locals/stack arrays in StackMapFrame are resource allocated.
 // locals/stack arrays can be shared between StackMapFrame's, except
 // the mutable StackMapFrame (current_frame).
-// Care needs to be taken to make sure resource objects don't outlive
-// the lifetime of their ResourceMark.
 
 // These macros are used similarly to CHECK macros but also check
 // the status of the verifier and return if that has an error.
@@ -94,9 +92,10 @@
 class ClassVerifier : public StackObj {
  private:
   Thread* _thread;
-  symbolHandle _exception_type;
+  Symbol* _exception_type;
   char* _message;
   size_t _message_buffer_len;
+  GrowableArray<Symbol*>* _symbols;  // keep a list of symbols created
 
   void verify_method(methodHandle method, TRAPS);
   char* generate_code_data(methodHandle m, u4 code_length, TRAPS);
@@ -110,7 +109,7 @@
 
   bool is_protected_access(
     instanceKlassHandle this_class, klassOop target_class,
-    symbolOop field_name, symbolOop field_sig, bool is_method);
+    Symbol* field_name, Symbol* field_sig, bool is_method);
 
   void verify_cp_index(constantPoolHandle cp, int index, TRAPS);
   void verify_cp_type(
@@ -165,7 +164,7 @@
   void verify_astore(u2 index, StackMapFrame* current_frame, TRAPS);
   void verify_iinc  (u2 index, StackMapFrame* current_frame, TRAPS);
 
-  bool name_in_supers(symbolOop ref_name, instanceKlassHandle current);
+  bool name_in_supers(Symbol* ref_name, instanceKlassHandle current);
 
   VerificationType object_type() const;
 
@@ -206,8 +205,8 @@
   void verify_class(TRAPS);
 
   // Return status modes
-  symbolHandle result() const { return _exception_type; }
-  bool has_error() const { return !(result().is_null()); }
+  Symbol* result() const { return _exception_type; }
+  bool has_error() const { return result() != NULL; }
 
   // Called when verify or class format errors are encountered.
   // May throw an exception based upon the mode.
@@ -216,16 +215,22 @@
   void class_format_error(const char* fmt, ...);
   void format_error_message(const char* fmt, int offset, va_list args);
 
-  klassOop load_class(symbolHandle name, TRAPS);
+  klassOop load_class(Symbol* name, TRAPS);
 
   int change_sig_to_verificationType(
     SignatureStream* sig_type, VerificationType* inference_type, TRAPS);
 
   VerificationType cp_index_to_type(int index, constantPoolHandle cp, TRAPS) {
-    return VerificationType::reference_type(
-      symbolHandle(THREAD, cp->klass_name_at(index)));
+    return VerificationType::reference_type(cp->klass_name_at(index));
   }
 
+  // Keep a list of temporary symbols created during verification because
+  // their reference counts need to be decrememented when the verifier object
+  // goes out of scope.  Since these symbols escape the scope in which they're
+  // created, we can't use a TempNewSymbol.
+  Symbol* create_temporary_symbol(const Symbol* s, int begin, int end, TRAPS);
+  Symbol* create_temporary_symbol(const char *s, int length, TRAPS);
+
   static bool _verify_verbose;  // for debugging
 };
 
@@ -236,9 +241,14 @@
     case T_OBJECT:
     case T_ARRAY:
       {
-        symbolOop name = sig_type->as_symbol(CHECK_0);
+        Symbol* name = sig_type->as_symbol(CHECK_0);
+        // Create another symbol to save as signature stream unreferences
+        // this symbol.
+        Symbol* name_copy =
+          create_temporary_symbol(name, 0, name->utf8_length(), CHECK_0);
+        assert(name_copy == name, "symbols don't match");
         *inference_type =
-          VerificationType::reference_type(symbolHandle(THREAD, name));
+          VerificationType::reference_type(name_copy);
         return 1;
       }
     case T_LONG:
--- a/src/share/vm/classfile/vmSymbols.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/vmSymbols.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -30,11 +30,11 @@
 #include "utilities/xmlstream.hpp"
 
 
-symbolOop vmSymbols::_symbols[vmSymbols::SID_LIMIT];
+Symbol* vmSymbols::_symbols[vmSymbols::SID_LIMIT];
 
-symbolOop vmSymbols::_type_signatures[T_VOID+1] = { NULL /*, NULL...*/ };
+Symbol* vmSymbols::_type_signatures[T_VOID+1] = { NULL /*, NULL...*/ };
 
-inline int compare_symbol(symbolOop a, symbolOop b) {
+inline int compare_symbol(Symbol* a, Symbol* b) {
   if (a == b)  return 0;
   // follow the natural address order:
   return (address)a > (address)b ? +1 : -1;
@@ -43,8 +43,8 @@
 static vmSymbols::SID vm_symbol_index[vmSymbols::SID_LIMIT];
 extern "C" {
   static int compare_vmsymbol_sid(const void* void_a, const void* void_b) {
-    symbolOop a = vmSymbols::symbol_at(*((vmSymbols::SID*) void_a));
-    symbolOop b = vmSymbols::symbol_at(*((vmSymbols::SID*) void_b));
+    Symbol* a = vmSymbols::symbol_at(*((vmSymbols::SID*) void_a));
+    Symbol* b = vmSymbols::symbol_at(*((vmSymbols::SID*) void_b));
     return compare_symbol(a, b);
   }
 }
@@ -79,7 +79,7 @@
   if (!UseSharedSpaces) {
     const char* string = &vm_symbol_bodies[0];
     for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
-      symbolOop sym = oopFactory::new_symbol(string, CHECK);
+      Symbol* sym = SymbolTable::new_symbol(string, CHECK);
       _symbols[index] = sym;
       string += strlen(string); // skip string body
       string += 1;              // skip trailing null
@@ -100,7 +100,7 @@
 #ifdef ASSERT
   // Check for duplicates:
   for (int i1 = (int)FIRST_SID; i1 < (int)SID_LIMIT; i1++) {
-    symbolOop sym = symbol_at((SID)i1);
+    Symbol* sym = symbol_at((SID)i1);
     for (int i2 = (int)FIRST_SID; i2 < i1; i2++) {
       if (symbol_at((SID)i2) == sym) {
         tty->print("*** Duplicate VM symbol SIDs %s(%d) and %s(%d): \"",
@@ -128,16 +128,16 @@
     // Spot-check correspondence between strings, symbols, and enums:
     assert(_symbols[NO_SID] == NULL, "must be");
     const char* str = "java/lang/Object";
-    symbolOop sym = oopFactory::new_symbol(str, CHECK);
-    assert(strcmp(str, (char*)sym->base()) == 0, "");
-    assert(sym == java_lang_Object(), "");
+    TempNewSymbol jlo = SymbolTable::new_symbol(str, CHECK);
+    assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, "");
+    assert(jlo == java_lang_Object(), "");
     SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object);
-    assert(find_sid(sym) == sid, "");
-    assert(symbol_at(sid) == sym, "");
+    assert(find_sid(jlo) == sid, "");
+    assert(symbol_at(sid) == jlo, "");
 
     // Make sure find_sid produces the right answer in each case.
     for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
-      sym = symbol_at((SID)index);
+      Symbol* sym = symbol_at((SID)index);
       sid = find_sid(sym);
       assert(sid == (SID)index, "symbol index works");
       // Note:  If there are duplicates, this assert will fail.
@@ -147,8 +147,8 @@
     // The string "format" happens (at the moment) not to be a vmSymbol,
     // though it is a method name in java.lang.String.
     str = "format";
-    sym = oopFactory::new_symbol(str, CHECK);
-    sid = find_sid(sym);
+    TempNewSymbol fmt = SymbolTable::new_symbol(str, CHECK);
+    sid = find_sid(fmt);
     assert(sid == NO_SID, "symbol index works (negative test)");
   }
 #endif
@@ -172,22 +172,23 @@
 
 
 
-void vmSymbols::oops_do(OopClosure* f, bool do_all) {
+void vmSymbols::symbols_do(SymbolClosure* f) {
   for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
-    f->do_oop((oop*) &_symbols[index]);
+    f->do_symbol(&_symbols[index]);
   }
   for (int i = 0; i < T_VOID+1; i++) {
-    if (_type_signatures[i] != NULL) {
-      assert(i >= T_BOOLEAN, "checking");
-      f->do_oop((oop*)&_type_signatures[i]);
-    } else if (do_all) {
-      f->do_oop((oop*)&_type_signatures[i]);
-    }
+    f->do_symbol(&_type_signatures[i]);
   }
 }
 
+void vmSymbols::serialize(SerializeOopClosure* soc) {
+  soc->do_region((u_char*)&_symbols[FIRST_SID],
+                 (SID_LIMIT - FIRST_SID) * sizeof(_symbols[0]));
+  soc->do_region((u_char*)_type_signatures, sizeof(_type_signatures));
+}
 
-BasicType vmSymbols::signature_type(symbolOop s) {
+
+BasicType vmSymbols::signature_type(Symbol* s) {
   assert(s != NULL, "checking");
   for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
     if (s == _type_signatures[i]) {
@@ -205,7 +206,7 @@
 // (Typical counts are calls=7000 and probes=17000.)
 #endif
 
-vmSymbols::SID vmSymbols::find_sid(symbolOop symbol) {
+vmSymbols::SID vmSymbols::find_sid(Symbol* symbol) {
   // Handle the majority of misses by a bounds check.
   // Then, use a binary search over the index.
   // Expected trip count is less than log2_SID_LIMIT, about eight.
@@ -260,7 +261,7 @@
     // (We have already proven that there are no duplicates in the list.)
     SID sid2 = NO_SID;
     for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
-      symbolOop sym2 = symbol_at((SID)index);
+      Symbol* sym2 = symbol_at((SID)index);
       if (sym2 == symbol) {
         sid2 = (SID)index;
         break;
@@ -319,9 +320,9 @@
 
 methodOop vmIntrinsics::method_for(vmIntrinsics::ID id) {
   if (id == _none)  return NULL;
-  symbolOop cname = vmSymbols::symbol_at(class_for(id));
-  symbolOop mname = vmSymbols::symbol_at(name_for(id));
-  symbolOop msig  = vmSymbols::symbol_at(signature_for(id));
+  Symbol* cname = vmSymbols::symbol_at(class_for(id));
+  Symbol* mname = vmSymbols::symbol_at(name_for(id));
+  Symbol* msig  = vmSymbols::symbol_at(signature_for(id));
   if (cname == NULL || mname == NULL || msig == NULL)  return NULL;
   klassOop k = SystemDictionary::find_well_known_klass(cname);
   if (k == NULL)  return NULL;
@@ -490,17 +491,17 @@
 #ifndef PRODUCT
 // verify_method performs an extra check on a matched intrinsic method
 
-static bool match_method(methodOop m, symbolOop n, symbolOop s) {
+static bool match_method(methodOop m, Symbol* n, Symbol* s) {
   return (m->name() == n &&
           m->signature() == s);
 }
 
-static vmIntrinsics::ID match_method_with_klass(methodOop m, symbolOop mk) {
+static vmIntrinsics::ID match_method_with_klass(methodOop m, Symbol* mk) {
 #define VM_INTRINSIC_MATCH(id, klassname, namepart, sigpart, flags) \
-  { symbolOop k = vmSymbols::klassname(); \
+  { Symbol* k = vmSymbols::klassname(); \
     if (mk == k) { \
-      symbolOop n = vmSymbols::namepart(); \
-      symbolOop s = vmSymbols::sigpart(); \
+      Symbol* n = vmSymbols::namepart(); \
+      Symbol* s = vmSymbols::sigpart(); \
       if (match_method(m, n, s)) \
         return vmIntrinsics::id; \
     } }
@@ -511,7 +512,7 @@
 }
 
 void vmIntrinsics::verify_method(ID actual_id, methodOop m) {
-  symbolOop mk = Klass::cast(m->method_holder())->name();
+  Symbol* mk = Klass::cast(m->method_holder())->name();
   ID declared_id = match_method_with_klass(m, mk);
 
   if (declared_id == actual_id)  return; // success
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,17 +25,15 @@
 #ifndef SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
 #define SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
 
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
+#include "memory/iterator.hpp"
 
-// The classes vmSymbols and vmSymbolHandles are a name spaces for fast lookup of
-// symbols commonly used in the VM. The first class return a symbolOop, while the
-// second class returns a SymbolHandle. The underlying data structure is shared
-// between the two classes.
+// The class vmSymbols is a name space for fast lookup of
+// symbols commonly used in the VM.
 //
 // Sample usage:
 //
-//   symbolOop obj       = vmSymbols::java_lang_Object()();
-//   SymbolHandle handle = vmSymbolHandles::java_lang_Object();
+//   Symbol* obj       = vmSymbols::java_lang_Object();
 
 
 // Useful sub-macros exported by this header file:
@@ -111,6 +109,7 @@
   template(sun_jkernel_DownloadManager,               "sun/jkernel/DownloadManager")              \
   template(getBootClassPathEntryForClass_name,        "getBootClassPathEntryForClass")            \
   template(setBootClassLoaderHook_name,               "setBootClassLoaderHook")                   \
+  template(sun_misc_PostVMInitHook,                   "sun/misc/PostVMInitHook")                  \
                                                                                                   \
   /* class file format tags */                                                                    \
   template(tag_source_file,                           "SourceFile")                               \
@@ -527,7 +526,7 @@
   VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, do_alias)           \
                                                                                                                   \
   /* returned by the C1 compiler in case there's not enough memory to allocate a new symbol*/                     \
-  template(dummy_symbol_oop,                          "illegal symbol")                                           \
+  template(dummy_symbol,                              "illegal symbol")                                           \
                                                                                                                   \
   /* used by ClassFormatError when class name is not known yet */                                                 \
   template(unknown_class_name,                        "<Unknown>")                                                \
@@ -1006,10 +1005,9 @@
 // Class vmSymbols
 
 class vmSymbols: AllStatic {
- friend class vmSymbolHandles;
  friend class vmIntrinsics;
  public:
-  // enum for figuring positions and size of array holding symbolOops
+  // enum for figuring positions and size of array holding Symbol*s
   enum SID {
     NO_SID = 0,
 
@@ -1031,39 +1029,42 @@
 
  private:
   // The symbol array
-  static symbolOop _symbols[];
+  static Symbol* _symbols[];
 
   // Field signatures indexed by BasicType.
-  static symbolOop _type_signatures[T_VOID+1];
+  static Symbol* _type_signatures[T_VOID+1];
 
  public:
   // Initialization
   static void initialize(TRAPS);
   // Accessing
-  #define VM_SYMBOL_DECLARE(name, ignore) \
-    static symbolOop name() { return _symbols[VM_SYMBOL_ENUM_NAME(name)]; }
+  #define VM_SYMBOL_DECLARE(name, ignore)                 \
+    static Symbol* name() {                               \
+      return _symbols[VM_SYMBOL_ENUM_NAME(name)];         \
+    }
   VM_SYMBOLS_DO(VM_SYMBOL_DECLARE, VM_SYMBOL_DECLARE)
   #undef VM_SYMBOL_DECLARE
 
-  // GC support
-  static void oops_do(OopClosure* f, bool do_all = false);
+  // Sharing support
+  static void symbols_do(SymbolClosure* f);
+  static void serialize(SerializeOopClosure* soc);
 
-  static symbolOop type_signature(BasicType t) {
+  static Symbol* type_signature(BasicType t) {
     assert((uint)t < T_VOID+1, "range check");
     assert(_type_signatures[t] != NULL, "domain check");
     return _type_signatures[t];
   }
   // inverse of type_signature; returns T_OBJECT if s is not recognized
-  static BasicType signature_type(symbolOop s);
+  static BasicType signature_type(Symbol* s);
 
-  static symbolOop symbol_at(SID id) {
+  static Symbol* symbol_at(SID id) {
     assert(id >= FIRST_SID && id < SID_LIMIT, "oob");
     assert(_symbols[id] != NULL, "init");
     return _symbols[id];
   }
 
   // Returns symbol's SID if one is assigned, else NO_SID.
-  static SID find_sid(symbolOop symbol);
+  static SID find_sid(Symbol* symbol);
 
 #ifndef PRODUCT
   // No need for this in the product:
@@ -1071,34 +1072,6 @@
 #endif //PRODUCT
 };
 
-
-// Class vmSymbolHandles
-
-class vmSymbolHandles: AllStatic {
-  friend class vmIntrinsics;
-  friend class ciObjectFactory;
-
- public:
-  // Accessing
-  #define VM_SYMBOL_HANDLE_DECLARE(name, ignore) \
-    static symbolHandle name() { return symbol_handle_at(vmSymbols::VM_SYMBOL_ENUM_NAME(name)); }
-  VM_SYMBOLS_DO(VM_SYMBOL_HANDLE_DECLARE, VM_SYMBOL_HANDLE_DECLARE)
-  #undef VM_SYMBOL_HANDLE_DECLARE
-
-  static symbolHandle symbol_handle_at(vmSymbols::SID id) {
-    return symbolHandle(&vmSymbols::_symbols[(int)id], false);
-  }
-
-  static symbolHandle type_signature(BasicType t) {
-    assert(vmSymbols::type_signature(t) != NULL, "domain check");
-    return symbolHandle(&vmSymbols::_type_signatures[t], false);
-  }
-  // inverse of type_signature; returns T_OBJECT if s is not recognized
-  static BasicType signature_type(symbolHandle s) {
-    return vmSymbols::signature_type(s());
-  }
-};
-
 // VM Intrinsic ID's uniquely identify some very special methods
 class vmIntrinsics: AllStatic {
   friend class vmSymbols;
--- a/src/share/vm/code/compiledIC.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/code/compiledIC.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -34,7 +34,7 @@
 #include "memory/oopFactory.hpp"
 #include "oops/methodOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/icache.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
--- a/src/share/vm/code/dependencies.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/code/dependencies.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -628,8 +628,8 @@
 
  private:
   // optional method descriptor to check for:
-  symbolOop _name;
-  symbolOop _signature;
+  Symbol* _name;
+  Symbol* _signature;
 
   // special classes which are not allowed to be witnesses:
   klassOop  _participants[PARTICIPANT_LIMIT+1];
--- a/src/share/vm/code/nmethod.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/code/nmethod.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,9 +57,9 @@
   {                                                                       \
     methodOop m = (method);                                               \
     if (m != NULL) {                                                      \
-      symbolOop klass_name = m->klass_name();                             \
-      symbolOop name = m->name();                                         \
-      symbolOop signature = m->signature();                               \
+      Symbol* klass_name = m->klass_name();                               \
+      Symbol* name = m->name();                                           \
+      Symbol* signature = m->signature();                                 \
       HS_DTRACE_PROBE6(hotspot, compiled__method__unload,                 \
         klass_name->bytes(), klass_name->utf8_length(),                   \
         name->bytes(), name->utf8_length(),                               \
@@ -1880,9 +1880,9 @@
 #ifndef SHARK
   if (!method()->is_native()) {
     SimpleScopeDesc ssd(this, fr.pc());
-    Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci());
-    bool has_receiver = call->has_receiver();
-    symbolOop signature = call->signature();
+    Bytecode_invoke call(ssd.method(), ssd.bci());
+    bool has_receiver = call.has_receiver();
+    Symbol* signature = call.signature();
     fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f);
   }
 #endif // !SHARK
@@ -2654,7 +2654,7 @@
         } else {
           bool did_name = false;
           if (!at_this && ss.is_object()) {
-            symbolOop name = ss.as_symbol_or_null();
+            Symbol* name = ss.as_symbol_or_null();
             if (name != NULL) {
               name->print_value_on(stream);
               did_name = true;
@@ -2716,8 +2716,7 @@
       } else if (sd->method()->is_native()) {
         st->print("method is native");
       } else {
-        address bcp  = sd->method()->bcp_from(sd->bci());
-        Bytecodes::Code bc = Bytecodes::java_code_at(bcp);
+        Bytecodes::Code bc = sd->method()->java_code_at(sd->bci());
         st->print(";*%s", Bytecodes::name(bc));
         switch (bc) {
         case Bytecodes::_invokevirtual:
@@ -2725,10 +2724,10 @@
         case Bytecodes::_invokestatic:
         case Bytecodes::_invokeinterface:
           {
-            Bytecode_invoke* invoke = Bytecode_invoke_at(sd->method(), sd->bci());
+            Bytecode_invoke invoke(sd->method(), sd->bci());
             st->print(" ");
-            if (invoke->name() != NULL)
-              invoke->name()->print_symbol_on(st);
+            if (invoke.name() != NULL)
+              invoke.name()->print_symbol_on(st);
             else
               st->print("<UNKNOWN>");
             break;
@@ -2738,10 +2737,10 @@
         case Bytecodes::_getstatic:
         case Bytecodes::_putstatic:
           {
-            Bytecode_field* field = Bytecode_field_at(sd->method(), sd->bci());
+            Bytecode_field field(sd->method(), sd->bci());
             st->print(" ");
-            if (field->name() != NULL)
-              field->name()->print_symbol_on(st);
+            if (field.name() != NULL)
+              field.name()->print_symbol_on(st);
             else
               st->print("<UNKNOWN>");
           }
--- a/src/share/vm/compiler/compileBroker.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/compiler/compileBroker.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -67,9 +67,9 @@
 #define DTRACE_METHOD_COMPILE_BEGIN_PROBE(compiler, method)              \
   {                                                                      \
     char* comp_name = (char*)(compiler)->name();                         \
-    symbolOop klass_name = (method)->klass_name();                       \
-    symbolOop name = (method)->name();                                   \
-    symbolOop signature = (method)->signature();                         \
+    Symbol* klass_name = (method)->klass_name();                         \
+    Symbol* name = (method)->name();                                     \
+    Symbol* signature = (method)->signature();                           \
     HS_DTRACE_PROBE8(hotspot, method__compile__begin,                    \
       comp_name, strlen(comp_name),                                      \
       klass_name->bytes(), klass_name->utf8_length(),                    \
@@ -80,9 +80,9 @@
 #define DTRACE_METHOD_COMPILE_END_PROBE(compiler, method, success)       \
   {                                                                      \
     char* comp_name = (char*)(compiler)->name();                         \
-    symbolOop klass_name = (method)->klass_name();                       \
-    symbolOop name = (method)->name();                                   \
-    symbolOop signature = (method)->signature();                         \
+    Symbol* klass_name = (method)->klass_name();                         \
+    Symbol* name = (method)->name();                                     \
+    Symbol* signature = (method)->signature();                           \
     HS_DTRACE_PROBE9(hotspot, method__compile__end,                      \
       comp_name, strlen(comp_name),                                      \
       klass_name->bytes(), klass_name->utf8_length(),                    \
@@ -766,7 +766,7 @@
   CompilerThread* compiler_thread = NULL;
 
   klassOop k =
-    SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(),
+    SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
                                       true, CHECK_0);
   instanceKlassHandle klass (THREAD, k);
   instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_0);
@@ -777,8 +777,8 @@
   JavaValue result(T_VOID);
   JavaCalls::call_special(&result, thread_oop,
                        klass,
-                       vmSymbolHandles::object_initializer_name(),
-                       vmSymbolHandles::threadgroup_string_void_signature(),
+                       vmSymbols::object_initializer_name(),
+                       vmSymbols::threadgroup_string_void_signature(),
                        thread_group,
                        string,
                        CHECK_0);
--- a/src/share/vm/compiler/compileLog.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/compiler/compileLog.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -63,7 +63,7 @@
   stringStream* context()                        { return &_context; }
 
   void          name(ciSymbol* s);               // name='s'
-  void          name(symbolHandle s)             { xmlStream::name(s); }
+  void          name(Symbol* s)                  { xmlStream::name(s); }
 
   // Output an object description, return obj->ident().
   int           identify(ciObject* obj);
--- a/src/share/vm/compiler/compilerOracle.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/compiler/compilerOracle.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -30,7 +30,7 @@
 #include "oops/klass.hpp"
 #include "oops/methodOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/jniHandles.hpp"
 
@@ -46,33 +46,33 @@
   };
 
  protected:
-  jobject        _class_name;
+  Symbol*        _class_name;
+  Symbol*        _method_name;
+  Symbol*        _signature;
   Mode           _class_mode;
-  jobject        _method_name;
   Mode           _method_mode;
-  jobject        _signature;
   MethodMatcher* _next;
 
-  static bool match(symbolHandle candidate, symbolHandle match, Mode match_mode);
+  static bool match(Symbol* candidate, Symbol* match, Mode match_mode);
 
-  symbolHandle class_name() const { return (symbolOop)JNIHandles::resolve_non_null(_class_name); }
-  symbolHandle method_name() const { return (symbolOop)JNIHandles::resolve_non_null(_method_name); }
-  symbolHandle signature() const { return (symbolOop)JNIHandles::resolve(_signature); }
+  Symbol* class_name() const { return _class_name; }
+  Symbol* method_name() const { return _method_name; }
+  Symbol* signature() const { return _signature; }
 
  public:
-  MethodMatcher(symbolHandle class_name, Mode class_mode,
-                symbolHandle method_name, Mode method_mode,
-                symbolHandle signature, MethodMatcher* next);
-  MethodMatcher(symbolHandle class_name, symbolHandle method_name, MethodMatcher* next);
+  MethodMatcher(Symbol* class_name, Mode class_mode,
+                Symbol* method_name, Mode method_mode,
+                Symbol* signature, MethodMatcher* next);
+  MethodMatcher(Symbol* class_name, Symbol* method_name, MethodMatcher* next);
 
   // utility method
   MethodMatcher* find(methodHandle method) {
-    symbolHandle class_name  = Klass::cast(method->method_holder())->name();
-    symbolHandle method_name = method->name();
+    Symbol* class_name  = Klass::cast(method->method_holder())->name();
+    Symbol* method_name = method->name();
     for (MethodMatcher* current = this; current != NULL; current = current->_next) {
       if (match(class_name, current->class_name(), current->_class_mode) &&
           match(method_name, current->method_name(), current->_method_mode) &&
-          (current->signature().is_null() || current->signature()() == method->signature())) {
+          (current->signature() == NULL || current->signature() == method->signature())) {
         return current;
       }
     }
@@ -85,14 +85,14 @@
 
   MethodMatcher* next() const { return _next; }
 
-  static void print_symbol(symbolHandle h, Mode mode) {
+  static void print_symbol(Symbol* h, Mode mode) {
     ResourceMark rm;
 
     if (mode == Suffix || mode == Substring || mode == Any) {
       tty->print("*");
     }
     if (mode != Any) {
-      h()->print_symbol_on(tty);
+      h->print_symbol_on(tty);
     }
     if (mode == Prefix || mode == Substring) {
       tty->print("*");
@@ -103,7 +103,7 @@
     print_symbol(class_name(), _class_mode);
     tty->print(".");
     print_symbol(method_name(), _method_mode);
-    if (!signature().is_null()) {
+    if (signature() != NULL) {
       tty->print(" ");
       signature()->print_symbol_on(tty);
     }
@@ -115,9 +115,9 @@
   }
 };
 
-MethodMatcher::MethodMatcher(symbolHandle class_name, symbolHandle method_name, MethodMatcher* next) {
-  _class_name  = JNIHandles::make_global(class_name);
-  _method_name = JNIHandles::make_global(method_name);
+MethodMatcher::MethodMatcher(Symbol* class_name, Symbol* method_name, MethodMatcher* next) {
+  _class_name  = class_name;
+  _method_name = method_name;
   _next        = next;
   _class_mode  = MethodMatcher::Exact;
   _method_mode = MethodMatcher::Exact;
@@ -125,24 +125,24 @@
 }
 
 
-MethodMatcher::MethodMatcher(symbolHandle class_name, Mode class_mode,
-                             symbolHandle method_name, Mode method_mode,
-                             symbolHandle signature, MethodMatcher* next):
+MethodMatcher::MethodMatcher(Symbol* class_name, Mode class_mode,
+                             Symbol* method_name, Mode method_mode,
+                             Symbol* signature, MethodMatcher* next):
     _class_mode(class_mode)
   , _method_mode(method_mode)
   , _next(next)
-  , _class_name(JNIHandles::make_global(class_name()))
-  , _method_name(JNIHandles::make_global(method_name()))
-  , _signature(JNIHandles::make_global(signature())) {
+  , _class_name(class_name)
+  , _method_name(method_name)
+  , _signature(signature) {
 }
 
-bool MethodMatcher::match(symbolHandle candidate, symbolHandle match, Mode match_mode) {
+bool MethodMatcher::match(Symbol* candidate, Symbol* match, Mode match_mode) {
   if (match_mode == Any) {
     return true;
   }
 
   if (match_mode == Exact) {
-    return candidate() == match();
+    return candidate == match;
   }
 
   ResourceMark rm;
@@ -171,9 +171,9 @@
 class MethodOptionMatcher: public MethodMatcher {
   const char * option;
  public:
-  MethodOptionMatcher(symbolHandle class_name, Mode class_mode,
-                             symbolHandle method_name, Mode method_mode,
-                             symbolHandle signature, const char * opt, MethodMatcher* next):
+  MethodOptionMatcher(Symbol* class_name, Mode class_mode,
+                             Symbol* method_name, Mode method_mode,
+                             Symbol* signature, const char * opt, MethodMatcher* next):
     MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) {
     option = opt;
   }
@@ -256,9 +256,9 @@
 
 
 static MethodMatcher* add_predicate(OracleCommand command,
-                                    symbolHandle class_name, MethodMatcher::Mode c_mode,
-                                    symbolHandle method_name, MethodMatcher::Mode m_mode,
-                                    symbolHandle signature) {
+                                    Symbol* class_name, MethodMatcher::Mode c_mode,
+                                    Symbol* method_name, MethodMatcher::Mode m_mode,
+                                    Symbol* signature) {
   assert(command != OptionCommand, "must use add_option_string");
   if (command == LogCommand && !LogCompilation && lists[LogCommand] == NULL)
     tty->print_cr("Warning:  +LogCompilation must be enabled in order for individual methods to be logged.");
@@ -268,9 +268,9 @@
 
 
 
-static MethodMatcher* add_option_string(symbolHandle class_name, MethodMatcher::Mode c_mode,
-                                        symbolHandle method_name, MethodMatcher::Mode m_mode,
-                                        symbolHandle signature,
+static MethodMatcher* add_option_string(Symbol* class_name, MethodMatcher::Mode c_mode,
+                                        Symbol* method_name, MethodMatcher::Mode m_mode,
+                                        Symbol* signature,
                                         const char* option) {
   lists[OptionCommand] = new MethodOptionMatcher(class_name, c_mode, method_name, m_mode,
                                                  signature, option, lists[OptionCommand]);
@@ -497,9 +497,9 @@
 
   if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) {
     EXCEPTION_MARK;
-    symbolHandle c_name = oopFactory::new_symbol_handle(class_name, CHECK);
-    symbolHandle m_name = oopFactory::new_symbol_handle(method_name, CHECK);
-    symbolHandle signature;
+    Symbol* c_name = SymbolTable::new_symbol(class_name, CHECK);
+    Symbol* m_name = SymbolTable::new_symbol(method_name, CHECK);
+    Symbol* signature = NULL;
 
     line += bytes_read;
     // there might be a signature following the method.
@@ -507,7 +507,7 @@
     if (1 == sscanf(line, "%*[ \t](%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) {
       sig[0] = '(';
       line += bytes_read;
-      signature = oopFactory::new_symbol_handle(sig, CHECK);
+      signature = SymbolTable::new_symbol(sig, CHECK);
     }
 
     if (command == OptionCommand) {
@@ -714,9 +714,9 @@
       }
 
       EXCEPTION_MARK;
-      symbolHandle c_name = oopFactory::new_symbol_handle(className, CHECK);
-      symbolHandle m_name = oopFactory::new_symbol_handle(methodName, CHECK);
-      symbolHandle signature;
+      Symbol* c_name = SymbolTable::new_symbol(className, CHECK);
+      Symbol* m_name = SymbolTable::new_symbol(methodName, CHECK);
+      Symbol* signature = NULL;
 
       add_predicate(CompileOnlyCommand, c_name, c_match, m_name, m_match, signature);
       if (PrintVMOptions) {
--- a/src/share/vm/compiler/compilerOracle.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/compiler/compilerOracle.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,8 +31,6 @@
 // CompilerOracle is an interface for turning on and off compilation
 // for some methods
 
-class symbolHandle;
-
 class CompilerOracle : AllStatic {
  private:
   static bool _quiet;
--- a/src/share/vm/compiler/methodLiveness.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/compiler/methodLiveness.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -286,16 +286,15 @@
         break;
       case Bytecodes::_tableswitch:
         {
-          Bytecode_tableswitch *tableswitch =
-            Bytecode_tableswitch_at(bytes.cur_bcp());
+          Bytecode_tableswitch tableswitch(&bytes);
 
-          int len = tableswitch->length();
+          int len = tableswitch.length();
 
-          dest = _block_map->at(bci + tableswitch->default_offset());
+          dest = _block_map->at(bci + tableswitch.default_offset());
           assert(dest != NULL, "branch desination must start a block.");
           dest->add_normal_predecessor(current_block);
           while (--len >= 0) {
-            dest = _block_map->at(bci + tableswitch->dest_offset_at(len));
+            dest = _block_map->at(bci + tableswitch.dest_offset_at(len));
             assert(dest != NULL, "branch desination must start a block.");
             dest->add_normal_predecessor(current_block);
           }
@@ -304,17 +303,16 @@
 
       case Bytecodes::_lookupswitch:
         {
-          Bytecode_lookupswitch *lookupswitch =
-            Bytecode_lookupswitch_at(bytes.cur_bcp());
+          Bytecode_lookupswitch lookupswitch(&bytes);
 
-          int npairs = lookupswitch->number_of_pairs();
+          int npairs = lookupswitch.number_of_pairs();
 
-          dest = _block_map->at(bci + lookupswitch->default_offset());
+          dest = _block_map->at(bci + lookupswitch.default_offset());
           assert(dest != NULL, "branch desination must start a block.");
           dest->add_normal_predecessor(current_block);
           while(--npairs >= 0) {
-            LookupswitchPair *pair = lookupswitch->pair_at(npairs);
-            dest = _block_map->at( bci + pair->offset());
+            LookupswitchPair pair = lookupswitch.pair_at(npairs);
+            dest = _block_map->at( bci + pair.offset());
             assert(dest != NULL, "branch desination must start a block.");
             dest->add_normal_predecessor(current_block);
           }
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -3478,6 +3478,7 @@
   assert(_collectorState == InitialMarking, "Wrong collector state");
   check_correct_thread_executing();
   TraceCMSMemoryManagerStats tms(_collectorState);
+
   ReferenceProcessor* rp = ref_processor();
   SpecializationStats::clear();
   assert(_restart_addr == NULL, "Control point invariant");
@@ -4978,6 +4979,7 @@
   if (should_unload_classes()) {
     CodeCache::gc_epilogue();
   }
+  JvmtiExport::gc_epilogue();
 
   // If we encountered any (marking stack / work queue) overflow
   // events during the current CMS cycle, take appropriate
@@ -5919,9 +5921,10 @@
 
     {
       TraceTime t("scrub symbol & string tables", PrintGCDetails, false, gclog_or_tty);
-      // Now clean up stale oops in SymbolTable and StringTable
-      SymbolTable::unlink(&_is_alive_closure);
+      // Now clean up stale oops in StringTable
       StringTable::unlink(&_is_alive_closure);
+      // Clean up unreferenced symbols in symbol table.
+      SymbolTable::unlink();
     }
   }
 
@@ -5940,11 +5943,6 @@
   }
   rp->verify_no_references_recorded();
   assert(!rp->discovery_enabled(), "should have been disabled");
-
-  // JVMTI object tagging is based on JNI weak refs. If any of these
-  // refs were cleared then JVMTI needs to update its maps and
-  // maybe post ObjectFrees to agents.
-  JvmtiExport::cms_ref_processing_epilogue();
 }
 
 #ifndef PRODUCT
@@ -6305,6 +6303,7 @@
 
   switch (op) {
     case CMS_op_checkpointRootsInitial: {
+      SvcGCMarker sgcm(SvcGCMarker::OTHER);
       checkpointRootsInitial(true);       // asynch
       if (PrintGC) {
         _cmsGen->printOccupancy("initial-mark");
@@ -6312,6 +6311,7 @@
       break;
     }
     case CMS_op_checkpointRootsFinal: {
+      SvcGCMarker sgcm(SvcGCMarker::OTHER);
       checkpointRootsFinal(true,    // asynch
                            false,   // !clear_all_soft_refs
                            false);  // !init_mark_was_synchronous
@@ -7881,25 +7881,23 @@
 }
 
 // We need this destructor to reclaim any space at the end
-// of the space, which do_blk below may not have added back to
-// the free lists. [basically dealing with the "fringe effect"]
+// of the space, which do_blk below may not yet have added back to
+// the free lists.
 SweepClosure::~SweepClosure() {
   assert_lock_strong(_freelistLock);
-  // this should be treated as the end of a free run if any
-  // The current free range should be returned to the free lists
-  // as one coalesced chunk.
+  assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
+         "sweep _limit out of bounds");
+  // Flush any remaining coterminal free run as a single
+  // coalesced chunk to the appropriate free list.
   if (inFreeRange()) {
-    flushCurFreeChunk(freeFinger(),
-      pointer_delta(_limit, freeFinger()));
-    assert(freeFinger() < _limit, "the finger pointeth off base");
+    assert(freeFinger() < _limit, "freeFinger points too high");
+    flush_cur_free_chunk(freeFinger(), pointer_delta(_limit, freeFinger()));
     if (CMSTraceSweeper) {
-      gclog_or_tty->print("destructor:");
-      gclog_or_tty->print("Sweep:put_free_blk 0x%x ("SIZE_FORMAT") "
-                 "[coalesced:"SIZE_FORMAT"]\n",
-                 freeFinger(), pointer_delta(_limit, freeFinger()),
-                 lastFreeRangeCoalesced());
-    }
-  }
+      gclog_or_tty->print("Sweep: last chunk: ");
+      gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") [coalesced:"SIZE_FORMAT"]\n",
+                          freeFinger(), pointer_delta(_limit, freeFinger()), lastFreeRangeCoalesced());
+    }
+  } // else nothing to flush
   NOT_PRODUCT(
     if (Verbose && PrintGC) {
       gclog_or_tty->print("Collected "SIZE_FORMAT" objects, "
@@ -7936,9 +7934,8 @@
 void SweepClosure::initialize_free_range(HeapWord* freeFinger,
     bool freeRangeInFreeLists) {
   if (CMSTraceSweeper) {
-    gclog_or_tty->print("---- Start free range 0x%x with free block [%d] (%d)\n",
-               freeFinger, _sp->block_size(freeFinger),
-               freeRangeInFreeLists);
+    gclog_or_tty->print("---- Start free range at 0x%x with free block (%d)\n",
+               freeFinger, freeRangeInFreeLists);
   }
   assert(!inFreeRange(), "Trampling existing free range");
   set_inFreeRange(true);
@@ -7993,21 +7990,36 @@
   // may have caused us to coalesce the block ending at the address _limit
   // with a newly expanded chunk (this happens when _limit was set to the
   // previous _end of the space), so we may have stepped past _limit; see CR 6977970.
-  if (addr >= _limit) { // we have swept up to or past the limit, do nothing more
+  if (addr >= _limit) { // we have swept up to or past the limit: finish up
     assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
            "sweep _limit out of bounds");
     assert(addr < _sp->end(), "addr out of bounds");
-    // help the closure application finish
+    // Flush any remaining coterminal free run as a single
+    // coalesced chunk to the appropriate free list.
+    if (inFreeRange()) {
+      assert(freeFinger() < _limit, "finger points too high");
+      flush_cur_free_chunk(freeFinger(),
+                           pointer_delta(addr, freeFinger()));
+      if (CMSTraceSweeper) {
+        gclog_or_tty->print("Sweep: last chunk: ");
+        gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") "
+                   "[coalesced:"SIZE_FORMAT"]\n",
+                   freeFinger(), pointer_delta(addr, freeFinger()),
+                   lastFreeRangeCoalesced());
+      }
+    }
+
+    // help the iterator loop finish
     return pointer_delta(_sp->end(), addr);
   }
+
   assert(addr < _limit, "sweep invariant");
-
   // check if we should yield
   do_yield_check(addr);
   if (fc->isFree()) {
     // Chunk that is already free
     res = fc->size();
-    doAlreadyFreeChunk(fc);
+    do_already_free_chunk(fc);
     debug_only(_sp->verifyFreeLists());
     assert(res == fc->size(), "Don't expect the size to change");
     NOT_PRODUCT(
@@ -8017,7 +8029,7 @@
     NOT_PRODUCT(_last_fc = fc;)
   } else if (!_bitMap->isMarked(addr)) {
     // Chunk is fresh garbage
-    res = doGarbageChunk(fc);
+    res = do_garbage_chunk(fc);
     debug_only(_sp->verifyFreeLists());
     NOT_PRODUCT(
       _numObjectsFreed++;
@@ -8025,7 +8037,7 @@
     )
   } else {
     // Chunk that is alive.
-    res = doLiveChunk(fc);
+    res = do_live_chunk(fc);
     debug_only(_sp->verifyFreeLists());
     NOT_PRODUCT(
         _numObjectsLive++;
@@ -8078,7 +8090,7 @@
 // to a free list which may be overpopulated.
 //
 
-void SweepClosure::doAlreadyFreeChunk(FreeChunk* fc) {
+void SweepClosure::do_already_free_chunk(FreeChunk* fc) {
   size_t size = fc->size();
   // Chunks that cannot be coalesced are not in the
   // free lists.
@@ -8094,23 +8106,23 @@
   // addr and purported end of this block.
   _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
 
-  // Some chunks cannot be coalesced in under any circumstances.
+  // Some chunks cannot be coalesced under any circumstances.
   // See the definition of cantCoalesce().
   if (!fc->cantCoalesce()) {
     // This chunk can potentially be coalesced.
     if (_sp->adaptive_freelists()) {
       // All the work is done in
-      doPostIsFreeOrGarbageChunk(fc, size);
+      do_post_free_or_garbage_chunk(fc, size);
     } else {  // Not adaptive free lists
       // this is a free chunk that can potentially be coalesced by the sweeper;
       if (!inFreeRange()) {
         // if the next chunk is a free block that can't be coalesced
         // it doesn't make sense to remove this chunk from the free lists
         FreeChunk* nextChunk = (FreeChunk*)(addr + size);
-        assert((HeapWord*)nextChunk <= _limit, "sweep invariant");
-        if ((HeapWord*)nextChunk < _limit  &&    // there's a next chunk...
-            nextChunk->isFree()    &&            // which is free...
-            nextChunk->cantCoalesce()) {         // ... but cant be coalesced
+        assert((HeapWord*)nextChunk <= _sp->end(), "Chunk size out of bounds?");
+        if ((HeapWord*)nextChunk < _sp->end() &&     // There is another free chunk to the right ...
+            nextChunk->isFree()               &&     // ... which is free...
+            nextChunk->cantCoalesce()) {             // ... but can't be coalesced
           // nothing to do
         } else {
           // Potentially the start of a new free range:
@@ -8156,14 +8168,14 @@
     // as the end of a free run if any
     if (inFreeRange()) {
       // we kicked some butt; time to pick up the garbage
-      assert(freeFinger() < addr, "the finger pointeth off base");
-      flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger()));
+      assert(freeFinger() < addr, "freeFinger points too high");
+      flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger()));
     }
     // else, nothing to do, just continue
   }
 }
 
-size_t SweepClosure::doGarbageChunk(FreeChunk* fc) {
+size_t SweepClosure::do_garbage_chunk(FreeChunk* fc) {
   // This is a chunk of garbage.  It is not in any free list.
   // Add it to a free list or let it possibly be coalesced into
   // a larger chunk.
@@ -8175,7 +8187,7 @@
     // addr and purported end of just dead object.
     _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
 
-    doPostIsFreeOrGarbageChunk(fc, size);
+    do_post_free_or_garbage_chunk(fc, size);
   } else {
     if (!inFreeRange()) {
       // start of a new free range
@@ -8214,35 +8226,16 @@
   return size;
 }
 
-size_t SweepClosure::doLiveChunk(FreeChunk* fc) {
+size_t SweepClosure::do_live_chunk(FreeChunk* fc) {
   HeapWord* addr = (HeapWord*) fc;
   // The sweeper has just found a live object. Return any accumulated
   // left hand chunk to the free lists.
   if (inFreeRange()) {
-    if (_sp->adaptive_freelists()) {
-      flushCurFreeChunk(freeFinger(),
-                        pointer_delta(addr, freeFinger()));
-    } else { // not adaptive freelists
-      set_inFreeRange(false);
-      // Add the free range back to the free list if it is not already
-      // there.
-      if (!freeRangeInFreeLists()) {
-        assert(freeFinger() < addr, "the finger pointeth off base");
-        if (CMSTraceSweeper) {
-          gclog_or_tty->print("Sweep:put_free_blk 0x%x (%d) "
-            "[coalesced:%d]\n",
-            freeFinger(), pointer_delta(addr, freeFinger()),
-            lastFreeRangeCoalesced());
-        }
-        _sp->addChunkAndRepairOffsetTable(freeFinger(),
-          pointer_delta(addr, freeFinger()), lastFreeRangeCoalesced());
-      }
-    }
-  }
-
-  // Common code path for original and adaptive free lists.
-
-  // this object is live: we'd normally expect this to be
+    assert(freeFinger() < addr, "freeFinger points too high");
+    flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger()));
+  }
+
+  // This object is live: we'd normally expect this to be
   // an oop, and like to assert the following:
   // assert(oop(addr)->is_oop(), "live block should be an oop");
   // However, as we commented above, this may be an object whose
@@ -8257,7 +8250,7 @@
     assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
            "alignment problem");
 
-    #ifdef DEBUG
+#ifdef DEBUG
       if (oop(addr)->klass_or_null() != NULL &&
           (   !_collector->should_unload_classes()
            || (oop(addr)->is_parsable()) &&
@@ -8271,7 +8264,7 @@
                CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size()),
                "P-mark and computed size do not agree");
       }
-    #endif
+#endif
 
   } else {
     // This should be an initialized object that's alive.
@@ -8298,18 +8291,16 @@
   return size;
 }
 
-void SweepClosure::doPostIsFreeOrGarbageChunk(FreeChunk* fc,
-                                            size_t chunkSize) {
-  // doPostIsFreeOrGarbageChunk() should only be called in the smart allocation
-  // scheme.
+void SweepClosure::do_post_free_or_garbage_chunk(FreeChunk* fc,
+                                                 size_t chunkSize) {
+  // do_post_free_or_garbage_chunk() should only be called in the case
+  // of the adaptive free list allocator.
   bool fcInFreeLists = fc->isFree();
   assert(_sp->adaptive_freelists(), "Should only be used in this case.");
   assert((HeapWord*)fc <= _limit, "sweep invariant");
   if (CMSTestInFreeList && fcInFreeLists) {
-    assert(_sp->verifyChunkInFreeLists(fc),
-      "free chunk is not in free lists");
-  }
-
+    assert(_sp->verifyChunkInFreeLists(fc), "free chunk is not in free lists");
+  }
 
   if (CMSTraceSweeper) {
     gclog_or_tty->print_cr("  -- pick up another chunk at 0x%x (%d)", fc, chunkSize);
@@ -8382,20 +8373,21 @@
     if (inFreeRange()) {
       // In a free range but cannot coalesce with the right hand chunk.
       // Put the current free range into the free lists.
-      flushCurFreeChunk(freeFinger(),
-        pointer_delta(addr, freeFinger()));
+      flush_cur_free_chunk(freeFinger(),
+                           pointer_delta(addr, freeFinger()));
     }
     // Set up for new free range.  Pass along whether the right hand
     // chunk is in the free lists.
     initialize_free_range((HeapWord*)fc, fcInFreeLists);
   }
 }
-void SweepClosure::flushCurFreeChunk(HeapWord* chunk, size_t size) {
+
+void SweepClosure::flush_cur_free_chunk(HeapWord* chunk, size_t size) {
   assert(inFreeRange(), "Should only be called if currently in a free range.");
   assert(size > 0,
     "A zero sized chunk cannot be added to the free lists.");
   if (!freeRangeInFreeLists()) {
-    if(CMSTestInFreeList) {
+    if (CMSTestInFreeList) {
       FreeChunk* fc = (FreeChunk*) chunk;
       fc->setSize(size);
       assert(!_sp->verifyChunkInFreeLists(fc),
@@ -8430,7 +8422,7 @@
   // chunk just flushed, they will need to wait for the next
   // sweep to be coalesced.
   if (inFreeRange()) {
-    flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger()));
+    flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger()));
   }
 
   // First give up the locks, then yield, then re-lock.
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1701,7 +1701,9 @@
   CMSCollector*                  _collector;  // collector doing the work
   ConcurrentMarkSweepGeneration* _g;    // Generation being swept
   CompactibleFreeListSpace*      _sp;   // Space being swept
-  HeapWord*                      _limit;
+  HeapWord*                      _limit;// the address at which the sweep should stop because
+                                        // we do not expect blocks eligible for sweeping past
+                                        // that address.
   Mutex*                         _freelistLock; // Free list lock (in space)
   CMSBitMap*                     _bitMap;       // Marking bit map (in
                                                 // generation)
@@ -1745,14 +1747,13 @@
  private:
   // Code that is common to a free chunk or garbage when
   // encountered during sweeping.
-  void doPostIsFreeOrGarbageChunk(FreeChunk *fc,
-                                  size_t chunkSize);
+  void do_post_free_or_garbage_chunk(FreeChunk *fc, size_t chunkSize);
   // Process a free chunk during sweeping.
-  void doAlreadyFreeChunk(FreeChunk *fc);
+  void do_already_free_chunk(FreeChunk *fc);
   // Process a garbage chunk during sweeping.
-  size_t doGarbageChunk(FreeChunk *fc);
+  size_t do_garbage_chunk(FreeChunk *fc);
   // Process a live chunk during sweeping.
-  size_t doLiveChunk(FreeChunk* fc);
+  size_t do_live_chunk(FreeChunk* fc);
 
   // Accessors.
   HeapWord* freeFinger() const          { return _freeFinger; }
@@ -1769,7 +1770,7 @@
   // Initialize a free range.
   void initialize_free_range(HeapWord* freeFinger, bool freeRangeInFreeLists);
   // Return this chunk to the free lists.
-  void flushCurFreeChunk(HeapWord* chunk, size_t size);
+  void flush_cur_free_chunk(HeapWord* chunk, size_t size);
 
   // Check if we should yield and do so when necessary.
   inline void do_yield_check(HeapWord* addr);
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 #include "gc_implementation/g1/g1RemSet.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
+#include "gc_implementation/shared/vmGCOperations.hpp"
 #include "memory/genOopClosures.inline.hpp"
 #include "memory/referencePolicy.hpp"
 #include "memory/resourceArea.hpp"
@@ -457,6 +458,7 @@
   _marking_task_overhead(1.0),
   _cleanup_sleep_factor(0.0),
   _cleanup_task_overhead(1.0),
+  _cleanup_list("Cleanup List"),
   _region_bm(max_regions, false /* in_resource_area*/),
   _card_bm((rs.size() + CardTableModRefBS::card_size - 1) >>
            CardTableModRefBS::card_shift,
@@ -520,12 +522,6 @@
   SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set();
   satb_qs.set_buffer_size(G1SATBBufferSize);
 
-  int size = (int) MAX2(ParallelGCThreads, (size_t)1);
-  _par_cleanup_thread_state = NEW_C_HEAP_ARRAY(ParCleanupThreadState*, size);
-  for (int i = 0 ; i < size; i++) {
-    _par_cleanup_thread_state[i] = new ParCleanupThreadState;
-  }
-
   _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num);
   _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num);
 
@@ -710,11 +706,6 @@
 }
 
 ConcurrentMark::~ConcurrentMark() {
-  int size = (int) MAX2(ParallelGCThreads, (size_t)1);
-  for (int i = 0; i < size; i++) delete _par_cleanup_thread_state[i];
-  FREE_C_HEAP_ARRAY(ParCleanupThreadState*,
-                    _par_cleanup_thread_state);
-
   for (int i = 0; i < (int) _max_task_num; ++i) {
     delete _task_queues->queue(i);
     delete _tasks[i];
@@ -1064,7 +1055,12 @@
       do {
         double start_vtime_sec = os::elapsedVTime();
         double start_time_sec = os::elapsedTime();
-        the_task->do_marking_step(10.0);
+        double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
+
+        the_task->do_marking_step(mark_step_duration_ms,
+                                  true /* do_stealing    */,
+                                  true /* do_termination */);
+
         double end_time_sec = os::elapsedTime();
         double end_vtime_sec = os::elapsedVTime();
         double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
@@ -1120,7 +1116,8 @@
 
   _restart_for_overflow = false;
 
-  set_phase(MAX2((size_t) 1, parallel_marking_threads()), true);
+  size_t active_workers = MAX2((size_t) 1, parallel_marking_threads());
+  set_phase(active_workers, true /* concurrent */);
 
   CMConcurrentMarkingTask markingTask(this, cmThread());
   if (parallel_marking_threads() > 0)
@@ -1142,6 +1139,8 @@
     return;
   }
 
+  SvcGCMarker sgcm(SvcGCMarker::OTHER);
+
   if (VerifyDuringGC) {
     HandleMark hm;  // handle scope
     gclog_or_tty->print(" VerifyDuringGC:(before)");
@@ -1168,12 +1167,12 @@
     if (G1TraceMarkStackOverflow)
       gclog_or_tty->print_cr("\nRemark led to restart for overflow.");
   } else {
+    SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
     // We're done with marking.
     // This is the end of  the marking cycle, we're expected all
     // threads to have SATB queues with active set to true.
-    JavaThread::satb_mark_queue_set().set_active_all_threads(
-                                                  false, /* new active value */
-                                                  true /* expected_active */);
+    satb_mq_set.set_active_all_threads(false, /* new active value */
+                                       true /* expected_active */);
 
     if (VerifyDuringGC) {
       HandleMark hm;  // handle scope
@@ -1183,6 +1182,12 @@
                                /* silent */           false,
                                /* use_prev_marking */ false);
     }
+    assert(!restart_for_overflow(), "sanity");
+  }
+
+  // Reset the marking state if marking completed
+  if (!restart_for_overflow()) {
+    set_non_marking_state();
   }
 
 #if VERIFY_OBJS_PROCESSED
@@ -1507,22 +1512,19 @@
   size_t _max_live_bytes;
   size_t _regions_claimed;
   size_t _freed_bytes;
-  size_t _cleared_h_regions;
-  size_t _freed_regions;
-  UncleanRegionList* _unclean_region_list;
+  FreeRegionList* _local_cleanup_list;
+  HumongousRegionSet* _humongous_proxy_set;
+  HRRSCleanupTask* _hrrs_cleanup_task;
   double _claimed_region_time;
   double _max_region_time;
 
 public:
   G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
-                             UncleanRegionList* list,
-                             int worker_num);
+                             int worker_num,
+                             FreeRegionList* local_cleanup_list,
+                             HumongousRegionSet* humongous_proxy_set,
+                             HRRSCleanupTask* hrrs_cleanup_task);
   size_t freed_bytes() { return _freed_bytes; }
-  size_t cleared_h_regions() { return _cleared_h_regions; }
-  size_t freed_regions() { return  _freed_regions; }
-  UncleanRegionList* unclean_region_list() {
-    return _unclean_region_list;
-  }
 
   bool doHeapRegion(HeapRegion *r);
 
@@ -1534,25 +1536,27 @@
 
 class G1ParNoteEndTask: public AbstractGangTask {
   friend class G1NoteEndOfConcMarkClosure;
+
 protected:
   G1CollectedHeap* _g1h;
   size_t _max_live_bytes;
   size_t _freed_bytes;
-  ConcurrentMark::ParCleanupThreadState** _par_cleanup_thread_state;
+  FreeRegionList* _cleanup_list;
+
 public:
   G1ParNoteEndTask(G1CollectedHeap* g1h,
-                   ConcurrentMark::ParCleanupThreadState**
-                   par_cleanup_thread_state) :
+                   FreeRegionList* cleanup_list) :
     AbstractGangTask("G1 note end"), _g1h(g1h),
-    _max_live_bytes(0), _freed_bytes(0),
-    _par_cleanup_thread_state(par_cleanup_thread_state)
-  {}
+    _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { }
 
   void work(int i) {
     double start = os::elapsedTime();
-    G1NoteEndOfConcMarkClosure g1_note_end(_g1h,
-                                           &_par_cleanup_thread_state[i]->list,
-                                           i);
+    FreeRegionList local_cleanup_list("Local Cleanup List");
+    HumongousRegionSet humongous_proxy_set("Local Cleanup Humongous Proxy Set");
+    HRRSCleanupTask hrrs_cleanup_task;
+    G1NoteEndOfConcMarkClosure g1_note_end(_g1h, i, &local_cleanup_list,
+                                           &humongous_proxy_set,
+                                           &hrrs_cleanup_task);
     if (G1CollectedHeap::use_parallel_gc_threads()) {
       _g1h->heap_region_par_iterate_chunked(&g1_note_end, i,
                                             HeapRegion::NoteEndClaimValue);
@@ -1561,14 +1565,20 @@
     }
     assert(g1_note_end.complete(), "Shouldn't have yielded!");
 
-    // Now finish up freeing the current thread's regions.
-    _g1h->finish_free_region_work(g1_note_end.freed_bytes(),
-                                  g1_note_end.cleared_h_regions(),
-                                  0, NULL);
+    // Now update the lists
+    _g1h->update_sets_after_freeing_regions(g1_note_end.freed_bytes(),
+                                            NULL /* free_list */,
+                                            &humongous_proxy_set,
+                                            true /* par */);
     {
       MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
       _max_live_bytes += g1_note_end.max_live_bytes();
       _freed_bytes += g1_note_end.freed_bytes();
+
+      _cleanup_list->add_as_tail(&local_cleanup_list);
+      assert(local_cleanup_list.is_empty(), "post-condition");
+
+      HeapRegionRemSet::finish_cleanup_task(&hrrs_cleanup_task);
     }
     double end = os::elapsedTime();
     if (G1PrintParCleanupStats) {
@@ -1609,30 +1619,33 @@
 
 G1NoteEndOfConcMarkClosure::
 G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
-                           UncleanRegionList* list,
-                           int worker_num)
+                           int worker_num,
+                           FreeRegionList* local_cleanup_list,
+                           HumongousRegionSet* humongous_proxy_set,
+                           HRRSCleanupTask* hrrs_cleanup_task)
   : _g1(g1), _worker_num(worker_num),
     _max_live_bytes(0), _regions_claimed(0),
-    _freed_bytes(0), _cleared_h_regions(0), _freed_regions(0),
+    _freed_bytes(0),
     _claimed_region_time(0.0), _max_region_time(0.0),
-    _unclean_region_list(list)
-{}
-
-bool G1NoteEndOfConcMarkClosure::doHeapRegion(HeapRegion *r) {
+    _local_cleanup_list(local_cleanup_list),
+    _humongous_proxy_set(humongous_proxy_set),
+    _hrrs_cleanup_task(hrrs_cleanup_task) { }
+
+bool G1NoteEndOfConcMarkClosure::doHeapRegion(HeapRegion *hr) {
   // We use a claim value of zero here because all regions
   // were claimed with value 1 in the FinalCount task.
-  r->reset_gc_time_stamp();
-  if (!r->continuesHumongous()) {
+  hr->reset_gc_time_stamp();
+  if (!hr->continuesHumongous()) {
     double start = os::elapsedTime();
     _regions_claimed++;
-    r->note_end_of_marking();
-    _max_live_bytes += r->max_live_bytes();
-    _g1->free_region_if_totally_empty_work(r,
-                                           _freed_bytes,
-                                           _cleared_h_regions,
-                                           _freed_regions,
-                                           _unclean_region_list,
-                                           true /*par*/);
+    hr->note_end_of_marking();
+    _max_live_bytes += hr->max_live_bytes();
+    _g1->free_region_if_empty(hr,
+                              &_freed_bytes,
+                              _local_cleanup_list,
+                              _humongous_proxy_set,
+                              _hrrs_cleanup_task,
+                              true /* par */);
     double region_time = (os::elapsedTime() - start);
     _claimed_region_time += region_time;
     if (region_time > _max_region_time) _max_region_time = region_time;
@@ -1652,6 +1665,8 @@
     return;
   }
 
+  g1h->verify_region_sets_optional();
+
   if (VerifyDuringGC) {
     HandleMark hm;  // handle scope
     gclog_or_tty->print(" VerifyDuringGC:(before)");
@@ -1666,6 +1681,8 @@
 
   double start = os::elapsedTime();
 
+  HeapRegionRemSet::reset_for_cleanup_tasks();
+
   // Do counting once more with the world stopped for good measure.
   G1ParFinalCountTask g1_par_count_task(g1h, nextMarkBitMap(),
                                         &_region_bm, &_card_bm);
@@ -1716,7 +1733,7 @@
 
   // Note end of marking in all heap regions.
   double note_end_start = os::elapsedTime();
-  G1ParNoteEndTask g1_par_note_end_task(g1h, _par_cleanup_thread_state);
+  G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list);
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     int n_workers = g1h->workers()->total_workers();
     g1h->set_par_threads(n_workers);
@@ -1728,9 +1745,14 @@
   } else {
     g1_par_note_end_task.work(0);
   }
-  g1h->set_unclean_regions_coming(true);
+
+  if (!cleanup_list_is_empty()) {
+    // The cleanup list is not empty, so we'll have to process it
+    // concurrently. Notify anyone else that might be wanting free
+    // regions that there will be more free regions coming soon.
+    g1h->set_free_regions_coming();
+  }
   double note_end_end = os::elapsedTime();
-  // Tell the mutators that there might be unclean regions coming...
   if (G1PrintParCleanupStats) {
     gclog_or_tty->print_cr("  note end of marking: %8.3f ms.",
                            (note_end_end - note_end_start)*1000.0);
@@ -1796,35 +1818,67 @@
                      /* silent       */ false,
                      /* prev marking */ true);
   }
+
+  g1h->verify_region_sets_optional();
 }
 
 void ConcurrentMark::completeCleanup() {
-  // A full collection intervened.
   if (has_aborted()) return;
 
-  int first = 0;
-  int last = (int)MAX2(ParallelGCThreads, (size_t)1);
-  for (int t = 0; t < last; t++) {
-    UncleanRegionList* list = &_par_cleanup_thread_state[t]->list;
-    assert(list->well_formed(), "Inv");
-    HeapRegion* hd = list->hd();
-    while (hd != NULL) {
-      // Now finish up the other stuff.
-      hd->rem_set()->clear();
-      HeapRegion* next_hd = hd->next_from_unclean_list();
-      (void)list->pop();
-      assert(list->hd() == next_hd, "how not?");
-      _g1h->put_region_on_unclean_list(hd);
-      if (!hd->isHumongous()) {
-        // Add this to the _free_regions count by 1.
-        _g1h->finish_free_region_work(0, 0, 1, NULL);
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+  _cleanup_list.verify_optional();
+  FreeRegionList local_free_list("Local Cleanup List");
+
+  if (G1ConcRegionFreeingVerbose) {
+    gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
+                           "cleanup list has "SIZE_FORMAT" entries",
+                           _cleanup_list.length());
+  }
+
+  // Noone else should be accessing the _cleanup_list at this point,
+  // so it's not necessary to take any locks
+  while (!_cleanup_list.is_empty()) {
+    HeapRegion* hr = _cleanup_list.remove_head();
+    assert(hr != NULL, "the list was not empty");
+    hr->rem_set()->clear();
+    local_free_list.add_as_tail(hr);
+
+    // Instead of adding one region at a time to the secondary_free_list,
+    // we accumulate them in the local list and move them a few at a
+    // time. This also cuts down on the number of notify_all() calls
+    // we do during this process. We'll also append the local list when
+    // _cleanup_list is empty (which means we just removed the last
+    // region from the _cleanup_list).
+    if ((local_free_list.length() % G1SecondaryFreeListAppendLength == 0) ||
+        _cleanup_list.is_empty()) {
+      if (G1ConcRegionFreeingVerbose) {
+        gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
+                               "appending "SIZE_FORMAT" entries to the "
+                               "secondary_free_list, clean list still has "
+                               SIZE_FORMAT" entries",
+                               local_free_list.length(),
+                               _cleanup_list.length());
       }
-      hd = list->hd();
-      assert(hd == next_hd, "how not?");
+
+      {
+        MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+        g1h->secondary_free_list_add_as_tail(&local_free_list);
+        SecondaryFreeList_lock->notify_all();
+      }
+
+      if (G1StressConcRegionFreeing) {
+        for (uintx i = 0; i < G1StressConcRegionFreeingDelayMillis; ++i) {
+          os::sleep(Thread::current(), (jlong) 1, false);
+        }
+      }
     }
   }
+  assert(local_free_list.is_empty(), "post-condition");
 }
 
+// Support closures for reference procssing in G1
+
 bool G1CMIsAliveClosure::do_object_b(oop obj) {
   HeapWord* addr = (HeapWord*)obj;
   return addr != NULL &&
@@ -1845,11 +1899,17 @@
   virtual void do_oop(      oop* p) { do_oop_work(p); }
 
   template <class T> void do_oop_work(T* p) {
-    oop thisOop = oopDesc::load_decode_heap_oop(p);
-    HeapWord* addr = (HeapWord*)thisOop;
-    if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(thisOop)) {
+    oop obj = oopDesc::load_decode_heap_oop(p);
+    HeapWord* addr = (HeapWord*)obj;
+
+    if (_cm->verbose_high())
+      gclog_or_tty->print_cr("\t[0] we're looking at location "
+                               "*"PTR_FORMAT" = "PTR_FORMAT,
+                               p, (void*) obj);
+
+    if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(obj)) {
       _bitMap->mark(addr);
-      _cm->mark_stack_push(thisOop);
+      _cm->mark_stack_push(obj);
     }
   }
 };
@@ -1871,6 +1931,199 @@
   }
 };
 
+// 'Keep Alive' closure used by parallel reference processing.
+// An instance of this closure is used in the parallel reference processing
+// code rather than an instance of G1CMKeepAliveClosure. We could have used
+// the G1CMKeepAliveClosure as it is MT-safe. Also reference objects are
+// placed on to discovered ref lists once so we can mark and push with no
+// need to check whether the object has already been marked. Using the
+// G1CMKeepAliveClosure would mean, however, having all the worker threads
+// operating on the global mark stack. This means that an individual
+// worker would be doing lock-free pushes while it processes its own
+// discovered ref list followed by drain call. If the discovered ref lists
+// are unbalanced then this could cause interference with the other
+// workers. Using a CMTask (and its embedded local data structures)
+// avoids that potential interference.
+class G1CMParKeepAliveAndDrainClosure: public OopClosure {
+  ConcurrentMark*  _cm;
+  CMTask*          _task;
+  CMBitMap*        _bitMap;
+  int              _ref_counter_limit;
+  int              _ref_counter;
+ public:
+  G1CMParKeepAliveAndDrainClosure(ConcurrentMark* cm,
+                                  CMTask* task,
+                                  CMBitMap* bitMap) :
+    _cm(cm), _task(task), _bitMap(bitMap),
+    _ref_counter_limit(G1RefProcDrainInterval)
+  {
+    assert(_ref_counter_limit > 0, "sanity");
+    _ref_counter = _ref_counter_limit;
+  }
+
+  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
+  virtual void do_oop(      oop* p) { do_oop_work(p); }
+
+  template <class T> void do_oop_work(T* p) {
+    if (!_cm->has_overflown()) {
+      oop obj = oopDesc::load_decode_heap_oop(p);
+      if (_cm->verbose_high())
+        gclog_or_tty->print_cr("\t[%d] we're looking at location "
+                               "*"PTR_FORMAT" = "PTR_FORMAT,
+                               _task->task_id(), p, (void*) obj);
+
+      _task->deal_with_reference(obj);
+      _ref_counter--;
+
+      if (_ref_counter == 0) {
+        // We have dealt with _ref_counter_limit references, pushing them and objects
+        // reachable from them on to the local stack (and possibly the global stack).
+        // Call do_marking_step() to process these entries. We call the routine in a
+        // loop, which we'll exit if there's nothing more to do (i.e. we're done
+        // with the entries that we've pushed as a result of the deal_with_reference
+        // calls above) or we overflow.
+        // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag
+        // while there may still be some work to do. (See the comment at the
+        // beginning of CMTask::do_marking_step() for those conditions - one of which
+        // is reaching the specified time target.) It is only when
+        // CMTask::do_marking_step() returns without setting the has_aborted() flag
+        // that the marking has completed.
+        do {
+          double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
+          _task->do_marking_step(mark_step_duration_ms,
+                                 false /* do_stealing    */,
+                                 false /* do_termination */);
+        } while (_task->has_aborted() && !_cm->has_overflown());
+        _ref_counter = _ref_counter_limit;
+      }
+    } else {
+       if (_cm->verbose_high())
+         gclog_or_tty->print_cr("\t[%d] CM Overflow", _task->task_id());
+    }
+  }
+};
+
+class G1CMParDrainMarkingStackClosure: public VoidClosure {
+  ConcurrentMark* _cm;
+  CMTask* _task;
+ public:
+  G1CMParDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task) :
+    _cm(cm), _task(task)
+  {}
+
+  void do_void() {
+    do {
+      if (_cm->verbose_high())
+        gclog_or_tty->print_cr("\t[%d] Drain: Calling do marking_step", _task->task_id());
+
+      // We call CMTask::do_marking_step() to completely drain the local and
+      // global marking stacks. The routine is called in a loop, which we'll
+      // exit if there's nothing more to do (i.e. we'completely drained the
+      // entries that were pushed as a result of applying the
+      // G1CMParKeepAliveAndDrainClosure to the entries on the discovered ref
+      // lists above) or we overflow the global marking stack.
+      // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag
+      // while there may still be some work to do. (See the comment at the
+      // beginning of CMTask::do_marking_step() for those conditions - one of which
+      // is reaching the specified time target.) It is only when
+      // CMTask::do_marking_step() returns without setting the has_aborted() flag
+      // that the marking has completed.
+
+      _task->do_marking_step(1000000000.0 /* something very large */,
+                             true /* do_stealing    */,
+                             true /* do_termination */);
+    } while (_task->has_aborted() && !_cm->has_overflown());
+  }
+};
+
+// Implementation of AbstractRefProcTaskExecutor for G1
+class G1RefProcTaskExecutor: public AbstractRefProcTaskExecutor {
+private:
+  G1CollectedHeap* _g1h;
+  ConcurrentMark*  _cm;
+  CMBitMap*        _bitmap;
+  WorkGang*        _workers;
+  int              _active_workers;
+
+public:
+  G1RefProcTaskExecutor(G1CollectedHeap* g1h,
+                        ConcurrentMark* cm,
+                        CMBitMap* bitmap,
+                        WorkGang* workers,
+                        int n_workers) :
+    _g1h(g1h), _cm(cm), _bitmap(bitmap),
+    _workers(workers), _active_workers(n_workers)
+  { }
+
+  // Executes the given task using concurrent marking worker threads.
+  virtual void execute(ProcessTask& task);
+  virtual void execute(EnqueueTask& task);
+};
+
+class G1RefProcTaskProxy: public AbstractGangTask {
+  typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
+  ProcessTask&     _proc_task;
+  G1CollectedHeap* _g1h;
+  ConcurrentMark*  _cm;
+  CMBitMap*        _bitmap;
+
+public:
+  G1RefProcTaskProxy(ProcessTask& proc_task,
+                     G1CollectedHeap* g1h,
+                     ConcurrentMark* cm,
+                     CMBitMap* bitmap) :
+    AbstractGangTask("Process reference objects in parallel"),
+    _proc_task(proc_task), _g1h(g1h), _cm(cm), _bitmap(bitmap)
+  {}
+
+  virtual void work(int i) {
+    CMTask* marking_task = _cm->task(i);
+    G1CMIsAliveClosure g1_is_alive(_g1h);
+    G1CMParKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task, _bitmap);
+    G1CMParDrainMarkingStackClosure g1_par_drain(_cm, marking_task);
+
+    _proc_task.work(i, g1_is_alive, g1_par_keep_alive, g1_par_drain);
+  }
+};
+
+void G1RefProcTaskExecutor::execute(ProcessTask& proc_task) {
+  assert(_workers != NULL, "Need parallel worker threads.");
+
+  G1RefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm, _bitmap);
+
+  // We need to reset the phase for each task execution so that
+  // the termination protocol of CMTask::do_marking_step works.
+  _cm->set_phase(_active_workers, false /* concurrent */);
+  _g1h->set_par_threads(_active_workers);
+  _workers->run_task(&proc_task_proxy);
+  _g1h->set_par_threads(0);
+}
+
+class G1RefEnqueueTaskProxy: public AbstractGangTask {
+  typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
+  EnqueueTask& _enq_task;
+
+public:
+  G1RefEnqueueTaskProxy(EnqueueTask& enq_task) :
+    AbstractGangTask("Enqueue reference objects in parallel"),
+    _enq_task(enq_task)
+  { }
+
+  virtual void work(int i) {
+    _enq_task.work(i);
+  }
+};
+
+void G1RefProcTaskExecutor::execute(EnqueueTask& enq_task) {
+  assert(_workers != NULL, "Need parallel worker threads.");
+
+  G1RefEnqueueTaskProxy enq_task_proxy(enq_task);
+
+  _g1h->set_par_threads(_active_workers);
+  _workers->run_task(&enq_task_proxy);
+  _g1h->set_par_threads(0);
+}
+
 void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
   ResourceMark rm;
   HandleMark   hm;
@@ -1889,24 +2142,59 @@
   G1CMDrainMarkingStackClosure
     g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive);
 
-  // XXXYYY  Also: copy the parallel ref processing code from CMS.
-  rp->process_discovered_references(&g1_is_alive,
-                                    &g1_keep_alive,
-                                    &g1_drain_mark_stack,
-                                    NULL);
+  // We use the work gang from the G1CollectedHeap and we utilize all
+  // the worker threads.
+  int active_workers = MAX2(MIN2(g1h->workers()->total_workers(), (int)_max_task_num), 1);
+
+  G1RefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(),
+                                          g1h->workers(), active_workers);
+
+  if (rp->processing_is_mt()) {
+    // Set the degree of MT here.  If the discovery is done MT, there
+    // may have been a different number of threads doing the discovery
+    // and a different number of discovered lists may have Ref objects.
+    // That is OK as long as the Reference lists are balanced (see
+    // balance_all_queues() and balance_queues()).
+    rp->set_mt_degree(active_workers);
+
+    rp->process_discovered_references(&g1_is_alive,
+                                      &g1_keep_alive,
+                                      &g1_drain_mark_stack,
+                                      &par_task_executor);
+
+    // The work routines of the parallel keep_alive and drain_marking_stack
+    // will set the has_overflown flag if we overflow the global marking
+    // stack.
+  } else {
+    rp->process_discovered_references(&g1_is_alive,
+                                      &g1_keep_alive,
+                                      &g1_drain_mark_stack,
+                                      NULL);
+
+  }
+
   assert(_markStack.overflow() || _markStack.isEmpty(),
-         "mark stack should be empty (unless it overflowed)");
+      "mark stack should be empty (unless it overflowed)");
   if (_markStack.overflow()) {
+    // Should have been done already when we tried to push an
+    // entry on to the global mark stack. But let's do it again.
     set_has_overflown();
   }
 
-  rp->enqueue_discovered_references();
+  if (rp->processing_is_mt()) {
+    assert(rp->num_q() == active_workers, "why not");
+    rp->enqueue_discovered_references(&par_task_executor);
+  } else {
+    rp->enqueue_discovered_references();
+  }
+
   rp->verify_no_references_recorded();
   assert(!rp->discovery_enabled(), "should have been disabled");
 
-  // Now clean up stale oops in SymbolTable and StringTable
-  SymbolTable::unlink(&g1_is_alive);
+  // Now clean up stale oops in StringTable
   StringTable::unlink(&g1_is_alive);
+  // Clean up unreferenced symbols in symbol table.
+  SymbolTable::unlink();
 }
 
 void ConcurrentMark::swapMarkBitMaps() {
@@ -1927,7 +2215,9 @@
       CMTask* task = _cm->task(worker_i);
       task->record_start_time();
       do {
-        task->do_marking_step(1000000000.0 /* something very large */);
+        task->do_marking_step(1000000000.0 /* something very large */,
+                              true /* do_stealing    */,
+                              true /* do_termination */);
       } while (task->has_aborted() && !_cm->has_overflown());
       // If we overflow, then we do not want to restart. We instead
       // want to abort remark and do concurrent marking again.
@@ -1950,7 +2240,7 @@
     G1CollectedHeap::StrongRootsScope srs(g1h);
     // this is remark, so we'll use up all available threads
     int active_workers = ParallelGCThreads;
-    set_phase(active_workers, false);
+    set_phase(active_workers, false /* concurrent */);
 
     CMRemarkTask remarkTask(this);
     // We will start all available threads, even if we decide that the
@@ -1964,7 +2254,7 @@
     G1CollectedHeap::StrongRootsScope srs(g1h);
     // this is remark, so we'll use up all available threads
     int active_workers = 1;
-    set_phase(active_workers, false);
+    set_phase(active_workers, false /* concurrent */);
 
     CMRemarkTask remarkTask(this);
     // We will start all available threads, even if we decide that the
@@ -1977,9 +2267,6 @@
 
   print_stats();
 
-  if (!restart_for_overflow())
-    set_non_marking_state();
-
 #if VERIFY_OBJS_PROCESSED
   if (_scan_obj_cl.objs_processed != ThreadLocalObjQueue::objs_enqueued) {
     gclog_or_tty->print_cr("Processed = %d, enqueued = %d.",
@@ -2894,9 +3181,9 @@
   virtual void do_oop(      oop* p) { do_oop_work(p); }
 
   template <class T> void do_oop_work(T* p) {
-    assert(_g1h->is_in_g1_reserved((HeapWord*) p), "invariant");
-    assert(!_g1h->heap_region_containing((HeapWord*) p)->is_on_free_list(),
-           "invariant");
+    assert( _g1h->is_in_g1_reserved((HeapWord*) p), "invariant");
+    assert(!_g1h->is_on_free_list(
+                    _g1h->heap_region_containing((HeapWord*) p)), "invariant");
 
     oop obj = oopDesc::load_decode_heap_oop(p);
     if (_cm->verbose_high())
@@ -3096,7 +3383,7 @@
           // do nothing
         }
 #else // _CHECK_BOTH_FINGERS_
-      // we will only check the global finger
+        // we will only check the global finger
 
         if (objAddr < global_finger) {
           // see long comment above
@@ -3116,8 +3403,8 @@
 void CMTask::push(oop obj) {
   HeapWord* objAddr = (HeapWord*) obj;
   assert(_g1h->is_in_g1_reserved(objAddr), "invariant");
-  assert(!_g1h->heap_region_containing(objAddr)->is_on_free_list(),
-         "invariant");
+  assert(!_g1h->is_on_free_list(
+              _g1h->heap_region_containing((HeapWord*) objAddr)), "invariant");
   assert(!_g1h->is_obj_ill(obj), "invariant");
   assert(_nextMarkBitMap->isMarked(objAddr), "invariant");
 
@@ -3221,7 +3508,7 @@
   double elapsed_time_ms = curr_time_ms - _start_time_ms;
   if (elapsed_time_ms > _time_target_ms) {
     set_has_aborted();
-    _has_aborted_timed_out = true;
+    _has_timed_out = true;
     statsOnly( ++_aborted_timed_out );
     return;
   }
@@ -3362,8 +3649,8 @@
                                (void*) obj);
 
       assert(_g1h->is_in_g1_reserved((HeapWord*) obj), "invariant" );
-      assert(!_g1h->heap_region_containing(obj)->is_on_free_list(),
-             "invariant");
+      assert(!_g1h->is_on_free_list(
+                  _g1h->heap_region_containing((HeapWord*) obj)), "invariant");
 
       scan_object(obj);
 
@@ -3726,7 +4013,9 @@
 
  *****************************************************************************/
 
-void CMTask::do_marking_step(double time_target_ms) {
+void CMTask::do_marking_step(double time_target_ms,
+                             bool do_stealing,
+                             bool do_termination) {
   assert(time_target_ms >= 1.0, "minimum granularity is 1ms");
   assert(concurrent() == _cm->concurrent(), "they should be the same");
 
@@ -3766,7 +4055,7 @@
 
   // clear all flags
   clear_has_aborted();
-  _has_aborted_timed_out = false;
+  _has_timed_out = false;
   _draining_satb_buffers = false;
 
   ++_calls;
@@ -3942,7 +4231,7 @@
   drain_global_stack(false);
 
   // Attempt at work stealing from other task's queues.
-  if (!has_aborted()) {
+  if (do_stealing && !has_aborted()) {
     // We have not aborted. This means that we have finished all that
     // we could. Let's try to do some stealing...
 
@@ -3983,7 +4272,7 @@
 
   // We still haven't aborted. Now, let's try to get into the
   // termination protocol.
-  if (!has_aborted()) {
+  if (do_termination && !has_aborted()) {
     // We cannot check whether the global stack is empty, since other
     // tasks might be concurrently pushing objects on it. We also cannot
     // check if the region stack is empty because if a thread is aborting
@@ -4059,7 +4348,7 @@
 
     statsOnly( ++_aborted );
 
-    if (_has_aborted_timed_out) {
+    if (_has_timed_out) {
       double diff_ms = elapsed_time_ms - _time_target_ms;
       // Keep statistics of how well we did with respect to hitting
       // our target only if we actually timed out (if we aborted for
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP
 
-#include "gc_implementation/g1/heapRegion.hpp"
+#include "gc_implementation/g1/heapRegionSets.hpp"
 #include "utilities/taskqueue.hpp"
 
 class G1CollectedHeap;
@@ -353,6 +353,10 @@
   friend class CMConcurrentMarkingTask;
   friend class G1ParNoteEndTask;
   friend class CalcLiveObjectsClosure;
+  friend class G1RefProcTaskProxy;
+  friend class G1RefProcTaskExecutor;
+  friend class G1CMParKeepAliveAndDrainClosure;
+  friend class G1CMParDrainMarkingStackClosure;
 
 protected:
   ConcurrentMarkThread* _cmThread;   // the thread doing the work
@@ -369,13 +373,7 @@
   double                _cleanup_sleep_factor;
   double                _cleanup_task_overhead;
 
-  // Stuff related to age cohort processing.
-  struct ParCleanupThreadState {
-    char _pre[64];
-    UncleanRegionList list;
-    char _post[64];
-  };
-  ParCleanupThreadState** _par_cleanup_thread_state;
+  FreeRegionList        _cleanup_list;
 
   // CMS marking support structures
   CMBitMap                _markBitMap1;
@@ -484,6 +482,10 @@
   // prints all gathered CM-related statistics
   void print_stats();
 
+  bool cleanup_list_is_empty() {
+    return _cleanup_list.is_empty();
+  }
+
   // accessor methods
   size_t parallel_marking_threads() { return _parallel_marking_threads; }
   double sleep_factor()             { return _sleep_factor; }
@@ -938,7 +940,7 @@
   // if this is true, then the task has aborted for some reason
   bool                        _has_aborted;
   // set when the task aborts because it has met its time quota
-  bool                        _has_aborted_timed_out;
+  bool                        _has_timed_out;
   // true when we're draining SATB buffers; this avoids the task
   // aborting due to SATB buffers being available (as we're already
   // dealing with them)
@@ -1043,7 +1045,7 @@
   // trying not to exceed the given duration. However, it might exit
   // prematurely, according to some conditions (i.e. SATB buffers are
   // available for processing).
-  void do_marking_step(double target_ms);
+  void do_marking_step(double target_ms, bool do_stealing, bool do_termination);
 
   // These two calls start and stop the timer
   void record_start_time() {
@@ -1065,7 +1067,8 @@
   bool has_aborted()            { return _has_aborted; }
   void set_has_aborted()        { _has_aborted = true; }
   void clear_has_aborted()      { _has_aborted = false; }
-  bool claimed() { return _claimed; }
+  bool has_timed_out()          { return _has_timed_out; }
+  bool claimed()                { return _claimed; }
 
   // Support routines for the partially scanned region that may be
   // recorded as a result of aborting while draining the CMRegionStack
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -95,8 +95,8 @@
   _vtime_start = os::elapsedVTime();
   wait_for_universe_init();
 
-  G1CollectedHeap* g1 = G1CollectedHeap::heap();
-  G1CollectorPolicy* g1_policy = g1->g1_policy();
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  G1CollectorPolicy* g1_policy = g1h->g1_policy();
   G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
   Thread *current_thread = Thread::current();
 
@@ -119,7 +119,7 @@
       if (!g1_policy->in_young_gc_mode()) {
         // this ensures the flag is not set if we bail out of the marking
         // cycle; normally the flag is cleared immediately after cleanup
-        g1->set_marking_complete();
+        g1h->set_marking_complete();
 
         if (g1_policy->adaptive_young_list_length()) {
           double now = os::elapsedTime();
@@ -228,10 +228,20 @@
         VM_CGC_Operation op(&cl_cl, verbose_str);
         VMThread::execute(&op);
       } else {
-        G1CollectedHeap::heap()->set_marking_complete();
+        g1h->set_marking_complete();
       }
 
-      if (!cm()->has_aborted()) {
+      // Check if cleanup set the free_regions_coming flag. If it
+      // hasn't, we can just skip the next step.
+      if (g1h->free_regions_coming()) {
+        // The following will finish freeing up any regions that we
+        // found to be empty during cleanup. We'll do this part
+        // without joining the suspendible set. If an evacuation pause
+        // takes places, then we would carry on freeing regions in
+        // case they are needed by the pause. If a Full GC takes
+        // places, it would wait for us to process the regions
+        // reclaimed by cleanup.
+
         double cleanup_start_sec = os::elapsedTime();
         if (PrintGC) {
           gclog_or_tty->date_stamp(PrintGCDateStamps);
@@ -240,23 +250,24 @@
         }
 
         // Now do the remainder of the cleanup operation.
+        _cm->completeCleanup();
         _sts.join();
-        _cm->completeCleanup();
-        if (!cm()->has_aborted()) {
-          g1_policy->record_concurrent_mark_cleanup_completed();
+        g1_policy->record_concurrent_mark_cleanup_completed();
+        _sts.leave();
 
-          double cleanup_end_sec = os::elapsedTime();
-          if (PrintGC) {
-            gclog_or_tty->date_stamp(PrintGCDateStamps);
-            gclog_or_tty->stamp(PrintGCTimeStamps);
-            gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]",
-                                   cleanup_end_sec - cleanup_start_sec);
-          }
+        double cleanup_end_sec = os::elapsedTime();
+        if (PrintGC) {
+          gclog_or_tty->date_stamp(PrintGCDateStamps);
+          gclog_or_tty->stamp(PrintGCTimeStamps);
+          gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]",
+                                 cleanup_end_sec - cleanup_start_sec);
         }
-        _sts.leave();
+
+        // We're done: no more free regions coming.
+        g1h->reset_free_regions_coming();
       }
-      // We're done: no more unclean regions coming.
-      G1CollectedHeap::heap()->set_unclean_regions_coming(false);
+      guarantee(cm()->cleanup_list_is_empty(),
+                "at this point there should be no regions on the cleanup list");
 
       if (cm()->has_aborted()) {
         if (PrintGC) {
@@ -278,7 +289,7 @@
     // Java thread is waiting for a full GC to happen (e.g., it
     // called System.gc() with +ExplicitGCInvokesConcurrent).
     _sts.join();
-    g1->increment_full_collections_completed(true /* concurrent */);
+    g1h->increment_full_collections_completed(true /* concurrent */);
     _sts.leave();
   }
   assert(_should_terminate, "just checking");
--- a/src/share/vm/gc_implementation/g1/concurrentZFThread.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/g1/concurrentZFThread.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
-#include "gc_implementation/g1/heapRegion.hpp"
-#include "memory/space.inline.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "utilities/copy.hpp"
-
-// ======= Concurrent Zero-Fill Thread ========
-
-// The CM thread is created when the G1 garbage collector is used
-
-int ConcurrentZFThread::_region_allocs = 0;
-int ConcurrentZFThread::_sync_zfs = 0;
-int ConcurrentZFThread::_zf_waits = 0;
-int ConcurrentZFThread::_regions_filled = 0;
-
-ConcurrentZFThread::ConcurrentZFThread() :
-  ConcurrentGCThread()
-{
-  create_and_start();
-}
-
-void ConcurrentZFThread::wait_for_ZF_completed(HeapRegion* hr) {
-  assert(ZF_mon->owned_by_self(), "Precondition.");
-  note_zf_wait();
-  while (hr->zero_fill_state() == HeapRegion::ZeroFilling) {
-    ZF_mon->wait(Mutex::_no_safepoint_check_flag);
-  }
-}
-
-void ConcurrentZFThread::processHeapRegion(HeapRegion* hr) {
-  assert(!Universe::heap()->is_gc_active(),
-         "This should not happen during GC.");
-  assert(hr != NULL, "Precondition");
-  // These are unlocked reads, but if this test is successful, then no
-  // other thread will attempt this zero filling.  Only a GC thread can
-  // modify the ZF state of a region whose state is zero-filling, and this
-  // should only happen while the ZF thread is locking out GC.
-  if (hr->zero_fill_state() == HeapRegion::ZeroFilling
-      && hr->zero_filler() == Thread::current()) {
-    assert(hr->top() == hr->bottom(), "better be empty!");
-    assert(!hr->isHumongous(), "Only free regions on unclean list.");
-    Copy::fill_to_words(hr->bottom(), hr->capacity()/HeapWordSize);
-    note_region_filled();
-  }
-}
-
-void ConcurrentZFThread::run() {
-  initialize_in_thread();
-  Thread* thr_self = Thread::current();
-  _vtime_start = os::elapsedVTime();
-  wait_for_universe_init();
-
-  G1CollectedHeap* g1 = G1CollectedHeap::heap();
-  _sts.join();
-  while (!_should_terminate) {
-    _sts.leave();
-
-    {
-      MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-
-      // This local variable will hold a region being zero-filled.  This
-      // region will neither be on the unclean or zero-filled lists, and
-      // will not be available for allocation; thus, we might have an
-      // allocation fail, causing a full GC, because of this, but this is a
-      // price we will pay.  (In future, we might want to make the fact
-      // that there's a region being zero-filled apparent to the G1 heap,
-      // which could then wait for it in this extreme case...)
-      HeapRegion* to_fill;
-
-      while (!g1->should_zf()
-             || (to_fill = g1->pop_unclean_region_list_locked()) == NULL)
-        ZF_mon->wait(Mutex::_no_safepoint_check_flag);
-      while (to_fill->zero_fill_state() == HeapRegion::ZeroFilling)
-        ZF_mon->wait(Mutex::_no_safepoint_check_flag);
-
-      // So now to_fill is non-NULL and is not ZeroFilling.  It might be
-      // Allocated or ZeroFilled.  (The latter could happen if this thread
-      // starts the zero-filling of a region, but a GC intervenes and
-      // pushes new regions needing on the front of the filling on the
-      // front of the list.)
-
-      switch (to_fill->zero_fill_state()) {
-      case HeapRegion::Allocated:
-        to_fill = NULL;
-        break;
-
-      case HeapRegion::NotZeroFilled:
-        to_fill->set_zero_fill_in_progress(thr_self);
-
-        ZF_mon->unlock();
-        _sts.join();
-        processHeapRegion(to_fill);
-        _sts.leave();
-        ZF_mon->lock_without_safepoint_check();
-
-        if (to_fill->zero_fill_state() == HeapRegion::ZeroFilling
-            && to_fill->zero_filler() == thr_self) {
-          to_fill->set_zero_fill_complete();
-          (void)g1->put_free_region_on_list_locked(to_fill);
-        }
-        break;
-
-      case HeapRegion::ZeroFilled:
-        (void)g1->put_free_region_on_list_locked(to_fill);
-        break;
-
-      case HeapRegion::ZeroFilling:
-        ShouldNotReachHere();
-        break;
-      }
-    }
-    _vtime_accum = (os::elapsedVTime() - _vtime_start);
-    _sts.join();
-  }
-  _sts.leave();
-
-  assert(_should_terminate, "just checking");
-  terminate();
-}
-
-bool ConcurrentZFThread::offer_yield() {
-  if (_sts.should_yield()) {
-    _sts.yield("Concurrent ZF");
-    return true;
-  } else {
-    return false;
-  }
-}
-
-void ConcurrentZFThread::stop() {
-  // it is ok to take late safepoints here, if needed
-  MutexLockerEx mu(Terminator_lock);
-  _should_terminate = true;
-  while (!_has_terminated) {
-    Terminator_lock->wait();
-  }
-}
-
-void ConcurrentZFThread::print() const {
-  print_on(tty);
-}
-
-void ConcurrentZFThread::print_on(outputStream* st) const {
-  st->print("\"G1 Concurrent Zero-Fill Thread\" ");
-  Thread::print_on(st);
-  st->cr();
-}
-
-
-double ConcurrentZFThread::_vtime_accum;
-
-void ConcurrentZFThread::print_summary_info() {
-  gclog_or_tty->print("\nConcurrent Zero-Filling:\n");
-  gclog_or_tty->print("  Filled %d regions, used %5.2fs.\n",
-                      _regions_filled,
-                      vtime_accum());
-  gclog_or_tty->print("  Of %d region allocs, %d (%5.2f%%) required sync ZF,\n",
-                      _region_allocs, _sync_zfs,
-                      (_region_allocs > 0 ?
-                       (float)_sync_zfs/(float)_region_allocs*100.0 :
-                       0.0));
-  gclog_or_tty->print("     and %d (%5.2f%%) required a ZF wait.\n",
-                      _zf_waits,
-                      (_region_allocs > 0 ?
-                       (float)_zf_waits/(float)_region_allocs*100.0 :
-                       0.0));
-
-}
--- a/src/share/vm/gc_implementation/g1/concurrentZFThread.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTZFTHREAD_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTZFTHREAD_HPP
-
-#include "gc_implementation/shared/concurrentGCThread.hpp"
-
-// The Concurrent ZF Thread.  Performs concurrent zero-filling.
-
-class ConcurrentZFThread: public ConcurrentGCThread {
-  friend class VMStructs;
-  friend class ZeroFillRegionClosure;
-
- private:
-
-  // Zero fill the heap region.
-  void processHeapRegion(HeapRegion* r);
-
-  // Stats
-  //   Allocation (protected by heap lock).
-  static int _region_allocs;  // Number of regions allocated
-  static int _sync_zfs;       //   Synchronous zero-fills +
-  static int _zf_waits;      //   Wait for conc zero-fill completion.
-
-  // Number of regions CFZ thread fills.
-  static int _regions_filled;
-
-  double _vtime_start;  // Initial virtual time.
-
-  // These are static because the "print_summary_info" method is, and
-  // it currently assumes there is only one ZF thread.  We'll change when
-  // we need to.
-  static double _vtime_accum;  // Initial virtual time.
-  static double vtime_accum() { return _vtime_accum; }
-
-  // Offer yield for GC.  Returns true if yield occurred.
-  bool offer_yield();
-
- public:
-  // Constructor
-  ConcurrentZFThread();
-
-  // Main loop.
-  virtual void run();
-
-  // Printing
-  void print_on(outputStream* st) const;
-  void print() const;
-
-  // Waits until "r" has been zero-filled.  Requires caller to hold the
-  // ZF_mon.
-  static void wait_for_ZF_completed(HeapRegion* r);
-
-  // Get or clear the current unclean region.  Should be done
-  // while holding the ZF_needed_mon lock.
-
-  // shutdown
-  void stop();
-
-  // Stats
-  static void note_region_alloc() {_region_allocs++; }
-  static void note_sync_zfs() { _sync_zfs++; }
-  static void note_zf_wait() { _zf_waits++; }
-  static void note_region_filled() { _regions_filled++; }
-
-  static void print_summary_info();
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTZFTHREAD_HPP
--- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -222,7 +222,7 @@
 
 // Action_mark - update the BOT for the block [blk_start, blk_end).
 //               Current typical use is for splitting a block.
-// Action_single - udpate the BOT for an allocation.
+// Action_single - update the BOT for an allocation.
 // Action_verify - BOT verification.
 void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start,
                                            HeapWord* blk_end,
@@ -331,47 +331,6 @@
   do_block_internal(blk_start, blk_end, Action_mark);
 }
 
-void G1BlockOffsetArray::join_blocks(HeapWord* blk1, HeapWord* blk2) {
-  HeapWord* blk1_start = Universe::heap()->block_start(blk1);
-  HeapWord* blk2_start = Universe::heap()->block_start(blk2);
-  assert(blk1 == blk1_start && blk2 == blk2_start,
-         "Must be block starts.");
-  assert(blk1 + _sp->block_size(blk1) == blk2, "Must be contiguous.");
-  size_t blk1_start_index = _array->index_for(blk1);
-  size_t blk2_start_index = _array->index_for(blk2);
-  assert(blk1_start_index <= blk2_start_index, "sanity");
-  HeapWord* blk2_card_start = _array->address_for_index(blk2_start_index);
-  if (blk2 == blk2_card_start) {
-    // blk2 starts a card.  Does blk1 start on the prevous card, or futher
-    // back?
-    assert(blk1_start_index < blk2_start_index, "must be lower card.");
-    if (blk1_start_index + 1 == blk2_start_index) {
-      // previous card; new value for blk2 card is size of blk1.
-      _array->set_offset_array(blk2_start_index, (u_char) _sp->block_size(blk1));
-    } else {
-      // Earlier card; go back a card.
-      _array->set_offset_array(blk2_start_index, N_words);
-    }
-  } else {
-    // blk2 does not start a card.  Does it cross a card?  If not, nothing
-    // to do.
-    size_t blk2_end_index =
-      _array->index_for(blk2 + _sp->block_size(blk2) - 1);
-    assert(blk2_end_index >= blk2_start_index, "sanity");
-    if (blk2_end_index > blk2_start_index) {
-      // Yes, it crosses a card.  The value for the next card must change.
-      if (blk1_start_index + 1 == blk2_start_index) {
-        // previous card; new value for second blk2 card is size of blk1.
-        _array->set_offset_array(blk2_start_index + 1,
-                                 (u_char) _sp->block_size(blk1));
-      } else {
-        // Earlier card; go back a card.
-        _array->set_offset_array(blk2_start_index + 1, N_words);
-      }
-    }
-  }
-}
-
 HeapWord* G1BlockOffsetArray::block_start_unsafe(const void* addr) {
   assert(_bottom <= addr && addr < _end,
          "addr must be covered by this Array");
@@ -580,15 +539,50 @@
 #endif
 }
 
-void
-G1BlockOffsetArray::set_for_starts_humongous(HeapWord* new_end) {
-  assert(_end ==  new_end, "_end should have already been updated");
+bool
+G1BlockOffsetArray::verify_for_object(HeapWord* obj_start,
+                                      size_t word_size) const {
+  size_t first_card = _array->index_for(obj_start);
+  size_t last_card = _array->index_for(obj_start + word_size - 1);
+  if (!_array->is_card_boundary(obj_start)) {
+    // If the object is not on a card boundary the BOT entry of the
+    // first card should point to another object so we should not
+    // check that one.
+    first_card += 1;
+  }
+  for (size_t card = first_card; card <= last_card; card += 1) {
+    HeapWord* card_addr = _array->address_for_index(card);
+    HeapWord* block_start = block_start_const(card_addr);
+    if (block_start != obj_start) {
+      gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - "
+                             "card index: "SIZE_FORMAT" "
+                             "card addr: "PTR_FORMAT" BOT entry: %u "
+                             "obj: "PTR_FORMAT" word size: "SIZE_FORMAT" "
+                             "cards: ["SIZE_FORMAT","SIZE_FORMAT"]",
+                             block_start, card, card_addr,
+                             _array->offset_array(card),
+                             obj_start, word_size, first_card, last_card);
+      return false;
+    }
+  }
+  return true;
+}
 
-  // The first BOT entry should have offset 0.
-  _array->set_offset_array(_array->index_for(_bottom), 0);
-  // The rest should point to the first one.
-  set_remainder_to_point_to_start(_bottom + N_words, new_end);
+#ifndef PRODUCT
+void
+G1BlockOffsetArray::print_on(outputStream* out) {
+  size_t from_index = _array->index_for(_bottom);
+  size_t to_index = _array->index_for(_end);
+  out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") "
+                "cards ["SIZE_FORMAT","SIZE_FORMAT")",
+                _bottom, _end, from_index, to_index);
+  for (size_t i = from_index; i < to_index; ++i) {
+    out->print_cr("  entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u",
+                  i, _array->address_for_index(i),
+                  (uint) _array->offset_array(i));
+  }
 }
+#endif // !PRODUCT
 
 //////////////////////////////////////////////////////////////////////
 // G1BlockOffsetArrayContigSpace
@@ -641,10 +635,20 @@
 }
 
 void
-G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_end) {
-  G1BlockOffsetArray::set_for_starts_humongous(new_end);
+G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) {
+  assert(new_top <= _end, "_end should have already been updated");
+
+  // The first BOT entry should have offset 0.
+  zero_bottom_entry();
+  initialize_threshold();
+  alloc_block(_bottom, new_top);
+ }
 
-  // Make sure _next_offset_threshold and _next_offset_index point to new_end.
-  _next_offset_threshold = new_end;
-  _next_offset_index     = _array->index_for(new_end);
+#ifndef PRODUCT
+void
+G1BlockOffsetArrayContigSpace::print_on(outputStream* out) {
+  G1BlockOffsetArray::print_on(out);
+  out->print_cr("  next offset threshold: "PTR_FORMAT, _next_offset_threshold);
+  out->print_cr("  next offset index:     "SIZE_FORMAT, _next_offset_index);
 }
+#endif // !PRODUCT
--- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -352,11 +352,6 @@
   // The following methods are useful and optimized for a
   // general, non-contiguous space.
 
-  // The given arguments are required to be the starts of adjacent ("blk1"
-  // before "blk2") well-formed blocks covered by "this".  After this call,
-  // they should be considered to form one block.
-  virtual void join_blocks(HeapWord* blk1, HeapWord* blk2);
-
   // Given a block [blk_start, blk_start + full_blk_size), and
   // a left_blk_size < full_blk_size, adjust the BOT to show two
   // blocks [blk_start, blk_start + left_blk_size) and
@@ -429,6 +424,12 @@
     verify_single_block(blk, blk + size);
   }
 
+  // Used by region verification. Checks that the contents of the
+  // BOT reflect that there's a single object that spans the address
+  // range [obj_start, obj_start + word_size); returns true if this is
+  // the case, returns false if it's not.
+  bool verify_for_object(HeapWord* obj_start, size_t word_size) const;
+
   // Verify that the given block is before _unallocated_block
   inline void verify_not_unallocated(HeapWord* blk_start,
                                      HeapWord* blk_end) const {
@@ -444,7 +445,7 @@
 
   void check_all_cards(size_t left_card, size_t right_card) const;
 
-  virtual void set_for_starts_humongous(HeapWord* new_end);
+  virtual void print_on(outputStream* out) PRODUCT_RETURN;
 };
 
 // A subtype of BlockOffsetArray that takes advantage of the fact
@@ -494,7 +495,9 @@
   HeapWord* block_start_unsafe(const void* addr);
   HeapWord* block_start_unsafe_const(const void* addr) const;
 
-  virtual void set_for_starts_humongous(HeapWord* new_end);
+  void set_for_starts_humongous(HeapWord* new_top);
+
+  virtual void print_on(outputStream* out) PRODUCT_RETURN;
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_HPP
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
 #include "gc_implementation/g1/concurrentG1Refine.hpp"
 #include "gc_implementation/g1/concurrentG1RefineThread.hpp"
 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
-#include "gc_implementation/g1/concurrentZFThread.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
 #include "gc_implementation/g1/g1MarkSweep.hpp"
@@ -425,11 +424,9 @@
 
 void G1CollectedHeap::stop_conc_gc_threads() {
   _cg1r->stop();
-  _czft->stop();
   _cmThread->stop();
 }
 
-
 void G1CollectedHeap::check_ct_logs_at_safepoint() {
   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   CardTableModRefBS* ct_bs = (CardTableModRefBS*)barrier_set();
@@ -481,49 +478,92 @@
 
 // Private methods.
 
-// Finds a HeapRegion that can be used to allocate a given size of block.
-
-
-HeapRegion* G1CollectedHeap::newAllocRegion_work(size_t word_size,
-                                                 bool do_expand,
-                                                 bool zero_filled) {
-  ConcurrentZFThread::note_region_alloc();
-  HeapRegion* res = alloc_free_region_from_lists(zero_filled);
+HeapRegion*
+G1CollectedHeap::new_region_try_secondary_free_list(size_t word_size) {
+  MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+  while (!_secondary_free_list.is_empty() || free_regions_coming()) {
+    if (!_secondary_free_list.is_empty()) {
+      if (G1ConcRegionFreeingVerbose) {
+        gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+                               "secondary_free_list has "SIZE_FORMAT" entries",
+                               _secondary_free_list.length());
+      }
+      // It looks as if there are free regions available on the
+      // secondary_free_list. Let's move them to the free_list and try
+      // again to allocate from it.
+      append_secondary_free_list();
+
+      assert(!_free_list.is_empty(), "if the secondary_free_list was not "
+             "empty we should have moved at least one entry to the free_list");
+      HeapRegion* res = _free_list.remove_head();
+      if (G1ConcRegionFreeingVerbose) {
+        gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+                               "allocated "HR_FORMAT" from secondary_free_list",
+                               HR_FORMAT_PARAMS(res));
+      }
+      return res;
+    }
+
+    // Wait here until we get notifed either when (a) there are no
+    // more free regions coming or (b) some regions have been moved on
+    // the secondary_free_list.
+    SecondaryFreeList_lock->wait(Mutex::_no_safepoint_check_flag);
+  }
+
+  if (G1ConcRegionFreeingVerbose) {
+    gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+                           "could not allocate from secondary_free_list");
+  }
+  return NULL;
+}
+
+HeapRegion* G1CollectedHeap::new_region_work(size_t word_size,
+                                             bool do_expand) {
+  assert(!isHumongous(word_size) ||
+                                  word_size <= (size_t) HeapRegion::GrainWords,
+         "the only time we use this to allocate a humongous region is "
+         "when we are allocating a single humongous region");
+
+  HeapRegion* res;
+  if (G1StressConcRegionFreeing) {
+    if (!_secondary_free_list.is_empty()) {
+      if (G1ConcRegionFreeingVerbose) {
+        gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+                               "forced to look at the secondary_free_list");
+      }
+      res = new_region_try_secondary_free_list(word_size);
+      if (res != NULL) {
+        return res;
+      }
+    }
+  }
+  res = _free_list.remove_head_or_null();
+  if (res == NULL) {
+    if (G1ConcRegionFreeingVerbose) {
+      gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+                             "res == NULL, trying the secondary_free_list");
+    }
+    res = new_region_try_secondary_free_list(word_size);
+  }
   if (res == NULL && do_expand) {
     expand(word_size * HeapWordSize);
-    res = alloc_free_region_from_lists(zero_filled);
-    assert(res == NULL ||
-           (!res->isHumongous() &&
-            (!zero_filled ||
-             res->zero_fill_state() == HeapRegion::Allocated)),
-           "Alloc Regions must be zero filled (and non-H)");
+    res = _free_list.remove_head_or_null();
   }
   if (res != NULL) {
-    if (res->is_empty()) {
-      _free_regions--;
-    }
-    assert(!res->isHumongous() &&
-           (!zero_filled || res->zero_fill_state() == HeapRegion::Allocated),
-           err_msg("Non-young alloc Regions must be zero filled (and non-H):"
-                   " res->isHumongous()=%d, zero_filled=%d, res->zero_fill_state()=%d",
-                   res->isHumongous(), zero_filled, res->zero_fill_state()));
-    assert(!res->is_on_unclean_list(),
-           "Alloc Regions must not be on the unclean list");
     if (G1PrintHeapRegions) {
-      gclog_or_tty->print_cr("new alloc region %d:["PTR_FORMAT", "PTR_FORMAT"], "
-                             "top "PTR_FORMAT,
-                             res->hrs_index(), res->bottom(), res->end(), res->top());
+      gclog_or_tty->print_cr("new alloc region %d:["PTR_FORMAT","PTR_FORMAT"], "
+                             "top "PTR_FORMAT, res->hrs_index(),
+                             res->bottom(), res->end(), res->top());
     }
   }
   return res;
 }
 
-HeapRegion* G1CollectedHeap::newAllocRegionWithExpansion(int purpose,
-                                                         size_t word_size,
-                                                         bool zero_filled) {
+HeapRegion* G1CollectedHeap::new_gc_alloc_region(int purpose,
+                                                 size_t word_size) {
   HeapRegion* alloc_region = NULL;
   if (_gc_alloc_region_counts[purpose] < g1_policy()->max_regions(purpose)) {
-    alloc_region = newAllocRegion_work(word_size, true, zero_filled);
+    alloc_region = new_region_work(word_size, true /* do_expand */);
     if (purpose == GCAllocForSurvived && alloc_region != NULL) {
       alloc_region->set_survivor();
     }
@@ -534,81 +574,220 @@
   return alloc_region;
 }
 
+int G1CollectedHeap::humongous_obj_allocate_find_first(size_t num_regions,
+                                                       size_t word_size) {
+  int first = -1;
+  if (num_regions == 1) {
+    // Only one region to allocate, no need to go through the slower
+    // path. The caller will attempt the expasion if this fails, so
+    // let's not try to expand here too.
+    HeapRegion* hr = new_region_work(word_size, false /* do_expand */);
+    if (hr != NULL) {
+      first = hr->hrs_index();
+    } else {
+      first = -1;
+    }
+  } else {
+    // We can't allocate humongous regions while cleanupComplete() is
+    // running, since some of the regions we find to be empty might not
+    // yet be added to the free list and it is not straightforward to
+    // know which list they are on so that we can remove them. Note
+    // that we only need to do this if we need to allocate more than
+    // one region to satisfy the current humongous allocation
+    // request. If we are only allocating one region we use the common
+    // region allocation code (see above).
+    wait_while_free_regions_coming();
+    append_secondary_free_list_if_not_empty();
+
+    if (free_regions() >= num_regions) {
+      first = _hrs->find_contiguous(num_regions);
+      if (first != -1) {
+        for (int i = first; i < first + (int) num_regions; ++i) {
+          HeapRegion* hr = _hrs->at(i);
+          assert(hr->is_empty(), "sanity");
+          assert(is_on_free_list(hr), "sanity");
+          hr->set_pending_removal(true);
+        }
+        _free_list.remove_all_pending(num_regions);
+      }
+    }
+  }
+  return first;
+}
+
 // If could fit into free regions w/o expansion, try.
 // Otherwise, if can expand, do so.
 // Otherwise, if using ex regions might help, try with ex given back.
 HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) {
-  assert_heap_locked_or_at_safepoint();
-  assert(regions_accounted_for(), "Region leakage!");
-
-  // We can't allocate humongous regions while cleanupComplete is
-  // running, since some of the regions we find to be empty might not
-  // yet be added to the unclean list. If we're already at a
-  // safepoint, this call is unnecessary, not to mention wrong.
-  if (!SafepointSynchronize::is_at_safepoint()) {
-    wait_for_cleanup_complete();
-  }
+  assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
+
+  verify_region_sets_optional();
 
   size_t num_regions =
          round_to(word_size, HeapRegion::GrainWords) / HeapRegion::GrainWords;
-
-  // Special case if < one region???
-
-  // Remember the ft size.
   size_t x_size = expansion_regions();
-
-  HeapWord* res = NULL;
-  bool eliminated_allocated_from_lists = false;
-
-  // Can the allocation potentially fit in the free regions?
-  if (free_regions() >= num_regions) {
-    res = _hrs->obj_allocate(word_size);
-  }
-  if (res == NULL) {
-    // Try expansion.
-    size_t fs = _hrs->free_suffix();
+  size_t fs = _hrs->free_suffix();
+  int first = humongous_obj_allocate_find_first(num_regions, word_size);
+  if (first == -1) {
+    // The only thing we can do now is attempt expansion.
     if (fs + x_size >= num_regions) {
       expand((num_regions - fs) * HeapRegion::GrainBytes);
-      res = _hrs->obj_allocate(word_size);
-      assert(res != NULL, "This should have worked.");
-    } else {
-      // Expansion won't help.  Are there enough free regions if we get rid
-      // of reservations?
-      size_t avail = free_regions();
-      if (avail >= num_regions) {
-        res = _hrs->obj_allocate(word_size);
-        if (res != NULL) {
-          remove_allocated_regions_from_lists();
-          eliminated_allocated_from_lists = true;
-        }
+      first = humongous_obj_allocate_find_first(num_regions, word_size);
+      assert(first != -1, "this should have worked");
+    }
+  }
+
+  if (first != -1) {
+    // Index of last region in the series + 1.
+    int last = first + (int) num_regions;
+
+    // We need to initialize the region(s) we just discovered. This is
+    // a bit tricky given that it can happen concurrently with
+    // refinement threads refining cards on these regions and
+    // potentially wanting to refine the BOT as they are scanning
+    // those cards (this can happen shortly after a cleanup; see CR
+    // 6991377). So we have to set up the region(s) carefully and in
+    // a specific order.
+
+    // The word size sum of all the regions we will allocate.
+    size_t word_size_sum = num_regions * HeapRegion::GrainWords;
+    assert(word_size <= word_size_sum, "sanity");
+
+    // This will be the "starts humongous" region.
+    HeapRegion* first_hr = _hrs->at(first);
+    // The header of the new object will be placed at the bottom of
+    // the first region.
+    HeapWord* new_obj = first_hr->bottom();
+    // This will be the new end of the first region in the series that
+    // should also match the end of the last region in the seriers.
+    HeapWord* new_end = new_obj + word_size_sum;
+    // This will be the new top of the first region that will reflect
+    // this allocation.
+    HeapWord* new_top = new_obj + word_size;
+
+    // First, we need to zero the header of the space that we will be
+    // allocating. When we update top further down, some refinement
+    // threads might try to scan the region. By zeroing the header we
+    // ensure that any thread that will try to scan the region will
+    // come across the zero klass word and bail out.
+    //
+    // NOTE: It would not have been correct to have used
+    // CollectedHeap::fill_with_object() and make the space look like
+    // an int array. The thread that is doing the allocation will
+    // later update the object header to a potentially different array
+    // type and, for a very short period of time, the klass and length
+    // fields will be inconsistent. This could cause a refinement
+    // thread to calculate the object size incorrectly.
+    Copy::fill_to_words(new_obj, oopDesc::header_size(), 0);
+
+    // We will set up the first region as "starts humongous". This
+    // will also update the BOT covering all the regions to reflect
+    // that there is a single object that starts at the bottom of the
+    // first region.
+    first_hr->set_startsHumongous(new_top, new_end);
+
+    // Then, if there are any, we will set up the "continues
+    // humongous" regions.
+    HeapRegion* hr = NULL;
+    for (int i = first + 1; i < last; ++i) {
+      hr = _hrs->at(i);
+      hr->set_continuesHumongous(first_hr);
+    }
+    // If we have "continues humongous" regions (hr != NULL), then the
+    // end of the last one should match new_end.
+    assert(hr == NULL || hr->end() == new_end, "sanity");
+
+    // Up to this point no concurrent thread would have been able to
+    // do any scanning on any region in this series. All the top
+    // fields still point to bottom, so the intersection between
+    // [bottom,top] and [card_start,card_end] will be empty. Before we
+    // update the top fields, we'll do a storestore to make sure that
+    // no thread sees the update to top before the zeroing of the
+    // object header and the BOT initialization.
+    OrderAccess::storestore();
+
+    // Now that the BOT and the object header have been initialized,
+    // we can update top of the "starts humongous" region.
+    assert(first_hr->bottom() < new_top && new_top <= first_hr->end(),
+           "new_top should be in this region");
+    first_hr->set_top(new_top);
+
+    // Now, we will update the top fields of the "continues humongous"
+    // regions. The reason we need to do this is that, otherwise,
+    // these regions would look empty and this will confuse parts of
+    // G1. For example, the code that looks for a consecutive number
+    // of empty regions will consider them empty and try to
+    // re-allocate them. We can extend is_empty() to also include
+    // !continuesHumongous(), but it is easier to just update the top
+    // fields here. The way we set top for all regions (i.e., top ==
+    // end for all regions but the last one, top == new_top for the
+    // last one) is actually used when we will free up the humongous
+    // region in free_humongous_region().
+    hr = NULL;
+    for (int i = first + 1; i < last; ++i) {
+      hr = _hrs->at(i);
+      if ((i + 1) == last) {
+        // last continues humongous region
+        assert(hr->bottom() < new_top && new_top <= hr->end(),
+               "new_top should fall on this region");
+        hr->set_top(new_top);
+      } else {
+        // not last one
+        assert(new_top > hr->end(), "new_top should be above this region");
+        hr->set_top(hr->end());
       }
     }
-  }
-  if (res != NULL) {
-    // Increment by the number of regions allocated.
-    // FIXME: Assumes regions all of size GrainBytes.
-#ifndef PRODUCT
-    mr_bs()->verify_clean_region(MemRegion(res, res + num_regions *
-                                           HeapRegion::GrainWords));
-#endif
-    if (!eliminated_allocated_from_lists)
-      remove_allocated_regions_from_lists();
-    _summary_bytes_used += word_size * HeapWordSize;
-    _free_regions -= num_regions;
-    _num_humongous_regions += (int) num_regions;
-  }
-  assert(regions_accounted_for(), "Region Leakage");
-  return res;
+    // If we have continues humongous regions (hr != NULL), then the
+    // end of the last one should match new_end and its top should
+    // match new_top.
+    assert(hr == NULL ||
+           (hr->end() == new_end && hr->top() == new_top), "sanity");
+
+    assert(first_hr->used() == word_size * HeapWordSize, "invariant");
+    _summary_bytes_used += first_hr->used();
+    _humongous_set.add(first_hr);
+
+    return new_obj;
+  }
+
+  verify_region_sets_optional();
+  return NULL;
 }
 
 void
 G1CollectedHeap::retire_cur_alloc_region(HeapRegion* cur_alloc_region) {
-  // The cleanup operation might update _summary_bytes_used
-  // concurrently with this method. So, right now, if we don't wait
-  // for it to complete, updates to _summary_bytes_used might get
-  // lost. This will be resolved in the near future when the operation
-  // of the free region list is revamped as part of CR 6977804.
-  wait_for_cleanup_complete();
+  // Other threads might still be trying to allocate using CASes out
+  // of the region we are retiring, as they can do so without holding
+  // the Heap_lock. So we first have to make sure that noone else can
+  // allocate in it by doing a maximal allocation. Even if our CAS
+  // attempt fails a few times, we'll succeed sooner or later given
+  // that a failed CAS attempt mean that the region is getting closed
+  // to being full (someone else succeeded in allocating into it).
+  size_t free_word_size = cur_alloc_region->free() / HeapWordSize;
+
+  // This is the minimum free chunk we can turn into a dummy
+  // object. If the free space falls below this, then noone can
+  // allocate in this region anyway (all allocation requests will be
+  // of a size larger than this) so we won't have to perform the dummy
+  // allocation.
+  size_t min_word_size_to_fill = CollectedHeap::min_fill_size();
+
+  while (free_word_size >= min_word_size_to_fill) {
+    HeapWord* dummy =
+      cur_alloc_region->par_allocate_no_bot_updates(free_word_size);
+    if (dummy != NULL) {
+      // If the allocation was successful we should fill in the space.
+      CollectedHeap::fill_with_object(dummy, free_word_size);
+      break;
+    }
+
+    free_word_size = cur_alloc_region->free() / HeapWordSize;
+    // It's also possible that someone else beats us to the
+    // allocation and they fill up the region. In that case, we can
+    // just get out of the loop
+  }
+  assert(cur_alloc_region->free() / HeapWordSize < min_word_size_to_fill,
+         "sanity");
 
   retire_cur_alloc_region_common(cur_alloc_region);
   assert(_cur_alloc_region == NULL, "post-condition");
@@ -621,7 +800,7 @@
                                                        bool at_safepoint,
                                                        bool do_dirtying,
                                                        bool can_expand) {
-  assert_heap_locked_or_at_safepoint();
+  assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
   assert(_cur_alloc_region == NULL,
          "replace_cur_alloc_region_and_allocate() should only be called "
          "after retiring the previous current alloc region");
@@ -632,25 +811,12 @@
          "we are not allowed to expand the young gen");
 
   if (can_expand || !g1_policy()->is_young_list_full()) {
-    if (!at_safepoint) {
-      // The cleanup operation might update _summary_bytes_used
-      // concurrently with this method. So, right now, if we don't
-      // wait for it to complete, updates to _summary_bytes_used might
-      // get lost. This will be resolved in the near future when the
-      // operation of the free region list is revamped as part of
-      // CR 6977804. If we're already at a safepoint, this call is
-      // unnecessary, not to mention wrong.
-      wait_for_cleanup_complete();
-    }
-
-    HeapRegion* new_cur_alloc_region = newAllocRegion(word_size,
-                                                      false /* zero_filled */);
+    HeapRegion* new_cur_alloc_region = new_alloc_region(word_size);
     if (new_cur_alloc_region != NULL) {
       assert(new_cur_alloc_region->is_empty(),
              "the newly-allocated region should be empty, "
              "as right now we only allocate new regions out of the free list");
       g1_policy()->update_region_num(true /* next_is_young */);
-      _summary_bytes_used -= new_cur_alloc_region->used();
       set_region_short_lived_locked(new_cur_alloc_region);
 
       assert(!new_cur_alloc_region->isHumongous(),
@@ -661,27 +827,29 @@
       // young type.
       OrderAccess::storestore();
 
-      // Now allocate out of the new current alloc region. We could
-      // have re-used allocate_from_cur_alloc_region() but its
-      // operation is slightly different to what we need here. First,
-      // allocate_from_cur_alloc_region() is only called outside a
-      // safepoint and will always unlock the Heap_lock if it returns
-      // a non-NULL result. Second, it assumes that the current alloc
-      // region is what's already assigned in _cur_alloc_region. What
-      // we want here is to actually do the allocation first before we
-      // assign the new region to _cur_alloc_region. This ordering is
-      // not currently important, but it will be essential when we
-      // change the code to support CAS allocation in the future (see
-      // CR 6994297).
-      //
-      // This allocate method does BOT updates and we don't need them in
-      // the young generation. This will be fixed in the near future by
-      // CR 6994297.
-      HeapWord* result = new_cur_alloc_region->allocate(word_size);
+      // Now, perform the allocation out of the region we just
+      // allocated. Note that noone else can access that region at
+      // this point (as _cur_alloc_region has not been updated yet),
+      // so we can just go ahead and do the allocation without any
+      // atomics (and we expect this allocation attempt to
+      // suceeded). Given that other threads can attempt an allocation
+      // with a CAS and without needing the Heap_lock, if we assigned
+      // the new region to _cur_alloc_region before first allocating
+      // into it other threads might have filled up the new region
+      // before we got a chance to do the allocation ourselves. In
+      // that case, we would have needed to retire the region, grab a
+      // new one, and go through all this again. Allocating out of the
+      // new region before assigning it to _cur_alloc_region avoids
+      // all this.
+      HeapWord* result =
+                     new_cur_alloc_region->allocate_no_bot_updates(word_size);
       assert(result != NULL, "we just allocate out of an empty region "
              "so allocation should have been successful");
       assert(is_in(result), "result should be in the heap");
 
+      // Now make sure that the store to _cur_alloc_region does not
+      // float above the store to top.
+      OrderAccess::storestore();
       _cur_alloc_region = new_cur_alloc_region;
 
       if (!at_safepoint) {
@@ -698,7 +866,7 @@
 
   assert(_cur_alloc_region == NULL, "we failed to allocate a new current "
          "alloc region, it should still be NULL");
-  assert_heap_locked_or_at_safepoint();
+  assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
   return NULL;
 }
 
@@ -710,6 +878,10 @@
   assert(!isHumongous(word_size), "attempt_allocation_slow() should not be "
          "used for humongous allocations");
 
+  // We should only reach here when we were unable to allocate
+  // otherwise. So, we should have not active current alloc region.
+  assert(_cur_alloc_region == NULL, "current alloc region should be NULL");
+
   // We will loop while succeeded is false, which means that we tried
   // to do a collection, but the VM op did not succeed. So, when we
   // exit the loop, either one of the allocation attempts was
@@ -718,28 +890,8 @@
   for (int try_count = 1; /* we'll return or break */; try_count += 1) {
     bool succeeded = true;
 
-    {
-      // We may have concurrent cleanup working at the time. Wait for
-      // it to complete. In the future we would probably want to make
-      // the concurrent cleanup truly concurrent by decoupling it from
-      // the allocation. This will happen in the near future as part
-      // of CR 6977804 which will revamp the operation of the free
-      // region list. The fact that wait_for_cleanup_complete() will
-      // do a wait() means that we'll give up the Heap_lock. So, it's
-      // possible that when we exit wait_for_cleanup_complete() we
-      // might be able to allocate successfully (since somebody else
-      // might have done a collection meanwhile). So, we'll attempt to
-      // allocate again, just in case. When we make cleanup truly
-      // concurrent with allocation, we should remove this allocation
-      // attempt as it's redundant (we only reach here after an
-      // allocation attempt has been unsuccessful).
-      wait_for_cleanup_complete();
-      HeapWord* result = attempt_allocation(word_size);
-      if (result != NULL) {
-        assert_heap_not_locked();
-        return result;
-      }
-    }
+    // Every time we go round the loop we should be holding the Heap_lock.
+    assert_heap_locked();
 
     if (GC_locker::is_active_and_needs_gc()) {
       // We are locked out of GC because of the GC locker. We can
@@ -748,7 +900,6 @@
       if (g1_policy()->can_expand_young_list()) {
         // Yes, we are allowed to expand the young gen. Let's try to
         // allocate a new current alloc region.
-
         HeapWord* result =
           replace_cur_alloc_region_and_allocate(word_size,
                                                 false, /* at_safepoint */
@@ -771,20 +922,23 @@
       // rather than causing more, now probably unnecessary, GC attempts.
       JavaThread* jthr = JavaThread::current();
       assert(jthr != NULL, "sanity");
-      if (!jthr->in_critical()) {
-        MutexUnlocker mul(Heap_lock);
-        GC_locker::stall_until_clear();
-
-        // We'll then fall off the end of the ("if GC locker active")
-        // if-statement and retry the allocation further down in the
-        // loop.
-      } else {
+      if (jthr->in_critical()) {
         if (CheckJNICalls) {
           fatal("Possible deadlock due to allocating while"
                 " in jni critical section");
         }
+        // We are returning NULL so the protocol is that we're still
+        // holding the Heap_lock.
+        assert_heap_locked();
         return NULL;
       }
+
+      Heap_lock->unlock();
+      GC_locker::stall_until_clear();
+
+      // No need to relock the Heap_lock. We'll fall off to the code
+      // below the else-statement which assumes that we are not
+      // holding the Heap_lock.
     } else {
       // We are not locked out. So, let's try to do a GC. The VM op
       // will retry the allocation before it completes.
@@ -805,11 +959,10 @@
         dirty_young_block(result, word_size);
         return result;
       }
-
-      Heap_lock->lock();
     }
 
-    assert_heap_locked();
+    // Both paths that get us here from above unlock the Heap_lock.
+    assert_heap_not_locked();
 
     // We can reach here when we were unsuccessful in doing a GC,
     // because another thread beat us to it, or because we were locked
@@ -854,7 +1007,7 @@
   // allocation paths that attempt to allocate a humongous object
   // should eventually reach here. Currently, the only paths are from
   // mem_allocate() and attempt_allocation_at_safepoint().
-  assert_heap_locked_or_at_safepoint();
+  assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
   assert(isHumongous(word_size), "attempt_allocation_humongous() "
          "should only be used for humongous allocations");
   assert(SafepointSynchronize::is_at_safepoint() == at_safepoint,
@@ -931,13 +1084,13 @@
     }
   }
 
-  assert_heap_locked_or_at_safepoint();
+  assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
   return NULL;
 }
 
 HeapWord* G1CollectedHeap::attempt_allocation_at_safepoint(size_t word_size,
                                            bool expect_null_cur_alloc_region) {
-  assert_at_safepoint();
+  assert_at_safepoint(true /* should_be_vm_thread */);
   assert(_cur_alloc_region == NULL || !expect_null_cur_alloc_region,
          err_msg("the current alloc region was unexpectedly found "
                  "to be non-NULL, cur alloc region: "PTR_FORMAT" "
@@ -948,10 +1101,8 @@
     if (!expect_null_cur_alloc_region) {
       HeapRegion* cur_alloc_region = _cur_alloc_region;
       if (cur_alloc_region != NULL) {
-        // This allocate method does BOT updates and we don't need them in
-        // the young generation. This will be fixed in the near future by
-        // CR 6994297.
-        HeapWord* result = cur_alloc_region->allocate(word_size);
+        // We are at a safepoint so no reason to use the MT-safe version.
+        HeapWord* result = cur_alloc_region->allocate_no_bot_updates(word_size);
         if (result != NULL) {
           assert(is_in(result), "result should be in the heap");
 
@@ -983,20 +1134,17 @@
   assert_heap_not_locked_and_not_at_safepoint();
   assert(!isHumongous(word_size), "we do not allow TLABs of humongous size");
 
-  Heap_lock->lock();
-
-  // First attempt: try allocating out of the current alloc region or
-  // after replacing the current alloc region.
+  // First attempt: Try allocating out of the current alloc region
+  // using a CAS. If that fails, take the Heap_lock and retry the
+  // allocation, potentially replacing the current alloc region.
   HeapWord* result = attempt_allocation(word_size);
   if (result != NULL) {
     assert_heap_not_locked();
     return result;
   }
 
-  assert_heap_locked();
-
-  // Second attempt: go into the even slower path where we might
-  // try to schedule a collection.
+  // Second attempt: Go to the slower path where we might try to
+  // schedule a collection.
   result = attempt_allocation_slow(word_size);
   if (result != NULL) {
     assert_heap_not_locked();
@@ -1004,6 +1152,7 @@
   }
 
   assert_heap_locked();
+  // Need to unlock the Heap_lock before returning.
   Heap_lock->unlock();
   return NULL;
 }
@@ -1022,11 +1171,10 @@
   for (int try_count = 1; /* we'll return */; try_count += 1) {
     unsigned int gc_count_before;
     {
-      Heap_lock->lock();
-
       if (!isHumongous(word_size)) {
-        // First attempt: try allocating out of the current alloc
-        // region or after replacing the current alloc region.
+        // First attempt: Try allocating out of the current alloc region
+        // using a CAS. If that fails, take the Heap_lock and retry the
+        // allocation, potentially replacing the current alloc region.
         HeapWord* result = attempt_allocation(word_size);
         if (result != NULL) {
           assert_heap_not_locked();
@@ -1035,14 +1183,17 @@
 
         assert_heap_locked();
 
-        // Second attempt: go into the even slower path where we might
-        // try to schedule a collection.
+        // Second attempt: Go to the slower path where we might try to
+        // schedule a collection.
         result = attempt_allocation_slow(word_size);
         if (result != NULL) {
           assert_heap_not_locked();
           return result;
         }
       } else {
+        // attempt_allocation_humongous() requires the Heap_lock to be held.
+        Heap_lock->lock();
+
         HeapWord* result = attempt_allocation_humongous(word_size,
                                                      false /* at_safepoint */);
         if (result != NULL) {
@@ -1054,7 +1205,8 @@
       assert_heap_locked();
       // Read the gc count while the heap lock is held.
       gc_count_before = SharedHeap::heap()->total_collections();
-      // We cannot be at a safepoint, so it is safe to unlock the Heap_lock
+
+      // Release the Heap_lock before attempting the collection.
       Heap_lock->unlock();
     }
 
@@ -1092,22 +1244,18 @@
 }
 
 void G1CollectedHeap::abandon_cur_alloc_region() {
-  if (_cur_alloc_region != NULL) {
-    // We're finished with the _cur_alloc_region.
-    if (_cur_alloc_region->is_empty()) {
-      _free_regions++;
-      free_region(_cur_alloc_region);
-    } else {
-      // As we're builing (at least the young portion) of the collection
-      // set incrementally we'll add the current allocation region to
-      // the collection set here.
-      if (_cur_alloc_region->is_young()) {
-        g1_policy()->add_region_to_incremental_cset_lhs(_cur_alloc_region);
-      }
-      _summary_bytes_used += _cur_alloc_region->used();
-    }
-    _cur_alloc_region = NULL;
-  }
+  assert_at_safepoint(true /* should_be_vm_thread */);
+
+  HeapRegion* cur_alloc_region = _cur_alloc_region;
+  if (cur_alloc_region != NULL) {
+    assert(!cur_alloc_region->is_empty(),
+           "the current alloc region can never be empty");
+    assert(cur_alloc_region->is_young(),
+           "the current alloc region should be young");
+
+    retire_cur_alloc_region_common(cur_alloc_region);
+  }
+  assert(_cur_alloc_region == NULL, "post-condition");
 }
 
 void G1CollectedHeap::abandon_gc_alloc_regions() {
@@ -1188,19 +1336,20 @@
 bool G1CollectedHeap::do_collection(bool explicit_gc,
                                     bool clear_all_soft_refs,
                                     size_t word_size) {
+  assert_at_safepoint(true /* should_be_vm_thread */);
+
   if (GC_locker::check_active_before_gc()) {
     return false;
   }
 
-  DTraceGCProbeMarker gc_probe_marker(true /* full */);
+  SvcGCMarker sgcm(SvcGCMarker::FULL);
   ResourceMark rm;
 
   if (PrintHeapAtGC) {
     Universe::print_heap_before_gc();
   }
 
-  assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
-  assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
+  verify_region_sets_optional();
 
   const bool do_clear_all_soft_refs = clear_all_soft_refs ||
                            collector_policy()->should_clear_all_soft_refs();
@@ -1223,6 +1372,9 @@
     double start = os::elapsedTime();
     g1_policy()->record_full_collection_start();
 
+    wait_while_free_regions_coming();
+    append_secondary_free_list_if_not_empty();
+
     gc_prologue(true);
     increment_total_collections(true /* full gc */);
 
@@ -1235,7 +1387,6 @@
       gclog_or_tty->print(" VerifyBeforeGC:");
       Universe::verify(true);
     }
-    assert(regions_accounted_for(), "Region leakage!");
 
     COMPILER2_PRESENT(DerivedPointerTable::clear());
 
@@ -1259,7 +1410,6 @@
     assert(_cur_alloc_region == NULL, "Invariant.");
     g1_rem_set()->cleanupHRRS();
     tear_down_region_lists();
-    set_used_regions_to_need_zero_fill();
 
     // We may have added regions to the current incremental collection
     // set between the last GC or pause and now. We need to clear the
@@ -1294,9 +1444,7 @@
       HandleMark hm;  // Discard invalid handles created during gc
       G1MarkSweep::invoke_at_safepoint(ref_processor(), do_clear_all_soft_refs);
     }
-    // Because freeing humongous regions may have added some unclean
-    // regions, it is necessary to tear down again before rebuilding.
-    tear_down_region_lists();
+    assert(free_regions() == 0, "we should not have added any free regions");
     rebuild_region_lists();
 
     _summary_bytes_used = recalculate_used();
@@ -1378,7 +1526,6 @@
     JavaThread::dirty_card_queue_set().abandon_logs();
     assert(!G1DeferredRSUpdate
            || (G1DeferredRSUpdate && (dirty_card_queue_set().completed_buffers_num() == 0)), "Should not be any");
-    assert(regions_accounted_for(), "Region leakage!");
   }
 
   if (g1_policy()->in_young_gc_mode()) {
@@ -1392,6 +1539,8 @@
   // Update the number of full collections that have been completed.
   increment_full_collections_completed(false /* concurrent */);
 
+  verify_region_sets_optional();
+
   if (PrintHeapAtGC) {
     Universe::print_heap_after_gc();
   }
@@ -1532,10 +1681,7 @@
 HeapWord*
 G1CollectedHeap::satisfy_failed_allocation(size_t word_size,
                                            bool* succeeded) {
-  assert(SafepointSynchronize::is_at_safepoint(),
-         "satisfy_failed_allocation() should only be called at a safepoint");
-  assert(Thread::current()->is_VM_thread(),
-         "satisfy_failed_allocation() should only be called by the VM thread");
+  assert_at_safepoint(true /* should_be_vm_thread */);
 
   *succeeded = true;
   // Let's attempt the allocation first.
@@ -1607,53 +1753,22 @@
 // allocated block, or else "NULL".
 
 HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) {
-  assert(SafepointSynchronize::is_at_safepoint(),
-         "expand_and_allocate() should only be called at a safepoint");
-  assert(Thread::current()->is_VM_thread(),
-         "expand_and_allocate() should only be called by the VM thread");
+  assert_at_safepoint(true /* should_be_vm_thread */);
+
+  verify_region_sets_optional();
 
   size_t expand_bytes = word_size * HeapWordSize;
   if (expand_bytes < MinHeapDeltaBytes) {
     expand_bytes = MinHeapDeltaBytes;
   }
   expand(expand_bytes);
-  assert(regions_accounted_for(), "Region leakage!");
+
+  verify_region_sets_optional();
 
   return attempt_allocation_at_safepoint(word_size,
                                      false /* expect_null_cur_alloc_region */);
 }
 
-size_t G1CollectedHeap::free_region_if_totally_empty(HeapRegion* hr) {
-  size_t pre_used = 0;
-  size_t cleared_h_regions = 0;
-  size_t freed_regions = 0;
-  UncleanRegionList local_list;
-  free_region_if_totally_empty_work(hr, pre_used, cleared_h_regions,
-                                    freed_regions, &local_list);
-
-  finish_free_region_work(pre_used, cleared_h_regions, freed_regions,
-                          &local_list);
-  return pre_used;
-}
-
-void
-G1CollectedHeap::free_region_if_totally_empty_work(HeapRegion* hr,
-                                                   size_t& pre_used,
-                                                   size_t& cleared_h,
-                                                   size_t& freed_regions,
-                                                   UncleanRegionList* list,
-                                                   bool par) {
-  assert(!hr->continuesHumongous(), "should have filtered these out");
-  size_t res = 0;
-  if (hr->used() > 0 && hr->garbage_bytes() == hr->used() &&
-      !hr->is_young()) {
-    if (G1PolicyVerbose > 0)
-      gclog_or_tty->print_cr("Freeing empty region "PTR_FORMAT "(" SIZE_FORMAT " bytes)"
-                                                                               " during cleanup", hr, hr->used());
-    free_region_work(hr, pre_used, cleared_h, freed_regions, list, par);
-  }
-}
-
 // FIXME: both this and shrink could probably be more efficient by
 // doing one "VirtualSpace::expand_by" call rather than several.
 void G1CollectedHeap::expand(size_t expand_bytes) {
@@ -1686,19 +1801,7 @@
 
       // Add it to the HeapRegionSeq.
       _hrs->insert(hr);
-      // Set the zero-fill state, according to whether it's already
-      // zeroed.
-      {
-        MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-        if (is_zeroed) {
-          hr->set_zero_fill_complete();
-          put_free_region_on_list_locked(hr);
-        } else {
-          hr->set_zero_fill_needed();
-          put_region_on_unclean_list_locked(hr);
-        }
-      }
-      _free_regions++;
+      _free_list.add_as_tail(hr);
       // And we used up an expansion region to create it.
       _expansion_regions--;
       // Tell the cardtable about it.
@@ -1707,6 +1810,7 @@
       _bot_shared->resize(_g1_committed.word_size());
     }
   }
+
   if (Verbose && PrintGC) {
     size_t new_mem_size = _g1_storage.committed_size();
     gclog_or_tty->print_cr("Expanding garbage-first heap from %ldK by %ldK to %ldK",
@@ -1731,7 +1835,6 @@
   assert(mr.start() == (HeapWord*)_g1_storage.high(), "Bad shrink!");
 
   _g1_committed.set_end(mr.start());
-  _free_regions -= num_regions_deleted;
   _expansion_regions += num_regions_deleted;
 
   // Tell the cardtable about it.
@@ -1751,10 +1854,17 @@
 }
 
 void G1CollectedHeap::shrink(size_t shrink_bytes) {
+  verify_region_sets_optional();
+
   release_gc_alloc_regions(true /* totally */);
+  // Instead of tearing down / rebuilding the free lists here, we
+  // could instead use the remove_all_pending() method on free_list to
+  // remove only the ones that we need to remove.
   tear_down_region_lists();  // We will rebuild them in a moment.
   shrink_helper(shrink_bytes);
   rebuild_region_lists();
+
+  verify_region_sets_optional();
 }
 
 // Public methods.
@@ -1773,18 +1883,17 @@
   _ref_processor(NULL),
   _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)),
   _bot_shared(NULL),
-  _par_alloc_during_gc_lock(Mutex::leaf, "par alloc during GC lock"),
   _objs_with_preserved_marks(NULL), _preserved_marks_of_objs(NULL),
   _evac_failure_scan_stack(NULL) ,
   _mark_in_progress(false),
-  _cg1r(NULL), _czft(NULL), _summary_bytes_used(0),
+  _cg1r(NULL), _summary_bytes_used(0),
   _cur_alloc_region(NULL),
   _refine_cte_cl(NULL),
-  _free_region_list(NULL), _free_region_list_size(0),
-  _free_regions(0),
   _full_collection(false),
-  _unclean_region_list(),
-  _unclean_regions_coming(false),
+  _free_list("Master Free List"),
+  _secondary_free_list("Secondary Free List"),
+  _humongous_set("Master Humongous Set"),
+  _free_regions_coming(false),
   _young_list(new YoungList(this)),
   _gc_time_stamp(0),
   _surviving_young_words(NULL),
@@ -1868,7 +1977,7 @@
 
   ReservedSpace heap_rs(max_byte_size + pgs->max_size(),
                         HeapRegion::GrainBytes,
-                        false /*ism*/, addr);
+                        UseLargePages, addr);
 
   if (UseCompressedOops) {
     if (addr != NULL && !heap_rs.is_reserved()) {
@@ -1877,13 +1986,13 @@
       // Try again to reserver heap higher.
       addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
       ReservedSpace heap_rs0(total_reserved, HeapRegion::GrainBytes,
-                             false /*ism*/, addr);
+                             UseLargePages, addr);
       if (addr != NULL && !heap_rs0.is_reserved()) {
         // Failed to reserve at specified address again - give up.
         addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
         assert(addr == NULL, "");
         ReservedSpace heap_rs1(total_reserved, HeapRegion::GrainBytes,
-                               false /*ism*/, addr);
+                               UseLargePages, addr);
         heap_rs = heap_rs1;
       } else {
         heap_rs = heap_rs0;
@@ -1905,8 +2014,6 @@
 
   _expansion_regions = max_byte_size/HeapRegion::GrainBytes;
 
-  _num_humongous_regions = 0;
-
   // Create the gen rem set (and barrier set) for the entire reserved region.
   _rem_set = collector_policy()->create_rem_set(_reserved, 2);
   set_barrier_set(rem_set()->bs());
@@ -1951,6 +2058,8 @@
   guarantee((size_t) HeapRegion::CardsPerRegion < max_cards_per_region,
             "too many cards per region");
 
+  HeapRegionSet::set_unrealistically_long_length(max_regions() + 1);
+
   _bot_shared = new G1BlockOffsetSharedArray(_reserved,
                                              heap_word_size(init_byte_size));
 
@@ -1975,11 +2084,6 @@
   _cm       = new ConcurrentMark(heap_rs, (int) max_regions());
   _cmThread = _cm->cmThread();
 
-  // ...and the concurrent zero-fill thread, if necessary.
-  if (G1ConcZeroFill) {
-    _czft = new ConcurrentZFThread();
-  }
-
   // Initialize the from_card cache structure of HeapRegionRemSet.
   HeapRegionRemSet::init_heap(max_regions());
 
@@ -2153,7 +2257,7 @@
 #endif // PRODUCT
 
 size_t G1CollectedHeap::unsafe_max_alloc() {
-  if (_free_regions > 0) return HeapRegion::GrainBytes;
+  if (free_regions() > 0) return HeapRegion::GrainBytes;
   // otherwise, is there space in the current allocation region?
 
   // We need to store the current allocation region in a local variable
@@ -2233,8 +2337,7 @@
 }
 
 void G1CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) {
-  assert(Thread::current()->is_VM_thread(), "Precondition#1");
-  assert(Heap_lock->is_locked(), "Precondition#2");
+  assert_at_safepoint(true /* should_be_vm_thread */);
   GCCauseSetter gcs(this, cause);
   switch (cause) {
     case GCCause::_heap_inspection:
@@ -2257,12 +2360,6 @@
   {
     MutexLocker ml(Heap_lock);
 
-    // Don't want to do a GC until cleanup is completed. This
-    // limitation will be removed in the near future when the
-    // operation of the free region list is revamped as part of
-    // CR 6977804.
-    wait_for_cleanup_complete();
-
     // Read the GC count while holding the Heap_lock
     gc_count_before = SharedHeap::heap()->total_collections();
     full_gc_count_before = SharedHeap::heap()->total_full_collections();
@@ -2641,10 +2738,6 @@
   }
 }
 
-bool G1CollectedHeap::allocs_are_zero_filled() {
-  return false;
-}
-
 size_t G1CollectedHeap::large_typearray_limit() {
   // FIXME
   return HeapRegion::GrainBytes/HeapWordSize;
@@ -2659,7 +2752,6 @@
   return 0;
 }
 
-
 void G1CollectedHeap::prepare_for_verify() {
   if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) {
     ensure_parsability(false);
@@ -2870,7 +2962,9 @@
                          &rootsCl);
     bool failures = rootsCl.failures();
     rem_set()->invalidate(perm_gen()->used_region(), false);
-    if (!silent) { gclog_or_tty->print("heapRegions "); }
+    if (!silent) { gclog_or_tty->print("HeapRegionSets "); }
+    verify_region_sets();
+    if (!silent) { gclog_or_tty->print("HeapRegions "); }
     if (GCParallelVerificationEnabled && ParallelGCThreads > 1) {
       assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
              "sanity check");
@@ -2898,7 +2992,7 @@
         failures = true;
       }
     }
-    if (!silent) gclog_or_tty->print("remset ");
+    if (!silent) gclog_or_tty->print("RemSet ");
     rem_set()->verify();
 
     if (failures) {
@@ -2969,15 +3063,10 @@
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     workers()->print_worker_threads_on(st);
   }
-
   _cmThread->print_on(st);
   st->cr();
-
   _cm->print_worker_threads_on(st);
-
   _cg1r->print_worker_threads_on(st);
-
-  _czft->print_on(st);
   st->cr();
 }
 
@@ -2987,7 +3076,6 @@
   }
   tc->do_thread(_cmThread);
   _cg1r->threads_do(tc);
-  tc->do_thread(_czft);
 }
 
 void G1CollectedHeap::print_tracing_info() const {
@@ -3003,15 +3091,10 @@
   if (G1SummarizeConcMark) {
     concurrent_mark()->print_summary_info();
   }
-  if (G1SummarizeZFStats) {
-    ConcurrentZFThread::print_summary_info();
-  }
   g1_policy()->print_yg_surv_rate_info();
-
   SpecializationStats::print();
 }
 
-
 int G1CollectedHeap::addr_to_arena_id(void* addr) const {
   HeapRegion* hr = heap_region_containing(addr);
   if (hr == NULL) {
@@ -3210,17 +3293,22 @@
 
 bool
 G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
+  assert_at_safepoint(true /* should_be_vm_thread */);
+  guarantee(!is_gc_active(), "collection is not reentrant");
+
   if (GC_locker::check_active_before_gc()) {
     return false;
   }
 
-  DTraceGCProbeMarker gc_probe_marker(false /* full */);
+  SvcGCMarker sgcm(SvcGCMarker::MINOR);
   ResourceMark rm;
 
   if (PrintHeapAtGC) {
     Universe::print_heap_before_gc();
   }
 
+  verify_region_sets_optional();
+
   {
     // This call will decide whether this pause is an initial-mark
     // pause. If it is, during_initial_mark_pause() will return true
@@ -3251,10 +3339,16 @@
 
     TraceMemoryManagerStats tms(false /* fullGC */);
 
-    assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
-    assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
-    guarantee(!is_gc_active(), "collection is not reentrant");
-    assert(regions_accounted_for(), "Region leakage!");
+    // If there are any free regions available on the secondary_free_list
+    // make sure we append them to the free_list. However, we don't
+    // have to wait for the rest of the cleanup operation to
+    // finish. If it's still going on that's OK. If we run out of
+    // regions, the region allocation code will check the
+    // secondary_free_list and potentially wait if more free regions
+    // are coming (see new_region_try_secondary_free_list()).
+    if (!G1StressConcRegionFreeing) {
+      append_secondary_free_list_if_not_empty();
+    }
 
     increment_gc_time_stamp();
 
@@ -3334,8 +3428,6 @@
       // progress, this will be zero.
       _cm->set_oops_do_bound();
 
-      assert(regions_accounted_for(), "Region leakage.");
-
       if (mark_in_progress())
         concurrent_mark()->newCSet();
 
@@ -3431,8 +3523,6 @@
       g1_policy()->record_pause_time_ms(pause_time_ms);
       g1_policy()->record_collection_pause_end();
 
-      assert(regions_accounted_for(), "Region leakage.");
-
       MemoryService::track_memory_usage();
 
       if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) {
@@ -3463,8 +3553,6 @@
       gc_epilogue(false);
     }
 
-    assert(verify_region_lists(), "Bad region lists.");
-
     if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) {
       gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum);
       print_tracing_info();
@@ -3472,6 +3560,8 @@
     }
   }
 
+  verify_region_sets_optional();
+
   TASKQUEUE_STATS_ONLY(if (ParallelGCVerbose) print_taskqueue_stats());
   TASKQUEUE_STATS_ONLY(reset_taskqueue_stats());
 
@@ -3578,7 +3668,7 @@
 
 void G1CollectedHeap::push_gc_alloc_region(HeapRegion* hr) {
   assert(Thread::current()->is_VM_thread() ||
-         par_alloc_during_gc_lock()->owned_by_self(), "Precondition");
+         FreeList_lock->owned_by_self(), "Precondition");
   assert(!hr->is_gc_alloc_region() && !hr->in_collection_set(),
          "Precondition.");
   hr->set_is_gc_alloc_region(true);
@@ -3600,7 +3690,7 @@
 #endif // G1_DEBUG
 
 void G1CollectedHeap::forget_alloc_region_list() {
-  assert(Thread::current()->is_VM_thread(), "Precondition");
+  assert_at_safepoint(true /* should_be_vm_thread */);
   while (_gc_alloc_region_list != NULL) {
     HeapRegion* r = _gc_alloc_region_list;
     assert(r->is_gc_alloc_region(), "Invariant.");
@@ -3620,9 +3710,6 @@
         _young_list->add_survivor_region(r);
       }
     }
-    if (r->is_empty()) {
-      ++_free_regions;
-    }
   }
 #ifdef G1_DEBUG
   FindGCAllocRegion fa;
@@ -3675,7 +3762,7 @@
 
     if (alloc_region == NULL) {
       // we will get a new GC alloc region
-      alloc_region = newAllocRegionWithExpansion(ap, 0);
+      alloc_region = new_gc_alloc_region(ap, 0);
     } else {
       // the region was retained from the last collection
       ++_gc_alloc_region_counts[ap];
@@ -3730,11 +3817,9 @@
       set_gc_alloc_region(ap, NULL);
 
       if (r->is_empty()) {
-        // we didn't actually allocate anything in it; let's just put
-        // it on the free list
-        MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-        r->set_zero_fill_complete();
-        put_free_region_on_list_locked(r);
+        // We didn't actually allocate anything in it; let's just put
+        // it back on the free list.
+        _free_list.add_as_tail(r);
       } else if (_retain_gc_alloc_region[ap] && !totally) {
         // retain it so that we can use it at the beginning of the next GC
         _retained_gc_alloc_regions[ap] = r;
@@ -3856,13 +3941,15 @@
   size_t _next_marked_bytes;
   OopsInHeapRegionClosure *_cl;
 public:
-  RemoveSelfPointerClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* cl) :
-    _g1(g1), _cm(_g1->concurrent_mark()),  _prev_marked_bytes(0),
+  RemoveSelfPointerClosure(G1CollectedHeap* g1, HeapRegion* hr,
+                           OopsInHeapRegionClosure* cl) :
+    _g1(g1), _hr(hr), _cm(_g1->concurrent_mark()),  _prev_marked_bytes(0),
     _next_marked_bytes(0), _cl(cl) {}
 
   size_t prev_marked_bytes() { return _prev_marked_bytes; }
   size_t next_marked_bytes() { return _next_marked_bytes; }
 
+  // <original comment>
   // The original idea here was to coalesce evacuated and dead objects.
   // However that caused complications with the block offset table (BOT).
   // In particular if there were two TLABs, one of them partially refined.
@@ -3871,15 +3958,24 @@
   // of TLAB_2. If the last object of the TLAB_1 and the first object
   // of TLAB_2 are coalesced, then the cards of the unrefined part
   // would point into middle of the filler object.
+  // The current approach is to not coalesce and leave the BOT contents intact.
+  // </original comment>
   //
-  // The current approach is to not coalesce and leave the BOT contents intact.
+  // We now reset the BOT when we start the object iteration over the
+  // region and refine its entries for every object we come across. So
+  // the above comment is not really relevant and we should be able
+  // to coalesce dead objects if we want to.
   void do_object(oop obj) {
+    HeapWord* obj_addr = (HeapWord*) obj;
+    assert(_hr->is_in(obj_addr), "sanity");
+    size_t obj_size = obj->size();
+    _hr->update_bot_for_object(obj_addr, obj_size);
     if (obj->is_forwarded() && obj->forwardee() == obj) {
       // The object failed to move.
       assert(!_g1->is_obj_dead(obj), "We should not be preserving dead objs.");
       _cm->markPrev(obj);
       assert(_cm->isPrevMarked(obj), "Should be marked!");
-      _prev_marked_bytes += (obj->size() * HeapWordSize);
+      _prev_marked_bytes += (obj_size * HeapWordSize);
       if (_g1->mark_in_progress() && !_g1->is_obj_ill(obj)) {
         _cm->markAndGrayObjectIfNecessary(obj);
       }
@@ -3901,7 +3997,7 @@
     } else {
       // The object has been either evacuated or is dead. Fill it with a
       // dummy object.
-      MemRegion mr((HeapWord*)obj, obj->size());
+      MemRegion mr((HeapWord*)obj, obj_size);
       CollectedHeap::fill_with_object(mr);
       _cm->clearRangeBothMaps(mr);
     }
@@ -3921,10 +4017,13 @@
   HeapRegion* cur = g1_policy()->collection_set();
   while (cur != NULL) {
     assert(g1_policy()->assertMarkedBytesDataOK(), "Should be!");
-
-    RemoveSelfPointerClosure rspc(_g1h, cl);
+    assert(!cur->isHumongous(), "sanity");
+
     if (cur->evacuation_failed()) {
       assert(cur->in_collection_set(), "bad CS");
+      RemoveSelfPointerClosure rspc(_g1h, cur, cl);
+
+      cur->reset_bot();
       cl->set_region(cur);
       cur->object_iterate(&rspc);
 
@@ -3989,15 +4088,6 @@
   }
 }
 
-void G1CollectedHeap::handle_evacuation_failure(oop old) {
-  markOop m = old->mark();
-  // forward to self
-  assert(!old->is_forwarded(), "precondition");
-
-  old->forward_to(old);
-  handle_evacuation_failure_common(old, m);
-}
-
 oop
 G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl,
                                                oop old) {
@@ -4084,8 +4174,6 @@
 
   HeapWord* block = alloc_region->par_allocate(word_size);
   if (block == NULL) {
-    MutexLockerEx x(par_alloc_during_gc_lock(),
-                    Mutex::_no_safepoint_check_flag);
     block = allocate_during_gc_slow(purpose, alloc_region, true, word_size);
   }
   return block;
@@ -4114,6 +4202,12 @@
          err_msg("we should not be seeing humongous allocation requests "
                  "during GC, word_size = "SIZE_FORMAT, word_size));
 
+  // We need to make sure we serialize calls to this method. Given
+  // that the FreeList_lock guards accesses to the free_list anyway,
+  // and we need to potentially remove a region from it, we'll use it
+  // to protect the whole call.
+  MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+
   HeapWord* block = NULL;
   // In the parallel case, a previous thread to obtain the lock may have
   // already assigned a new gc_alloc_region.
@@ -4159,7 +4253,7 @@
   }
 
   // Now allocate a new region for allocation.
-  alloc_region = newAllocRegionWithExpansion(purpose, word_size, false /*zero_filled*/);
+  alloc_region = new_gc_alloc_region(purpose, word_size);
 
   // let the caller handle alloc failure
   if (alloc_region != NULL) {
@@ -4167,9 +4261,6 @@
     assert(check_gc_alloc_regions(), "alloc regions messed up");
     assert(alloc_region->saved_mark_at_top(),
            "Mark should have been saved already.");
-    // We used to assert that the region was zero-filled here, but no
-    // longer.
-
     // This must be done last: once it's installed, other regions may
     // allocate in it (without holding the lock.)
     set_gc_alloc_region(purpose, alloc_region);
@@ -4834,91 +4925,94 @@
   COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
 }
 
-void G1CollectedHeap::free_region(HeapRegion* hr) {
-  size_t pre_used = 0;
-  size_t cleared_h_regions = 0;
-  size_t freed_regions = 0;
-  UncleanRegionList local_list;
-
-  HeapWord* start = hr->bottom();
-  HeapWord* end   = hr->prev_top_at_mark_start();
-  size_t used_bytes = hr->used();
-  size_t live_bytes = hr->max_live_bytes();
-  if (used_bytes > 0) {
-    guarantee( live_bytes <= used_bytes, "invariant" );
-  } else {
-    guarantee( live_bytes == 0, "invariant" );
-  }
-
-  size_t garbage_bytes = used_bytes - live_bytes;
-  if (garbage_bytes > 0)
-    g1_policy()->decrease_known_garbage_bytes(garbage_bytes);
-
-  free_region_work(hr, pre_used, cleared_h_regions, freed_regions,
-                   &local_list);
-  finish_free_region_work(pre_used, cleared_h_regions, freed_regions,
-                          &local_list);
-}
-
-void
-G1CollectedHeap::free_region_work(HeapRegion* hr,
-                                  size_t& pre_used,
-                                  size_t& cleared_h_regions,
-                                  size_t& freed_regions,
-                                  UncleanRegionList* list,
-                                  bool par) {
-  pre_used += hr->used();
-  if (hr->isHumongous()) {
-    assert(hr->startsHumongous(),
-           "Only the start of a humongous region should be freed.");
-    int ind = _hrs->find(hr);
-    assert(ind != -1, "Should have an index.");
-    // Clear the start region.
-    hr->hr_clear(par, true /*clear_space*/);
-    list->insert_before_head(hr);
-    cleared_h_regions++;
-    freed_regions++;
-    // Clear any continued regions.
-    ind++;
-    while ((size_t)ind < n_regions()) {
-      HeapRegion* hrc = _hrs->at(ind);
-      if (!hrc->continuesHumongous()) break;
-      // Otherwise, does continue the H region.
-      assert(hrc->humongous_start_region() == hr, "Huh?");
-      hrc->hr_clear(par, true /*clear_space*/);
-      cleared_h_regions++;
-      freed_regions++;
-      list->insert_before_head(hrc);
-      ind++;
+void G1CollectedHeap::free_region_if_empty(HeapRegion* hr,
+                                     size_t* pre_used,
+                                     FreeRegionList* free_list,
+                                     HumongousRegionSet* humongous_proxy_set,
+                                     HRRSCleanupTask* hrrs_cleanup_task,
+                                     bool par) {
+  if (hr->used() > 0 && hr->max_live_bytes() == 0 && !hr->is_young()) {
+    if (hr->isHumongous()) {
+      assert(hr->startsHumongous(), "we should only see starts humongous");
+      free_humongous_region(hr, pre_used, free_list, humongous_proxy_set, par);
+    } else {
+      free_region(hr, pre_used, free_list, par);
     }
   } else {
-    hr->hr_clear(par, true /*clear_space*/);
-    list->insert_before_head(hr);
-    freed_regions++;
-    // If we're using clear2, this should not be enabled.
-    // assert(!hr->in_cohort(), "Can't be both free and in a cohort.");
+    hr->rem_set()->do_cleanup_work(hrrs_cleanup_task);
   }
 }
 
-void G1CollectedHeap::finish_free_region_work(size_t pre_used,
-                                              size_t cleared_h_regions,
-                                              size_t freed_regions,
-                                              UncleanRegionList* list) {
-  if (list != NULL && list->sz() > 0) {
-    prepend_region_list_on_unclean_list(list);
-  }
-  // Acquire a lock, if we're parallel, to update possibly-shared
-  // variables.
-  Mutex* lock = (n_par_threads() > 0) ? ParGCRareEvent_lock : NULL;
-  {
+void G1CollectedHeap::free_region(HeapRegion* hr,
+                                  size_t* pre_used,
+                                  FreeRegionList* free_list,
+                                  bool par) {
+  assert(!hr->isHumongous(), "this is only for non-humongous regions");
+  assert(!hr->is_empty(), "the region should not be empty");
+  assert(free_list != NULL, "pre-condition");
+
+  *pre_used += hr->used();
+  hr->hr_clear(par, true /* clear_space */);
+  free_list->add_as_tail(hr);
+}
+
+void G1CollectedHeap::free_humongous_region(HeapRegion* hr,
+                                     size_t* pre_used,
+                                     FreeRegionList* free_list,
+                                     HumongousRegionSet* humongous_proxy_set,
+                                     bool par) {
+  assert(hr->startsHumongous(), "this is only for starts humongous regions");
+  assert(free_list != NULL, "pre-condition");
+  assert(humongous_proxy_set != NULL, "pre-condition");
+
+  size_t hr_used = hr->used();
+  size_t hr_capacity = hr->capacity();
+  size_t hr_pre_used = 0;
+  _humongous_set.remove_with_proxy(hr, humongous_proxy_set);
+  hr->set_notHumongous();
+  free_region(hr, &hr_pre_used, free_list, par);
+
+  int i = hr->hrs_index() + 1;
+  size_t num = 1;
+  while ((size_t) i < n_regions()) {
+    HeapRegion* curr_hr = _hrs->at(i);
+    if (!curr_hr->continuesHumongous()) {
+      break;
+    }
+    curr_hr->set_notHumongous();
+    free_region(curr_hr, &hr_pre_used, free_list, par);
+    num += 1;
+    i += 1;
+  }
+  assert(hr_pre_used == hr_used,
+         err_msg("hr_pre_used: "SIZE_FORMAT" and hr_used: "SIZE_FORMAT" "
+                 "should be the same", hr_pre_used, hr_used));
+  *pre_used += hr_pre_used;
+}
+
+void G1CollectedHeap::update_sets_after_freeing_regions(size_t pre_used,
+                                       FreeRegionList* free_list,
+                                       HumongousRegionSet* humongous_proxy_set,
+                                       bool par) {
+  if (pre_used > 0) {
+    Mutex* lock = (par) ? ParGCRareEvent_lock : NULL;
     MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
+    assert(_summary_bytes_used >= pre_used,
+           err_msg("invariant: _summary_bytes_used: "SIZE_FORMAT" "
+                   "should be >= pre_used: "SIZE_FORMAT,
+                   _summary_bytes_used, pre_used));
     _summary_bytes_used -= pre_used;
-    _num_humongous_regions -= (int) cleared_h_regions;
-    _free_regions += freed_regions;
+  }
+  if (free_list != NULL && !free_list->is_empty()) {
+    MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+    _free_list.add_as_tail(free_list);
+  }
+  if (humongous_proxy_set != NULL && !humongous_proxy_set->is_empty()) {
+    MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag);
+    _humongous_set.update_from_proxy(humongous_proxy_set);
   }
 }
 
-
 void G1CollectedHeap::dirtyCardsForYoungRegions(CardTableModRefBS* ct_bs, HeapRegion* list) {
   while (list != NULL) {
     guarantee( list->is_young(), "invariant" );
@@ -5041,6 +5135,9 @@
 }
 
 void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) {
+  size_t pre_used = 0;
+  FreeRegionList local_free_list("Local List for CSet Freeing");
+
   double young_time_ms     = 0.0;
   double non_young_time_ms = 0.0;
 
@@ -5059,6 +5156,8 @@
   size_t rs_lengths = 0;
 
   while (cur != NULL) {
+    assert(!is_on_free_list(cur), "sanity");
+
     if (non_young) {
       if (cur->is_young()) {
         double end_sec = os::elapsedTime();
@@ -5069,14 +5168,12 @@
         non_young = false;
       }
     } else {
-      if (!cur->is_on_free_list()) {
-        double end_sec = os::elapsedTime();
-        double elapsed_ms = (end_sec - start_sec) * 1000.0;
-        young_time_ms += elapsed_ms;
-
-        start_sec = os::elapsedTime();
-        non_young = true;
-      }
+      double end_sec = os::elapsedTime();
+      double elapsed_ms = (end_sec - start_sec) * 1000.0;
+      young_time_ms += elapsed_ms;
+
+      start_sec = os::elapsedTime();
+      non_young = true;
     }
 
     rs_lengths += cur->rem_set()->occupied();
@@ -5109,9 +5206,8 @@
 
     if (!cur->evacuation_failed()) {
       // And the region is empty.
-      assert(!cur->is_empty(),
-             "Should not have empty regions in a CS.");
-      free_region(cur);
+      assert(!cur->is_empty(), "Should not have empty regions in a CS.");
+      free_region(cur, &pre_used, &local_free_list, false /* par */);
     } else {
       cur->uninstall_surv_rate_group();
       if (cur->is_young())
@@ -5132,6 +5228,9 @@
   else
     young_time_ms += elapsed_ms;
 
+  update_sets_after_freeing_regions(pre_used, &local_free_list,
+                                    NULL /* humongous_proxy_set */,
+                                    false /* par */);
   policy->record_young_free_cset_time_ms(young_time_ms);
   policy->record_non_young_free_cset_time_ms(non_young_time_ms);
 }
@@ -5157,291 +5256,53 @@
   }
 }
 
-HeapRegion*
-G1CollectedHeap::alloc_region_from_unclean_list_locked(bool zero_filled) {
-  assert(ZF_mon->owned_by_self(), "Precondition");
-  HeapRegion* res = pop_unclean_region_list_locked();
-  if (res != NULL) {
-    assert(!res->continuesHumongous() &&
-           res->zero_fill_state() != HeapRegion::Allocated,
-           "Only free regions on unclean list.");
-    if (zero_filled) {
-      res->ensure_zero_filled_locked();
-      res->set_zero_fill_allocated();
-    }
-  }
-  return res;
-}
-
-HeapRegion* G1CollectedHeap::alloc_region_from_unclean_list(bool zero_filled) {
-  MutexLockerEx zx(ZF_mon, Mutex::_no_safepoint_check_flag);
-  return alloc_region_from_unclean_list_locked(zero_filled);
+void G1CollectedHeap::set_free_regions_coming() {
+  if (G1ConcRegionFreeingVerbose) {
+    gclog_or_tty->print_cr("G1ConcRegionFreeing [cm thread] : "
+                           "setting free regions coming");
+  }
+
+  assert(!free_regions_coming(), "pre-condition");
+  _free_regions_coming = true;
 }
 
-void G1CollectedHeap::put_region_on_unclean_list(HeapRegion* r) {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-  put_region_on_unclean_list_locked(r);
-  if (should_zf()) ZF_mon->notify_all(); // Wake up ZF thread.
-}
-
-void G1CollectedHeap::set_unclean_regions_coming(bool b) {
-  MutexLockerEx x(Cleanup_mon);
-  set_unclean_regions_coming_locked(b);
-}
-
-void G1CollectedHeap::set_unclean_regions_coming_locked(bool b) {
-  assert(Cleanup_mon->owned_by_self(), "Precondition");
-  _unclean_regions_coming = b;
-  // Wake up mutator threads that might be waiting for completeCleanup to
-  // finish.
-  if (!b) Cleanup_mon->notify_all();
-}
-
-void G1CollectedHeap::wait_for_cleanup_complete() {
-  assert_not_at_safepoint();
-  MutexLockerEx x(Cleanup_mon);
-  wait_for_cleanup_complete_locked();
-}
-
-void G1CollectedHeap::wait_for_cleanup_complete_locked() {
-  assert(Cleanup_mon->owned_by_self(), "precondition");
-  while (_unclean_regions_coming) {
-    Cleanup_mon->wait();
+void G1CollectedHeap::reset_free_regions_coming() {
+  {
+    assert(free_regions_coming(), "pre-condition");
+    MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+    _free_regions_coming = false;
+    SecondaryFreeList_lock->notify_all();
+  }
+
+  if (G1ConcRegionFreeingVerbose) {
+    gclog_or_tty->print_cr("G1ConcRegionFreeing [cm thread] : "
+                           "reset free regions coming");
   }
 }
 
-void
-G1CollectedHeap::put_region_on_unclean_list_locked(HeapRegion* r) {
-  assert(ZF_mon->owned_by_self(), "precondition.");
-#ifdef ASSERT
-  if (r->is_gc_alloc_region()) {
-    ResourceMark rm;
-    stringStream region_str;
-    print_on(&region_str);
-    assert(!r->is_gc_alloc_region(), err_msg("Unexpected GC allocation region: %s",
-                                             region_str.as_string()));
-  }
-#endif
-  _unclean_region_list.insert_before_head(r);
-}
-
-void
-G1CollectedHeap::prepend_region_list_on_unclean_list(UncleanRegionList* list) {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-  prepend_region_list_on_unclean_list_locked(list);
-  if (should_zf()) ZF_mon->notify_all(); // Wake up ZF thread.
-}
-
-void
-G1CollectedHeap::
-prepend_region_list_on_unclean_list_locked(UncleanRegionList* list) {
-  assert(ZF_mon->owned_by_self(), "precondition.");
-  _unclean_region_list.prepend_list(list);
-}
-
-HeapRegion* G1CollectedHeap::pop_unclean_region_list_locked() {
-  assert(ZF_mon->owned_by_self(), "precondition.");
-  HeapRegion* res = _unclean_region_list.pop();
-  if (res != NULL) {
-    // Inform ZF thread that there's a new unclean head.
-    if (_unclean_region_list.hd() != NULL && should_zf())
-      ZF_mon->notify_all();
-  }
-  return res;
-}
-
-HeapRegion* G1CollectedHeap::peek_unclean_region_list_locked() {
-  assert(ZF_mon->owned_by_self(), "precondition.");
-  return _unclean_region_list.hd();
-}
-
-
-bool G1CollectedHeap::move_cleaned_region_to_free_list_locked() {
-  assert(ZF_mon->owned_by_self(), "Precondition");
-  HeapRegion* r = peek_unclean_region_list_locked();
-  if (r != NULL && r->zero_fill_state() == HeapRegion::ZeroFilled) {
-    // Result of below must be equal to "r", since we hold the lock.
-    (void)pop_unclean_region_list_locked();
-    put_free_region_on_list_locked(r);
-    return true;
-  } else {
-    return false;
-  }
-}
-
-bool G1CollectedHeap::move_cleaned_region_to_free_list() {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-  return move_cleaned_region_to_free_list_locked();
-}
-
-
-void G1CollectedHeap::put_free_region_on_list_locked(HeapRegion* r) {
-  assert(ZF_mon->owned_by_self(), "precondition.");
-  assert(_free_region_list_size == free_region_list_length(), "Inv");
-  assert(r->zero_fill_state() == HeapRegion::ZeroFilled,
-        "Regions on free list must be zero filled");
-  assert(!r->isHumongous(), "Must not be humongous.");
-  assert(r->is_empty(), "Better be empty");
-  assert(!r->is_on_free_list(),
-         "Better not already be on free list");
-  assert(!r->is_on_unclean_list(),
-         "Better not already be on unclean list");
-  r->set_on_free_list(true);
-  r->set_next_on_free_list(_free_region_list);
-  _free_region_list = r;
-  _free_region_list_size++;
-  assert(_free_region_list_size == free_region_list_length(), "Inv");
-}
-
-void G1CollectedHeap::put_free_region_on_list(HeapRegion* r) {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-  put_free_region_on_list_locked(r);
-}
-
-HeapRegion* G1CollectedHeap::pop_free_region_list_locked() {
-  assert(ZF_mon->owned_by_self(), "precondition.");
-  assert(_free_region_list_size == free_region_list_length(), "Inv");
-  HeapRegion* res = _free_region_list;
-  if (res != NULL) {
-    _free_region_list = res->next_from_free_list();
-    _free_region_list_size--;
-    res->set_on_free_list(false);
-    res->set_next_on_free_list(NULL);
-    assert(_free_region_list_size == free_region_list_length(), "Inv");
-  }
-  return res;
-}
-
-
-HeapRegion* G1CollectedHeap::alloc_free_region_from_lists(bool zero_filled) {
-  // By self, or on behalf of self.
-  assert(Heap_lock->is_locked(), "Precondition");
-  HeapRegion* res = NULL;
-  bool first = true;
-  while (res == NULL) {
-    if (zero_filled || !first) {
-      MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-      res = pop_free_region_list_locked();
-      if (res != NULL) {
-        assert(!res->zero_fill_is_allocated(),
-               "No allocated regions on free list.");
-        res->set_zero_fill_allocated();
-      } else if (!first) {
-        break;  // We tried both, time to return NULL.
-      }
-    }
-
-    if (res == NULL) {
-      res = alloc_region_from_unclean_list(zero_filled);
-    }
-    assert(res == NULL ||
-           !zero_filled ||
-           res->zero_fill_is_allocated(),
-           "We must have allocated the region we're returning");
-    first = false;
-  }
-  return res;
-}
-
-void G1CollectedHeap::remove_allocated_regions_from_lists() {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-  {
-    HeapRegion* prev = NULL;
-    HeapRegion* cur = _unclean_region_list.hd();
-    while (cur != NULL) {
-      HeapRegion* next = cur->next_from_unclean_list();
-      if (cur->zero_fill_is_allocated()) {
-        // Remove from the list.
-        if (prev == NULL) {
-          (void)_unclean_region_list.pop();
-        } else {
-          _unclean_region_list.delete_after(prev);
-        }
-        cur->set_on_unclean_list(false);
-        cur->set_next_on_unclean_list(NULL);
-      } else {
-        prev = cur;
-      }
-      cur = next;
-    }
-    assert(_unclean_region_list.sz() == unclean_region_list_length(),
-           "Inv");
+void G1CollectedHeap::wait_while_free_regions_coming() {
+  // Most of the time we won't have to wait, so let's do a quick test
+  // first before we take the lock.
+  if (!free_regions_coming()) {
+    return;
+  }
+
+  if (G1ConcRegionFreeingVerbose) {
+    gclog_or_tty->print_cr("G1ConcRegionFreeing [other] : "
+                           "waiting for free regions");
   }
 
   {
-    HeapRegion* prev = NULL;
-    HeapRegion* cur = _free_region_list;
-    while (cur != NULL) {
-      HeapRegion* next = cur->next_from_free_list();
-      if (cur->zero_fill_is_allocated()) {
-        // Remove from the list.
-        if (prev == NULL) {
-          _free_region_list = cur->next_from_free_list();
-        } else {
-          prev->set_next_on_free_list(cur->next_from_free_list());
-        }
-        cur->set_on_free_list(false);
-        cur->set_next_on_free_list(NULL);
-        _free_region_list_size--;
-      } else {
-        prev = cur;
-      }
-      cur = next;
+    MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+    while (free_regions_coming()) {
+      SecondaryFreeList_lock->wait(Mutex::_no_safepoint_check_flag);
     }
-    assert(_free_region_list_size == free_region_list_length(), "Inv");
-  }
-}
-
-bool G1CollectedHeap::verify_region_lists() {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-  return verify_region_lists_locked();
-}
-
-bool G1CollectedHeap::verify_region_lists_locked() {
-  HeapRegion* unclean = _unclean_region_list.hd();
-  while (unclean != NULL) {
-    guarantee(unclean->is_on_unclean_list(), "Well, it is!");
-    guarantee(!unclean->is_on_free_list(), "Well, it shouldn't be!");
-    guarantee(unclean->zero_fill_state() != HeapRegion::Allocated,
-              "Everything else is possible.");
-    unclean = unclean->next_from_unclean_list();
-  }
-  guarantee(_unclean_region_list.sz() == unclean_region_list_length(), "Inv");
-
-  HeapRegion* free_r = _free_region_list;
-  while (free_r != NULL) {
-    assert(free_r->is_on_free_list(), "Well, it is!");
-    assert(!free_r->is_on_unclean_list(), "Well, it shouldn't be!");
-    switch (free_r->zero_fill_state()) {
-    case HeapRegion::NotZeroFilled:
-    case HeapRegion::ZeroFilling:
-      guarantee(false, "Should not be on free list.");
-      break;
-    default:
-      // Everything else is possible.
-      break;
-    }
-    free_r = free_r->next_from_free_list();
-  }
-  guarantee(_free_region_list_size == free_region_list_length(), "Inv");
-  // If we didn't do an assertion...
-  return true;
-}
-
-size_t G1CollectedHeap::free_region_list_length() {
-  assert(ZF_mon->owned_by_self(), "precondition.");
-  size_t len = 0;
-  HeapRegion* cur = _free_region_list;
-  while (cur != NULL) {
-    len++;
-    cur = cur->next_from_free_list();
-  }
-  return len;
-}
-
-size_t G1CollectedHeap::unclean_region_list_length() {
-  assert(ZF_mon->owned_by_self(), "precondition.");
-  return _unclean_region_list.length();
+  }
+
+  if (G1ConcRegionFreeingVerbose) {
+    gclog_or_tty->print_cr("G1ConcRegionFreeing [other] : "
+                           "done waiting for free regions");
+  }
 }
 
 size_t G1CollectedHeap::n_regions() {
@@ -5454,55 +5315,6 @@
     HeapRegion::GrainBytes;
 }
 
-size_t G1CollectedHeap::free_regions() {
-  /* Possibly-expensive assert.
-  assert(_free_regions == count_free_regions(),
-         "_free_regions is off.");
-  */
-  return _free_regions;
-}
-
-bool G1CollectedHeap::should_zf() {
-  return _free_region_list_size < (size_t) G1ConcZFMaxRegions;
-}
-
-class RegionCounter: public HeapRegionClosure {
-  size_t _n;
-public:
-  RegionCounter() : _n(0) {}
-  bool doHeapRegion(HeapRegion* r) {
-    if (r->is_empty()) {
-      assert(!r->isHumongous(), "H regions should not be empty.");
-      _n++;
-    }
-    return false;
-  }
-  int res() { return (int) _n; }
-};
-
-size_t G1CollectedHeap::count_free_regions() {
-  RegionCounter rc;
-  heap_region_iterate(&rc);
-  size_t n = rc.res();
-  if (_cur_alloc_region != NULL && _cur_alloc_region->is_empty())
-    n--;
-  return n;
-}
-
-size_t G1CollectedHeap::count_free_regions_list() {
-  size_t n = 0;
-  size_t o = 0;
-  ZF_mon->lock_without_safepoint_check();
-  HeapRegion* cur = _free_region_list;
-  while (cur != NULL) {
-    cur = cur->next_from_free_list();
-    n++;
-  }
-  size_t m = unclean_region_list_length();
-  ZF_mon->unlock();
-  return n + m;
-}
-
 void G1CollectedHeap::set_region_short_lived_locked(HeapRegion* hr) {
   assert(heap_lock_held_for_gc(),
               "the heap lock should already be held by or for this thread");
@@ -5574,28 +5386,19 @@
   }
 }
 
-
 // Done at the start of full GC.
 void G1CollectedHeap::tear_down_region_lists() {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-  while (pop_unclean_region_list_locked() != NULL) ;
-  assert(_unclean_region_list.hd() == NULL && _unclean_region_list.sz() == 0,
-         "Postconditions of loop.");
-  while (pop_free_region_list_locked() != NULL) ;
-  assert(_free_region_list == NULL, "Postcondition of loop.");
-  if (_free_region_list_size != 0) {
-    gclog_or_tty->print_cr("Size is %d.", _free_region_list_size);
-    print_on(gclog_or_tty, true /* extended */);
-  }
-  assert(_free_region_list_size == 0, "Postconditions of loop.");
+  _free_list.remove_all();
 }
 
-
 class RegionResetter: public HeapRegionClosure {
-  G1CollectedHeap* _g1;
-  int _n;
+  G1CollectedHeap* _g1h;
+  FreeRegionList _local_free_list;
+
 public:
-  RegionResetter() : _g1(G1CollectedHeap::heap()), _n(0) {}
+  RegionResetter() : _g1h(G1CollectedHeap::heap()),
+                     _local_free_list("Local Free List for RegionResetter") { }
+
   bool doHeapRegion(HeapRegion* r) {
     if (r->continuesHumongous()) return false;
     if (r->top() > r->bottom()) {
@@ -5603,152 +5406,32 @@
         Copy::fill_to_words(r->top(),
                           pointer_delta(r->end(), r->top()));
       }
-      r->set_zero_fill_allocated();
     } else {
       assert(r->is_empty(), "tautology");
-      _n++;
-      switch (r->zero_fill_state()) {
-        case HeapRegion::NotZeroFilled:
-        case HeapRegion::ZeroFilling:
-          _g1->put_region_on_unclean_list_locked(r);
-          break;
-        case HeapRegion::Allocated:
-          r->set_zero_fill_complete();
-          // no break; go on to put on free list.
-        case HeapRegion::ZeroFilled:
-          _g1->put_free_region_on_list_locked(r);
-          break;
-      }
+      _local_free_list.add_as_tail(r);
     }
     return false;
   }
 
-  int getFreeRegionCount() {return _n;}
+  void update_free_lists() {
+    _g1h->update_sets_after_freeing_regions(0, &_local_free_list, NULL,
+                                            false /* par */);
+  }
 };
 
 // Done at the end of full GC.
 void G1CollectedHeap::rebuild_region_lists() {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
   // This needs to go at the end of the full GC.
   RegionResetter rs;
   heap_region_iterate(&rs);
-  _free_regions = rs.getFreeRegionCount();
-  // Tell the ZF thread it may have work to do.
-  if (should_zf()) ZF_mon->notify_all();
-}
-
-class UsedRegionsNeedZeroFillSetter: public HeapRegionClosure {
-  G1CollectedHeap* _g1;
-  int _n;
-public:
-  UsedRegionsNeedZeroFillSetter() : _g1(G1CollectedHeap::heap()), _n(0) {}
-  bool doHeapRegion(HeapRegion* r) {
-    if (r->continuesHumongous()) return false;
-    if (r->top() > r->bottom()) {
-      // There are assertions in "set_zero_fill_needed()" below that
-      // require top() == bottom(), so this is technically illegal.
-      // We'll skirt the law here, by making that true temporarily.
-      DEBUG_ONLY(HeapWord* save_top = r->top();
-                 r->set_top(r->bottom()));
-      r->set_zero_fill_needed();
-      DEBUG_ONLY(r->set_top(save_top));
-    }
-    return false;
-  }
-};
-
-// Done at the start of full GC.
-void G1CollectedHeap::set_used_regions_to_need_zero_fill() {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-  // This needs to go at the end of the full GC.
-  UsedRegionsNeedZeroFillSetter rs;
-  heap_region_iterate(&rs);
+  rs.update_free_lists();
 }
 
 void G1CollectedHeap::set_refine_cte_cl_concurrency(bool concurrent) {
   _refine_cte_cl->set_concurrent(concurrent);
 }
 
-#ifndef PRODUCT
-
-class PrintHeapRegionClosure: public HeapRegionClosure {
-public:
-  bool doHeapRegion(HeapRegion *r) {
-    gclog_or_tty->print("Region: "PTR_FORMAT":", r);
-    if (r != NULL) {
-      if (r->is_on_free_list())
-        gclog_or_tty->print("Free ");
-      if (r->is_young())
-        gclog_or_tty->print("Young ");
-      if (r->isHumongous())
-        gclog_or_tty->print("Is Humongous ");
-      r->print();
-    }
-    return false;
-  }
-};
-
-class SortHeapRegionClosure : public HeapRegionClosure {
-  size_t young_regions,free_regions, unclean_regions;
-  size_t hum_regions, count;
-  size_t unaccounted, cur_unclean, cur_alloc;
-  size_t total_free;
-  HeapRegion* cur;
-public:
-  SortHeapRegionClosure(HeapRegion *_cur) : cur(_cur), young_regions(0),
-    free_regions(0), unclean_regions(0),
-    hum_regions(0),
-    count(0), unaccounted(0),
-    cur_alloc(0), total_free(0)
-  {}
-  bool doHeapRegion(HeapRegion *r) {
-    count++;
-    if (r->is_on_free_list()) free_regions++;
-    else if (r->is_on_unclean_list()) unclean_regions++;
-    else if (r->isHumongous())  hum_regions++;
-    else if (r->is_young()) young_regions++;
-    else if (r == cur) cur_alloc++;
-    else unaccounted++;
-    return false;
-  }
-  void print() {
-    total_free = free_regions + unclean_regions;
-    gclog_or_tty->print("%d regions\n", count);
-    gclog_or_tty->print("%d free: free_list = %d unclean = %d\n",
-                        total_free, free_regions, unclean_regions);
-    gclog_or_tty->print("%d humongous %d young\n",
-                        hum_regions, young_regions);
-    gclog_or_tty->print("%d cur_alloc\n", cur_alloc);
-    gclog_or_tty->print("UHOH unaccounted = %d\n", unaccounted);
-  }
-};
-
-void G1CollectedHeap::print_region_counts() {
-  SortHeapRegionClosure sc(_cur_alloc_region);
-  PrintHeapRegionClosure cl;
-  heap_region_iterate(&cl);
-  heap_region_iterate(&sc);
-  sc.print();
-  print_region_accounting_info();
-};
-
-bool G1CollectedHeap::regions_accounted_for() {
-  // TODO: regions accounting for young/survivor/tenured
-  return true;
-}
-
-bool G1CollectedHeap::print_region_accounting_info() {
-  gclog_or_tty->print_cr("Free regions: %d (count: %d count list %d) (clean: %d unclean: %d).",
-                         free_regions(),
-                         count_free_regions(), count_free_regions_list(),
-                         _free_region_list_size, _unclean_region_list.sz());
-  gclog_or_tty->print_cr("cur_alloc: %d.",
-                         (_cur_alloc_region == NULL ? 0 : 1));
-  gclog_or_tty->print_cr("H regions: %d.", _num_humongous_regions);
-
-  // TODO: check regions accounting for young/survivor/tenured
-  return true;
-}
+#ifdef ASSERT
 
 bool G1CollectedHeap::is_in_closed_subset(const void* p) const {
   HeapRegion* hr = heap_region_containing(p);
@@ -5758,8 +5441,84 @@
     return hr->is_in(p);
   }
 }
-#endif // !PRODUCT
-
-void G1CollectedHeap::g1_unimplemented() {
-  // Unimplemented();
+#endif // ASSERT
+
+class VerifyRegionListsClosure : public HeapRegionClosure {
+private:
+  HumongousRegionSet* _humongous_set;
+  FreeRegionList*     _free_list;
+  size_t              _region_count;
+
+public:
+  VerifyRegionListsClosure(HumongousRegionSet* humongous_set,
+                           FreeRegionList* free_list) :
+    _humongous_set(humongous_set), _free_list(free_list),
+    _region_count(0) { }
+
+  size_t region_count()      { return _region_count;      }
+
+  bool doHeapRegion(HeapRegion* hr) {
+    _region_count += 1;
+
+    if (hr->continuesHumongous()) {
+      return false;
+    }
+
+    if (hr->is_young()) {
+      // TODO
+    } else if (hr->startsHumongous()) {
+      _humongous_set->verify_next_region(hr);
+    } else if (hr->is_empty()) {
+      _free_list->verify_next_region(hr);
+    }
+    return false;
+  }
+};
+
+void G1CollectedHeap::verify_region_sets() {
+  assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
+
+  // First, check the explicit lists.
+  _free_list.verify();
+  {
+    // Given that a concurrent operation might be adding regions to
+    // the secondary free list we have to take the lock before
+    // verifying it.
+    MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+    _secondary_free_list.verify();
+  }
+  _humongous_set.verify();
+
+  // If a concurrent region freeing operation is in progress it will
+  // be difficult to correctly attributed any free regions we come
+  // across to the correct free list given that they might belong to
+  // one of several (free_list, secondary_free_list, any local lists,
+  // etc.). So, if that's the case we will skip the rest of the
+  // verification operation. Alternatively, waiting for the concurrent
+  // operation to complete will have a non-trivial effect on the GC's
+  // operation (no concurrent operation will last longer than the
+  // interval between two calls to verification) and it might hide
+  // any issues that we would like to catch during testing.
+  if (free_regions_coming()) {
+    return;
+  }
+
+  {
+    MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+    // Make sure we append the secondary_free_list on the free_list so
+    // that all free regions we will come across can be safely
+    // attributed to the free_list.
+    append_secondary_free_list();
+  }
+
+  // Finally, make sure that the region accounting in the lists is
+  // consistent with what we see in the heap.
+  _humongous_set.verify_start();
+  _free_list.verify_start();
+
+  VerifyRegionListsClosure cl(&_humongous_set, &_free_list);
+  heap_region_iterate(&cl);
+
+  _humongous_set.verify_end();
+  _free_list.verify_end();
 }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
 
 #include "gc_implementation/g1/concurrentMark.hpp"
 #include "gc_implementation/g1/g1RemSet.hpp"
-#include "gc_implementation/g1/heapRegion.hpp"
+#include "gc_implementation/g1/heapRegionSets.hpp"
 #include "gc_implementation/parNew/parGCAllocBuffer.hpp"
 #include "memory/barrierSet.hpp"
 #include "memory/memRegion.hpp"
@@ -40,6 +40,7 @@
 
 class HeapRegion;
 class HeapRegionSeq;
+class HRRSCleanupTask;
 class PermanentGenerationSpec;
 class GenerationSpec;
 class OopsInHeapRegionClosure;
@@ -66,8 +67,7 @@
 enum G1GCThreadGroups {
   G1CRGroup = 0,
   G1ZFGroup = 1,
-  G1CMGroup = 2,
-  G1CLGroup = 3
+  G1CMGroup = 2
 };
 
 enum GCAllocPurpose {
@@ -155,6 +155,7 @@
   friend class RefineCardTableEntryClosure;
   friend class G1PrepareCompactClosure;
   friend class RegionSorter;
+  friend class RegionResetter;
   friend class CountRCClosure;
   friend class EvacPopObjClosure;
   friend class G1ParCleanupCTTask;
@@ -178,17 +179,20 @@
   // The maximum part of _g1_storage that has ever been committed.
   MemRegion _g1_max_committed;
 
-  // The number of regions that are completely free.
-  size_t _free_regions;
+  // The master free list. It will satisfy all new region allocations.
+  MasterFreeRegionList      _free_list;
+
+  // The secondary free list which contains regions that have been
+  // freed up during the cleanup process. This will be appended to the
+  // master free list when appropriate.
+  SecondaryFreeRegionList   _secondary_free_list;
+
+  // It keeps track of the humongous regions.
+  MasterHumongousRegionSet  _humongous_set;
 
   // The number of regions we could create by expansion.
   size_t _expansion_regions;
 
-  // Return the number of free regions in the heap (by direct counting.)
-  size_t count_free_regions();
-  // Return the number of free regions on the free and unclean lists.
-  size_t count_free_regions_list();
-
   // The block offset table for the G1 heap.
   G1BlockOffsetSharedArray* _bot_shared;
 
@@ -196,9 +200,6 @@
   // lists, before and after full GC.
   void tear_down_region_lists();
   void rebuild_region_lists();
-  // This sets all non-empty regions to need zero-fill (which they will if
-  // they are empty after full collection.)
-  void set_used_regions_to_need_zero_fill();
 
   // The sequence of all heap regions in the heap.
   HeapRegionSeq* _hrs;
@@ -231,7 +232,7 @@
   // Determines PLAB size for a particular allocation purpose.
   static size_t desired_plab_sz(GCAllocPurpose purpose);
 
-  // When called by par thread, require par_alloc_during_gc_lock() to be held.
+  // When called by par thread, requires the FreeList_lock to be held.
   void push_gc_alloc_region(HeapRegion* hr);
 
   // This should only be called single-threaded.  Undeclares all GC alloc
@@ -294,10 +295,11 @@
   // line number, file, etc.
 
 #define heap_locking_asserts_err_msg(__extra_message)                         \
-  err_msg("%s : Heap_lock %slocked, %sat a safepoint",                        \
+  err_msg("%s : Heap_lock locked: %s, at safepoint: %s, is VM thread: %s",    \
           (__extra_message),                                                  \
-          (!Heap_lock->owned_by_self()) ? "NOT " : "",                        \
-          (!SafepointSynchronize::is_at_safepoint()) ? "NOT " : "")
+          BOOL_TO_STR(Heap_lock->owned_by_self()),                            \
+          BOOL_TO_STR(SafepointSynchronize::is_at_safepoint()),               \
+          BOOL_TO_STR(Thread::current()->is_VM_thread()))
 
 #define assert_heap_locked()                                                  \
   do {                                                                        \
@@ -305,10 +307,11 @@
            heap_locking_asserts_err_msg("should be holding the Heap_lock"));  \
   } while (0)
 
-#define assert_heap_locked_or_at_safepoint()                                  \
+#define assert_heap_locked_or_at_safepoint(__should_be_vm_thread)             \
   do {                                                                        \
     assert(Heap_lock->owned_by_self() ||                                      \
-                                     SafepointSynchronize::is_at_safepoint(), \
+           (SafepointSynchronize::is_at_safepoint() &&                        \
+             ((__should_be_vm_thread) == Thread::current()->is_VM_thread())), \
            heap_locking_asserts_err_msg("should be holding the Heap_lock or " \
                                         "should be at a safepoint"));         \
   } while (0)
@@ -335,9 +338,10 @@
                                    "should not be at a safepoint"));          \
   } while (0)
 
-#define assert_at_safepoint()                                                 \
+#define assert_at_safepoint(__should_be_vm_thread)                            \
   do {                                                                        \
-    assert(SafepointSynchronize::is_at_safepoint(),                           \
+    assert(SafepointSynchronize::is_at_safepoint() &&                         \
+              ((__should_be_vm_thread) == Thread::current()->is_VM_thread()), \
            heap_locking_asserts_err_msg("should be at a safepoint"));         \
   } while (0)
 
@@ -362,31 +366,41 @@
   // The current policy object for the collector.
   G1CollectorPolicy* _g1_policy;
 
-  // Parallel allocation lock to protect the current allocation region.
-  Mutex  _par_alloc_during_gc_lock;
-  Mutex* par_alloc_during_gc_lock() { return &_par_alloc_during_gc_lock; }
+  // This is the second level of trying to allocate a new region. If
+  // new_region_work didn't find a region in the free_list, this call
+  // will check whether there's anything available in the
+  // secondary_free_list and/or wait for more regions to appear in that
+  // list, if _free_regions_coming is set.
+  HeapRegion* new_region_try_secondary_free_list(size_t word_size);
 
-  // If possible/desirable, allocate a new HeapRegion for normal object
-  // allocation sufficient for an allocation of the given "word_size".
-  // If "do_expand" is true, will attempt to expand the heap if necessary
-  // to to satisfy the request.  If "zero_filled" is true, requires a
-  // zero-filled region.
-  // (Returning NULL will trigger a GC.)
-  virtual HeapRegion* newAllocRegion_work(size_t word_size,
-                                          bool do_expand,
-                                          bool zero_filled);
+  // It will try to allocate a single non-humongous HeapRegion
+  // sufficient for an allocation of the given word_size.  If
+  // do_expand is true, it will attempt to expand the heap if
+  // necessary to satisfy the allocation request. Note that word_size
+  // is only used to make sure that we expand sufficiently but, given
+  // that the allocation request is assumed not to be humongous,
+  // having word_size is not strictly necessary (expanding by a single
+  // region will always be sufficient). But let's keep that parameter
+  // in case we need it in the future.
+  HeapRegion* new_region_work(size_t word_size, bool do_expand);
 
-  virtual HeapRegion* newAllocRegion(size_t word_size,
-                                     bool zero_filled = true) {
-    return newAllocRegion_work(word_size, false, zero_filled);
+  // It will try to allocate a new region to be used for allocation by
+  // mutator threads. It will not try to expand the heap if not region
+  // is available.
+  HeapRegion* new_alloc_region(size_t word_size) {
+    return new_region_work(word_size, false /* do_expand */);
   }
-  virtual HeapRegion* newAllocRegionWithExpansion(int purpose,
-                                                  size_t word_size,
-                                                  bool zero_filled = true);
+
+  // It will try to allocate a new region to be used for allocation by
+  // a GC thread. It will try to expand the heap if no region is
+  // available.
+  HeapRegion* new_gc_alloc_region(int purpose, size_t word_size);
+
+  int humongous_obj_allocate_find_first(size_t num_regions, size_t word_size);
 
   // Attempt to allocate an object of the given (very large) "word_size".
   // Returns "NULL" on failure.
-  virtual HeapWord* humongous_obj_allocate(size_t word_size);
+  HeapWord* humongous_obj_allocate(size_t word_size);
 
   // The following two methods, allocate_new_tlab() and
   // mem_allocate(), are the two main entry points from the runtime
@@ -430,7 +444,8 @@
                                  bool*  gc_overhead_limit_was_exceeded);
 
   // The following methods, allocate_from_cur_allocation_region(),
-  // attempt_allocation(), replace_cur_alloc_region_and_allocate(),
+  // attempt_allocation(), attempt_allocation_locked(),
+  // replace_cur_alloc_region_and_allocate(),
   // attempt_allocation_slow(), and attempt_allocation_humongous()
   // have very awkward pre- and post-conditions with respect to
   // locking:
@@ -481,20 +496,30 @@
   // successfully manage to allocate it, or NULL.
 
   // It tries to satisfy an allocation request out of the current
-  // allocating region, which is passed as a parameter. It assumes
-  // that the caller has checked that the current allocating region is
-  // not NULL. Given that the caller has to check the current
-  // allocating region for at least NULL, it might as well pass it as
-  // the first parameter so that the method doesn't have to read it
-  // from the _cur_alloc_region field again.
+  // alloc region, which is passed as a parameter. It assumes that the
+  // caller has checked that the current alloc region is not NULL.
+  // Given that the caller has to check the current alloc region for
+  // at least NULL, it might as well pass it as the first parameter so
+  // that the method doesn't have to read it from the
+  // _cur_alloc_region field again. It is called from both
+  // attempt_allocation() and attempt_allocation_locked() and the
+  // with_heap_lock parameter indicates whether the caller was holding
+  // the heap lock when it called it or not.
   inline HeapWord* allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
-                                                  size_t word_size);
+                                                  size_t word_size,
+                                                  bool with_heap_lock);
 
-  // It attempts to allocate out of the current alloc region. If that
-  // fails, it retires the current alloc region (if there is one),
-  // tries to get a new one and retries the allocation.
+  // First-level of allocation slow path: it attempts to allocate out
+  // of the current alloc region in a lock-free manner using a CAS. If
+  // that fails it takes the Heap_lock and calls
+  // attempt_allocation_locked() for the second-level slow path.
   inline HeapWord* attempt_allocation(size_t word_size);
 
+  // Second-level of allocation slow path: while holding the Heap_lock
+  // it tries to allocate out of the current alloc region and, if that
+  // fails, tries to allocate out of a new current alloc region.
+  inline HeapWord* attempt_allocation_locked(size_t word_size);
+
   // It assumes that the current alloc region has been retired and
   // tries to allocate a new one. If it's successful, it performs the
   // allocation out of the new current alloc region and updates
@@ -506,11 +531,11 @@
                                                   bool do_dirtying,
                                                   bool can_expand);
 
-  // The slow path when we are unable to allocate a new current alloc
-  // region to satisfy an allocation request (i.e., when
-  // attempt_allocation() fails). It will try to do an evacuation
-  // pause, which might stall due to the GC locker, and retry the
-  // allocation attempt when appropriate.
+  // Third-level of allocation slow path: when we are unable to
+  // allocate a new current alloc region to satisfy an allocation
+  // request (i.e., when attempt_allocation_locked() fails). It will
+  // try to do an evacuation pause, which might stall due to the GC
+  // locker, and retry the allocation attempt when appropriate.
   HeapWord* attempt_allocation_slow(size_t word_size);
 
   // The method that tries to satisfy a humongous allocation
@@ -749,20 +774,29 @@
   // Invoke "save_marks" on all heap regions.
   void save_marks();
 
-  // Free a heap region.
-  void free_region(HeapRegion* hr);
-  // A component of "free_region", exposed for 'batching'.
-  // All the params after "hr" are out params: the used bytes of the freed
-  // region(s), the number of H regions cleared, the number of regions
-  // freed, and pointers to the head and tail of a list of freed contig
-  // regions, linked throught the "next_on_unclean_list" field.
-  void free_region_work(HeapRegion* hr,
-                        size_t& pre_used,
-                        size_t& cleared_h,
-                        size_t& freed_regions,
-                        UncleanRegionList* list,
-                        bool par = false);
+  // It frees a non-humongous region by initializing its contents and
+  // adding it to the free list that's passed as a parameter (this is
+  // usually a local list which will be appended to the master free
+  // list later). The used bytes of freed regions are accumulated in
+  // pre_used. If par is true, the region's RSet will not be freed
+  // up. The assumption is that this will be done later.
+  void free_region(HeapRegion* hr,
+                   size_t* pre_used,
+                   FreeRegionList* free_list,
+                   bool par);
 
+  // It frees a humongous region by collapsing it into individual
+  // regions and calling free_region() for each of them. The freed
+  // regions will be added to the free list that's passed as a parameter
+  // (this is usually a local list which will be appended to the
+  // master free list later). The used bytes of freed regions are
+  // accumulated in pre_used. If par is true, the region's RSet will
+  // not be freed up. The assumption is that this will be done later.
+  void free_humongous_region(HeapRegion* hr,
+                             size_t* pre_used,
+                             FreeRegionList* free_list,
+                             HumongousRegionSet* humongous_proxy_set,
+                             bool par);
 
   // The concurrent marker (and the thread it runs in.)
   ConcurrentMark* _cm;
@@ -772,9 +806,6 @@
   // The concurrent refiner.
   ConcurrentG1Refine* _cg1r;
 
-  // The concurrent zero-fill thread.
-  ConcurrentZFThread* _czft;
-
   // The parallel task queues
   RefToScanQueueSet *_task_queues;
 
@@ -826,7 +857,6 @@
   void finalize_for_evac_failure();
 
   // An attempt to evacuate "obj" has failed; take necessary steps.
-  void handle_evacuation_failure(oop obj);
   oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj);
   void handle_evacuation_failure_common(oop obj, markOop m);
 
@@ -867,9 +897,7 @@
 
   SubTasksDone* _process_strong_tasks;
 
-  // List of regions which require zero filling.
-  UncleanRegionList _unclean_region_list;
-  bool _unclean_regions_coming;
+  volatile bool _free_regions_coming;
 
 public:
 
@@ -992,71 +1020,64 @@
   size_t max_regions();
 
   // The number of regions that are completely free.
-  size_t free_regions();
+  size_t free_regions() {
+    return _free_list.length();
+  }
 
   // The number of regions that are not completely free.
   size_t used_regions() { return n_regions() - free_regions(); }
 
-  // True iff the ZF thread should run.
-  bool should_zf();
-
   // The number of regions available for "regular" expansion.
   size_t expansion_regions() { return _expansion_regions; }
 
-#ifndef PRODUCT
-  bool regions_accounted_for();
-  bool print_region_accounting_info();
-  void print_region_counts();
-#endif
-
-  HeapRegion* alloc_region_from_unclean_list(bool zero_filled);
-  HeapRegion* alloc_region_from_unclean_list_locked(bool zero_filled);
-
-  void put_region_on_unclean_list(HeapRegion* r);
-  void put_region_on_unclean_list_locked(HeapRegion* r);
+  // verify_region_sets() performs verification over the region
+  // lists. It will be compiled in the product code to be used when
+  // necessary (i.e., during heap verification).
+  void verify_region_sets();
 
-  void prepend_region_list_on_unclean_list(UncleanRegionList* list);
-  void prepend_region_list_on_unclean_list_locked(UncleanRegionList* list);
+  // verify_region_sets_optional() is planted in the code for
+  // list verification in non-product builds (and it can be enabled in
+  // product builds by definning HEAP_REGION_SET_FORCE_VERIFY to be 1).
+#if HEAP_REGION_SET_FORCE_VERIFY
+  void verify_region_sets_optional() {
+    verify_region_sets();
+  }
+#else // HEAP_REGION_SET_FORCE_VERIFY
+  void verify_region_sets_optional() { }
+#endif // HEAP_REGION_SET_FORCE_VERIFY
 
-  void set_unclean_regions_coming(bool b);
-  void set_unclean_regions_coming_locked(bool b);
-  // Wait for cleanup to be complete.
-  void wait_for_cleanup_complete();
-  // Like above, but assumes that the calling thread owns the Heap_lock.
-  void wait_for_cleanup_complete_locked();
-
-  // Return the head of the unclean list.
-  HeapRegion* peek_unclean_region_list_locked();
-  // Remove and return the head of the unclean list.
-  HeapRegion* pop_unclean_region_list_locked();
+#ifdef ASSERT
+  bool is_on_free_list(HeapRegion* hr) {
+    return hr->containing_set() == &_free_list;
+  }
 
-  // List of regions which are zero filled and ready for allocation.
-  HeapRegion* _free_region_list;
-  // Number of elements on the free list.
-  size_t _free_region_list_size;
+  bool is_on_humongous_set(HeapRegion* hr) {
+    return hr->containing_set() == &_humongous_set;
+}
+#endif // ASSERT
 
-  // If the head of the unclean list is ZeroFilled, move it to the free
-  // list.
-  bool move_cleaned_region_to_free_list_locked();
-  bool move_cleaned_region_to_free_list();
+  // Wrapper for the region list operations that can be called from
+  // methods outside this class.
 
-  void put_free_region_on_list_locked(HeapRegion* r);
-  void put_free_region_on_list(HeapRegion* r);
+  void secondary_free_list_add_as_tail(FreeRegionList* list) {
+    _secondary_free_list.add_as_tail(list);
+  }
 
-  // Remove and return the head element of the free list.
-  HeapRegion* pop_free_region_list_locked();
+  void append_secondary_free_list() {
+    _free_list.add_as_tail(&_secondary_free_list);
+  }
 
-  // If "zero_filled" is true, we first try the free list, then we try the
-  // unclean list, zero-filling the result.  If "zero_filled" is false, we
-  // first try the unclean list, then the zero-filled list.
-  HeapRegion* alloc_free_region_from_lists(bool zero_filled);
+  void append_secondary_free_list_if_not_empty() {
+    if (!_secondary_free_list.is_empty()) {
+      MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+      append_secondary_free_list();
+    }
+  }
 
-  // Verify the integrity of the region lists.
-  void remove_allocated_regions_from_lists();
-  bool verify_region_lists();
-  bool verify_region_lists_locked();
-  size_t unclean_region_list_length();
-  size_t free_region_list_length();
+  void set_free_regions_coming();
+  void reset_free_regions_coming();
+  bool free_regions_coming() { return _free_regions_coming; }
+  void wait_while_free_regions_coming();
 
   // Perform a collection of the heap; intended for use in implementing
   // "System.gc".  This probably implies as full a collection as the
@@ -1075,23 +1096,25 @@
   // True iff a evacuation has failed in the most-recent collection.
   bool evacuation_failed() { return _evacuation_failed; }
 
-  // Free a region if it is totally full of garbage.  Returns the number of
-  // bytes freed (0 ==> didn't free it).
-  size_t free_region_if_totally_empty(HeapRegion *hr);
-  void free_region_if_totally_empty_work(HeapRegion *hr,
-                                         size_t& pre_used,
-                                         size_t& cleared_h_regions,
-                                         size_t& freed_regions,
-                                         UncleanRegionList* list,
-                                         bool par = false);
+  // It will free a region if it has allocated objects in it that are
+  // all dead. It calls either free_region() or
+  // free_humongous_region() depending on the type of the region that
+  // is passed to it.
+  void free_region_if_empty(HeapRegion* hr,
+                            size_t* pre_used,
+                            FreeRegionList* free_list,
+                            HumongousRegionSet* humongous_proxy_set,
+                            HRRSCleanupTask* hrrs_cleanup_task,
+                            bool par);
 
-  // If we've done free region work that yields the given changes, update
-  // the relevant global variables.
-  void finish_free_region_work(size_t pre_used,
-                               size_t cleared_h_regions,
-                               size_t freed_regions,
-                               UncleanRegionList* list);
-
+  // It appends the free list to the master free list and updates the
+  // master humongous list according to the contents of the proxy
+  // list. It also adjusts the total used bytes according to pre_used
+  // (if par is true, it will do so by taking the ParGCRareEvent_lock).
+  void update_sets_after_freeing_regions(size_t pre_used,
+                                       FreeRegionList* free_list,
+                                       HumongousRegionSet* humongous_proxy_set,
+                                       bool par);
 
   // Returns "TRUE" iff "p" points into the allocated area of the heap.
   virtual bool is_in(const void* p) const;
@@ -1304,8 +1327,6 @@
     return true;
   }
 
-  virtual bool allocs_are_zero_filled();
-
   // The boundary between a "large" and "small" array of primitives, in
   // words.
   virtual size_t large_typearray_limit();
@@ -1536,13 +1557,6 @@
 
 protected:
   size_t _max_heap_capacity;
-
-public:
-  // Temporary: call to mark things unimplemented for the G1 heap (e.g.,
-  // MemoryService).  In productization, we can make this assert false
-  // to catch such places (as well as searching for calls to this...)
-  static void g1_unimplemented();
-
 };
 
 #define use_local_bitmaps         1
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
 #include "gc_implementation/g1/concurrentMark.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
-#include "gc_implementation/g1/heapRegionSeq.hpp"
+#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
 #include "utilities/taskqueue.hpp"
 
 // Inline functions for G1CollectedHeap
@@ -63,10 +63,12 @@
 // assumptions of this method (and other related ones).
 inline HeapWord*
 G1CollectedHeap::allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
-                                                size_t word_size) {
-  assert_heap_locked_and_not_at_safepoint();
+                                                size_t word_size,
+                                                bool with_heap_lock) {
+  assert_not_at_safepoint();
+  assert(with_heap_lock == Heap_lock->owned_by_self(),
+         "with_heap_lock and Heap_lock->owned_by_self() should be a tautology");
   assert(cur_alloc_region != NULL, "pre-condition of the method");
-  assert(cur_alloc_region == _cur_alloc_region, "pre-condition of the method");
   assert(cur_alloc_region->is_young(),
          "we only support young current alloc regions");
   assert(!isHumongous(word_size), "allocate_from_cur_alloc_region() "
@@ -76,20 +78,24 @@
   assert(!cur_alloc_region->is_empty(),
          err_msg("region ["PTR_FORMAT","PTR_FORMAT"] should not be empty",
                  cur_alloc_region->bottom(), cur_alloc_region->end()));
-  // This allocate method does BOT updates and we don't need them in
-  // the young generation. This will be fixed in the near future by
-  // CR 6994297.
-  HeapWord* result = cur_alloc_region->allocate(word_size);
+  HeapWord* result = cur_alloc_region->par_allocate_no_bot_updates(word_size);
   if (result != NULL) {
     assert(is_in(result), "result should be in the heap");
-    Heap_lock->unlock();
 
+    if (with_heap_lock) {
+      Heap_lock->unlock();
+    }
+    assert_heap_not_locked();
     // Do the dirtying after we release the Heap_lock.
     dirty_young_block(result, word_size);
     return result;
   }
 
-  assert_heap_locked();
+  if (with_heap_lock) {
+    assert_heap_locked();
+  } else {
+    assert_heap_not_locked();
+  }
   return NULL;
 }
 
@@ -97,26 +103,75 @@
 // assumptions of this method (and other related ones).
 inline HeapWord*
 G1CollectedHeap::attempt_allocation(size_t word_size) {
-  assert_heap_locked_and_not_at_safepoint();
+  assert_heap_not_locked_and_not_at_safepoint();
   assert(!isHumongous(word_size), "attempt_allocation() should not be called "
          "for humongous allocation requests");
 
   HeapRegion* cur_alloc_region = _cur_alloc_region;
   if (cur_alloc_region != NULL) {
     HeapWord* result = allocate_from_cur_alloc_region(cur_alloc_region,
-                                                      word_size);
+                                                   word_size,
+                                                   false /* with_heap_lock */);
+    assert_heap_not_locked();
+    if (result != NULL) {
+      return result;
+    }
+  }
+
+  // Our attempt to allocate lock-free failed as the current
+  // allocation region is either NULL or full. So, we'll now take the
+  // Heap_lock and retry.
+  Heap_lock->lock();
+
+  HeapWord* result = attempt_allocation_locked(word_size);
+  if (result != NULL) {
+    assert_heap_not_locked();
+    return result;
+  }
+
+  assert_heap_locked();
+  return NULL;
+}
+
+inline void
+G1CollectedHeap::retire_cur_alloc_region_common(HeapRegion* cur_alloc_region) {
+  assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
+  assert(cur_alloc_region != NULL && cur_alloc_region == _cur_alloc_region,
+         "pre-condition of the call");
+  assert(cur_alloc_region->is_young(),
+         "we only support young current alloc regions");
+
+  // The region is guaranteed to be young
+  g1_policy()->add_region_to_incremental_cset_lhs(cur_alloc_region);
+  _summary_bytes_used += cur_alloc_region->used();
+  _cur_alloc_region = NULL;
+}
+
+inline HeapWord*
+G1CollectedHeap::attempt_allocation_locked(size_t word_size) {
+  assert_heap_locked_and_not_at_safepoint();
+  assert(!isHumongous(word_size), "attempt_allocation_locked() "
+         "should not be called for humongous allocation requests");
+
+  // First, reread the current alloc region and retry the allocation
+  // in case somebody replaced it while we were waiting to get the
+  // Heap_lock.
+  HeapRegion* cur_alloc_region = _cur_alloc_region;
+  if (cur_alloc_region != NULL) {
+    HeapWord* result = allocate_from_cur_alloc_region(
+                                                  cur_alloc_region, word_size,
+                                                  true /* with_heap_lock */);
     if (result != NULL) {
       assert_heap_not_locked();
       return result;
     }
 
-    assert_heap_locked();
-
-    // Since we couldn't successfully allocate into it, retire the
-    // current alloc region.
+    // We failed to allocate out of the current alloc region, so let's
+    // retire it before getting a new one.
     retire_cur_alloc_region(cur_alloc_region);
   }
 
+  assert_heap_locked();
   // Try to get a new region and allocate out of it
   HeapWord* result = replace_cur_alloc_region_and_allocate(word_size,
                                                      false, /* at_safepoint */
@@ -131,20 +186,6 @@
   return NULL;
 }
 
-inline void
-G1CollectedHeap::retire_cur_alloc_region_common(HeapRegion* cur_alloc_region) {
-  assert_heap_locked_or_at_safepoint();
-  assert(cur_alloc_region != NULL && cur_alloc_region == _cur_alloc_region,
-         "pre-condition of the call");
-  assert(cur_alloc_region->is_young(),
-         "we only support young current alloc regions");
-
-  // The region is guaranteed to be young
-  g1_policy()->add_region_to_incremental_cset_lhs(cur_alloc_region);
-  _summary_bytes_used += cur_alloc_region->used();
-  _cur_alloc_region = NULL;
-}
-
 // It dirties the cards that cover the block so that so that the post
 // write barrier never queues anything when updating objects on this
 // block. It is assumed (and in fact we assert) that the block
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2875,8 +2875,6 @@
   // Adjust for expansion and slop.
   max_live_bytes = max_live_bytes + expansion_bytes;
 
-  assert(_g1->regions_accounted_for(), "Region leakage!");
-
   HeapRegion* hr;
   if (in_young_gc_mode()) {
     double young_start_time_sec = os::elapsedTime();
--- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -113,6 +113,7 @@
 
   Threads::gc_epilogue();
   CodeCache::gc_epilogue();
+  JvmtiExport::gc_epilogue();
 
   // refs processing: clean slate
   GenMarkSweep::_ref_processor = NULL;
@@ -171,35 +172,56 @@
   assert(GenMarkSweep::_marking_stack.is_empty(), "just drained");
 
 
-  // Visit symbol and interned string tables and delete unmarked oops
-  SymbolTable::unlink(&GenMarkSweep::is_alive);
+  // Visit interned string tables and delete unmarked oops
   StringTable::unlink(&GenMarkSweep::is_alive);
+  // Clean up unreferenced symbols in symbol table.
+  SymbolTable::unlink();
 
   assert(GenMarkSweep::_marking_stack.is_empty(),
          "stack should be empty by now");
 }
 
 class G1PrepareCompactClosure: public HeapRegionClosure {
+  G1CollectedHeap* _g1h;
   ModRefBarrierSet* _mrbs;
   CompactPoint _cp;
+  size_t _pre_used;
+  FreeRegionList _free_list;
+  HumongousRegionSet _humongous_proxy_set;
 
   void free_humongous_region(HeapRegion* hr) {
-    HeapWord* bot = hr->bottom();
     HeapWord* end = hr->end();
     assert(hr->startsHumongous(),
            "Only the start of a humongous region should be freed.");
-    G1CollectedHeap::heap()->free_region(hr);
+    _g1h->free_humongous_region(hr, &_pre_used, &_free_list,
+                                &_humongous_proxy_set, false /* par */);
+    // Do we also need to do this for the continues humongous regions
+    // we just collapsed?
     hr->prepare_for_compaction(&_cp);
     // Also clear the part of the card table that will be unused after
     // compaction.
-    _mrbs->clear(MemRegion(hr->compaction_top(), hr->end()));
+    _mrbs->clear(MemRegion(hr->compaction_top(), end));
   }
 
 public:
-  G1PrepareCompactClosure(CompactibleSpace* cs) :
+  G1PrepareCompactClosure(CompactibleSpace* cs)
+  : _g1h(G1CollectedHeap::heap()),
+    _mrbs(G1CollectedHeap::heap()->mr_bs()),
     _cp(NULL, cs, cs->initialize_threshold()),
-    _mrbs(G1CollectedHeap::heap()->mr_bs())
-  {}
+    _pre_used(0),
+    _free_list("Local Free List for G1MarkSweep"),
+    _humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { }
+
+  void update_sets() {
+    // We'll recalculate total used bytes and recreate the free list
+    // at the end of the GC, so no point in updating those values here.
+    _g1h->update_sets_after_freeing_regions(0, /* pre_used */
+                                            NULL, /* free_list */
+                                            &_humongous_proxy_set,
+                                            false /* par */);
+    _free_list.remove_all();
+  }
+
   bool doHeapRegion(HeapRegion* hr) {
     if (hr->isHumongous()) {
       if (hr->startsHumongous()) {
@@ -265,6 +287,7 @@
 
   G1PrepareCompactClosure blk(sp);
   g1h->heap_region_iterate(&blk);
+  blk.update_sets();
 
   CompactPoint perm_cp(pg, NULL, NULL);
   pg->prepare_for_compaction(&perm_cp);
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,20 +75,19 @@
           "(0 means do not periodically generate this info); "              \
           "it also requires -XX:+G1SummarizeRSetStats")                     \
                                                                             \
-  diagnostic(bool, G1SummarizeZFStats, false,                               \
-          "Summarize zero-filling info")                                    \
-                                                                            \
   diagnostic(bool, G1TraceConcRefinement, false,                            \
           "Trace G1 concurrent refinement")                                 \
                                                                             \
   product(intx, G1MarkRegionStackSize, 1024 * 1024,                         \
           "Size of the region stack for concurrent marking.")               \
                                                                             \
-  develop(bool, G1ConcZeroFill, true,                                       \
-          "If true, run concurrent zero-filling thread")                    \
+  product(double, G1ConcMarkStepDurationMillis, 10.0,                       \
+          "Target duration of individual concurrent marking steps "         \
+          "in milliseconds.")                                               \
                                                                             \
-  develop(intx, G1ConcZFMaxRegions, 1,                                      \
-          "Stop zero-filling when # of zf'd regions reaches")               \
+  product(intx, G1RefProcDrainInterval, 10,                                 \
+          "The number of discovered reference objects to process before "   \
+          "draining concurrent marking work queues.")                       \
                                                                             \
   develop(bool, G1SATBBarrierPrintNullPreVals, false,                       \
           "If true, count frac of ptr writes with null pre-vals.")          \
@@ -99,6 +98,13 @@
   develop(intx, G1SATBProcessCompletedThreshold, 20,                        \
           "Number of completed buffers that triggers log processing.")      \
                                                                             \
+  product(uintx, G1SATBBufferEnqueueingThresholdPercent, 60,                \
+          "Before enqueueing them, each mutator thread tries to do some "   \
+          "filtering on the SATB buffers it generates. If post-filtering "  \
+          "the percentage of retained entries is over this threshold "      \
+          "the buffer will be enqueued for processing. A value of 0 "       \
+          "specifies that mutator threads should not do such filtering.")   \
+                                                                            \
   develop(intx, G1ExtraRegionSurvRate, 33,                                  \
           "If the young survival rate is S, and there's room left in "      \
           "to-space, we will allow regions whose survival rate is up to "   \
@@ -282,7 +288,20 @@
           "Size of a work unit of cards claimed by a worker thread"         \
           "during RSet scanning.")                                          \
                                                                             \
-  develop(bool, ReduceInitialCardMarksForG1, false,                         \
+  develop(uintx, G1SecondaryFreeListAppendLength, 5,                        \
+          "The number of regions we will add to the secondary free list "   \
+          "at every append operation")                                      \
+                                                                            \
+  develop(bool, G1ConcRegionFreeingVerbose, false,                          \
+          "Enables verboseness during concurrent region freeing")           \
+                                                                            \
+  develop(bool, G1StressConcRegionFreeing, false,                           \
+          "It stresses the concurrent region freeing operation")            \
+                                                                            \
+  develop(uintx, G1StressConcRegionFreeingDelayMillis, 0,                   \
+          "Artificial delay during concurrent region freeing")              \
+                                                                            \
+   develop(bool, ReduceInitialCardMarksForG1, false,                        \
           "When ReduceInitialCardMarks is true, this flag setting "         \
           " controls whether G1 allows the RICM optimization")
 
--- a/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@
  */
 
 #include "precompiled.hpp"
-#include "gc_implementation/g1/concurrentZFThread.hpp"
 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
@@ -348,22 +347,20 @@
 }
 
 void HeapRegion::hr_clear(bool par, bool clear_space) {
-  _humongous_type = NotHumongous;
-  _humongous_start_region = NULL;
+  assert(_humongous_type == NotHumongous,
+         "we should have already filtered out humongous regions");
+  assert(_humongous_start_region == NULL,
+         "we should have already filtered out humongous regions");
+  assert(_end == _orig_end,
+         "we should have already filtered out humongous regions");
+
   _in_collection_set = false;
   _is_gc_alloc_region = false;
 
-  // Age stuff (if parallel, this will be done separately, since it needs
-  // to be sequential).
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
   set_young_index_in_cset(-1);
   uninstall_surv_rate_group();
   set_young_type(NotYoung);
 
-  // In case it had been the start of a humongous sequence, reset its end.
-  set_end(_orig_end);
-
   if (!par) {
     // If this is parallel, this will be done later.
     HeapRegionRemSet* hrrs = rem_set();
@@ -386,26 +383,49 @@
 }
 // </PREDICTION>
 
-void HeapRegion::set_startsHumongous(HeapWord* new_end) {
+void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) {
+  assert(!isHumongous(), "sanity / pre-condition");
   assert(end() == _orig_end,
          "Should be normal before the humongous object allocation");
   assert(top() == bottom(), "should be empty");
+  assert(bottom() <= new_top && new_top <= new_end, "pre-condition");
 
   _humongous_type = StartsHumongous;
   _humongous_start_region = this;
 
   set_end(new_end);
-  _offsets.set_for_starts_humongous(new_end);
+  _offsets.set_for_starts_humongous(new_top);
 }
 
-void HeapRegion::set_continuesHumongous(HeapRegion* start) {
+void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) {
+  assert(!isHumongous(), "sanity / pre-condition");
   assert(end() == _orig_end,
          "Should be normal before the humongous object allocation");
   assert(top() == bottom(), "should be empty");
-  assert(start->startsHumongous(), "pre-condition");
+  assert(first_hr->startsHumongous(), "pre-condition");
 
   _humongous_type = ContinuesHumongous;
-  _humongous_start_region = start;
+  _humongous_start_region = first_hr;
+}
+
+void HeapRegion::set_notHumongous() {
+  assert(isHumongous(), "pre-condition");
+
+  if (startsHumongous()) {
+    assert(top() <= end(), "pre-condition");
+    set_end(_orig_end);
+    if (top() > end()) {
+      // at least one "continues humongous" region after it
+      set_top(end());
+    }
+  } else {
+    // continues humongous
+    assert(end() == _orig_end, "sanity");
+  }
+
+  assert(capacity() == (size_t) HeapRegion::GrainBytes, "pre-condition");
+  _humongous_type = NotHumongous;
+  _humongous_start_region = NULL;
 }
 
 bool HeapRegion::claimHeapRegion(jint claimValue) {
@@ -442,15 +462,6 @@
   return low;
 }
 
-void HeapRegion::set_next_on_unclean_list(HeapRegion* r) {
-  assert(r == NULL || r->is_on_unclean_list(), "Malformed unclean list.");
-  _next_in_special_set = r;
-}
-
-void HeapRegion::set_on_unclean_list(bool b) {
-  _is_on_unclean_list = b;
-}
-
 void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) {
   G1OffsetTableContigSpace::initialize(mr, false, mangle_space);
   hr_clear(false/*par*/, clear_space);
@@ -468,15 +479,16 @@
     _hrs_index(-1),
     _humongous_type(NotHumongous), _humongous_start_region(NULL),
     _in_collection_set(false), _is_gc_alloc_region(false),
-    _is_on_free_list(false), _is_on_unclean_list(false),
     _next_in_special_set(NULL), _orig_end(NULL),
     _claimed(InitialClaimValue), _evacuation_failed(false),
     _prev_marked_bytes(0), _next_marked_bytes(0), _sort_index(-1),
     _young_type(NotYoung), _next_young_region(NULL),
-    _next_dirty_cards_region(NULL),
-    _young_index_in_cset(-1), _surv_rate_group(NULL), _age_index(-1),
-    _rem_set(NULL), _zfs(NotZeroFilled),
-    _recorded_rs_length(0), _predicted_elapsed_time_ms(0),
+    _next_dirty_cards_region(NULL), _next(NULL), _pending_removal(false),
+#ifdef ASSERT
+    _containing_set(NULL),
+#endif // ASSERT
+     _young_index_in_cset(-1), _surv_rate_group(NULL), _age_index(-1),
+    _rem_set(NULL), _recorded_rs_length(0), _predicted_elapsed_time_ms(0),
     _predicted_bytes_to_copy(0)
 {
   _orig_end = mr.end();
@@ -551,86 +563,6 @@
   oops_in_mr_iterate(MemRegion(bottom(), saved_mark_word()), cl);
 }
 
-#ifdef DEBUG
-HeapWord* HeapRegion::allocate(size_t size) {
-  jint state = zero_fill_state();
-  assert(!G1CollectedHeap::heap()->allocs_are_zero_filled() ||
-         zero_fill_is_allocated(),
-         "When ZF is on, only alloc in ZF'd regions");
-  return G1OffsetTableContigSpace::allocate(size);
-}
-#endif
-
-void HeapRegion::set_zero_fill_state_work(ZeroFillState zfs) {
-  assert(ZF_mon->owned_by_self() ||
-         Universe::heap()->is_gc_active(),
-         "Must hold the lock or be a full GC to modify.");
-#ifdef ASSERT
-  if (top() != bottom() && zfs != Allocated) {
-    ResourceMark rm;
-    stringStream region_str;
-    print_on(&region_str);
-    assert(top() == bottom() || zfs == Allocated,
-           err_msg("Region must be empty, or we must be setting it to allocated. "
-                   "_zfs=%d, zfs=%d, region: %s", _zfs, zfs, region_str.as_string()));
-  }
-#endif
-  _zfs = zfs;
-}
-
-void HeapRegion::set_zero_fill_complete() {
-  set_zero_fill_state_work(ZeroFilled);
-  if (ZF_mon->owned_by_self()) {
-    ZF_mon->notify_all();
-  }
-}
-
-
-void HeapRegion::ensure_zero_filled() {
-  MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-  ensure_zero_filled_locked();
-}
-
-void HeapRegion::ensure_zero_filled_locked() {
-  assert(ZF_mon->owned_by_self(), "Precondition");
-  bool should_ignore_zf = SafepointSynchronize::is_at_safepoint();
-  assert(should_ignore_zf || Heap_lock->is_locked(),
-         "Either we're in a GC or we're allocating a region.");
-  switch (zero_fill_state()) {
-  case HeapRegion::NotZeroFilled:
-    set_zero_fill_in_progress(Thread::current());
-    {
-      ZF_mon->unlock();
-      Copy::fill_to_words(bottom(), capacity()/HeapWordSize);
-      ZF_mon->lock_without_safepoint_check();
-    }
-    // A trap.
-    guarantee(zero_fill_state() == HeapRegion::ZeroFilling
-              && zero_filler() == Thread::current(),
-              "AHA!  Tell Dave D if you see this...");
-    set_zero_fill_complete();
-    // gclog_or_tty->print_cr("Did sync ZF.");
-    ConcurrentZFThread::note_sync_zfs();
-    break;
-  case HeapRegion::ZeroFilling:
-    if (should_ignore_zf) {
-      // We can "break" the lock and take over the work.
-      Copy::fill_to_words(bottom(), capacity()/HeapWordSize);
-      set_zero_fill_complete();
-      ConcurrentZFThread::note_sync_zfs();
-      break;
-    } else {
-      ConcurrentZFThread::wait_for_ZF_completed(this);
-    }
-  case HeapRegion::ZeroFilled:
-    // Nothing to do.
-    break;
-  case HeapRegion::Allocated:
-    guarantee(false, "Should not call on allocated regions.");
-  }
-  assert(zero_fill_state() == HeapRegion::ZeroFilled, "Post");
-}
-
 HeapWord*
 HeapRegion::object_iterate_mem_careful(MemRegion mr,
                                                  ObjectClosure* cl) {
@@ -782,9 +714,6 @@
   verify(allow_dirty, /* use_prev_marking */ true, /* failures */ &dummy);
 }
 
-#define OBJ_SAMPLE_INTERVAL 0
-#define BLOCK_SAMPLE_INTERVAL 100
-
 // This really ought to be commoned up into OffsetTableContigSpace somehow.
 // We would need a mechanism to make that code skip dead objects.
 
@@ -795,83 +724,125 @@
   *failures = false;
   HeapWord* p = bottom();
   HeapWord* prev_p = NULL;
-  int objs = 0;
-  int blocks = 0;
   VerifyLiveClosure vl_cl(g1, use_prev_marking);
   bool is_humongous = isHumongous();
+  bool do_bot_verify = !is_young();
   size_t object_num = 0;
   while (p < top()) {
-    size_t size = oop(p)->size();
-    if (is_humongous != g1->isHumongous(size)) {
+    oop obj = oop(p);
+    size_t obj_size = obj->size();
+    object_num += 1;
+
+    if (is_humongous != g1->isHumongous(obj_size)) {
       gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size ("
                              SIZE_FORMAT" words) in a %shumongous region",
-                             p, g1->isHumongous(size) ? "" : "non-",
-                             size, is_humongous ? "" : "non-");
+                             p, g1->isHumongous(obj_size) ? "" : "non-",
+                             obj_size, is_humongous ? "" : "non-");
        *failures = true;
+       return;
+    }
+
+    // If it returns false, verify_for_object() will output the
+    // appropriate messasge.
+    if (do_bot_verify && !_offsets.verify_for_object(p, obj_size)) {
+      *failures = true;
+      return;
     }
-    object_num += 1;
-    if (blocks == BLOCK_SAMPLE_INTERVAL) {
-      HeapWord* res = block_start_const(p + (size/2));
-      if (p != res) {
-        gclog_or_tty->print_cr("offset computation 1 for "PTR_FORMAT" and "
-                               SIZE_FORMAT" returned "PTR_FORMAT,
-                               p, size, res);
+
+    if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) {
+      if (obj->is_oop()) {
+        klassOop klass = obj->klass();
+        if (!klass->is_perm()) {
+          gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
+                                 "not in perm", klass, obj);
+          *failures = true;
+          return;
+        } else if (!klass->is_klass()) {
+          gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
+                                 "not a klass", klass, obj);
+          *failures = true;
+          return;
+        } else {
+          vl_cl.set_containing_obj(obj);
+          obj->oop_iterate(&vl_cl);
+          if (vl_cl.failures()) {
+            *failures = true;
+          }
+          if (G1MaxVerifyFailures >= 0 &&
+              vl_cl.n_failures() >= G1MaxVerifyFailures) {
+            return;
+          }
+        }
+      } else {
+        gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj);
         *failures = true;
         return;
       }
-      blocks = 0;
-    } else {
-      blocks++;
-    }
-    if (objs == OBJ_SAMPLE_INTERVAL) {
-      oop obj = oop(p);
-      if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) {
-        if (obj->is_oop()) {
-          klassOop klass = obj->klass();
-          if (!klass->is_perm()) {
-            gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
-                                   "not in perm", klass, obj);
-            *failures = true;
-            return;
-          } else if (!klass->is_klass()) {
-            gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
-                                   "not a klass", klass, obj);
-            *failures = true;
-            return;
-          } else {
-            vl_cl.set_containing_obj(obj);
-            obj->oop_iterate(&vl_cl);
-            if (vl_cl.failures()) {
-              *failures = true;
-            }
-            if (G1MaxVerifyFailures >= 0 &&
-                vl_cl.n_failures() >= G1MaxVerifyFailures) {
-              return;
-            }
-          }
-        } else {
-          gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj);
-          *failures = true;
-          return;
-        }
-      }
-      objs = 0;
-    } else {
-      objs++;
     }
     prev_p = p;
-    p += size;
+    p += obj_size;
+  }
+
+  if (p != top()) {
+    gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
+                           "does not match top "PTR_FORMAT, p, top());
+    *failures = true;
+    return;
   }
-  HeapWord* rend = end();
-  HeapWord* rtop = top();
-  if (rtop < rend) {
-    HeapWord* res = block_start_const(rtop + (rend - rtop) / 2);
-    if (res != rtop) {
-        gclog_or_tty->print_cr("offset computation 2 for "PTR_FORMAT" and "
-                               PTR_FORMAT" returned "PTR_FORMAT,
-                               rtop, rend, res);
+
+  HeapWord* the_end = end();
+  assert(p == top(), "it should still hold");
+  // Do some extra BOT consistency checking for addresses in the
+  // range [top, end). BOT look-ups in this range should yield
+  // top. No point in doing that if top == end (there's nothing there).
+  if (p < the_end) {
+    // Look up top
+    HeapWord* addr_1 = p;
+    HeapWord* b_start_1 = _offsets.block_start_const(addr_1);
+    if (b_start_1 != p) {
+      gclog_or_tty->print_cr("BOT look up for top: "PTR_FORMAT" "
+                             " yielded "PTR_FORMAT", expecting "PTR_FORMAT,
+                             addr_1, b_start_1, p);
+      *failures = true;
+      return;
+    }
+
+    // Look up top + 1
+    HeapWord* addr_2 = p + 1;
+    if (addr_2 < the_end) {
+      HeapWord* b_start_2 = _offsets.block_start_const(addr_2);
+      if (b_start_2 != p) {
+        gclog_or_tty->print_cr("BOT look up for top + 1: "PTR_FORMAT" "
+                               " yielded "PTR_FORMAT", expecting "PTR_FORMAT,
+                               addr_2, b_start_2, p);
         *failures = true;
         return;
+      }
+    }
+
+    // Look up an address between top and end
+    size_t diff = pointer_delta(the_end, p) / 2;
+    HeapWord* addr_3 = p + diff;
+    if (addr_3 < the_end) {
+      HeapWord* b_start_3 = _offsets.block_start_const(addr_3);
+      if (b_start_3 != p) {
+        gclog_or_tty->print_cr("BOT look up for top + diff: "PTR_FORMAT" "
+                               " yielded "PTR_FORMAT", expecting "PTR_FORMAT,
+                               addr_3, b_start_3, p);
+        *failures = true;
+        return;
+      }
+    }
+
+    // Loook up end - 1
+    HeapWord* addr_4 = the_end - 1;
+    HeapWord* b_start_4 = _offsets.block_start_const(addr_4);
+    if (b_start_4 != p) {
+      gclog_or_tty->print_cr("BOT look up for end - 1: "PTR_FORMAT" "
+                             " yielded "PTR_FORMAT", expecting "PTR_FORMAT,
+                             addr_4, b_start_4, p);
+      *failures = true;
+      return;
     }
   }
 
@@ -880,12 +851,6 @@
                            "but has "SIZE_FORMAT", objects",
                            bottom(), end(), object_num);
     *failures = true;
-  }
-
-  if (p != top()) {
-    gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
-                           "does not match top "PTR_FORMAT, p, top());
-    *failures = true;
     return;
   }
 }
@@ -976,67 +941,3 @@
   _offsets.set_space(this);
   initialize(mr, !is_zeroed, SpaceDecorator::Mangle);
 }
-
-size_t RegionList::length() {
-  size_t len = 0;
-  HeapRegion* cur = hd();
-  DEBUG_ONLY(HeapRegion* last = NULL);
-  while (cur != NULL) {
-    len++;
-    DEBUG_ONLY(last = cur);
-    cur = get_next(cur);
-  }
-  assert(last == tl(), "Invariant");
-  return len;
-}
-
-void RegionList::insert_before_head(HeapRegion* r) {
-  assert(well_formed(), "Inv");
-  set_next(r, hd());
-  _hd = r;
-  _sz++;
-  if (tl() == NULL) _tl = r;
-  assert(well_formed(), "Inv");
-}
-
-void RegionList::prepend_list(RegionList* new_list) {
-  assert(well_formed(), "Precondition");
-  assert(new_list->well_formed(), "Precondition");
-  HeapRegion* new_tl = new_list->tl();
-  if (new_tl != NULL) {
-    set_next(new_tl, hd());
-    _hd = new_list->hd();
-    _sz += new_list->sz();
-    if (tl() == NULL) _tl = new_list->tl();
-  } else {
-    assert(new_list->hd() == NULL && new_list->sz() == 0, "Inv");
-  }
-  assert(well_formed(), "Inv");
-}
-
-void RegionList::delete_after(HeapRegion* r) {
-  assert(well_formed(), "Precondition");
-  HeapRegion* next = get_next(r);
-  assert(r != NULL, "Precondition");
-  HeapRegion* next_tl = get_next(next);
-  set_next(r, next_tl);
-  dec_sz();
-  if (next == tl()) {
-    assert(next_tl == NULL, "Inv");
-    _tl = r;
-  }
-  assert(well_formed(), "Inv");
-}
-
-HeapRegion* RegionList::pop() {
-  assert(well_formed(), "Inv");
-  HeapRegion* res = hd();
-  if (res != NULL) {
-    _hd = get_next(res);
-    _sz--;
-    set_next(res, NULL);
-    if (sz() == 0) _tl = NULL;
-  }
-  assert(well_formed(), "Inv");
-  return res;
-}
--- a/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,11 @@
 class HeapRegionRemSet;
 class HeapRegionRemSetIterator;
 class HeapRegion;
+class HeapRegionSetBase;
+
+#define HR_FORMAT "%d:["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]"
+#define HR_FORMAT_PARAMS(__hr) (__hr)->hrs_index(), (__hr)->bottom(), \
+                               (__hr)->top(), (__hr)->end()
 
 // A dirty card to oop closure for heap regions. It
 // knows how to get the G1 heap and how to use the bitmap
@@ -173,6 +178,19 @@
   virtual HeapWord* cross_threshold(HeapWord* start, HeapWord* end);
 
   virtual void print() const;
+
+  void reset_bot() {
+    _offsets.zero_bottom_entry();
+    _offsets.initialize_threshold();
+  }
+
+  void update_bot_for_object(HeapWord* start, size_t word_size) {
+    _offsets.alloc_block(start, word_size);
+  }
+
+  void print_bot_on(outputStream* out) {
+    _offsets.print_on(out);
+  }
 };
 
 class HeapRegion: public G1OffsetTableContigSpace {
@@ -214,12 +232,6 @@
   // True iff the region is in current collection_set.
   bool _in_collection_set;
 
-    // True iff the region is on the unclean list, waiting to be zero filled.
-  bool _is_on_unclean_list;
-
-  // True iff the region is on the free list, ready for allocation.
-  bool _is_on_free_list;
-
   // Is this or has it been an allocation region in the current collection
   // pause.
   bool _is_gc_alloc_region;
@@ -241,6 +253,13 @@
   // Next region whose cards need cleaning
   HeapRegion* _next_dirty_cards_region;
 
+  // Fields used by the HeapRegionSetBase class and subclasses.
+  HeapRegion* _next;
+#ifdef ASSERT
+  HeapRegionSetBase* _containing_set;
+#endif // ASSERT
+  bool _pending_removal;
+
   // For parallel heapRegion traversal.
   jint _claimed;
 
@@ -292,10 +311,6 @@
     _top_at_conc_mark_count = bot;
   }
 
-  jint _zfs;  // A member of ZeroFillState.  Protected by ZF_lock.
-  Thread* _zero_filler; // If _zfs is ZeroFilling, the thread that (last)
-                        // made it so.
-
   void set_young_type(YoungType new_type) {
     //assert(_young_type != new_type, "setting the same type" );
     // TODO: add more assertions here
@@ -349,15 +364,14 @@
     RebuildRSClaimValue   = 5
   };
 
-  // Concurrent refinement requires contiguous heap regions (in which TLABs
-  // might be allocated) to be zero-filled.  Each region therefore has a
-  // zero-fill-state.
-  enum ZeroFillState {
-    NotZeroFilled,
-    ZeroFilling,
-    ZeroFilled,
-    Allocated
-  };
+  inline HeapWord* par_allocate_no_bot_updates(size_t word_size) {
+    assert(is_young(), "we can only skip BOT updates on young regions");
+    return ContiguousSpace::par_allocate(word_size);
+  }
+  inline HeapWord* allocate_no_bot_updates(size_t word_size) {
+    assert(is_young(), "we can only skip BOT updates on young regions");
+    return ContiguousSpace::allocate(word_size);
+  }
 
   // If this region is a member of a HeapRegionSeq, the index in that
   // sequence, otherwise -1.
@@ -404,13 +418,38 @@
     return _humongous_start_region;
   }
 
-  // Causes the current region to represent a humongous object spanning "n"
-  // regions.
-  void set_startsHumongous(HeapWord* new_end);
+  // Makes the current region be a "starts humongous" region, i.e.,
+  // the first region in a series of one or more contiguous regions
+  // that will contain a single "humongous" object. The two parameters
+  // are as follows:
+  //
+  // new_top : The new value of the top field of this region which
+  // points to the end of the humongous object that's being
+  // allocated. If there is more than one region in the series, top
+  // will lie beyond this region's original end field and on the last
+  // region in the series.
+  //
+  // new_end : The new value of the end field of this region which
+  // points to the end of the last region in the series. If there is
+  // one region in the series (namely: this one) end will be the same
+  // as the original end of this region.
+  //
+  // Updating top and end as described above makes this region look as
+  // if it spans the entire space taken up by all the regions in the
+  // series and an single allocation moved its top to new_top. This
+  // ensures that the space (capacity / allocated) taken up by all
+  // humongous regions can be calculated by just looking at the
+  // "starts humongous" regions and by ignoring the "continues
+  // humongous" regions.
+  void set_startsHumongous(HeapWord* new_top, HeapWord* new_end);
 
-  // The regions that continue a humongous sequence should be added using
-  // this method, in increasing address order.
-  void set_continuesHumongous(HeapRegion* start);
+  // Makes the current region be a "continues humongous'
+  // region. first_hr is the "start humongous" region of the series
+  // which this region will be part of.
+  void set_continuesHumongous(HeapRegion* first_hr);
+
+  // Unsets the humongous-related fields on the region.
+  void set_notHumongous();
 
   // If the region has a remembered set, return a pointer to it.
   HeapRegionRemSet* rem_set() const {
@@ -458,45 +497,56 @@
     _next_in_special_set = r;
   }
 
-  bool is_on_free_list() {
-    return _is_on_free_list;
-  }
+  // Methods used by the HeapRegionSetBase class and subclasses.
 
-  void set_on_free_list(bool b) {
-    _is_on_free_list = b;
-  }
+  // Getter and setter for the next field used to link regions into
+  // linked lists.
+  HeapRegion* next()              { return _next; }
+
+  void set_next(HeapRegion* next) { _next = next; }
 
-  HeapRegion* next_from_free_list() {
-    assert(is_on_free_list(),
-           "Should only invoke on free space.");
-    assert(_next_in_special_set == NULL ||
-           _next_in_special_set->is_on_free_list(),
-           "Malformed Free List.");
-    return _next_in_special_set;
-  }
+  // Every region added to a set is tagged with a reference to that
+  // set. This is used for doing consistency checking to make sure that
+  // the contents of a set are as they should be and it's only
+  // available in non-product builds.
+#ifdef ASSERT
+  void set_containing_set(HeapRegionSetBase* containing_set) {
+    assert((containing_set == NULL && _containing_set != NULL) ||
+           (containing_set != NULL && _containing_set == NULL),
+           err_msg("containing_set: "PTR_FORMAT" "
+                   "_containing_set: "PTR_FORMAT,
+                   containing_set, _containing_set));
+
+    _containing_set = containing_set;
+}
 
-  void set_next_on_free_list(HeapRegion* r) {
-    assert(r == NULL || r->is_on_free_list(), "Malformed free list.");
-    _next_in_special_set = r;
-  }
+  HeapRegionSetBase* containing_set() { return _containing_set; }
+#else // ASSERT
+  void set_containing_set(HeapRegionSetBase* containing_set) { }
 
-  bool is_on_unclean_list() {
-    return _is_on_unclean_list;
-  }
+  // containing_set() is only used in asserts so there's not reason
+  // to provide a dummy version of it.
+#endif // ASSERT
 
-  void set_on_unclean_list(bool b);
+  // If we want to remove regions from a list in bulk we can simply tag
+  // them with the pending_removal tag and call the
+  // remove_all_pending() method on the list.
 
-  HeapRegion* next_from_unclean_list() {
-    assert(is_on_unclean_list(),
-           "Should only invoke on unclean space.");
-    assert(_next_in_special_set == NULL ||
-           _next_in_special_set->is_on_unclean_list(),
-           "Malformed unclean List.");
-    return _next_in_special_set;
+  bool pending_removal() { return _pending_removal; }
+
+  void set_pending_removal(bool pending_removal) {
+    // We can only set pending_removal to true, if it's false and the
+    // region belongs to a set.
+    assert(!pending_removal ||
+           (!_pending_removal && containing_set() != NULL), "pre-condition");
+    // We can only set pending_removal to false, if it's true and the
+    // region does not belong to a set.
+    assert( pending_removal ||
+           ( _pending_removal && containing_set() == NULL), "pre-condition");
+
+    _pending_removal = pending_removal;
   }
 
-  void set_next_on_unclean_list(HeapRegion* r);
-
   HeapRegion* get_next_young_region() { return _next_young_region; }
   void set_next_young_region(HeapRegion* hr) {
     _next_young_region = hr;
@@ -515,11 +565,6 @@
 
   void initialize(MemRegion mr, bool clear_space, bool mangle_space);
 
-  // Ensure that "this" is zero-filled.
-  void ensure_zero_filled();
-  // This one requires that the calling thread holds ZF_mon.
-  void ensure_zero_filled_locked();
-
   // Get the start of the unmarked area in this region.
   HeapWord* prev_top_at_mark_start() const { return _prev_top_at_mark_start; }
   HeapWord* next_top_at_mark_start() const { return _next_top_at_mark_start; }
@@ -754,36 +799,6 @@
   // "end" of the region if there is no such block.
   HeapWord* next_block_start_careful(HeapWord* addr);
 
-  // Returns the zero-fill-state of the current region.
-  ZeroFillState zero_fill_state() { return (ZeroFillState)_zfs; }
-  bool zero_fill_is_allocated() { return _zfs == Allocated; }
-  Thread* zero_filler() { return _zero_filler; }
-
-  // Indicate that the contents of the region are unknown, and therefore
-  // might require zero-filling.
-  void set_zero_fill_needed() {
-    set_zero_fill_state_work(NotZeroFilled);
-  }
-  void set_zero_fill_in_progress(Thread* t) {
-    set_zero_fill_state_work(ZeroFilling);
-    _zero_filler = t;
-  }
-  void set_zero_fill_complete();
-  void set_zero_fill_allocated() {
-    set_zero_fill_state_work(Allocated);
-  }
-
-  void set_zero_fill_state_work(ZeroFillState zfs);
-
-  // This is called when a full collection shrinks the heap.
-  // We want to set the heap region to a value which says
-  // it is no longer part of the heap.  For now, we'll let "NotZF" fill
-  // that role.
-  void reset_zero_fill() {
-    set_zero_fill_state_work(NotZeroFilled);
-    _zero_filler = NULL;
-  }
-
   size_t recorded_rs_length() const        { return _recorded_rs_length; }
   double predicted_elapsed_time_ms() const { return _predicted_elapsed_time_ms; }
   size_t predicted_bytes_to_copy() const   { return _predicted_bytes_to_copy; }
@@ -822,10 +837,6 @@
 
   // Override; it uses the "prev" marking information
   virtual void verify(bool allow_dirty) const;
-
-#ifdef DEBUG
-  HeapWord* allocate(size_t size);
-#endif
 };
 
 // HeapRegionClosure is used for iterating over regions.
@@ -848,113 +859,6 @@
   bool complete() { return _complete; }
 };
 
-// A linked lists of heap regions.  It leaves the "next" field
-// unspecified; that's up to subtypes.
-class RegionList VALUE_OBJ_CLASS_SPEC {
-protected:
-  virtual HeapRegion* get_next(HeapRegion* chr) = 0;
-  virtual void set_next(HeapRegion* chr,
-                        HeapRegion* new_next) = 0;
-
-  HeapRegion* _hd;
-  HeapRegion* _tl;
-  size_t _sz;
-
-  // Protected constructor because this type is only meaningful
-  // when the _get/_set next functions are defined.
-  RegionList() : _hd(NULL), _tl(NULL), _sz(0) {}
-public:
-  void reset() {
-    _hd = NULL;
-    _tl = NULL;
-    _sz = 0;
-  }
-  HeapRegion* hd() { return _hd; }
-  HeapRegion* tl() { return _tl; }
-  size_t sz() { return _sz; }
-  size_t length();
-
-  bool well_formed() {
-    return
-      ((hd() == NULL && tl() == NULL && sz() == 0)
-       || (hd() != NULL && tl() != NULL && sz() > 0))
-      && (sz() == length());
-  }
-  virtual void insert_before_head(HeapRegion* r);
-  void prepend_list(RegionList* new_list);
-  virtual HeapRegion* pop();
-  void dec_sz() { _sz--; }
-  // Requires that "r" is an element of the list, and is not the tail.
-  void delete_after(HeapRegion* r);
-};
-
-class EmptyNonHRegionList: public RegionList {
-protected:
-  // Protected constructor because this type is only meaningful
-  // when the _get/_set next functions are defined.
-  EmptyNonHRegionList() : RegionList() {}
-
-public:
-  void insert_before_head(HeapRegion* r) {
-    //    assert(r->is_empty(), "Better be empty");
-    assert(!r->isHumongous(), "Better not be humongous.");
-    RegionList::insert_before_head(r);
-  }
-  void prepend_list(EmptyNonHRegionList* new_list) {
-    //    assert(new_list->hd() == NULL || new_list->hd()->is_empty(),
-    //     "Better be empty");
-    assert(new_list->hd() == NULL || !new_list->hd()->isHumongous(),
-           "Better not be humongous.");
-    //    assert(new_list->tl() == NULL || new_list->tl()->is_empty(),
-    //     "Better be empty");
-    assert(new_list->tl() == NULL || !new_list->tl()->isHumongous(),
-           "Better not be humongous.");
-    RegionList::prepend_list(new_list);
-  }
-};
-
-class UncleanRegionList: public EmptyNonHRegionList {
-public:
-  HeapRegion* get_next(HeapRegion* hr) {
-    return hr->next_from_unclean_list();
-  }
-  void set_next(HeapRegion* hr, HeapRegion* new_next) {
-    hr->set_next_on_unclean_list(new_next);
-  }
-
-  UncleanRegionList() : EmptyNonHRegionList() {}
-
-  void insert_before_head(HeapRegion* r) {
-    assert(!r->is_on_free_list(),
-           "Better not already be on free list");
-    assert(!r->is_on_unclean_list(),
-           "Better not already be on unclean list");
-    r->set_zero_fill_needed();
-    r->set_on_unclean_list(true);
-    EmptyNonHRegionList::insert_before_head(r);
-  }
-  void prepend_list(UncleanRegionList* new_list) {
-    assert(new_list->tl() == NULL || !new_list->tl()->is_on_free_list(),
-           "Better not already be on free list");
-    assert(new_list->tl() == NULL || new_list->tl()->is_on_unclean_list(),
-           "Better already be marked as on unclean list");
-    assert(new_list->hd() == NULL || !new_list->hd()->is_on_free_list(),
-           "Better not already be on free list");
-    assert(new_list->hd() == NULL || new_list->hd()->is_on_unclean_list(),
-           "Better already be marked as on unclean list");
-    EmptyNonHRegionList::prepend_list(new_list);
-  }
-  HeapRegion* pop() {
-    HeapRegion* res = RegionList::pop();
-    if (res != NULL) res->set_on_unclean_list(false);
-    return res;
-  }
-};
-
-// Local Variables: ***
-// c-indentation-style: gnu ***
-// End: ***
-
 #endif // SERIALGC
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -463,7 +463,6 @@
   }
 
   static void par_contract_all();
-
 };
 
 void PosParPRT::par_contract_all() {
@@ -1070,6 +1069,11 @@
 
 }
 
+void
+OtherRegionsTable::do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task) {
+  _sparse_table.do_cleanup_work(hrrs_cleanup_task);
+}
+
 // Determines how many threads can add records to an rset in parallel.
 // This can be done by either mutator threads together with the
 // concurrent refinement threads or GC threads.
@@ -1384,6 +1388,19 @@
   }
 }
 
+void HeapRegionRemSet::reset_for_cleanup_tasks() {
+  SparsePRT::reset_for_cleanup_tasks();
+}
+
+void HeapRegionRemSet::do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task) {
+  _other_regions.do_cleanup_work(hrrs_cleanup_task);
+}
+
+void
+HeapRegionRemSet::finish_cleanup_task(HRRSCleanupTask* hrrs_cleanup_task) {
+  SparsePRT::finish_cleanup_task(hrrs_cleanup_task);
+}
+
 #ifndef PRODUCT
 void HeapRegionRemSet::test() {
   os::sleep(Thread::current(), (jlong)5000, false);
--- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,10 @@
 class PosParPRT;
 class SparsePRT;
 
+// Essentially a wrapper around SparsePRTCleanupTask. See
+// sparsePRT.hpp for more details.
+class HRRSCleanupTask : public SparsePRTCleanupTask {
+};
 
 // The "_coarse_map" is a bitmap with one bit for each region, where set
 // bits indicate that the corresponding region may contain some pointer
@@ -156,6 +160,8 @@
   // "from_hr" is being cleared; remove any entries from it.
   void clear_incoming_entry(HeapRegion* from_hr);
 
+  void do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task);
+
   // Declare the heap size (in # of regions) to the OtherRegionsTable.
   // (Uses it to initialize from_card_cache).
   static void init_from_card_cache(size_t max_regions);
@@ -165,10 +171,8 @@
   static void shrink_from_card_cache(size_t new_n_regs);
 
   static void print_from_card_cache();
-
 };
 
-
 class HeapRegionRemSet : public CHeapObj {
   friend class VMStructs;
   friend class HeapRegionRemSetIterator;
@@ -342,11 +346,16 @@
   static void print_recorded();
   static void record_event(Event evnt);
 
+  // These are wrappers for the similarly-named methods on
+  // SparsePRT. Look at sparsePRT.hpp for more details.
+  static void reset_for_cleanup_tasks();
+  void do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task);
+  static void finish_cleanup_task(HRRSCleanupTask* hrrs_cleanup_task);
+
   // Run unit tests.
 #ifndef PRODUCT
   static void test();
 #endif
-
 };
 
 class HeapRegionRemSetIterator : public CHeapObj {
--- a/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,152 +65,6 @@
 
 // Private methods.
 
-HeapWord*
-HeapRegionSeq::alloc_obj_from_region_index(int ind, size_t word_size) {
-  assert(G1CollectedHeap::isHumongous(word_size),
-         "Allocation size should be humongous");
-  int cur = ind;
-  int first = cur;
-  size_t sumSizes = 0;
-  while (cur < _regions.length() && sumSizes < word_size) {
-    // Loop invariant:
-    //  For all i in [first, cur):
-    //       _regions.at(i)->is_empty()
-    //    && _regions.at(i) is contiguous with its predecessor, if any
-    //  && sumSizes is the sum of the sizes of the regions in the interval
-    //       [first, cur)
-    HeapRegion* curhr = _regions.at(cur);
-    if (curhr->is_empty()
-        && (first == cur
-            || (_regions.at(cur-1)->end() ==
-                curhr->bottom()))) {
-      sumSizes += curhr->capacity() / HeapWordSize;
-    } else {
-      first = cur + 1;
-      sumSizes = 0;
-    }
-    cur++;
-  }
-  if (sumSizes >= word_size) {
-    _alloc_search_start = cur;
-
-    // We need to initialize the region(s) we just discovered. This is
-    // a bit tricky given that it can happen concurrently with
-    // refinement threads refining cards on these regions and
-    // potentially wanting to refine the BOT as they are scanning
-    // those cards (this can happen shortly after a cleanup; see CR
-    // 6991377). So we have to set up the region(s) carefully and in
-    // a specific order.
-
-    // Currently, allocs_are_zero_filled() returns false. The zero
-    // filling infrastructure will be going away soon (see CR 6977804).
-    // So no need to do anything else here.
-    bool zf = G1CollectedHeap::heap()->allocs_are_zero_filled();
-    assert(!zf, "not supported");
-
-    // This will be the "starts humongous" region.
-    HeapRegion* first_hr = _regions.at(first);
-    {
-      MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-      first_hr->set_zero_fill_allocated();
-    }
-    // The header of the new object will be placed at the bottom of
-    // the first region.
-    HeapWord* new_obj = first_hr->bottom();
-    // This will be the new end of the first region in the series that
-    // should also match the end of the last region in the seriers.
-    // (Note: sumSizes = "region size" x "number of regions we found").
-    HeapWord* new_end = new_obj + sumSizes;
-    // This will be the new top of the first region that will reflect
-    // this allocation.
-    HeapWord* new_top = new_obj + word_size;
-
-    // First, we need to zero the header of the space that we will be
-    // allocating. When we update top further down, some refinement
-    // threads might try to scan the region. By zeroing the header we
-    // ensure that any thread that will try to scan the region will
-    // come across the zero klass word and bail out.
-    //
-    // NOTE: It would not have been correct to have used
-    // CollectedHeap::fill_with_object() and make the space look like
-    // an int array. The thread that is doing the allocation will
-    // later update the object header to a potentially different array
-    // type and, for a very short period of time, the klass and length
-    // fields will be inconsistent. This could cause a refinement
-    // thread to calculate the object size incorrectly.
-    Copy::fill_to_words(new_obj, oopDesc::header_size(), 0);
-
-    // We will set up the first region as "starts humongous". This
-    // will also update the BOT covering all the regions to reflect
-    // that there is a single object that starts at the bottom of the
-    // first region.
-    first_hr->set_startsHumongous(new_end);
-
-    // Then, if there are any, we will set up the "continues
-    // humongous" regions.
-    HeapRegion* hr = NULL;
-    for (int i = first + 1; i < cur; ++i) {
-      hr = _regions.at(i);
-      {
-        MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-        hr->set_zero_fill_allocated();
-      }
-      hr->set_continuesHumongous(first_hr);
-    }
-    // If we have "continues humongous" regions (hr != NULL), then the
-    // end of the last one should match new_end.
-    assert(hr == NULL || hr->end() == new_end, "sanity");
-
-    // Up to this point no concurrent thread would have been able to
-    // do any scanning on any region in this series. All the top
-    // fields still point to bottom, so the intersection between
-    // [bottom,top] and [card_start,card_end] will be empty. Before we
-    // update the top fields, we'll do a storestore to make sure that
-    // no thread sees the update to top before the zeroing of the
-    // object header and the BOT initialization.
-    OrderAccess::storestore();
-
-    // Now that the BOT and the object header have been initialized,
-    // we can update top of the "starts humongous" region.
-    assert(first_hr->bottom() < new_top && new_top <= first_hr->end(),
-           "new_top should be in this region");
-    first_hr->set_top(new_top);
-
-    // Now, we will update the top fields of the "continues humongous"
-    // regions. The reason we need to do this is that, otherwise,
-    // these regions would look empty and this will confuse parts of
-    // G1. For example, the code that looks for a consecutive number
-    // of empty regions will consider them empty and try to
-    // re-allocate them. We can extend is_empty() to also include
-    // !continuesHumongous(), but it is easier to just update the top
-    // fields here.
-    hr = NULL;
-    for (int i = first + 1; i < cur; ++i) {
-      hr = _regions.at(i);
-      if ((i + 1) == cur) {
-        // last continues humongous region
-        assert(hr->bottom() < new_top && new_top <= hr->end(),
-               "new_top should fall on this region");
-        hr->set_top(new_top);
-      } else {
-        // not last one
-        assert(new_top > hr->end(), "new_top should be above this region");
-        hr->set_top(hr->end());
-      }
-    }
-    // If we have continues humongous regions (hr != NULL), then the
-    // end of the last one should match new_end and its top should
-    // match new_top.
-    assert(hr == NULL ||
-           (hr->end() == new_end && hr->top() == new_top), "sanity");
-
-    return new_obj;
-  } else {
-    // If we started from the beginning, we want to know why we can't alloc.
-    return NULL;
-  }
-}
-
 void HeapRegionSeq::print_empty_runs() {
   int empty_run = 0;
   int n_empty = 0;
@@ -284,13 +138,67 @@
   return res;
 }
 
-HeapWord* HeapRegionSeq::obj_allocate(size_t word_size) {
-  int cur = _alloc_search_start;
-  // Make sure "cur" is a valid index.
-  assert(cur >= 0, "Invariant.");
-  HeapWord* res = alloc_obj_from_region_index(cur, word_size);
-  if (res == NULL)
-    res = alloc_obj_from_region_index(0, word_size);
+int HeapRegionSeq::find_contiguous_from(int from, size_t num) {
+  assert(num > 1, "pre-condition");
+  assert(0 <= from && from <= _regions.length(),
+         err_msg("from: %d should be valid and <= than %d",
+                 from, _regions.length()));
+
+  int curr = from;
+  int first = -1;
+  size_t num_so_far = 0;
+  while (curr < _regions.length() && num_so_far < num) {
+    HeapRegion* curr_hr = _regions.at(curr);
+    if (curr_hr->is_empty()) {
+      if (first == -1) {
+        first = curr;
+        num_so_far = 1;
+      } else {
+        num_so_far += 1;
+      }
+    } else {
+      first = -1;
+      num_so_far = 0;
+    }
+    curr += 1;
+  }
+
+  assert(num_so_far <= num, "post-condition");
+  if (num_so_far == num) {
+    // we find enough space for the humongous object
+    assert(from <= first && first < _regions.length(), "post-condition");
+    assert(first < curr && (curr - first) == (int) num, "post-condition");
+    for (int i = first; i < first + (int) num; ++i) {
+      assert(_regions.at(i)->is_empty(), "post-condition");
+    }
+    return first;
+  } else {
+    // we failed to find enough space for the humongous object
+    return -1;
+  }
+}
+
+int HeapRegionSeq::find_contiguous(size_t num) {
+  assert(num > 1, "otherwise we should not be calling this");
+  assert(0 <= _alloc_search_start && _alloc_search_start <= _regions.length(),
+         err_msg("_alloc_search_start: %d should be valid and <= than %d",
+                 _alloc_search_start, _regions.length()));
+
+  int start = _alloc_search_start;
+  int res = find_contiguous_from(start, num);
+  if (res == -1 && start != 0) {
+    // Try starting from the beginning. If _alloc_search_start was 0,
+    // no point in doing this again.
+    res = find_contiguous_from(0, num);
+  }
+  if (res != -1) {
+    assert(0 <= res && res < _regions.length(),
+           err_msg("res: %d should be valid", res));
+    _alloc_search_start = res + (int) num;
+    assert(0 < _alloc_search_start && _alloc_search_start <= _regions.length(),
+           err_msg("_alloc_search_start: %d should be valid",
+                   _alloc_search_start));
+  }
   return res;
 }
 
@@ -376,6 +284,10 @@
 
 MemRegion HeapRegionSeq::shrink_by(size_t shrink_bytes,
                                    size_t& num_regions_deleted) {
+  // Reset this in case it's currently pointing into the regions that
+  // we just removed.
+  _alloc_search_start = 0;
+
   assert(shrink_bytes % os::vm_page_size() == 0, "unaligned");
   assert(shrink_bytes % HeapRegion::GrainBytes == 0, "unaligned");
 
@@ -395,7 +307,6 @@
     }
     assert(cur == _regions.top(), "Should be top");
     if (!cur->is_empty()) break;
-    cur->reset_zero_fill();
     shrink_bytes -= cur->capacity();
     num_regions_deleted++;
     _regions.pop();
@@ -410,7 +321,6 @@
   return MemRegion(last_start, end);
 }
 
-
 class PrintHeapRegionClosure : public  HeapRegionClosure {
 public:
   bool doHeapRegion(HeapRegion* r) {
--- a/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,9 +41,9 @@
   // (For efficiency only; private to obj_allocate after initialization.)
   int _alloc_search_start;
 
-  // Attempts to allocate a block of the (assumed humongous) word_size,
-  // starting at the region "ind".
-  HeapWord* alloc_obj_from_region_index(int ind, size_t word_size);
+  // Finds a contiguous set of empty regions of length num, starting
+  // from a given index.
+  int find_contiguous_from(int from, size_t num);
 
   // Currently, we're choosing collection sets in a round-robin fashion,
   // starting here.
@@ -76,11 +76,8 @@
   // that are available for allocation.
   size_t free_suffix();
 
-  // Requires "word_size" to be humongous (in the technical sense).  If
-  // possible, allocates a contiguous subsequence of the heap regions to
-  // satisfy the allocation, and returns the address of the beginning of
-  // that sequence, otherwise returns NULL.
-  HeapWord* obj_allocate(size_t word_size);
+  // Finds a contiguous set of empty regions of length num.
+  int find_contiguous(size_t num);
 
   // Apply the "doHeapRegion" method of "blk" to all regions in "this",
   // in address order, terminating the iteration early
@@ -106,7 +103,7 @@
 
   // If "addr" falls within a region in the sequence, return that region,
   // or else NULL.
-  HeapRegion* addr_to_region(const void* addr);
+  inline HeapRegion* addr_to_region(const void* addr);
 
   void print();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/heapRegionSet.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/heapRegionSet.inline.hpp"
+
+size_t HeapRegionSetBase::_unrealistically_long_length = 0;
+
+//////////////////// HeapRegionSetBase ////////////////////
+
+void HeapRegionSetBase::set_unrealistically_long_length(size_t len) {
+  guarantee(_unrealistically_long_length == 0, "should only be set once");
+  _unrealistically_long_length = len;
+}
+
+size_t HeapRegionSetBase::calculate_region_num(HeapRegion* hr) {
+  assert(hr->startsHumongous(), "pre-condition");
+  assert(hr->capacity() % HeapRegion::GrainBytes == 0, "invariant");
+  size_t region_num = hr->capacity() >> HeapRegion::LogOfHRGrainBytes;
+  assert(region_num > 0, "sanity");
+  return region_num;
+}
+
+void HeapRegionSetBase::fill_in_ext_msg(hrl_ext_msg* msg, const char* message) {
+  msg->append("[%s] %s "
+              "ln: "SIZE_FORMAT" rn: "SIZE_FORMAT" "
+              "cy: "SIZE_FORMAT" ud: "SIZE_FORMAT,
+              name(), message, length(), region_num(),
+              total_capacity_bytes(), total_used_bytes());
+  fill_in_ext_msg_extra(msg);
+}
+
+bool HeapRegionSetBase::verify_region(HeapRegion* hr,
+                                  HeapRegionSetBase* expected_containing_set) {
+  const char* error_message = NULL;
+
+  if (!regions_humongous()) {
+    if (hr->isHumongous()) {
+      error_message = "the region should not be humongous";
+    }
+  } else {
+    if (!hr->isHumongous() || !hr->startsHumongous()) {
+      error_message = "the region should be 'starts humongous'";
+    }
+  }
+
+  if (!regions_empty()) {
+    if (hr->is_empty()) {
+      error_message = "the region should not be empty";
+    }
+  } else {
+    if (!hr->is_empty()) {
+      error_message = "the region should be empty";
+    }
+  }
+
+#ifdef ASSERT
+  // The _containing_set field is only available when ASSERT is defined.
+  if (hr->containing_set() != expected_containing_set) {
+    error_message = "inconsistent containing set found";
+  }
+#endif // ASSERT
+
+  const char* extra_error_message = verify_region_extra(hr);
+  if (extra_error_message != NULL) {
+    error_message = extra_error_message;
+  }
+
+  if (error_message != NULL) {
+    outputStream* out = tty;
+    out->cr();
+    out->print_cr("## [%s] %s", name(), error_message);
+    out->print_cr("## Offending Region: "PTR_FORMAT, hr);
+    out->print_cr("   "HR_FORMAT, HR_FORMAT_PARAMS(hr));
+#ifdef ASSERT
+    out->print_cr("   containing set: "PTR_FORMAT, hr->containing_set());
+#endif // ASSERT
+    out->print_cr("## Offending Region Set: "PTR_FORMAT, this);
+    print_on(out);
+    return false;
+  } else {
+    return true;
+  }
+}
+
+void HeapRegionSetBase::verify() {
+  // It's important that we also observe the MT safety protocol even
+  // for the verification calls. If we do verification without the
+  // appropriate locks and the set changes underneath our feet
+  // verification might fail and send us on a wild goose chase.
+  hrl_assert_mt_safety_ok(this);
+
+  guarantee(( is_empty() && length() == 0 && region_num() == 0 &&
+              total_used_bytes() == 0 && total_capacity_bytes() == 0) ||
+            (!is_empty() && length() >= 0 && region_num() >= 0 &&
+              total_used_bytes() >= 0 && total_capacity_bytes() >= 0),
+            hrl_ext_msg(this, "invariant"));
+
+  guarantee((!regions_humongous() && region_num() == length()) ||
+            ( regions_humongous() && region_num() >= length()),
+            hrl_ext_msg(this, "invariant"));
+
+  guarantee(!regions_empty() || total_used_bytes() == 0,
+            hrl_ext_msg(this, "invariant"));
+
+  guarantee(total_used_bytes() <= total_capacity_bytes(),
+            hrl_ext_msg(this, "invariant"));
+}
+
+void HeapRegionSetBase::verify_start() {
+  // See comment in verify() about MT safety and verification.
+  hrl_assert_mt_safety_ok(this);
+  assert(!_verify_in_progress,
+         hrl_ext_msg(this, "verification should not be in progress"));
+
+  // Do the basic verification first before we do the checks over the regions.
+  HeapRegionSetBase::verify();
+
+  _calc_length               = 0;
+  _calc_region_num           = 0;
+  _calc_total_capacity_bytes = 0;
+  _calc_total_used_bytes     = 0;
+  _verify_in_progress        = true;
+}
+
+void HeapRegionSetBase::verify_next_region(HeapRegion* hr) {
+  // See comment in verify() about MT safety and verification.
+  hrl_assert_mt_safety_ok(this);
+  assert(_verify_in_progress,
+         hrl_ext_msg(this, "verification should be in progress"));
+
+  guarantee(verify_region(hr, this), hrl_ext_msg(this, "region verification"));
+
+  _calc_length               += 1;
+  if (!hr->isHumongous()) {
+    _calc_region_num         += 1;
+  } else {
+    _calc_region_num         += calculate_region_num(hr);
+  }
+  _calc_total_capacity_bytes += hr->capacity();
+  _calc_total_used_bytes     += hr->used();
+}
+
+void HeapRegionSetBase::verify_end() {
+  // See comment in verify() about MT safety and verification.
+  hrl_assert_mt_safety_ok(this);
+  assert(_verify_in_progress,
+         hrl_ext_msg(this, "verification should be in progress"));
+
+  guarantee(length() == _calc_length,
+            hrl_err_msg("[%s] length: "SIZE_FORMAT" should be == "
+                        "calc length: "SIZE_FORMAT,
+                        name(), length(), _calc_length));
+
+  guarantee(region_num() == _calc_region_num,
+            hrl_err_msg("[%s] region num: "SIZE_FORMAT" should be == "
+                        "calc region num: "SIZE_FORMAT,
+                        name(), region_num(), _calc_region_num));
+
+  guarantee(total_capacity_bytes() == _calc_total_capacity_bytes,
+            hrl_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == "
+                        "calc capacity bytes: "SIZE_FORMAT,
+                        name(),
+                        total_capacity_bytes(), _calc_total_capacity_bytes));
+
+  guarantee(total_used_bytes() == _calc_total_used_bytes,
+            hrl_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == "
+                        "calc used bytes: "SIZE_FORMAT,
+                        name(), total_used_bytes(), _calc_total_used_bytes));
+
+  _verify_in_progress = false;
+}
+
+void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
+  out->cr();
+  out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
+  out->print_cr("  Region Assumptions");
+  out->print_cr("    humongous         : %s", BOOL_TO_STR(regions_humongous()));
+  out->print_cr("    empty             : %s", BOOL_TO_STR(regions_empty()));
+  out->print_cr("  Attributes");
+  out->print_cr("    length            : "SIZE_FORMAT_W(14), length());
+  out->print_cr("    region num        : "SIZE_FORMAT_W(14), region_num());
+  out->print_cr("    total capacity    : "SIZE_FORMAT_W(14)" bytes",
+                total_capacity_bytes());
+  out->print_cr("    total used        : "SIZE_FORMAT_W(14)" bytes",
+                total_used_bytes());
+}
+
+void HeapRegionSetBase::clear() {
+  _length           = 0;
+  _region_num       = 0;
+  _total_used_bytes = 0;
+}
+
+HeapRegionSetBase::HeapRegionSetBase(const char* name)
+  : _name(name), _verify_in_progress(false),
+    _calc_length(0), _calc_region_num(0),
+    _calc_total_capacity_bytes(0), _calc_total_used_bytes(0) { }
+
+//////////////////// HeapRegionSet ////////////////////
+
+void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) {
+  hrl_assert_mt_safety_ok(this);
+  hrl_assert_mt_safety_ok(proxy_set);
+  hrl_assert_sets_match(this, proxy_set);
+
+  verify_optional();
+  proxy_set->verify_optional();
+
+  if (proxy_set->is_empty()) return;
+
+  assert(proxy_set->length() <= _length,
+         hrl_err_msg("[%s] proxy set length: "SIZE_FORMAT" "
+                     "should be <= length: "SIZE_FORMAT,
+                     name(), proxy_set->length(), _length));
+  _length -= proxy_set->length();
+
+  assert(proxy_set->region_num() <= _region_num,
+         hrl_err_msg("[%s] proxy set region num: "SIZE_FORMAT" "
+                     "should be <= region num: "SIZE_FORMAT,
+                     name(), proxy_set->region_num(), _region_num));
+  _region_num -= proxy_set->region_num();
+
+  assert(proxy_set->total_used_bytes() <= _total_used_bytes,
+         hrl_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" "
+                     "should be <= used bytes: "SIZE_FORMAT,
+                     name(), proxy_set->total_used_bytes(),
+                     _total_used_bytes));
+  _total_used_bytes -= proxy_set->total_used_bytes();
+
+  proxy_set->clear();
+
+  verify_optional();
+  proxy_set->verify_optional();
+}
+
+//////////////////// HeapRegionLinkedList ////////////////////
+
+void HeapRegionLinkedList::fill_in_ext_msg_extra(hrl_ext_msg* msg) {
+  msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail());
+}
+
+void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) {
+  hrl_assert_mt_safety_ok(this);
+  hrl_assert_mt_safety_ok(from_list);
+
+  verify_optional();
+  from_list->verify_optional();
+
+  if (from_list->is_empty()) return;
+
+#ifdef ASSERT
+  HeapRegionLinkedListIterator iter(from_list);
+  while (iter.more_available()) {
+    HeapRegion* hr = iter.get_next();
+    // In set_containing_set() we check that we either set the value
+    // from NULL to non-NULL or vice versa to catch bugs. So, we have
+    // to NULL it first before setting it to the value.
+    hr->set_containing_set(NULL);
+    hr->set_containing_set(this);
+  }
+#endif // ASSERT
+
+  if (_tail != NULL) {
+    assert(length() >  0 && _head != NULL, hrl_ext_msg(this, "invariant"));
+    _tail->set_next(from_list->_head);
+  } else {
+    assert(length() == 0 && _head == NULL, hrl_ext_msg(this, "invariant"));
+    _head = from_list->_head;
+  }
+  _tail = from_list->_tail;
+
+  _length           += from_list->length();
+  _region_num       += from_list->region_num();
+  _total_used_bytes += from_list->total_used_bytes();
+  from_list->clear();
+
+  verify_optional();
+  from_list->verify_optional();
+}
+
+void HeapRegionLinkedList::remove_all() {
+  hrl_assert_mt_safety_ok(this);
+  verify_optional();
+
+  HeapRegion* curr = _head;
+  while (curr != NULL) {
+    hrl_assert_region_ok(this, curr, this);
+
+    HeapRegion* next = curr->next();
+    curr->set_next(NULL);
+    curr->set_containing_set(NULL);
+    curr = next;
+  }
+  clear();
+
+  verify_optional();
+}
+
+void HeapRegionLinkedList::remove_all_pending(size_t target_count) {
+  hrl_assert_mt_safety_ok(this);
+  assert(target_count > 1, hrl_ext_msg(this, "pre-condition"));
+  assert(!is_empty(), hrl_ext_msg(this, "pre-condition"));
+
+  verify_optional();
+  DEBUG_ONLY(size_t old_length = length();)
+
+  HeapRegion* curr = _head;
+  HeapRegion* prev = NULL;
+  size_t count = 0;
+  while (curr != NULL) {
+    hrl_assert_region_ok(this, curr, this);
+    HeapRegion* next = curr->next();
+
+    if (curr->pending_removal()) {
+      assert(count < target_count,
+             hrl_err_msg("[%s] should not come across more regions "
+                         "pending for removal than target_count: "SIZE_FORMAT,
+                         name(), target_count));
+
+      if (prev == NULL) {
+        assert(_head == curr, hrl_ext_msg(this, "invariant"));
+        _head = next;
+      } else {
+        assert(_head != curr, hrl_ext_msg(this, "invariant"));
+        prev->set_next(next);
+      }
+      if (next == NULL) {
+        assert(_tail == curr, hrl_ext_msg(this, "invariant"));
+        _tail = prev;
+      } else {
+        assert(_tail != curr, hrl_ext_msg(this, "invariant"));
+      }
+
+      curr->set_next(NULL);
+      remove_internal(curr);
+      curr->set_pending_removal(false);
+
+      count += 1;
+
+      // If we have come across the target number of regions we can
+      // just bail out. However, for debugging purposes, we can just
+      // carry on iterating to make sure there are not more regions
+      // tagged with pending removal.
+      DEBUG_ONLY(if (count == target_count) break;)
+    } else {
+      prev = curr;
+    }
+    curr = next;
+  }
+
+  assert(count == target_count,
+         hrl_err_msg("[%s] count: "SIZE_FORMAT" should be == "
+                     "target_count: "SIZE_FORMAT, name(), count, target_count));
+  assert(length() + target_count == old_length,
+         hrl_err_msg("[%s] new length should be consistent "
+                     "new length: "SIZE_FORMAT" old length: "SIZE_FORMAT" "
+                     "target_count: "SIZE_FORMAT,
+                     name(), length(), old_length, target_count));
+
+  verify_optional();
+}
+
+void HeapRegionLinkedList::verify() {
+  // See comment in HeapRegionSetBase::verify() about MT safety and
+  // verification.
+  hrl_assert_mt_safety_ok(this);
+
+  // This will also do the basic verification too.
+  verify_start();
+
+  HeapRegion* curr  = _head;
+  HeapRegion* prev1 = NULL;
+  HeapRegion* prev0 = NULL;
+  size_t      count = 0;
+  while (curr != NULL) {
+    verify_next_region(curr);
+
+    count += 1;
+    guarantee(count < _unrealistically_long_length,
+              hrl_err_msg("[%s] the calculated length: "SIZE_FORMAT" "
+                          "seems very long, is there maybe a cycle? "
+                          "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" "
+                          "prev1: "PTR_FORMAT" length: "SIZE_FORMAT,
+                          name(), count, curr, prev0, prev1, length()));
+
+    prev1 = prev0;
+    prev0 = curr;
+    curr  = curr->next();
+  }
+
+  guarantee(_tail == prev0, hrl_ext_msg(this, "post-condition"));
+
+  verify_end();
+}
+
+void HeapRegionLinkedList::clear() {
+  HeapRegionSetBase::clear();
+  _head = NULL;
+  _tail = NULL;
+}
+
+void HeapRegionLinkedList::print_on(outputStream* out, bool print_contents) {
+  HeapRegionSetBase::print_on(out, print_contents);
+  out->print_cr("  Linking");
+  out->print_cr("    head              : "PTR_FORMAT, _head);
+  out->print_cr("    tail              : "PTR_FORMAT, _tail);
+
+  if (print_contents) {
+    out->print_cr("  Contents");
+    HeapRegionLinkedListIterator iter(this);
+    while (iter.more_available()) {
+      HeapRegion* hr = iter.get_next();
+      hr->print_on(out);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/heapRegionSet.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -0,0 +1,346 @@
+/*
+ * copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_HPP
+
+#include "gc_implementation/g1/heapRegion.hpp"
+
+// Large buffer for some cases where the output might be larger than normal.
+#define HRL_ERR_MSG_BUFSZ 512
+typedef FormatBuffer<HRL_ERR_MSG_BUFSZ> hrl_err_msg;
+
+// Set verification will be forced either if someone defines
+// HEAP_REGION_SET_FORCE_VERIFY to be 1, or in builds in which
+// asserts are compiled in.
+#ifndef HEAP_REGION_SET_FORCE_VERIFY
+#define HEAP_REGION_SET_FORCE_VERIFY defined(ASSERT)
+#endif // HEAP_REGION_SET_FORCE_VERIFY
+
+//////////////////// HeapRegionSetBase ////////////////////
+
+// Base class for all the classes that represent heap region sets. It
+// contains the basic attributes that each set needs to maintain
+// (e.g., length, region num, used bytes sum) plus any shared
+// functionality (e.g., verification).
+
+class hrl_ext_msg;
+
+class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC {
+  friend class hrl_ext_msg;
+
+protected:
+  static size_t calculate_region_num(HeapRegion* hr);
+
+  static size_t _unrealistically_long_length;
+
+  // The number of regions added to the set. If the set contains
+  // only humongous regions, this reflects only 'starts humongous'
+  // regions and does not include 'continues humongous' ones.
+  size_t _length;
+
+  // The total number of regions represented by the set. If the set
+  // does not contain humongous regions, this should be the same as
+  // _length. If the set contains only humongous regions, this will
+  // include the 'continues humongous' regions.
+  size_t _region_num;
+
+  // We don't keep track of the total capacity explicitly, we instead
+  // recalculate it based on _region_num and the heap region size.
+
+  // The sum of used bytes in the all the regions in the set.
+  size_t _total_used_bytes;
+
+  const char* _name;
+
+  bool        _verify_in_progress;
+  size_t      _calc_length;
+  size_t      _calc_region_num;
+  size_t      _calc_total_capacity_bytes;
+  size_t      _calc_total_used_bytes;
+
+  // verify_region() is used to ensure that the contents of a region
+  // added to / removed from a set are consistent. Different sets
+  // make different assumptions about the regions added to them. So
+  // each set can override verify_region_extra(), which is called
+  // from verify_region(), and do any extra verification it needs to
+  // perform in that.
+  virtual const char* verify_region_extra(HeapRegion* hr) { return NULL; }
+  bool verify_region(HeapRegion* hr,
+                     HeapRegionSetBase* expected_containing_set);
+
+  // Indicates whether all regions in the set should be humongous or
+  // not. Only used during verification.
+  virtual bool regions_humongous() = 0;
+
+  // Indicates whether all regions in the set should be empty or
+  // not. Only used during verification.
+  virtual bool regions_empty() = 0;
+
+  // Subclasses can optionally override this to do MT safety protocol
+  // checks. It is called in an assert from all methods that perform
+  // updates on the set (and subclasses should also call it too).
+  virtual bool check_mt_safety() { return true; }
+
+  // fill_in_ext_msg() writes the the values of the set's attributes
+  // in the custom err_msg (hrl_ext_msg). fill_in_ext_msg_extra()
+  // allows subclasses to append further information.
+  virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg) { }
+  void fill_in_ext_msg(hrl_ext_msg* msg, const char* message);
+
+  // It updates the fields of the set to reflect hr being added to
+  // the set.
+  inline void update_for_addition(HeapRegion* hr);
+
+  // It updates the fields of the set to reflect hr being added to
+  // the set and tags the region appropriately.
+  inline void add_internal(HeapRegion* hr);
+
+  // It updates the fields of the set to reflect hr being removed
+  // from the set.
+  inline void update_for_removal(HeapRegion* hr);
+
+  // It updates the fields of the set to reflect hr being removed
+  // from the set and tags the region appropriately.
+  inline void remove_internal(HeapRegion* hr);
+
+  // It clears all the fields of the sets. Note: it will not iterate
+  // over the set and remove regions from it. It assumes that the
+  // caller has already done so. It will literally just clear the fields.
+  virtual void clear();
+
+  HeapRegionSetBase(const char* name);
+
+public:
+  static void set_unrealistically_long_length(size_t len);
+
+  const char* name() { return _name; }
+
+  size_t length() { return _length; }
+
+  bool is_empty() { return _length == 0; }
+
+  size_t region_num() { return _region_num; }
+
+  size_t total_capacity_bytes() {
+    return region_num() << HeapRegion::LogOfHRGrainBytes;
+  }
+
+  size_t total_used_bytes() { return _total_used_bytes; }
+
+  virtual void verify();
+  void verify_start();
+  void verify_next_region(HeapRegion* hr);
+  void verify_end();
+
+#if HEAP_REGION_SET_FORCE_VERIFY
+  void verify_optional() {
+    verify();
+  }
+#else // HEAP_REGION_SET_FORCE_VERIFY
+  void verify_optional() { }
+#endif // HEAP_REGION_SET_FORCE_VERIFY
+
+  virtual void print_on(outputStream* out, bool print_contents = false);
+};
+
+// Customized err_msg for heap region sets. Apart from a
+// assert/guarantee-specific message it also prints out the values of
+// the fields of the associated set. This can be very helpful in
+// diagnosing failures.
+
+class hrl_ext_msg : public hrl_err_msg {
+public:
+  hrl_ext_msg(HeapRegionSetBase* set, const char* message) : hrl_err_msg("") {
+    set->fill_in_ext_msg(this, message);
+  }
+};
+
+// These two macros are provided for convenience, to keep the uses of
+// these two asserts a bit more concise.
+
+#define hrl_assert_mt_safety_ok(_set_)                                        \
+  do {                                                                        \
+    assert((_set_)->check_mt_safety(), hrl_ext_msg((_set_), "MT safety"));    \
+  } while (0)
+
+#define hrl_assert_region_ok(_set_, _hr_, _expected_)                         \
+  do {                                                                        \
+    assert((_set_)->verify_region((_hr_), (_expected_)),                      \
+           hrl_ext_msg((_set_), "region verification"));                      \
+  } while (0)
+
+//////////////////// HeapRegionSet ////////////////////
+
+#define hrl_assert_sets_match(_set1_, _set2_)                                 \
+  do {                                                                        \
+    assert(((_set1_)->regions_humongous() ==                                  \
+                                            (_set2_)->regions_humongous()) && \
+           ((_set1_)->regions_empty() == (_set2_)->regions_empty()),          \
+           hrl_err_msg("the contents of set %s and set %s should match",      \
+                       (_set1_)->name(), (_set2_)->name()));                  \
+  } while (0)
+
+// This class represents heap region sets whose members are not
+// explicitly tracked. It's helpful to group regions using such sets
+// so that we can reason about all the region groups in the heap using
+// the same interface (namely, the HeapRegionSetBase API).
+
+class HeapRegionSet : public HeapRegionSetBase {
+protected:
+  virtual const char* verify_region_extra(HeapRegion* hr) {
+    if (hr->next() != NULL) {
+      return "next() should always be NULL as we do not link the regions";
+    }
+
+    return HeapRegionSetBase::verify_region_extra(hr);
+  }
+
+  HeapRegionSet(const char* name) : HeapRegionSetBase(name) {
+    clear();
+  }
+
+public:
+  // It adds hr to the set. The region should not be a member of
+  // another set.
+  inline void add(HeapRegion* hr);
+
+  // It removes hr from the set. The region should be a member of
+  // this set.
+  inline void remove(HeapRegion* hr);
+
+  // It removes a region from the set. Instead of updating the fields
+  // of the set to reflect this removal, it accumulates the updates
+  // in proxy_set. The idea is that proxy_set is thread-local to
+  // avoid multiple threads updating the fields of the set
+  // concurrently and having to synchronize. The method
+  // update_from_proxy() will update the fields of the set from the
+  // proxy_set.
+  inline void remove_with_proxy(HeapRegion* hr, HeapRegionSet* proxy_set);
+
+  // After multiple calls to remove_with_proxy() the updates to the
+  // fields of the set are accumulated in proxy_set. This call
+  // updates the fields of the set from proxy_set.
+  void update_from_proxy(HeapRegionSet* proxy_set);
+};
+
+//////////////////// HeapRegionLinkedList ////////////////////
+
+// A set that links all the regions added to it in a singly-linked
+// list. We should try to avoid doing operations that iterate over
+// such lists in performance critical paths. Typically we should
+// add / remove one region at a time or concatenate two lists. All
+// those operations are done in constant time.
+
+class HeapRegionLinkedListIterator;
+
+class HeapRegionLinkedList : public HeapRegionSetBase {
+  friend class HeapRegionLinkedListIterator;
+
+private:
+  HeapRegion* _head;
+  HeapRegion* _tail;
+
+  // These are provided for use by the friend classes.
+  HeapRegion* head() { return _head; }
+  HeapRegion* tail() { return _tail; }
+
+protected:
+  virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg);
+
+  // See the comment for HeapRegionSetBase::clear()
+  virtual void clear();
+
+  HeapRegionLinkedList(const char* name) : HeapRegionSetBase(name) {
+    clear();
+  }
+
+public:
+  // It adds hr to the list as the new tail. The region should not be
+  // a member of another set.
+  inline void add_as_tail(HeapRegion* hr);
+
+  // It removes and returns the head of the list. It assumes that the
+  // list is not empty so it will return a non-NULL value.
+  inline HeapRegion* remove_head();
+
+  // Convenience method.
+  inline HeapRegion* remove_head_or_null();
+
+  // It moves the regions from from_list to this list and empties
+  // from_list. The new regions will appear in the same order as they
+  // were in from_list and be linked in the end of this list.
+  void add_as_tail(HeapRegionLinkedList* from_list);
+
+  // It empties the list by removing all regions from it.
+  void remove_all();
+
+  // It removes all regions in the list that are pending for removal
+  // (i.e., they have been tagged with "pending_removal"). The list
+  // must not be empty, target_count should reflect the exact number
+  // of regions that are pending for removal in the list, and
+  // target_count should be > 1 (currently, we never need to remove a
+  // single region using this).
+  void remove_all_pending(size_t target_count);
+
+  virtual void verify();
+
+  virtual void print_on(outputStream* out, bool print_contents = false);
+};
+
+//////////////////// HeapRegionLinkedList ////////////////////
+
+// Iterator class that provides a convenient way to iterator over the
+// regions in a HeapRegionLinkedList instance.
+
+class HeapRegionLinkedListIterator : public StackObj {
+private:
+  HeapRegionLinkedList* _list;
+  HeapRegion*           _curr;
+
+public:
+  bool more_available() {
+    return _curr != NULL;
+  }
+
+  HeapRegion* get_next() {
+    assert(more_available(),
+           "get_next() should be called when more regions are available");
+
+    // If we are going to introduce a count in the iterator we should
+    // do the "cycle" check.
+
+    HeapRegion* hr = _curr;
+    assert(_list->verify_region(hr, _list), "region verification");
+    _curr = hr->next();
+    return hr;
+  }
+
+  HeapRegionLinkedListIterator(HeapRegionLinkedList* list)
+    : _curr(NULL), _list(list) {
+    _curr = list->head();
+  }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -0,0 +1,159 @@
+/*
+ * copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_INLINE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_INLINE_HPP
+
+#include "gc_implementation/g1/heapRegionSet.hpp"
+
+//////////////////// HeapRegionSetBase ////////////////////
+
+inline void HeapRegionSetBase::update_for_addition(HeapRegion* hr) {
+  // Assumes the caller has already verified the region.
+
+  _length           += 1;
+  if (!hr->isHumongous()) {
+    _region_num     += 1;
+  } else {
+    _region_num     += calculate_region_num(hr);
+  }
+  _total_used_bytes += hr->used();
+}
+
+inline void HeapRegionSetBase::add_internal(HeapRegion* hr) {
+  hrl_assert_region_ok(this, hr, NULL);
+  assert(hr->next() == NULL, hrl_ext_msg(this, "should not already be linked"));
+
+  update_for_addition(hr);
+  hr->set_containing_set(this);
+}
+
+inline void HeapRegionSetBase::update_for_removal(HeapRegion* hr) {
+  // Assumes the caller has already verified the region.
+  assert(_length > 0, hrl_ext_msg(this, "pre-condition"));
+  _length -= 1;
+
+  size_t region_num_diff;
+  if (!hr->isHumongous()) {
+    region_num_diff = 1;
+  } else {
+    region_num_diff = calculate_region_num(hr);
+  }
+  assert(region_num_diff <= _region_num,
+         hrl_err_msg("[%s] region's region num: "SIZE_FORMAT" "
+                     "should be <= region num: "SIZE_FORMAT,
+                     name(), region_num_diff, _region_num));
+  _region_num -= region_num_diff;
+
+  size_t used_bytes = hr->used();
+  assert(used_bytes <= _total_used_bytes,
+         hrl_err_msg("[%s] region's used bytes: "SIZE_FORMAT" "
+                     "should be <= used bytes: "SIZE_FORMAT,
+                     name(), used_bytes, _total_used_bytes));
+  _total_used_bytes -= used_bytes;
+}
+
+inline void HeapRegionSetBase::remove_internal(HeapRegion* hr) {
+  hrl_assert_region_ok(this, hr, this);
+  assert(hr->next() == NULL, hrl_ext_msg(this, "should already be unlinked"));
+
+  hr->set_containing_set(NULL);
+  update_for_removal(hr);
+}
+
+//////////////////// HeapRegionSet ////////////////////
+
+inline void HeapRegionSet::add(HeapRegion* hr) {
+  hrl_assert_mt_safety_ok(this);
+  // add_internal() will verify the region.
+  add_internal(hr);
+}
+
+inline void HeapRegionSet::remove(HeapRegion* hr) {
+  hrl_assert_mt_safety_ok(this);
+  // remove_internal() will verify the region.
+  remove_internal(hr);
+}
+
+inline void HeapRegionSet::remove_with_proxy(HeapRegion* hr,
+                                             HeapRegionSet* proxy_set) {
+  // No need to fo the MT safety check here given that this method
+  // does not update the contents of the set but instead accumulates
+  // the changes in proxy_set which is assumed to be thread-local.
+  hrl_assert_sets_match(this, proxy_set);
+  hrl_assert_region_ok(this, hr, this);
+
+  hr->set_containing_set(NULL);
+  proxy_set->update_for_addition(hr);
+}
+
+//////////////////// HeapRegionLinkedList ////////////////////
+
+inline void HeapRegionLinkedList::add_as_tail(HeapRegion* hr) {
+  hrl_assert_mt_safety_ok(this);
+  assert((length() == 0 && _head == NULL && _tail == NULL) ||
+         (length() >  0 && _head != NULL && _tail != NULL),
+         hrl_ext_msg(this, "invariant"));
+  // add_internal() will verify the region.
+  add_internal(hr);
+
+  // Now link the region.
+  if (_tail != NULL) {
+    _tail->set_next(hr);
+  } else {
+    _head = hr;
+  }
+  _tail = hr;
+}
+
+inline HeapRegion* HeapRegionLinkedList::remove_head() {
+  hrl_assert_mt_safety_ok(this);
+  assert(!is_empty(), hrl_ext_msg(this, "the list should not be empty"));
+  assert(length() > 0 && _head != NULL && _tail != NULL,
+         hrl_ext_msg(this, "invariant"));
+
+  // We need to unlink it first.
+  HeapRegion* hr = _head;
+  _head = hr->next();
+  if (_head == NULL) {
+    _tail = NULL;
+  }
+  hr->set_next(NULL);
+
+  // remove_internal() will verify the region.
+  remove_internal(hr);
+  return hr;
+}
+
+inline HeapRegion* HeapRegionLinkedList::remove_head_or_null() {
+  hrl_assert_mt_safety_ok(this);
+
+  if (!is_empty()) {
+    return remove_head();
+  } else {
+    return NULL;
+  }
+}
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/heapRegionSets.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/heapRegionSets.hpp"
+
+//////////////////// FreeRegionList ////////////////////
+
+const char* FreeRegionList::verify_region_extra(HeapRegion* hr) {
+  if (hr->is_young()) {
+    return "the region should not be young";
+  }
+  // The superclass will check that the region is empty and
+  // not-humongous.
+  return HeapRegionLinkedList::verify_region_extra(hr);
+}
+
+//////////////////// MasterFreeRegionList ////////////////////
+
+bool MasterFreeRegionList::check_mt_safety() {
+  // Master Free List MT safety protocol:
+  // (a) If we're at a safepoint, operations on the master free list
+  // should be invoked by either the VM thread (which will serialize
+  // them) or by the GC workers while holding the
+  // FreeList_lock.
+  // (b) If we're not at a safepoint, operations on the master free
+  // list should be invoked while holding the Heap_lock.
+
+  guarantee((SafepointSynchronize::is_at_safepoint() &&
+               (Thread::current()->is_VM_thread() ||
+                                            FreeList_lock->owned_by_self())) ||
+            (!SafepointSynchronize::is_at_safepoint() &&
+                                                Heap_lock->owned_by_self()),
+            hrl_ext_msg(this, "master free list MT safety protocol"));
+
+  return FreeRegionList::check_mt_safety();
+}
+
+//////////////////// SecondaryFreeRegionList ////////////////////
+
+bool SecondaryFreeRegionList::check_mt_safety() {
+  // Secondary Free List MT safety protocol:
+  // Operations on the secondary free list should always be invoked
+  // while holding the SecondaryFreeList_lock.
+
+  guarantee(SecondaryFreeList_lock->owned_by_self(),
+            hrl_ext_msg(this, "secondary free list MT safety protocol"));
+
+  return FreeRegionList::check_mt_safety();
+}
+
+//////////////////// HumongousRegionSet ////////////////////
+
+const char* HumongousRegionSet::verify_region_extra(HeapRegion* hr) {
+  if (hr->is_young()) {
+    return "the region should not be young";
+  }
+  // The superclass will check that the region is not empty and
+  // humongous.
+  return HeapRegionSet::verify_region_extra(hr);
+}
+
+//////////////////// HumongousRegionSet ////////////////////
+
+bool MasterHumongousRegionSet::check_mt_safety() {
+  // Master Humongous Set MT safety protocol:
+  // (a) If we're at a safepoint, operations on the master humongous
+  // set should be invoked by either the VM thread (which will
+  // serialize them) or by the GC workers while holding the
+  // OldSets_lock.
+  // (b) If we're not at a safepoint, operations on the master
+  // humongous set should be invoked while holding the Heap_lock.
+
+  guarantee((SafepointSynchronize::is_at_safepoint() &&
+               (Thread::current()->is_VM_thread() ||
+                                             OldSets_lock->owned_by_self())) ||
+            (!SafepointSynchronize::is_at_safepoint() &&
+                                                 Heap_lock->owned_by_self()),
+            hrl_ext_msg(this, "master humongous set MT safety protocol"));
+  return HumongousRegionSet::check_mt_safety();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/gc_implementation/g1/heapRegionSets.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -0,0 +1,86 @@
+/*
+ * copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
+
+#include "gc_implementation/g1/heapRegionSet.inline.hpp"
+
+//////////////////// FreeRegionList ////////////////////
+
+class FreeRegionList : public HeapRegionLinkedList {
+protected:
+  virtual const char* verify_region_extra(HeapRegion* hr);
+
+  virtual bool regions_humongous() { return false; }
+  virtual bool regions_empty()     { return true;  }
+
+public:
+  FreeRegionList(const char* name) : HeapRegionLinkedList(name) { }
+};
+
+//////////////////// MasterFreeRegionList ////////////////////
+
+class MasterFreeRegionList : public FreeRegionList {
+protected:
+  virtual bool check_mt_safety();
+
+public:
+  MasterFreeRegionList(const char* name) : FreeRegionList(name) { }
+};
+
+//////////////////// SecondaryFreeRegionList ////////////////////
+
+class SecondaryFreeRegionList : public FreeRegionList {
+protected:
+  virtual bool check_mt_safety();
+
+public:
+  SecondaryFreeRegionList(const char* name) : FreeRegionList(name) { }
+};
+
+//////////////////// HumongousRegionSet ////////////////////
+
+class HumongousRegionSet : public HeapRegionSet {
+protected:
+  virtual const char* verify_region_extra(HeapRegion* hr);
+
+  virtual bool regions_humongous() { return true;  }
+  virtual bool regions_empty()     { return false; }
+
+public:
+  HumongousRegionSet(const char* name) : HeapRegionSet(name) { }
+};
+
+//////////////////// MasterHumongousRegionSet ////////////////////
+
+class MasterHumongousRegionSet : public HumongousRegionSet {
+protected:
+  virtual bool check_mt_safety();
+
+public:
+  MasterHumongousRegionSet(const char* name) : HumongousRegionSet(name) { }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
--- a/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/ptrQueue.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,8 +38,8 @@
 # include "thread_windows.inline.hpp"
 #endif
 
-PtrQueue::PtrQueue(PtrQueueSet* qset_, bool perm, bool active) :
-  _qset(qset_), _buf(NULL), _index(0), _active(active),
+PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) :
+  _qset(qset), _buf(NULL), _index(0), _active(active),
   _perm(perm), _lock(NULL)
 {}
 
@@ -153,10 +153,16 @@
 }
 
 void PtrQueue::handle_zero_index() {
-  assert(0 == _index, "Precondition.");
+  assert(_index == 0, "Precondition.");
+
   // This thread records the full buffer and allocates a new one (while
   // holding the lock if there is one).
   if (_buf != NULL) {
+    if (!should_enqueue_buffer()) {
+      assert(_index > 0, "the buffer can only be re-used if it's not full");
+      return;
+    }
+
     if (_lock) {
       assert(_lock->owned_by_self(), "Required.");
 
--- a/src/share/vm/gc_implementation/g1/ptrQueue.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/ptrQueue.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,7 @@
 public:
   // Initialize this queue to contain a null buffer, and be part of the
   // given PtrQueueSet.
-  PtrQueue(PtrQueueSet*, bool perm = false, bool active = false);
+  PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false);
   // Release any contained resources.
   void flush();
   // Calls flush() when destroyed.
@@ -85,6 +85,14 @@
     else enqueue_known_active(ptr);
   }
 
+  // This method is called when we're doing the zero index handling
+  // and gives a chance to the queues to do any pre-enqueueing
+  // processing they might want to do on the buffer. It should return
+  // true if the buffer should be enqueued, or false if enough
+  // entries were cleared from it so that it can be re-used. It should
+  // not return false if the buffer is still full (otherwise we can
+  // get into an infinite loop).
+  virtual bool should_enqueue_buffer() { return true; }
   void handle_zero_index();
   void locking_enqueue_completed_buffer(void** buf);
 
--- a/src/share/vm/gc_implementation/g1/satbQueue.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/satbQueue.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,12 +23,98 @@
  */
 
 #include "precompiled.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/satbQueue.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/sharedHeap.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/thread.hpp"
 
+// This method removes entries from an SATB buffer that will not be
+// useful to the concurrent marking threads. An entry is removed if it
+// satisfies one of the following conditions:
+//
+// * it points to an object outside the G1 heap (G1's concurrent
+//     marking only visits objects inside the G1 heap),
+// * it points to an object that has been allocated since marking
+//     started (according to SATB those objects do not need to be
+//     visited during marking), or
+// * it points to an object that has already been marked (no need to
+//     process it again).
+//
+// The rest of the entries will be retained and are compacted towards
+// the top of the buffer. If with this filtering we clear a large
+// enough chunk of the buffer we can re-use it (instead of enqueueing
+// it) and we can just allow the mutator to carry on executing.
+
+bool ObjPtrQueue::should_enqueue_buffer() {
+  assert(_lock == NULL || _lock->owned_by_self(),
+         "we should have taken the lock before calling this");
+
+  // A value of 0 means "don't filter SATB buffers".
+  if (G1SATBBufferEnqueueingThresholdPercent == 0) {
+    return true;
+  }
+
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+  // This method should only be called if there is a non-NULL buffer
+  // that is full.
+  assert(_index == 0, "pre-condition");
+  assert(_buf != NULL, "pre-condition");
+
+  void** buf = _buf;
+  size_t sz = _sz;
+
+  // Used for sanity checking at the end of the loop.
+  debug_only(size_t entries = 0; size_t retained = 0;)
+
+  size_t i = sz;
+  size_t new_index = sz;
+
+  // Given that we are expecting _index == 0, we could have changed
+  // the loop condition to (i > 0). But we are using _index for
+  // generality.
+  while (i > _index) {
+    assert(i > 0, "we should have at least one more entry to process");
+    i -= oopSize;
+    debug_only(entries += 1;)
+    oop* p = (oop*) &buf[byte_index_to_index((int) i)];
+    oop obj = *p;
+    // NULL the entry so that unused parts of the buffer contain NULLs
+    // at the end. If we are going to retain it we will copy it to its
+    // final place. If we have retained all entries we have visited so
+    // far, we'll just end up copying it to the same place.
+    *p = NULL;
+
+    bool retain = g1h->is_obj_ill(obj);
+    if (retain) {
+      assert(new_index > 0, "we should not have already filled up the buffer");
+      new_index -= oopSize;
+      assert(new_index >= i,
+             "new_index should never be below i, as we alwaysr compact 'up'");
+      oop* new_p = (oop*) &buf[byte_index_to_index((int) new_index)];
+      assert(new_p >= p, "the destination location should never be below "
+             "the source as we always compact 'up'");
+      assert(*new_p == NULL,
+             "we should have already cleared the destination location");
+      *new_p = obj;
+      debug_only(retained += 1;)
+    }
+  }
+  size_t entries_calc = (sz - _index) / oopSize;
+  assert(entries == entries_calc, "the number of entries we counted "
+         "should match the number of entries we calculated");
+  size_t retained_calc = (sz - new_index) / oopSize;
+  assert(retained == retained_calc, "the number of retained entries we counted "
+         "should match the number of retained entries we calculated");
+  size_t perc = retained_calc * 100 / entries_calc;
+  bool should_enqueue = perc > (size_t) G1SATBBufferEnqueueingThresholdPercent;
+  _index = new_index;
+
+  return should_enqueue;
+}
+
 void ObjPtrQueue::apply_closure(ObjectClosure* cl) {
   if (_buf != NULL) {
     apply_closure_to_buffer(cl, _buf, _index, _sz);
--- a/src/share/vm/gc_implementation/g1/satbQueue.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/satbQueue.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,13 +33,18 @@
 // A ptrQueue whose elements are "oops", pointers to object heads.
 class ObjPtrQueue: public PtrQueue {
 public:
-  ObjPtrQueue(PtrQueueSet* qset_, bool perm = false) :
+  ObjPtrQueue(PtrQueueSet* qset, bool perm = false) :
     // SATB queues are only active during marking cycles. We create
     // them with their active field set to false. If a thread is
     // created during a cycle and its SATB queue needs to be activated
     // before the thread starts running, we'll need to set its active
     // field to true. This is done in JavaThread::initialize_queues().
-    PtrQueue(qset_, perm, false /* active */) { }
+    PtrQueue(qset, perm, false /* active */) { }
+
+  // Overrides PtrQueue::should_enqueue_buffer(). See the method's
+  // definition for more information.
+  virtual bool should_enqueue_buffer();
+
   // Apply the closure to all elements, and reset the index to make the
   // buffer empty.
   void apply_closure(ObjectClosure* cl);
--- a/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -415,6 +415,38 @@
   return NULL;
 }
 
+void SparsePRT::reset_for_cleanup_tasks() {
+  _head_expanded_list = NULL;
+}
+
+void SparsePRT::do_cleanup_work(SparsePRTCleanupTask* sprt_cleanup_task) {
+  if (should_be_on_expanded_list()) {
+    sprt_cleanup_task->add(this);
+  }
+}
+
+void SparsePRT::finish_cleanup_task(SparsePRTCleanupTask* sprt_cleanup_task) {
+  assert(ParGCRareEvent_lock->owned_by_self(), "pre-condition");
+  SparsePRT* head = sprt_cleanup_task->head();
+  SparsePRT* tail = sprt_cleanup_task->tail();
+  if (head != NULL) {
+    assert(tail != NULL, "if head is not NULL, so should tail");
+
+    tail->set_next_expanded(_head_expanded_list);
+    _head_expanded_list = head;
+  } else {
+    assert(tail == NULL, "if head is NULL, so should tail");
+  }
+}
+
+bool SparsePRT::should_be_on_expanded_list() {
+  if (_expanded) {
+    assert(_cur != _next, "if _expanded is true, cur should be != _next");
+  } else {
+    assert(_cur == _next, "if _expanded is false, cur should be == _next");
+  }
+  return expanded();
+}
 
 void SparsePRT::cleanup_all() {
   // First clean up all expanded tables so they agree on next and cur.
@@ -484,6 +516,7 @@
     _cur->clear();
   }
   _next = _cur;
+  _expanded = false;
 }
 
 void SparsePRT::cleanup() {
@@ -518,3 +551,15 @@
   }
   add_to_expanded_list(this);
 }
+
+void SparsePRTCleanupTask::add(SparsePRT* sprt) {
+  assert(sprt->should_be_on_expanded_list(), "pre-condition");
+
+  sprt->set_next_expanded(NULL);
+  if (_tail != NULL) {
+    _tail->set_next_expanded(sprt);
+  } else {
+    _head = sprt;
+  }
+  _tail = sprt;
+}
--- a/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -212,8 +212,11 @@
 // mutex.
 
 class SparsePRTIter;
+class SparsePRTCleanupTask;
 
 class SparsePRT VALUE_OBJ_CLASS_SPEC {
+  friend class SparsePRTCleanupTask;
+
   //  Iterations are done on the _cur hash table, since they only need to
   //  see entries visible at the start of a collection pause.
   //  All other operations are done using the _next hash table.
@@ -238,6 +241,8 @@
   SparsePRT* next_expanded() { return _next_expanded; }
   void set_next_expanded(SparsePRT* nxt) { _next_expanded = nxt; }
 
+  bool should_be_on_expanded_list();
+
   static SparsePRT* _head_expanded_list;
 
 public:
@@ -284,12 +289,36 @@
   static void add_to_expanded_list(SparsePRT* sprt);
   static SparsePRT* get_from_expanded_list();
 
+  // The purpose of these three methods is to help the GC workers
+  // during the cleanup pause to recreate the expanded list, purging
+  // any tables from it that belong to regions that are freed during
+  // cleanup (if we don't purge those tables, there is a race that
+  // causes various crashes; see CR 7014261).
+  //
+  // We chose to recreate the expanded list, instead of purging
+  // entries from it by iterating over it, to avoid this serial phase
+  // at the end of the cleanup pause.
+  //
+  // The three methods below work as follows:
+  // * reset_for_cleanup_tasks() : Nulls the expanded list head at the
+  //   start of the cleanup pause.
+  // * do_cleanup_work() : Called by the cleanup workers for every
+  //   region that is not free / is being freed by the cleanup
+  //   pause. It creates a list of expanded tables whose head / tail
+  //   are on the thread-local SparsePRTCleanupTask object.
+  // * finish_cleanup_task() : Called by the cleanup workers after
+  //   they complete their cleanup task. It adds the local list into
+  //   the global expanded list. It assumes that the
+  //   ParGCRareEvent_lock is being held to ensure MT-safety.
+  static void reset_for_cleanup_tasks();
+  void do_cleanup_work(SparsePRTCleanupTask* sprt_cleanup_task);
+  static void finish_cleanup_task(SparsePRTCleanupTask* sprt_cleanup_task);
+
   bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const {
     return _next->contains_card(region_id, card_index);
   }
 };
 
-
 class SparsePRTIter: public RSHashTableIter {
 public:
   void init(const SparsePRT* sprt) {
@@ -300,4 +329,22 @@
   }
 };
 
+// This allows each worker during a cleanup pause to create a
+// thread-local list of sparse tables that have been expanded and need
+// to be processed at the beginning of the next GC pause. This lists
+// are concatenated into the single expanded list at the end of the
+// cleanup pause.
+class SparsePRTCleanupTask VALUE_OBJ_CLASS_SPEC {
+private:
+  SparsePRT* _head;
+  SparsePRT* _tail;
+
+public:
+  SparsePRTCleanupTask() : _head(NULL), _tail(NULL) { }
+
+  void add(SparsePRT* sprt);
+  SparsePRT* head() { return _head; }
+  SparsePRT* tail() { return _tail; }
+};
+
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_SPARSEPRT_HPP
--- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -38,7 +38,6 @@
 }
 
 void VM_G1CollectForAllocation::doit() {
-  JvmtiGCForAllocationMarker jgcm;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   _result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded);
   assert(_result == NULL || _pause_succeeded,
@@ -46,7 +45,6 @@
 }
 
 void VM_G1CollectFull::doit() {
-  JvmtiGCFullMarker jgcm;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   GCCauseSetter x(g1h, _gc_cause);
   g1h->do_full_collection(false /* clear_all_soft_refs */);
@@ -72,7 +70,6 @@
 }
 
 void VM_G1IncCollectionPause::doit() {
-  JvmtiGCForAllocationMarker jgcm;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   assert(!_should_initiate_conc_mark ||
   ((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
--- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -116,10 +116,6 @@
       SystemDictionary::always_strong_oops_do(&mark_and_push_closure);
       break;
 
-    case vm_symbols:
-      vmSymbols::oops_do(&mark_and_push_closure);
-      break;
-
     case code_cache:
       // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
       //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure));
--- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -98,9 +98,8 @@
     management            = 6,
     jvmti                 = 7,
     system_dictionary     = 8,
-    vm_symbols            = 9,
-    reference_processing  = 10,
-    code_cache            = 11
+    reference_processing  = 9,
+    code_cache            = 10
   };
  private:
   RootType _root_type;
--- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -258,6 +258,7 @@
     BiasedLocking::restore_marks();
     Threads::gc_epilogue();
     CodeCache::gc_epilogue();
+    JvmtiExport::gc_epilogue();
 
     COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
 
@@ -526,7 +527,6 @@
     Management::oops_do(mark_and_push_closure());
     JvmtiExport::oops_do(mark_and_push_closure());
     SystemDictionary::always_strong_oops_do(mark_and_push_closure());
-    vmSymbols::oops_do(mark_and_push_closure());
     // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
     //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
   }
@@ -557,9 +557,10 @@
   follow_mdo_weak_refs();
   assert(_marking_stack.is_empty(), "just drained");
 
-  // Visit symbol and interned string tables and delete unmarked oops
-  SymbolTable::unlink(is_alive_closure());
+  // Visit interned string tables and delete unmarked oops
   StringTable::unlink(is_alive_closure());
+  // Clean up unreferenced symbols in symbol table.
+  SymbolTable::unlink();
 
   assert(_marking_stack.is_empty(), "stack should be empty by now");
 }
@@ -633,7 +634,6 @@
   JvmtiExport::oops_do(adjust_root_pointer_closure());
   // SO_AllClasses
   SystemDictionary::oops_do(adjust_root_pointer_closure());
-  vmSymbols::oops_do(adjust_root_pointer_closure());
   //CodeCache::scavenge_root_nmethods_oops_do(adjust_root_pointer_closure());
 
   // Now adjust pointers in remaining weak roots.  (All of which should
@@ -642,7 +642,6 @@
   JNIHandles::weak_oops_do(&always_true, adjust_root_pointer_closure());
 
   CodeCache::oops_do(adjust_pointer_closure());
-  SymbolTable::oops_do(adjust_root_pointer_closure());
   StringTable::oops_do(adjust_root_pointer_closure());
   ref_processor()->weak_oops_do(adjust_root_pointer_closure());
   PSScavenge::reference_processor()->weak_oops_do(adjust_root_pointer_closure());
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1054,6 +1054,7 @@
 
   Threads::gc_epilogue();
   CodeCache::gc_epilogue();
+  JvmtiExport::gc_epilogue();
 
   COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
 
@@ -2374,7 +2375,6 @@
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::management));
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::system_dictionary));
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmti));
-    q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::vm_symbols));
     q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::code_cache));
 
     if (parallel_gc_threads > 1) {
@@ -2424,9 +2424,10 @@
   // Revisit memoized MDO's and clear any unmarked weak refs
   follow_mdo_weak_refs();
 
-  // Visit symbol and interned string tables and delete unmarked oops
-  SymbolTable::unlink(is_alive_closure());
+  // Visit interned string tables and delete unmarked oops
   StringTable::unlink(is_alive_closure());
+  // Clean up unreferenced symbols in symbol table.
+  SymbolTable::unlink();
 
   assert(cm->marking_stacks_empty(), "marking stacks should be empty");
 }
@@ -2455,7 +2456,6 @@
   JvmtiExport::oops_do(adjust_root_pointer_closure());
   // SO_AllClasses
   SystemDictionary::oops_do(adjust_root_pointer_closure());
-  vmSymbols::oops_do(adjust_root_pointer_closure());
 
   // Now adjust pointers in remaining weak roots.  (All of which should
   // have been cleared if they pointed to non-surviving objects.)
@@ -2463,7 +2463,6 @@
   JNIHandles::weak_oops_do(&always_true, adjust_root_pointer_closure());
 
   CodeCache::oops_do(adjust_pointer_closure());
-  SymbolTable::oops_do(adjust_root_pointer_closure());
   StringTable::oops_do(adjust_root_pointer_closure());
   ref_processor()->weak_oops_do(adjust_root_pointer_closure());
   // Roots were visited so references into the young gen in roots
--- a/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -42,8 +42,7 @@
 }
 
 void VM_ParallelGCFailedAllocation::doit() {
-  JvmtiGCForAllocationMarker jgcm;
-  notify_gc_begin(false);
+  SvcGCMarker sgcm(SvcGCMarker::MINOR);
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
   assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "must be a ParallelScavengeHeap");
@@ -54,8 +53,6 @@
   if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
     set_gc_locked();
   }
-
-  notify_gc_end();
 }
 
 VM_ParallelGCFailedPermanentAllocation::VM_ParallelGCFailedPermanentAllocation(size_t size,
@@ -67,8 +64,7 @@
 }
 
 void VM_ParallelGCFailedPermanentAllocation::doit() {
-  JvmtiGCFullMarker jgcm;
-  notify_gc_begin(true);
+  SvcGCMarker sgcm(SvcGCMarker::FULL);
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
   assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "must be a ParallelScavengeHeap");
@@ -78,7 +74,6 @@
   if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
     set_gc_locked();
   }
-  notify_gc_end();
 }
 
 // Only used for System.gc() calls
@@ -91,8 +86,7 @@
 }
 
 void VM_ParallelGCSystemGC::doit() {
-  JvmtiGCFullMarker jgcm;
-  notify_gc_begin(true);
+  SvcGCMarker sgcm(SvcGCMarker::FULL);
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
   assert(heap->kind() == CollectedHeap::ParallelScavengeHeap,
@@ -106,5 +100,4 @@
   } else {
     heap->invoke_full_gc(false);
   }
-  notify_gc_end();
 }
--- a/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -187,7 +187,7 @@
 
 SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
   klassOop k =
-    SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(),
+    SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
                                       true, CHECK_NULL);
   instanceKlassHandle klass (THREAD, k);
   instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
@@ -200,8 +200,8 @@
   JavaValue result(T_VOID);
   JavaCalls::call_special(&result, thread_oop,
                           klass,
-                          vmSymbolHandles::object_initializer_name(),
-                          vmSymbolHandles::threadgroup_string_void_signature(),
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::threadgroup_string_void_signature(),
                           thread_group,
                           string,
                           CHECK_NULL);
--- a/src/share/vm/gc_implementation/shared/markSweep.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/shared/markSweep.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -111,7 +111,7 @@
 
 MarkSweep::MarkAndPushClosure MarkSweep::mark_and_push_closure;
 
-void MarkSweep::MarkAndPushClosure::do_oop(oop* p)       { mark_and_push(p); }
+void MarkSweep::MarkAndPushClosure::do_oop(oop* p)       { assert(*p == NULL || (*p)->is_oop(), ""); mark_and_push(p); }
 void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(p); }
 
 void MarkSweep::follow_stack() {
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,7 +31,6 @@
 #include "memory/oopFactory.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/instanceRefKlass.hpp"
-#include "prims/jvmtiExport.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/init.hpp"
 #include "runtime/interfaceSupport.hpp"
@@ -40,6 +39,7 @@
 #ifndef SERIALGC
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #endif
+
 HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool);
 HS_DTRACE_PROBE_DECL(hotspot, gc__end);
 
@@ -158,8 +158,7 @@
 
 
 void VM_GenCollectForAllocation::doit() {
-  JvmtiGCForAllocationMarker jgcm;
-  notify_gc_begin(false);
+  SvcGCMarker sgcm(SvcGCMarker::MINOR);
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   GCCauseSetter gccs(gch, _gc_cause);
@@ -169,22 +168,19 @@
   if (_res == NULL && GC_locker::is_active_and_needs_gc()) {
     set_gc_locked();
   }
-  notify_gc_end();
 }
 
 void VM_GenCollectFull::doit() {
-  JvmtiGCFullMarker jgcm;
-  notify_gc_begin(true);
+  SvcGCMarker sgcm(SvcGCMarker::FULL);
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   GCCauseSetter gccs(gch, _gc_cause);
   gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
-  notify_gc_end();
 }
 
 void VM_GenCollectForPermanentAllocation::doit() {
-  JvmtiGCForAllocationMarker jgcm;
-  notify_gc_begin(true);
+  SvcGCMarker sgcm(SvcGCMarker::FULL);
+
   SharedHeap* heap = (SharedHeap*)Universe::heap();
   GCCauseSetter gccs(heap, _gc_cause);
   switch (heap->kind()) {
@@ -209,5 +205,4 @@
   if (_res == NULL && GC_locker::is_active_and_needs_gc()) {
     set_gc_locked();
   }
-  notify_gc_end();
 }
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -30,6 +30,7 @@
 #include "runtime/jniHandles.hpp"
 #include "runtime/synchronizer.hpp"
 #include "runtime/vm_operations.hpp"
+#include "prims/jvmtiExport.hpp"
 
 // The following class hierarchy represents
 // a set of operations (VM_Operation) related to GC.
@@ -209,13 +210,17 @@
   HeapWord* result() const       { return _res; }
 };
 
-class DTraceGCProbeMarker : public StackObj {
-public:
-  DTraceGCProbeMarker(bool full) {
-    VM_GC_Operation::notify_gc_begin(full);
+class SvcGCMarker : public StackObj {
+ private:
+  JvmtiGCMarker _jgcm;
+ public:
+  typedef enum { MINOR, FULL, OTHER } reason_type;
+
+  SvcGCMarker(reason_type reason ) {
+    VM_GC_Operation::notify_gc_begin(reason == FULL);
   }
 
-  ~DTraceGCProbeMarker() {
+  ~SvcGCMarker() {
     VM_GC_Operation::notify_gc_end();
   }
 };
--- a/src/share/vm/interpreter/bytecode.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/bytecode.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,30 +34,6 @@
 
 // Implementation of Bytecode
 
-bool Bytecode::check_must_rewrite(Bytecodes::Code code) const {
-  assert(Bytecodes::can_rewrite(code), "post-check only");
-
-  // Some codes are conditionally rewriting.  Look closely at them.
-  switch (code) {
-  case Bytecodes::_aload_0:
-    // Even if RewriteFrequentPairs is turned on,
-    // the _aload_0 code might delay its rewrite until
-    // a following _getfield rewrites itself.
-    return false;
-
-  case Bytecodes::_lookupswitch:
-    return false;  // the rewrite is not done by the interpreter
-
-  case Bytecodes::_new:
-    // (Could actually look at the class here, but the profit would be small.)
-    return false;  // the rewrite is not always done
-  }
-
-  // No other special cases.
-  return true;
-}
-
-
 #ifdef ASSERT
 
 void Bytecode::assert_same_format_as(Bytecodes::Code testbc, bool is_wide) const {
@@ -148,21 +124,20 @@
 }
 
 
-symbolOop Bytecode_member_ref::signature() const {
+Symbol* Bytecode_member_ref::signature() const {
   constantPoolOop constants = method()->constants();
   return constants->signature_ref_at(index());
 }
 
 
-symbolOop Bytecode_member_ref::name() const {
+Symbol* Bytecode_member_ref::name() const {
   constantPoolOop constants = method()->constants();
   return constants->name_ref_at(index());
 }
 
 
-BasicType Bytecode_member_ref::result_type(Thread *thread) const {
-  symbolHandle sh(thread, signature());
-  ResultTypeFinder rts(sh);
+BasicType Bytecode_member_ref::result_type() const {
+  ResultTypeFinder rts(signature());
   rts.iterate();
   return rts.type();
 }
@@ -188,17 +163,16 @@
   // Note:  Rewriter::rewrite changes the Java_u2 of an invokedynamic to a native_u4,
   // at the same time it allocates per-call-site CP cache entries.
   Bytecodes::Code rawc = code();
-  Bytecode* invoke = bytecode();
-  if (invoke->has_index_u4(rawc))
-    return invoke->get_index_u4(rawc);
+  if (has_index_u4(rawc))
+    return get_index_u4(rawc);
   else
-    return invoke->get_index_u2_cpcache(rawc);
+    return get_index_u2_cpcache(rawc);
 }
 
 int Bytecode_member_ref::pool_index() const {
   int index = this->index();
   DEBUG_ONLY({
-      if (!bytecode()->has_index_u4(code()))
+      if (!has_index_u4(code()))
         index -= constantPoolOopDesc::CPCACHE_INDEX_TAG;
     });
   return _method->constants()->cache()->entry_at(index)->constant_pool_index();
@@ -214,13 +188,12 @@
 // Implementation of Bytecode_loadconstant
 
 int Bytecode_loadconstant::raw_index() const {
-  Bytecode* bcp = bytecode();
-  Bytecodes::Code rawc = bcp->code();
+  Bytecodes::Code rawc = code();
   assert(rawc != Bytecodes::_wide, "verifier prevents this");
   if (Bytecodes::java_code(rawc) == Bytecodes::_ldc)
-    return bcp->get_index_u1(rawc);
+    return get_index_u1(rawc);
   else
-    return bcp->get_index_u2(rawc, false);
+    return get_index_u2(rawc, false);
 }
 
 int Bytecode_loadconstant::pool_index() const {
@@ -258,7 +231,7 @@
     case Bytecodes::_lookupswitch:
       { int i = number_of_pairs() - 1;
         while (i-- > 0) {
-          assert(pair_at(i)->match() < pair_at(i+1)->match(), "unsorted table entries");
+          assert(pair_at(i).match() < pair_at(i+1).match(), "unsorted table entries");
         }
       }
       break;
--- a/src/share/vm/interpreter/bytecode.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/bytecode.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,14 +38,20 @@
 # include "bytes_zero.hpp"
 #endif
 
-// Base class for different kinds of abstractions working
-// relative to an objects 'this' pointer.
+class ciBytecodeStream;
+
+// The base class for different kinds of bytecode abstractions.
+// Provides the primitive operations to manipulate code relative
+// to the bcp.
 
-class ThisRelativeObj VALUE_OBJ_CLASS_SPEC {
- public:
+class Bytecode: public StackObj {
+ protected:
+  const address   _bcp;
+  const Bytecodes::Code _code;
+
   // Address computation
-  address addr_at            (int offset)        const     { return (address)this + offset; }
-  int     byte_at            (int offset)        const     { return *(addr_at(offset)); }
+  address addr_at            (int offset)        const     { return (address)_bcp + offset; }
+  u_char byte_at(int offset) const               { return *addr_at(offset); }
   address aligned_addr_at    (int offset)        const     { return (address)round_to((intptr_t)addr_at(offset), jintSize); }
   int     aligned_offset     (int offset)        const     { return aligned_addr_at(offset) - addr_at(0); }
 
@@ -54,31 +60,20 @@
   int     get_Java_u4_at     (int offset)        const     { return Bytes::get_Java_u4(addr_at(offset)); }
   int     get_native_u2_at   (int offset)        const     { return Bytes::get_native_u2(addr_at(offset)); }
   int     get_native_u4_at   (int offset)        const     { return Bytes::get_native_u4(addr_at(offset)); }
-};
-
-
-// The base class for different kinds of bytecode abstractions.
-// Provides the primitive operations to manipulate code relative
-// to an objects 'this' pointer.
-// FIXME: Make this a ResourceObj, include the enclosing methodOop, and cache the opcode.
-
-class Bytecode: public ThisRelativeObj {
- protected:
-  u_char byte_at(int offset) const               { return *addr_at(offset); }
-  bool check_must_rewrite(Bytecodes::Code bc) const;
 
  public:
-  // Attributes
-  address bcp() const                            { return addr_at(0); }
-  int instruction_size() const                   { return Bytecodes::length_at(bcp()); }
+  Bytecode(methodOop method, address bcp): _bcp(bcp), _code(Bytecodes::code_at(method, addr_at(0))) {
+    assert(method != NULL, "this form requires a valid methodOop");
+  }
+  // Defined in ciStreams.hpp
+  inline Bytecode(const ciBytecodeStream* stream, address bcp = NULL);
 
-  // Warning: Use code() with caution on live bytecode streams.  4926272
-  Bytecodes::Code code() const                   { return Bytecodes::code_at(addr_at(0)); }
+  // Attributes
+  address bcp() const                            { return _bcp; }
+  int instruction_size() const                   { return Bytecodes::length_for_code_at(_code, bcp()); }
+
+  Bytecodes::Code code() const                   { return _code; }
   Bytecodes::Code java_code() const              { return Bytecodes::java_code(code()); }
-  bool must_rewrite(Bytecodes::Code code) const  { return Bytecodes::can_rewrite(code) && check_must_rewrite(code); }
-
-  // Creation
-  inline friend Bytecode* Bytecode_at(address bcp);
 
   // Static functions for parsing bytecodes in place.
   int get_index_u1(Bytecodes::Code bc) const {
@@ -89,7 +84,7 @@
     assert_same_format_as(bc, is_wide); assert_index_size(2, bc, is_wide);
     address p = addr_at(is_wide ? 2 : 1);
     if (can_use_native_byte_order(bc, is_wide))
-          return Bytes::get_native_u2(p);
+      return Bytes::get_native_u2(p);
     else  return Bytes::get_Java_u2(p);
   }
   int get_index_u1_cpcache(Bytecodes::Code bc) const {
@@ -138,20 +133,17 @@
   }
 };
 
-inline Bytecode* Bytecode_at(address bcp) {
-  // Warning: Use with caution on live bytecode streams.  4926272
-  return (Bytecode*)bcp;
-}
-
 
 // Abstractions for lookupswitch bytecode
-
-class LookupswitchPair: ThisRelativeObj {
+class LookupswitchPair VALUE_OBJ_CLASS_SPEC {
  private:
-  int  _match;
-  int  _offset;
+  const address _bcp;
+
+  address addr_at            (int offset)        const     { return _bcp + offset; }
+  int     get_Java_u4_at     (int offset)        const     { return Bytes::get_Java_u4(addr_at(offset)); }
 
  public:
+  LookupswitchPair(address bcp): _bcp(bcp) {}
   int  match() const                             { return get_Java_u4_at(0 * jintSize); }
   int  offset() const                            { return get_Java_u4_at(1 * jintSize); }
 };
@@ -159,26 +151,25 @@
 
 class Bytecode_lookupswitch: public Bytecode {
  public:
+  Bytecode_lookupswitch(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
+  // Defined in ciStreams.hpp
+  inline Bytecode_lookupswitch(const ciBytecodeStream* stream);
   void verify() const PRODUCT_RETURN;
 
   // Attributes
   int  default_offset() const                    { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
   int  number_of_pairs() const                   { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
-  LookupswitchPair* pair_at(int i) const         { assert(0 <= i && i < number_of_pairs(), "pair index out of bounds");
-                                                   return (LookupswitchPair*)aligned_addr_at(1 + (1 + i)*2*jintSize); }
-  // Creation
-  inline friend Bytecode_lookupswitch* Bytecode_lookupswitch_at(address bcp);
+  LookupswitchPair pair_at(int i) const          {
+    assert(0 <= i && i < number_of_pairs(), "pair index out of bounds");
+    return LookupswitchPair(aligned_addr_at(1 + (1 + i)*2*jintSize));
+  }
 };
 
-inline Bytecode_lookupswitch* Bytecode_lookupswitch_at(address bcp) {
-  Bytecode_lookupswitch* b = (Bytecode_lookupswitch*)bcp;
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
-
 class Bytecode_tableswitch: public Bytecode {
  public:
+  Bytecode_tableswitch(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
+  // Defined in ciStreams.hpp
+  inline Bytecode_tableswitch(const ciBytecodeStream* stream);
   void verify() const PRODUCT_RETURN;
 
   // Attributes
@@ -187,52 +178,36 @@
   int  high_key() const                          { return get_Java_u4_at(aligned_offset(1 + 2*jintSize)); }
   int  dest_offset_at(int i) const;
   int  length()                                  { return high_key()-low_key()+1; }
-
-  // Creation
-  inline friend Bytecode_tableswitch* Bytecode_tableswitch_at(address bcp);
 };
 
-inline Bytecode_tableswitch* Bytecode_tableswitch_at(address bcp) {
-  Bytecode_tableswitch* b = (Bytecode_tableswitch*)bcp;
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
-
 // Common code for decoding invokes and field references.
 
-class Bytecode_member_ref: public ResourceObj {
+class Bytecode_member_ref: public Bytecode {
  protected:
-  methodHandle _method;                          // method containing the bytecode
-  int          _bci;                             // position of the bytecode
+  const methodHandle _method;                          // method containing the bytecode
 
-  Bytecode_member_ref(methodHandle method, int bci)  : _method(method), _bci(bci) {}
+  Bytecode_member_ref(methodHandle method, int bci)  : Bytecode(method(), method()->bcp_from(bci)), _method(method) {}
+
+  methodHandle method() const                    { return _method; }
 
  public:
-  // Attributes
-  methodHandle method() const                    { return _method; }
-  int          bci() const                       { return _bci; }
-  address      bcp() const                       { return _method->bcp_from(bci()); }
-  Bytecode*    bytecode() const                  { return Bytecode_at(bcp()); }
-
   int          index() const;                    // cache index (loaded from instruction)
   int          pool_index() const;               // constant pool index
-  symbolOop    name() const;                     // returns the name of the method or field
-  symbolOop    signature() const;                // returns the signature of the method or field
+  Symbol*      name() const;                     // returns the name of the method or field
+  Symbol*      signature() const;                // returns the signature of the method or field
 
-  BasicType    result_type(Thread* thread) const; // returns the result type of the getfield or invoke
-
-  Bytecodes::Code code() const                   { return Bytecodes::code_at(bcp(), _method()); }
-  Bytecodes::Code java_code() const              { return Bytecodes::java_code(code()); }
+  BasicType    result_type() const;              // returns the result type of the getfield or invoke
 };
 
 // Abstraction for invoke_{virtual, static, interface, special}
 
 class Bytecode_invoke: public Bytecode_member_ref {
  protected:
-  Bytecode_invoke(methodHandle method, int bci)  : Bytecode_member_ref(method, bci) {}
+  // Constructor that skips verification
+  Bytecode_invoke(methodHandle method, int bci, bool unused)  : Bytecode_member_ref(method, bci) {}
 
  public:
+  Bytecode_invoke(methodHandle method, int bci)  : Bytecode_member_ref(method, bci) { verify(); }
   void verify() const;
 
   // Attributes
@@ -253,31 +228,20 @@
                                                           is_invokespecial()   ||
                                                           is_invokedynamic(); }
 
-  // Creation
-  inline friend Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci);
-
-  // Like Bytecode_invoke_at. Instead it returns NULL if the bci is not at an invoke.
-  inline friend Bytecode_invoke* Bytecode_invoke_at_check(methodHandle method, int bci);
+  // Helper to skip verification.   Used is_valid() to check if the result is really an invoke
+  inline friend Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci);
 };
 
-inline Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci) {
-  Bytecode_invoke* b = new Bytecode_invoke(method, bci);
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
-inline Bytecode_invoke* Bytecode_invoke_at_check(methodHandle method, int bci) {
-  Bytecode_invoke* b = new Bytecode_invoke(method, bci);
-  return b->is_valid() ? b : NULL;
+inline Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci) {
+  return Bytecode_invoke(method, bci, false);
 }
 
 
 // Abstraction for all field accesses (put/get field/static)
 class Bytecode_field: public Bytecode_member_ref {
- protected:
-  Bytecode_field(methodHandle method, int bci)  : Bytecode_member_ref(method, bci) {}
+ public:
+  Bytecode_field(methodHandle method, int bci)  : Bytecode_member_ref(method, bci) { verify(); }
 
- public:
   // Testers
   bool is_getfield() const                       { return java_code() == Bytecodes::_getfield; }
   bool is_putfield() const                       { return java_code() == Bytecodes::_putfield; }
@@ -292,131 +256,64 @@
                                                           is_getstatic()  ||
                                                           is_putstatic(); }
   void verify() const;
-
-  // Creation
-  inline friend Bytecode_field* Bytecode_field_at(methodHandle method, int bci);
 };
 
-inline Bytecode_field* Bytecode_field_at(methodHandle method, int bci) {
-  Bytecode_field* b = new Bytecode_field(method, bci);
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
-
 // Abstraction for checkcast
-
 class Bytecode_checkcast: public Bytecode {
  public:
+  Bytecode_checkcast(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
   void verify() const { assert(Bytecodes::java_code(code()) == Bytecodes::_checkcast, "check checkcast"); }
 
   // Returns index
   long index() const   { return get_index_u2(Bytecodes::_checkcast); };
-
-  // Creation
-  inline friend Bytecode_checkcast* Bytecode_checkcast_at(address bcp);
 };
 
-inline Bytecode_checkcast* Bytecode_checkcast_at(address bcp) {
-  Bytecode_checkcast* b = (Bytecode_checkcast*)bcp;
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
-
 // Abstraction for instanceof
-
 class Bytecode_instanceof: public Bytecode {
  public:
+  Bytecode_instanceof(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
   void verify() const { assert(code() == Bytecodes::_instanceof, "check instanceof"); }
 
   // Returns index
   long index() const   { return get_index_u2(Bytecodes::_instanceof); };
-
-  // Creation
-  inline friend Bytecode_instanceof* Bytecode_instanceof_at(address bcp);
 };
 
-inline Bytecode_instanceof* Bytecode_instanceof_at(address bcp) {
-  Bytecode_instanceof* b = (Bytecode_instanceof*)bcp;
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
-
 class Bytecode_new: public Bytecode {
  public:
+  Bytecode_new(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
   void verify() const { assert(java_code() == Bytecodes::_new, "check new"); }
 
   // Returns index
   long index() const   { return get_index_u2(Bytecodes::_new); };
-
-  // Creation
-  inline friend Bytecode_new* Bytecode_new_at(address bcp);
 };
 
-inline Bytecode_new* Bytecode_new_at(address bcp) {
-  Bytecode_new* b = (Bytecode_new*)bcp;
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
-
 class Bytecode_multianewarray: public Bytecode {
  public:
+  Bytecode_multianewarray(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
   void verify() const { assert(java_code() == Bytecodes::_multianewarray, "check new"); }
 
   // Returns index
   long index() const   { return get_index_u2(Bytecodes::_multianewarray); };
-
-  // Creation
-  inline friend Bytecode_multianewarray* Bytecode_multianewarray_at(address bcp);
 };
 
-inline Bytecode_multianewarray* Bytecode_multianewarray_at(address bcp) {
-  Bytecode_multianewarray* b = (Bytecode_multianewarray*)bcp;
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
-
 class Bytecode_anewarray: public Bytecode {
  public:
+  Bytecode_anewarray(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
   void verify() const { assert(java_code() == Bytecodes::_anewarray, "check anewarray"); }
 
   // Returns index
   long index() const   { return get_index_u2(Bytecodes::_anewarray); };
-
-  // Creation
-  inline friend Bytecode_anewarray* Bytecode_anewarray_at(address bcp);
 };
 
-inline Bytecode_anewarray* Bytecode_anewarray_at(address bcp) {
-  Bytecode_anewarray* b = (Bytecode_anewarray*)bcp;
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
-
 // Abstraction for ldc, ldc_w and ldc2_w
-
-class Bytecode_loadconstant: public ResourceObj {
+class Bytecode_loadconstant: public Bytecode {
  private:
-  int          _bci;
-  methodHandle _method;
-
-  Bytecodes::Code code() const                   { return bytecode()->code(); }
+  const methodHandle _method;
 
   int raw_index() const;
 
-  Bytecode_loadconstant(methodHandle method, int bci) : _method(method), _bci(bci) {}
-
  public:
-  // Attributes
-  methodHandle method() const                    { return _method; }
-  int          bci() const                       { return _bci; }
-  address      bcp() const                       { return _method->bcp_from(bci()); }
-  Bytecode*    bytecode() const                  { return Bytecode_at(bcp()); }
+  Bytecode_loadconstant(methodHandle method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method) { verify(); }
 
   void verify() const {
     assert(_method.not_null(), "must supply method");
@@ -437,15 +334,6 @@
   BasicType result_type() const;        // returns the result type of the ldc
 
   oop resolve_constant(TRAPS) const;
-
-  // Creation
-  inline friend Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci);
 };
 
-inline Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci) {
-  Bytecode_loadconstant* b = new Bytecode_loadconstant(method, bci);
-  DEBUG_ONLY(b->verify());
-  return b;
-}
-
 #endif // SHARE_VM_INTERPRETER_BYTECODE_HPP
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -831,11 +831,11 @@
       // much like trying to deopt at a poll return. In that has we simply
       // get out of here
       //
-      if ( Bytecodes::code_at(pc, METHOD) == Bytecodes::_return_register_finalizer) {
+      if ( Bytecodes::code_at(METHOD, pc) == Bytecodes::_return_register_finalizer) {
         // this will do the right thing even if an exception is pending.
         goto handle_return;
       }
-      UPDATE_PC(Bytecodes::length_at(pc));
+      UPDATE_PC(Bytecodes::length_at(METHOD, pc));
       if (THREAD->has_pending_exception()) goto handle_exception;
       goto run;
     }
--- a/src/share/vm/interpreter/bytecodeStream.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/bytecodeStream.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,7 @@
     // in raw mode, pretend indy is "bJJ__"
     assert(size == 2, "raw invokedynamic instruction has 2-byte index only");
   } else {
-    bytecode()->assert_index_size(size, raw_code(), is_wide());
+    bytecode().assert_index_size(size, raw_code(), is_wide());
   }
 }
 
--- a/src/share/vm/interpreter/bytecodeStream.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/bytecodeStream.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -105,14 +105,14 @@
   bool            is_last_bytecode() const       { return _next_bci >= _end_bci; }
 
   address         bcp() const                    { return method()->code_base() + _bci; }
-  Bytecode*       bytecode() const               { return Bytecode_at(bcp()); }
+  Bytecode        bytecode() const               { return Bytecode(_method(), bcp()); }
 
   // State changes
   void            set_next_bci(int bci)          { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
 
   // Bytecode-specific attributes
-  int             dest() const                   { return bci() + bytecode()->get_offset_s2(raw_code()); }
-  int             dest_w() const                 { return bci() + bytecode()->get_offset_s4(raw_code()); }
+  int             dest() const                   { return bci() + bytecode().get_offset_s2(raw_code()); }
+  int             dest_w() const                 { return bci() + bytecode().get_offset_s4(raw_code()); }
 
   // One-byte indices.
   int             get_index_u1() const           { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }
@@ -189,7 +189,7 @@
     } else {
       // get bytecode
       address bcp = this->bcp();
-      raw_code = Bytecodes::code_at(bcp);
+      raw_code = Bytecodes::code_at(_method(), bcp);
       code = Bytecodes::java_code(raw_code);
       // set next bytecode position
       //
@@ -197,7 +197,7 @@
       // tty bytecode otherwise the stepping is wrong!
       // (carefull: length_for(...) must be used first!)
       int l = Bytecodes::length_for(code);
-      if (l == 0) l = Bytecodes::length_at(bcp);
+      if (l == 0) l = Bytecodes::length_at(_method(), bcp);
       _next_bci  += l;
       assert(_bci < _next_bci, "length must be > 0");
       // set attributes
@@ -219,16 +219,16 @@
   Bytecodes::Code code() const                   { return _code; }
 
   // Unsigned indices, widening
-  int             get_index() const              { return is_wide() ? bytecode()->get_index_u2(raw_code(), true) : get_index_u1(); }
+  int             get_index() const              { return is_wide() ? bytecode().get_index_u2(raw_code(), true) : get_index_u1(); }
   // Get an unsigned 2-byte index, swapping the bytes if necessary.
   int             get_index_u2() const           { assert_raw_stream(false);
-                                                   return bytecode()->get_index_u2(raw_code(), false); }
+                                                   return bytecode().get_index_u2(raw_code(), false); }
   // Get an unsigned 2-byte index in native order.
   int             get_index_u2_cpcache() const   { assert_raw_stream(false);
-                                                   return bytecode()->get_index_u2_cpcache(raw_code()); }
+                                                   return bytecode().get_index_u2_cpcache(raw_code()); }
   int             get_index_u4() const           { assert_raw_stream(false);
-                                                   return bytecode()->get_index_u4(raw_code()); }
-  bool            has_index_u4() const           { return bytecode()->has_index_u4(raw_code()); }
+                                                   return bytecode().get_index_u4(raw_code()); }
+  bool            has_index_u4() const           { return bytecode().has_index_u4(raw_code()); }
 };
 
 #endif // SHARE_VM_INTERPRETER_BYTECODESTREAM_HPP
--- a/src/share/vm/interpreter/bytecodeTracer.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/bytecodeTracer.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -100,9 +100,9 @@
     Bytecodes::Code code;
     if (is_wide()) {
       // bcp wasn't advanced if previous bytecode was _wide.
-      code = Bytecodes::code_at(bcp+1);
+      code = Bytecodes::code_at(method(), bcp+1);
     } else {
-      code = Bytecodes::code_at(bcp);
+      code = Bytecodes::code_at(method(), bcp);
     }
     _code = code;
      int bci = bcp - method->code_base();
@@ -127,11 +127,11 @@
   void trace(methodHandle method, address bcp, outputStream* st) {
     _current_method = method();
     ResourceMark rm;
-    Bytecodes::Code code = Bytecodes::code_at(bcp);
+    Bytecodes::Code code = Bytecodes::code_at(method(), bcp);
     // Set is_wide
     _is_wide = (code == Bytecodes::_wide);
     if (is_wide()) {
-      code = Bytecodes::code_at(bcp+1);
+      code = Bytecodes::code_at(method(), bcp+1);
     }
     _code = code;
     int bci = bcp - method->code_base();
@@ -188,7 +188,7 @@
   _closure->trace(method, bcp, st);
 }
 
-void print_symbol(symbolOop sym, outputStream* st) {
+void print_symbol(Symbol* sym, outputStream* st) {
   char buf[40];
   int len = sym->utf8_length();
   if (len >= (int)sizeof(buf)) {
@@ -205,10 +205,9 @@
   } else if (java_lang_String::is_instance(value)) {
     EXCEPTION_MARK;
     Handle h_value (THREAD, value);
-    symbolHandle sym = java_lang_String::as_symbol(h_value, CATCH);
-    print_symbol(sym(), st);
-  } else if (value->is_symbol()) {
-    print_symbol(symbolOop(value), st);
+    Symbol* sym = java_lang_String::as_symbol(h_value, CATCH);
+    print_symbol(sym, st);
+    sym->decrement_refcount();
   } else {
     st->print_cr(" " PTR_FORMAT, (intptr_t) value);
   }
@@ -316,7 +315,7 @@
   } else if (tag.is_method_type()) {
     int i2 = constants->method_type_index_at(i);
     st->print(" <MethodType> %d", i2);
-    print_oop(constants->symbol_at(i2), st);
+    print_symbol(constants->symbol_at(i2), st);
   } else if (tag.is_method_handle()) {
     int kind = constants->method_handle_ref_kind_at(i);
     int i2 = constants->method_handle_index_at(i);
@@ -354,11 +353,11 @@
     return;
   }
 
-  symbolOop name = constants->uncached_name_ref_at(i);
-  symbolOop signature = constants->uncached_signature_ref_at(i);
+  Symbol* name = constants->uncached_name_ref_at(i);
+  Symbol* signature = constants->uncached_signature_ref_at(i);
   const char* sep = (tag.is_field() ? "/" : "");
   if (has_klass) {
-    symbolOop klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i));
+    Symbol* klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i));
     st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string());
   } else {
     if (tag.is_invoke_dynamic()) {
@@ -438,7 +437,7 @@
     case Bytecodes::_anewarray: {
         int klass_index = get_index_u2();
         constantPoolOop constants = method()->constants();
-        symbolOop name = constants->klass_name_at(klass_index);
+        Symbol* name = constants->klass_name_at(klass_index);
         st->print_cr(" %s ", name->as_C_string());
       }
       break;
@@ -446,7 +445,7 @@
         int klass_index = get_index_u2();
         int nof_dims = get_index_u1();
         constantPoolOop constants = method()->constants();
-        symbolOop name = constants->klass_name_at(klass_index);
+        Symbol* name = constants->klass_name_at(klass_index);
         st->print_cr(" %s %d", name->as_C_string(), nof_dims);
       }
       break;
@@ -552,7 +551,7 @@
     case Bytecodes::_instanceof:
       { int i = get_index_u2();
         constantPoolOop constants = method()->constants();
-        symbolOop name = constants->klass_name_at(i);
+        Symbol* name = constants->klass_name_at(i);
         st->print_cr(" %d <%s>", i, name->as_C_string());
       }
       break;
--- a/src/share/vm/interpreter/bytecodes.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/bytecodes.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,18 +54,46 @@
 Bytecodes::Code Bytecodes::_java_code     [Bytecodes::number_of_codes];
 u_short         Bytecodes::_flags         [(1<<BitsPerByte)*2];
 
+#ifdef ASSERT
+bool Bytecodes::check_method(const methodOopDesc* method, address bcp) {
+  return method->contains(bcp);
+}
+#endif
+
+bool Bytecodes::check_must_rewrite(Bytecodes::Code code) {
+  assert(can_rewrite(code), "post-check only");
+
+  // Some codes are conditionally rewriting.  Look closely at them.
+  switch (code) {
+  case Bytecodes::_aload_0:
+    // Even if RewriteFrequentPairs is turned on,
+    // the _aload_0 code might delay its rewrite until
+    // a following _getfield rewrites itself.
+    return false;
+
+  case Bytecodes::_lookupswitch:
+    return false;  // the rewrite is not done by the interpreter
+
+  case Bytecodes::_new:
+    // (Could actually look at the class here, but the profit would be small.)
+    return false;  // the rewrite is not always done
+  }
+
+  // No other special cases.
+  return true;
+}
 
 Bytecodes::Code Bytecodes::code_at(methodOop method, int bci) {
-  return code_at(method->bcp_from(bci), method);
+  return code_at(method, method->bcp_from(bci));
 }
 
-Bytecodes::Code Bytecodes::non_breakpoint_code_at(address bcp, methodOop method) {
-  if (method == NULL)  method = methodOopDesc::method_from_bcp(bcp);
+Bytecodes::Code Bytecodes::non_breakpoint_code_at(const methodOopDesc* method, address bcp) {
+  assert(method != NULL, "must have the method for breakpoint conversion");
+  assert(method->contains(bcp), "must be valid bcp in method");
   return method->orig_bytecode_at(method->bci_from(bcp));
 }
 
-int Bytecodes::special_length_at(address bcp, address end) {
-  Code code = code_at(bcp);
+int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end) {
   switch (code) {
   case _wide:
     if (end != NULL && bcp + 1 >= end) {
@@ -120,7 +148,7 @@
   if (code == _breakpoint) {
     return 1;
   } else {
-    return special_length_at(bcp, end);
+    return special_length_at(code, bcp, end);
   }
 }
 
--- a/src/share/vm/interpreter/bytecodes.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/bytecodes.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -342,6 +342,12 @@
   static void        pd_initialize();              // platform specific initialization
   static Code        pd_base_code_for(Code code);  // platform specific base_code_for implementation
 
+  // Verify that bcp points into method
+#ifdef ASSERT
+  static bool        check_method(const methodOopDesc* method, address bcp);
+#endif
+  static bool check_must_rewrite(Bytecodes::Code bc);
+
  public:
   // Conversion
   static void        check          (Code code)    { assert(is_defined(code), "illegal code"); }
@@ -349,22 +355,30 @@
   static Code        cast           (int  code)    { return (Code)code; }
 
 
-   // Fetch a bytecode, hiding breakpoints as necessary:
-   static Code       code_at(address bcp, methodOop method = NULL) {
-          Code code = cast(*bcp); return (code != _breakpoint) ? code : non_breakpoint_code_at(bcp, method);
-   }
-   static Code       java_code_at(address bcp, methodOop method = NULL) {
-          return java_code(code_at(bcp, method));
-   }
+  // Fetch a bytecode, hiding breakpoints as necessary.  The method
+  // argument is used for conversion of breakpoints into the original
+  // bytecode.  The CI uses these methods but guarantees that
+  // breakpoints are hidden so the method argument should be passed as
+  // NULL since in that case the bcp and methodOop are unrelated
+  // memory.
+  static Code       code_at(const methodOopDesc* method, address bcp) {
+    assert(method == NULL || check_method(method, bcp), "bcp must point into method");
+    Code code = cast(*bcp);
+    assert(code != _breakpoint || method != NULL, "need methodOop to decode breakpoint");
+    return (code != _breakpoint) ? code : non_breakpoint_code_at(method, bcp);
+  }
+  static Code       java_code_at(const methodOopDesc* method, address bcp) {
+    return java_code(code_at(method, bcp));
+  }
 
-   // Fetch a bytecode or a breakpoint:
-   static Code       code_or_bp_at(address bcp)    { return (Code)cast(*bcp); }
+  // Fetch a bytecode or a breakpoint:
+  static Code       code_or_bp_at(address bcp)    { return (Code)cast(*bcp); }
 
-   static Code       code_at(methodOop method, int bci);
-   static bool       is_active_breakpoint_at(address bcp) { return (Code)*bcp == _breakpoint; }
+  static Code       code_at(methodOop method, int bci);
+  static bool       is_active_breakpoint_at(address bcp) { return (Code)*bcp == _breakpoint; }
 
-   // find a bytecode, behind a breakpoint if necessary:
-   static Code       non_breakpoint_code_at(address bcp, methodOop method = NULL);
+  // find a bytecode, behind a breakpoint if necessary:
+  static Code       non_breakpoint_code_at(const methodOopDesc* method, address bcp);
 
   // Bytecode attributes
   static bool        is_defined     (int  code)    { return 0 <= code && code < number_of_codes && flags(code, false) != 0; }
@@ -379,14 +393,17 @@
   static bool        can_trap       (Code code)    { check(code);      return has_all_flags(code, _bc_can_trap, false); }
   static Code        java_code      (Code code)    { check(code);      return _java_code     [code]; }
   static bool        can_rewrite    (Code code)    { check(code);      return has_all_flags(code, _bc_can_rewrite, false); }
+  static bool        must_rewrite(Bytecodes::Code code) { return can_rewrite(code) && check_must_rewrite(code); }
   static bool        native_byte_order(Code code)  { check(code);      return has_all_flags(code, _fmt_has_nbo, false); }
   static bool        uses_cp_cache  (Code code)    { check(code);      return has_all_flags(code, _fmt_has_j, false); }
   // if 'end' is provided, it indicates the end of the code buffer which
   // should not be read past when parsing.
-  static int         special_length_at(address bcp, address end = NULL);
+  static int         special_length_at(Bytecodes::Code code, address bcp, address end = NULL);
+  static int         special_length_at(methodOop method, address bcp, address end = NULL) { return special_length_at(code_at(method, bcp), bcp, end); }
   static int         raw_special_length_at(address bcp, address end = NULL);
-  static int         length_at      (address bcp)  { int l = length_for(code_at(bcp)); return l > 0 ? l : special_length_at(bcp); }
-  static int         java_length_at (address bcp)  { int l = length_for(java_code_at(bcp)); return l > 0 ? l : special_length_at(bcp); }
+  static int         length_for_code_at(Bytecodes::Code code, address bcp)  { int l = length_for(code); return l > 0 ? l : special_length_at(code, bcp); }
+  static int         length_at      (methodOop method, address bcp)  { return length_for_code_at(code_at(method, bcp), bcp); }
+  static int         java_length_at (methodOop method, address bcp)  { return length_for_code_at(java_code_at(method, bcp), bcp); }
   static bool        is_java_code   (Code code)    { return 0 <= code && code < number_of_java_codes; }
 
   static bool        is_aload       (Code code)    { return (code == _aload  || code == _aload_0  || code == _aload_1
--- a/src/share/vm/interpreter/interpreter.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/interpreter.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -237,10 +237,9 @@
 // Return true if the interpreter can prove that the given bytecode has
 // not yet been executed (in Java semantics, not in actual operation).
 bool AbstractInterpreter::is_not_reached(methodHandle method, int bci) {
-  address bcp = method->bcp_from(bci);
-  Bytecodes::Code code = Bytecodes::code_at(bcp, method());
+  Bytecodes::Code code = method()->code_at(bci);
 
-  if (!Bytecode_at(bcp)->must_rewrite(code)) {
+  if (!Bytecodes::must_rewrite(code)) {
     // might have been reached
     return false;
   }
@@ -286,12 +285,12 @@
 // If deoptimization happens, this function returns the point of next bytecode to continue execution
 address AbstractInterpreter::deopt_continue_after_entry(methodOop method, address bcp, int callee_parameters, bool is_top_frame) {
   assert(method->contains(bcp), "just checkin'");
-  Bytecodes::Code code   = Bytecodes::java_code_at(bcp);
+  Bytecodes::Code code   = Bytecodes::java_code_at(method, bcp);
   assert(!Interpreter::bytecode_should_reexecute(code), "should not reexecute");
   int             bci    = method->bci_from(bcp);
   int             length = -1; // initial value for debugging
   // compute continuation length
-  length = Bytecodes::length_at(bcp);
+  length = Bytecodes::length_at(method, bcp);
   // compute result type
   BasicType type = T_ILLEGAL;
 
@@ -303,7 +302,7 @@
       Thread *thread = Thread::current();
       ResourceMark rm(thread);
       methodHandle mh(thread, method);
-      type = Bytecode_invoke_at(mh, bci)->result_type(thread);
+      type = Bytecode_invoke(mh, bci).result_type();
       // since the cache entry might not be initialized:
       // (NOT needed for the old calling convension)
       if (!is_top_frame) {
@@ -317,7 +316,7 @@
       Thread *thread = Thread::current();
       ResourceMark rm(thread);
       methodHandle mh(thread, method);
-      type = Bytecode_invoke_at(mh, bci)->result_type(thread);
+      type = Bytecode_invoke(mh, bci).result_type();
       // since the cache entry might not be initialized:
       // (NOT needed for the old calling convension)
       if (!is_top_frame) {
@@ -334,7 +333,7 @@
         Thread *thread = Thread::current();
         ResourceMark rm(thread);
         methodHandle mh(thread, method);
-        type = Bytecode_loadconstant_at(mh, bci)->result_type();
+        type = Bytecode_loadconstant(mh, bci).result_type();
         break;
       }
 
@@ -356,7 +355,7 @@
 //       Interpreter::deopt_entry(vtos, 0) like others
 address AbstractInterpreter::deopt_reexecute_entry(methodOop method, address bcp) {
   assert(method->contains(bcp), "just checkin'");
-  Bytecodes::Code code   = Bytecodes::java_code_at(bcp);
+  Bytecodes::Code code   = Bytecodes::java_code_at(method, bcp);
 #ifdef COMPILER1
   if(code == Bytecodes::_athrow ) {
     return Interpreter::rethrow_exception_entry();
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,7 @@
 #include "oops/methodDataOop.hpp"
 #include "oops/objArrayKlass.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/nativeLookup.hpp"
 #include "runtime/biasedLocking.hpp"
@@ -132,9 +132,9 @@
          bytecode == Bytecodes::_fast_aldc_w, "wrong bc");
   ResourceMark rm(thread);
   methodHandle m (thread, method(thread));
-  Bytecode_loadconstant* ldc = Bytecode_loadconstant_at(m, bci(thread));
-  oop result = ldc->resolve_constant(THREAD);
-  DEBUG_ONLY(ConstantPoolCacheEntry* cpce = m->constants()->cache()->entry_at(ldc->cache_index()));
+  Bytecode_loadconstant ldc(m, bci(thread));
+  oop result = ldc.resolve_constant(THREAD);
+  DEBUG_ONLY(ConstantPoolCacheEntry* cpce = m->constants()->cache()->entry_at(ldc.cache_index()));
   assert(result == cpce->f1(), "expected result for assembly code");
 }
 IRT_END
@@ -295,7 +295,7 @@
 
 IRT_ENTRY(void, InterpreterRuntime::create_exception(JavaThread* thread, char* name, char* message))
   // lookup exception klass
-  symbolHandle s = oopFactory::new_symbol_handle(name, CHECK);
+  TempNewSymbol s = SymbolTable::new_symbol(name, CHECK);
   if (ProfileTraps) {
     if (s == vmSymbols::java_lang_ArithmeticException()) {
       note_trap(thread, Deoptimization::Reason_div0_check, CHECK);
@@ -304,7 +304,7 @@
     }
   }
   // create exception
-  Handle exception = Exceptions::new_exception(thread, s(), message);
+  Handle exception = Exceptions::new_exception(thread, s, message);
   thread->set_vm_result(exception());
 IRT_END
 
@@ -313,12 +313,12 @@
   ResourceMark rm(thread);
   const char* klass_name = Klass::cast(obj->klass())->external_name();
   // lookup exception klass
-  symbolHandle s = oopFactory::new_symbol_handle(name, CHECK);
+  TempNewSymbol s = SymbolTable::new_symbol(name, CHECK);
   if (ProfileTraps) {
     note_trap(thread, Deoptimization::Reason_class_check, CHECK);
   }
   // create exception, with klass name as detail message
-  Handle exception = Exceptions::new_exception(thread, s(), klass_name);
+  Handle exception = Exceptions::new_exception(thread, s, klass_name);
   thread->set_vm_result(exception());
 IRT_END
 
@@ -326,13 +326,13 @@
 IRT_ENTRY(void, InterpreterRuntime::throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index))
   char message[jintAsStringSize];
   // lookup exception klass
-  symbolHandle s = oopFactory::new_symbol_handle(name, CHECK);
+  TempNewSymbol s = SymbolTable::new_symbol(name, CHECK);
   if (ProfileTraps) {
     note_trap(thread, Deoptimization::Reason_range_check, CHECK);
   }
   // create exception
   sprintf(message, "%d", index);
-  THROW_MSG(s(), message);
+  THROW_MSG(s, message);
 IRT_END
 
 IRT_ENTRY(void, InterpreterRuntime::throw_ClassCastException(
@@ -672,8 +672,8 @@
   if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
     ResourceMark rm(thread);
     methodHandle m (thread, method(thread));
-    Bytecode_invoke* call = Bytecode_invoke_at(m, bci(thread));
-    symbolHandle signature (thread, call->signature());
+    Bytecode_invoke call(m, bci(thread));
+    Symbol* signature = call.signature();
     receiver = Handle(thread,
                   thread->last_frame().interpreter_callee_receiver(signature));
     assert(Universe::heap()->is_in_reserved_or_null(receiver()),
@@ -756,7 +756,7 @@
     caller_bci = caller_method->bci_from(caller_bcp);
     site_index = Bytes::get_native_u4(caller_bcp+1);
   }
-  assert(site_index == InterpreterRuntime::bytecode(thread)->get_index_u4(bytecode), "");
+  assert(site_index == InterpreterRuntime::bytecode(thread).get_index_u4(bytecode), "");
   assert(constantPoolCacheOopDesc::is_secondary_index(site_index), "proper format");
   // there is a second CPC entries that is of interest; it caches signature info:
   int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index();
@@ -797,7 +797,7 @@
   if (!pool->cache()->secondary_entry_at(site_index)->is_f1_null())
     return;
 
-  symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index));
+  Symbol*  call_site_name = pool->name_ref_at(site_index);
 
   Handle call_site
     = SystemDictionary::make_dynamic_call_site(bootm,
@@ -884,7 +884,7 @@
   return mdo->bci_to_di(bci);
 IRT_END
 
-IRT_ENTRY(jint, InterpreterRuntime::profile_method(JavaThread* thread, address cur_bcp))
+IRT_ENTRY(void, InterpreterRuntime::profile_method(JavaThread* thread))
   // use UnlockFlagSaver to clear and restore the _do_not_unlock_if_synchronized
   // flag, in case this method triggers classloading which will call into Java.
   UnlockFlagSaver fs(thread);
@@ -893,16 +893,12 @@
   frame fr = thread->last_frame();
   assert(fr.is_interpreted_frame(), "must come from interpreter");
   methodHandle method(thread, fr.interpreter_frame_method());
-  int bci = method->bci_from(cur_bcp);
   methodOopDesc::build_interpreter_method_data(method, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here");
     CLEAR_PENDING_EXCEPTION;
     // and fall through...
   }
-  methodDataOop mdo = method->method_data();
-  if (mdo == NULL)  return 0;
-  return mdo->bci_to_di(bci);
 IRT_END
 
 
@@ -1245,9 +1241,9 @@
   assert(fr.is_interpreted_frame(), "");
   jint bci = fr.interpreter_frame_bci();
   methodHandle mh(thread, fr.interpreter_frame_method());
-  Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci);
-  ArgumentSizeComputer asc(invoke->signature());
-  int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver
+  Bytecode_invoke invoke(mh, bci);
+  ArgumentSizeComputer asc(invoke.signature());
+  int size_of_arguments = (asc.size() + (invoke.has_receiver() ? 1 : 0)); // receiver
   Copy::conjoint_jbytes(src_address, dest_address,
                        size_of_arguments * Interpreter::stackElementSize);
 IRT_END
--- a/src/share/vm/interpreter/interpreterRuntime.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/interpreterRuntime.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,16 +58,16 @@
   static void      set_bcp_and_mdp(address bcp, JavaThread*thread);
   static Bytecodes::Code code(JavaThread *thread)    {
     // pass method to avoid calling unsafe bcp_to_method (partial fix 4926272)
-    return Bytecodes::code_at(bcp(thread), method(thread));
+    return Bytecodes::code_at(method(thread), bcp(thread));
   }
   static bool      already_resolved(JavaThread *thread) { return cache_entry(thread)->is_resolved(code(thread)); }
-  static Bytecode* bytecode(JavaThread *thread)      { return Bytecode_at(bcp(thread)); }
+  static Bytecode  bytecode(JavaThread *thread)      { return Bytecode(method(thread), bcp(thread)); }
   static int       get_index_u1(JavaThread *thread, Bytecodes::Code bc)
-                                                        { return bytecode(thread)->get_index_u1(bc); }
+                                                        { return bytecode(thread).get_index_u1(bc); }
   static int       get_index_u2(JavaThread *thread, Bytecodes::Code bc)
-                                                        { return bytecode(thread)->get_index_u2(bc); }
+                                                        { return bytecode(thread).get_index_u2(bc); }
   static int       get_index_u2_cpcache(JavaThread *thread, Bytecodes::Code bc)
-                                                        { return bytecode(thread)->get_index_u2_cpcache(bc); }
+                                                        { return bytecode(thread).get_index_u2_cpcache(bc); }
   static int       number_of_dimensions(JavaThread *thread)  { return bcp(thread)[3]; }
 
   static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i)  { return method(thread)->constants()->cache()->entry_at(i); }
@@ -164,7 +164,7 @@
 
   // Interpreter profiling support
   static jint    bcp_to_di(methodOopDesc* method, address cur_bcp);
-  static jint    profile_method(JavaThread* thread, address cur_bcp);
+  static void    profile_method(JavaThread* thread);
   static void    update_mdp_for_ret(JavaThread* thread, int bci);
 #ifdef ASSERT
   static void    verify_mdp(methodOopDesc* method, address bcp, address mdp);
--- a/src/share/vm/interpreter/linkResolver.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/linkResolver.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -56,7 +56,7 @@
 //------------------------------------------------------------------------------------------------------------------------
 // Implementation of FieldAccessInfo
 
-void FieldAccessInfo::set(KlassHandle klass, symbolHandle name, int field_index, int field_offset,
+void FieldAccessInfo::set(KlassHandle klass, Symbol* name, int field_index, int field_offset,
 BasicType field_type, AccessFlags access_flags) {
   _klass        = klass;
   _name         = name;
@@ -148,7 +148,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_IllegalAccessError(),
+      vmSymbols::java_lang_IllegalAccessError(),
       "tried to access class %s from class %s",
       sel_klass->external_name(),
       ref_klass->external_name()
@@ -174,8 +174,8 @@
 //
 // According to JVM spec. $5.4.3c & $5.4.3d
 
-void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
-  methodOop result_oop = klass->uncached_lookup_method(name(), signature());
+void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
+  methodOop result_oop = klass->uncached_lookup_method(name, signature);
   if (EnableMethodHandles && result_oop != NULL) {
     switch (result_oop->intrinsic_id()) {
     case vmIntrinsics::_invokeExact:
@@ -189,39 +189,39 @@
 }
 
 // returns first instance method
-void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
-  methodOop result_oop = klass->uncached_lookup_method(name(), signature());
+void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
+  methodOop result_oop = klass->uncached_lookup_method(name, signature);
   result = methodHandle(THREAD, result_oop);
   while (!result.is_null() && result->is_static()) {
     klass = KlassHandle(THREAD, Klass::cast(result->method_holder())->super());
-    result = methodHandle(THREAD, klass->uncached_lookup_method(name(), signature()));
+    result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature));
   }
 }
 
 
-int LinkResolver::vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
+int LinkResolver::vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
   ResourceMark rm(THREAD);
   klassVtable *vt = instanceKlass::cast(klass())->vtable();
-  return vt->index_of_miranda(name(), signature());
+  return vt->index_of_miranda(name, signature);
 }
 
-void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
+void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
   instanceKlass *ik = instanceKlass::cast(klass());
-  result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature()));
+  result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature));
 }
 
 void LinkResolver::lookup_implicit_method(methodHandle& result,
-                                          KlassHandle klass, symbolHandle name, symbolHandle signature,
+                                          KlassHandle klass, Symbol* name, Symbol* signature,
                                           KlassHandle current_klass,
                                           TRAPS) {
   if (EnableMethodHandles &&
       klass() == SystemDictionary::MethodHandle_klass() &&
-      methodOopDesc::is_method_handle_invoke_name(name())) {
+      methodOopDesc::is_method_handle_invoke_name(name)) {
     if (!MethodHandles::enabled()) {
       // Make sure the Java part of the runtime has been booted up.
       klassOop natives = SystemDictionary::MethodHandleNatives_klass();
       if (natives == NULL || instanceKlass::cast(natives)->is_not_initialized()) {
-        SystemDictionary::resolve_or_fail(vmSymbolHandles::sun_dyn_MethodHandleNatives(),
+        SystemDictionary::resolve_or_fail(vmSymbols::sun_dyn_MethodHandleNatives(),
                                           Handle(),
                                           Handle(),
                                           true,
@@ -233,7 +233,7 @@
                                                                        current_klass,
                                                                        CHECK);
     if (result_oop != NULL) {
-      assert(result_oop->is_method_handle_invoke() && result_oop->signature() == signature(), "consistent");
+      assert(result_oop->is_method_handle_invoke() && result_oop->signature() == signature, "consistent");
       result = methodHandle(THREAD, result_oop);
     }
   }
@@ -273,7 +273,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_IllegalAccessError(),
+      vmSymbols::java_lang_IllegalAccessError(),
       "tried to access method %s.%s%s from class %s",
       sel_klass->external_name(),
       sel_method->name()->as_C_string(),
@@ -290,8 +290,8 @@
   // resolve klass
   resolve_klass(resolved_klass, pool, index, CHECK);
 
-  symbolHandle method_name      (THREAD, pool->name_ref_at(index));
-  symbolHandle method_signature (THREAD, pool->signature_ref_at(index));
+  Symbol*  method_name       = pool->name_ref_at(index);
+  Symbol*  method_signature  = pool->signature_ref_at(index);
   KlassHandle  current_klass(THREAD, pool->pool_holder());
 
   resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
@@ -301,9 +301,9 @@
   // The class is java.dyn.MethodHandle
   resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
 
-  symbolHandle method_name = vmSymbolHandles::invokeExact_name();
+  Symbol* method_name = vmSymbols::invokeExact_name();
 
-  symbolHandle method_signature(THREAD, pool->signature_ref_at(index));
+  Symbol*  method_signature = pool->signature_ref_at(index);
   KlassHandle  current_klass   (THREAD, pool->pool_holder());
 
   resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
@@ -313,8 +313,8 @@
 
   // resolve klass
   resolve_klass(resolved_klass, pool, index, CHECK);
-  symbolHandle method_name      (THREAD, pool->name_ref_at(index));
-  symbolHandle method_signature (THREAD, pool->signature_ref_at(index));
+  Symbol*  method_name       = pool->name_ref_at(index);
+  Symbol*  method_signature  = pool->signature_ref_at(index);
   KlassHandle  current_klass(THREAD, pool->pool_holder());
 
   resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
@@ -322,7 +322,7 @@
 
 
 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass,
-                                  symbolHandle method_name, symbolHandle method_signature,
+                                  Symbol* method_name, Symbol* method_signature,
                                   KlassHandle current_klass, bool check_access, TRAPS) {
 
   // 1. check if klass is not interface
@@ -349,8 +349,8 @@
       ResourceMark rm(THREAD);
       THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
                 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
-                                                        method_name(),
-                                                        method_signature()));
+                                                        method_name,
+                                                        method_signature));
     }
   }
 
@@ -359,8 +359,8 @@
     ResourceMark rm(THREAD);
     THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
               methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
-                                                      method_name(),
-                                                      method_signature()));
+                                                      method_name,
+                                                      method_signature));
   }
 
   // 6. access checks, access checking may be turned off when calling from within the VM.
@@ -387,7 +387,7 @@
           " \"%s\" the class loader (instance of %s) of the current class, %s,"
           " and the class loader (instance of %s) for resolved class, %s, have"
           " different Class objects for the type %s used in the signature";
-        char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name(),method_signature());
+        char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature);
         const char* loader1 = SystemDictionary::loader_name(loader());
         char* current = instanceKlass::cast(current_klass())->name()->as_C_string();
         const char* loader2 = SystemDictionary::loader_name(class_loader());
@@ -406,8 +406,8 @@
 
 void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
                                             KlassHandle resolved_klass,
-                                            symbolHandle method_name,
-                                            symbolHandle method_signature,
+                                            Symbol* method_name,
+                                            Symbol* method_signature,
                                             KlassHandle current_klass,
                                             bool check_access, TRAPS) {
 
@@ -429,8 +429,8 @@
       ResourceMark rm(THREAD);
       THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
                 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
-                                                        method_name(),
-                                                        method_signature()));
+                                                        method_name,
+                                                        method_signature));
     }
   }
 
@@ -449,7 +449,7 @@
           "current class, %s, and the class loader (instance of %s) for "
           "resolved class, %s, have different Class objects for the type %s "
           "used in the signature";
-        char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name(),method_signature());
+        char* sig = methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature);
         const char* loader1 = SystemDictionary::loader_name(loader());
         char* current = instanceKlass::cast(current_klass())->name()->as_C_string();
         const char* loader2 = SystemDictionary::loader_name(class_loader());
@@ -482,7 +482,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_IllegalAccessError(),
+      vmSymbols::java_lang_IllegalAccessError(),
       "tried to access field %s.%s from class %s",
       sel_klass->external_name(),
       fd.name()->as_C_string(),
@@ -511,9 +511,8 @@
     resolve_klass_no_update(resolved_klass, pool, index, CHECK);
   }
   // Load these early in case the resolve of the containing klass fails
-  symbolOop field = pool->name_ref_at(index);
-  symbolHandle field_h (THREAD, field); // preserve in case we need the name
-  symbolOop sig   = pool->signature_ref_at(index);
+  Symbol* field = pool->name_ref_at(index);
+  Symbol* sig   = pool->signature_ref_at(index);
   // Check if there's a resolved klass containing the field
   if( resolved_klass.is_null() ) {
     ResourceMark rm(THREAD);
@@ -559,7 +558,7 @@
     HandleMark hm(THREAD);
     Handle ref_loader (THREAD, instanceKlass::cast(ref_klass())->class_loader());
     Handle sel_loader (THREAD, instanceKlass::cast(sel_klass())->class_loader());
-    symbolHandle signature_ref (THREAD, pool->signature_ref_at(index));
+    Symbol*  signature_ref  = pool->signature_ref_at(index);
     {
       ResourceMark rm(THREAD);
       char* failed_type_name =
@@ -572,7 +571,7 @@
           " \"%s\" the class loader (instance of %s) of the referring class, "
           "%s, and the class loader (instance of %s) for the field's resolved "
           "type, %s, have different Class objects for that type";
-        char* field_name = field_h()->as_C_string();
+        char* field_name = field->as_C_string();
         const char* loader1 = SystemDictionary::loader_name(ref_loader());
         char* sel = instanceKlass::cast(sel_klass())->name()->as_C_string();
         const char* loader2 = SystemDictionary::loader_name(sel_loader());
@@ -589,7 +588,7 @@
   // return information. note that the klass is set to the actual klass containing the
   // field, otherwise access of static fields in superclasses will not work.
   KlassHandle holder (THREAD, fd.field_holder());
-  symbolHandle name  (THREAD, fd.name());
+  Symbol*  name   = fd.name();
   result.set(holder, name, fd.index(), fd.offset(), fd.field_type(), fd.access_flags());
 }
 
@@ -605,8 +604,8 @@
 // recv_klass         the receiver klass
 
 
-void LinkResolver::resolve_static_call(CallInfo& result, KlassHandle& resolved_klass, symbolHandle method_name,
-                                       symbolHandle method_signature, KlassHandle current_klass,
+void LinkResolver::resolve_static_call(CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name,
+                                       Symbol* method_signature, KlassHandle current_klass,
                                        bool check_access, bool initialize_class, TRAPS) {
   methodHandle resolved_method;
   linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
@@ -624,7 +623,7 @@
 
 // throws linktime exceptions
 void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, KlassHandle resolved_klass,
-                                                  symbolHandle method_name, symbolHandle method_signature,
+                                                  Symbol* method_name, Symbol* method_signature,
                                                   KlassHandle current_klass, bool check_access, TRAPS) {
 
   resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
@@ -641,8 +640,8 @@
 }
 
 
-void LinkResolver::resolve_special_call(CallInfo& result, KlassHandle resolved_klass, symbolHandle method_name,
-                                        symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
+void LinkResolver::resolve_special_call(CallInfo& result, KlassHandle resolved_klass, Symbol* method_name,
+                                        Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
   methodHandle resolved_method;
   linktime_resolve_special_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
   runtime_resolve_special_method(result, resolved_method, resolved_klass, current_klass, check_access, CHECK);
@@ -650,7 +649,7 @@
 
 // throws linktime exceptions
 void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass,
-                                                   symbolHandle method_name, symbolHandle method_signature,
+                                                   Symbol* method_name, Symbol* method_signature,
                                                    KlassHandle current_klass, bool check_access, TRAPS) {
 
   resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
@@ -661,7 +660,7 @@
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
-      vmSymbolHandles::java_lang_NoSuchMethodError(),
+      vmSymbols::java_lang_NoSuchMethodError(),
       "%s: method %s%s not found",
       resolved_klass->external_name(),
       resolved_method->name()->as_C_string(),
@@ -703,8 +702,8 @@
       // Lookup super method
       KlassHandle super_klass(THREAD, current_klass->super());
       lookup_instance_method_in_klasses(sel_method, super_klass,
-                           symbolHandle(THREAD, resolved_method->name()),
-                           symbolHandle(THREAD, resolved_method->signature()), CHECK);
+                           resolved_method->name(),
+                           resolved_method->signature(), CHECK);
       // check if found
       if (sel_method.is_null()) {
         ResourceMark rm(THREAD);
@@ -739,7 +738,7 @@
 }
 
 void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, KlassHandle resolved_klass,
-                                        symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass,
+                                        Symbol* method_name, Symbol* method_signature, KlassHandle current_klass,
                                         bool check_access, bool check_null_and_abstract, TRAPS) {
   methodHandle resolved_method;
   linktime_resolve_virtual_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
@@ -748,7 +747,7 @@
 
 // throws linktime exceptions
 void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method, KlassHandle resolved_klass,
-                                                   symbolHandle method_name, symbolHandle method_signature,
+                                                   Symbol* method_name, Symbol* method_signature,
                                                    KlassHandle current_klass, bool check_access, TRAPS) {
   // normal method resolution
   resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
@@ -798,8 +797,8 @@
   // do lookup based on receiver klass using the vtable index
   if (resolved_method->method_holder()->klass_part()->is_interface()) { // miranda method
     vtable_index = vtable_index_of_miranda_method(resolved_klass,
-                           symbolHandle(THREAD, resolved_method->name()),
-                           symbolHandle(THREAD, resolved_method->signature()), CHECK);
+                           resolved_method->name(),
+                           resolved_method->signature(), CHECK);
     assert(vtable_index >= 0 , "we should have valid vtable index at this point");
 
     instanceKlass* inst = instanceKlass::cast(recv_klass());
@@ -847,7 +846,7 @@
 }
 
 void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass,
-                                          symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass,
+                                          Symbol* method_name, Symbol* method_signature, KlassHandle current_klass,
                                           bool check_access, bool check_null_and_abstract, TRAPS) {
   methodHandle resolved_method;
   linktime_resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
@@ -855,8 +854,8 @@
 }
 
 // throws linktime exceptions
-void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, symbolHandle method_name,
-                                                     symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
+void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name,
+                                                     Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
   // normal interface method resolution
   resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
 
@@ -883,8 +882,8 @@
   // do lookup based on receiver klass
   methodHandle sel_method;
   lookup_instance_method_in_klasses(sel_method, recv_klass,
-            symbolHandle(THREAD, resolved_method->name()),
-            symbolHandle(THREAD, resolved_method->signature()), CHECK);
+            resolved_method->name(),
+            resolved_method->signature(), CHECK);
   // check if method exists
   if (sel_method.is_null()) {
     ResourceMark rm(THREAD);
@@ -916,8 +915,8 @@
 
 methodHandle LinkResolver::linktime_resolve_interface_method_or_null(
                                                  KlassHandle resolved_klass,
-                                                 symbolHandle method_name,
-                                                 symbolHandle method_signature,
+                                                 Symbol* method_name,
+                                                 Symbol* method_signature,
                                                  KlassHandle current_klass,
                                                  bool check_access) {
   EXCEPTION_MARK;
@@ -933,8 +932,8 @@
 
 methodHandle LinkResolver::linktime_resolve_virtual_method_or_null(
                                                  KlassHandle resolved_klass,
-                                                 symbolHandle method_name,
-                                                 symbolHandle method_signature,
+                                                 Symbol* method_name,
+                                                 Symbol* method_signature,
                                                  KlassHandle current_klass,
                                                  bool check_access) {
   EXCEPTION_MARK;
@@ -951,8 +950,8 @@
 methodHandle LinkResolver::resolve_virtual_call_or_null(
                                                  KlassHandle receiver_klass,
                                                  KlassHandle resolved_klass,
-                                                 symbolHandle name,
-                                                 symbolHandle signature,
+                                                 Symbol* name,
+                                                 Symbol* signature,
                                                  KlassHandle current_klass) {
   EXCEPTION_MARK;
   CallInfo info;
@@ -967,8 +966,8 @@
 methodHandle LinkResolver::resolve_interface_call_or_null(
                                                  KlassHandle receiver_klass,
                                                  KlassHandle resolved_klass,
-                                                 symbolHandle name,
-                                                 symbolHandle signature,
+                                                 Symbol* name,
+                                                 Symbol* signature,
                                                  KlassHandle current_klass) {
   EXCEPTION_MARK;
   CallInfo info;
@@ -983,8 +982,8 @@
 int LinkResolver::resolve_virtual_vtable_index(
                                                KlassHandle receiver_klass,
                                                KlassHandle resolved_klass,
-                                               symbolHandle name,
-                                               symbolHandle signature,
+                                               Symbol* name,
+                                               Symbol* signature,
                                                KlassHandle current_klass) {
   EXCEPTION_MARK;
   CallInfo info;
@@ -998,8 +997,8 @@
 
 methodHandle LinkResolver::resolve_static_call_or_null(
                                                   KlassHandle resolved_klass,
-                                                  symbolHandle name,
-                                                  symbolHandle signature,
+                                                  Symbol* name,
+                                                  Symbol* signature,
                                                   KlassHandle current_klass) {
   EXCEPTION_MARK;
   CallInfo info;
@@ -1011,7 +1010,7 @@
   return info.selected_method();
 }
 
-methodHandle LinkResolver::resolve_special_call_or_null(KlassHandle resolved_klass, symbolHandle name, symbolHandle signature,
+methodHandle LinkResolver::resolve_special_call_or_null(KlassHandle resolved_klass, Symbol* name, Symbol* signature,
                                                         KlassHandle current_klass) {
   EXCEPTION_MARK;
   CallInfo info;
@@ -1039,22 +1038,22 @@
   return;
 }
 
-void LinkResolver::resolve_pool(KlassHandle& resolved_klass, symbolHandle& method_name, symbolHandle& method_signature,
+void LinkResolver::resolve_pool(KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature,
                                 KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS) {
    // resolve klass
   resolve_klass(resolved_klass, pool, index, CHECK);
 
   // Get name, signature, and static klass
-  method_name      = symbolHandle(THREAD, pool->name_ref_at(index));
-  method_signature = symbolHandle(THREAD, pool->signature_ref_at(index));
+  method_name      = pool->name_ref_at(index);
+  method_signature = pool->signature_ref_at(index);
   current_klass    = KlassHandle(THREAD, pool->pool_holder());
 }
 
 
 void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
   KlassHandle  resolved_klass;
-  symbolHandle method_name;
-  symbolHandle method_signature;
+  Symbol* method_name = NULL;
+  Symbol* method_signature = NULL;
   KlassHandle  current_klass;
   resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
   resolve_static_call(result, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
@@ -1063,8 +1062,8 @@
 
 void LinkResolver::resolve_invokespecial(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
   KlassHandle  resolved_klass;
-  symbolHandle method_name;
-  symbolHandle method_signature;
+  Symbol* method_name = NULL;
+  Symbol* method_signature = NULL;
   KlassHandle  current_klass;
   resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
   resolve_special_call(result, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
@@ -1076,8 +1075,8 @@
                                           TRAPS) {
 
   KlassHandle  resolved_klass;
-  symbolHandle method_name;
-  symbolHandle method_signature;
+  Symbol* method_name = NULL;
+  Symbol* method_signature = NULL;
   KlassHandle  current_klass;
   resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
   KlassHandle recvrKlass (THREAD, recv.is_null() ? (klassOop)NULL : recv->klass());
@@ -1087,8 +1086,8 @@
 
 void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) {
   KlassHandle  resolved_klass;
-  symbolHandle method_name;
-  symbolHandle method_signature;
+  Symbol* method_name = NULL;
+  Symbol* method_signature = NULL;
   KlassHandle  current_klass;
   resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
   KlassHandle recvrKlass (THREAD, recv.is_null() ? (klassOop)NULL : recv->klass());
@@ -1102,8 +1101,8 @@
   // This guy is reached from InterpreterRuntime::resolve_invokedynamic.
 
   // At this point, we only need the signature, and can ignore the name.
-  symbolHandle method_signature(THREAD, pool->signature_ref_at(raw_index));  // raw_index works directly
-  symbolHandle method_name = vmSymbolHandles::invokeExact_name();
+  Symbol*  method_signature = pool->signature_ref_at(raw_index);  // raw_index works directly
+  Symbol* method_name = vmSymbols::invokeExact_name();
   KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
 
   // JSR 292:  this must be an implicitly generated method MethodHandle.invokeExact(*...)
--- a/src/share/vm/interpreter/linkResolver.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/linkResolver.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -45,17 +45,17 @@
 class FieldAccessInfo: public LinkInfo {
  protected:
   KlassHandle  _klass;
-  symbolHandle _name;
+  Symbol*      _name;
   AccessFlags  _access_flags;
   int          _field_index;  // original index in the klass
   int          _field_offset;
   BasicType    _field_type;
 
  public:
-  void         set(KlassHandle klass, symbolHandle name, int field_index, int field_offset,
+  void         set(KlassHandle klass, Symbol* name, int field_index, int field_offset,
                  BasicType field_type, AccessFlags access_flags);
   KlassHandle  klass() const                     { return _klass; }
-  symbolHandle name() const                      { return _name; }
+  Symbol* name() const                           { return _name; }
   int          field_index() const               { return _field_index; }
   int          field_offset() const              { return _field_offset; }
   BasicType    field_type() const                { return _field_type; }
@@ -107,26 +107,26 @@
 
 class LinkResolver: AllStatic {
  private:
-  static void lookup_method_in_klasses          (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
-  static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
-  static void lookup_method_in_interfaces       (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
-  static void lookup_implicit_method            (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature,
+  static void lookup_method_in_klasses          (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
+  static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
+  static void lookup_method_in_interfaces       (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
+  static void lookup_implicit_method            (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
                                                  KlassHandle current_klass, TRAPS);
 
-  static int vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
+  static int vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
 
   static void resolve_klass           (KlassHandle& result, constantPoolHandle  pool, int index, TRAPS);
   static void resolve_klass_no_update (KlassHandle& result, constantPoolHandle pool, int index, TRAPS); // no update of constantPool entry
 
-  static void resolve_pool  (KlassHandle& resolved_klass, symbolHandle& method_name, symbolHandle& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);
+  static void resolve_pool  (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);
 
-  static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS);
-  static void resolve_method          (methodHandle& resolved_method, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+  static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+  static void resolve_method          (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
 
-  static void linktime_resolve_static_method    (methodHandle& resolved_method, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS);
-  static void linktime_resolve_special_method   (methodHandle& resolved_method, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS);
-  static void linktime_resolve_virtual_method   (methodHandle &resolved_method, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature,KlassHandle current_klass, bool check_access, TRAPS);
-  static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+  static void linktime_resolve_static_method    (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+  static void linktime_resolve_special_method   (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+  static void linktime_resolve_virtual_method   (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS);
+  static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
 
   static void runtime_resolve_special_method    (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, bool check_access, TRAPS);
   static void runtime_resolve_virtual_method    (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
@@ -152,24 +152,24 @@
   // runtime resolving:
   //   resolved_klass = specified class (i.e., static receiver class)
   //   current_klass  = sending method holder (i.e., class containing the method containing the call being resolved)
-  static void resolve_static_call   (CallInfo& result,              KlassHandle& resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS);
-  static void resolve_special_call  (CallInfo& result,              KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS);
-  static void resolve_virtual_call  (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
-  static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
+  static void resolve_static_call   (CallInfo& result,              KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS);
+  static void resolve_special_call  (CallInfo& result,              KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+  static void resolve_virtual_call  (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
+  static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
 
   // same as above for compile-time resolution; but returns null handle instead of throwing an exception on error
   // also, does not initialize klass (i.e., no side effects)
-  static methodHandle resolve_virtual_call_or_null  (KlassHandle receiver_klass, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass);
-  static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass);
-  static methodHandle resolve_static_call_or_null   (KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass);
-  static methodHandle resolve_special_call_or_null  (KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass);
+  static methodHandle resolve_virtual_call_or_null  (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass);
+  static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass);
+  static methodHandle resolve_static_call_or_null   (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass);
+  static methodHandle resolve_special_call_or_null  (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass);
 
   // same as above for compile-time resolution; returns vtable_index if current_klass if linked
-  static int resolve_virtual_vtable_index  (KlassHandle receiver_klass, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass);
+  static int resolve_virtual_vtable_index  (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass);
 
   // static resolving for compiler (does not throw exceptions, returns null handle if unsuccessful)
-  static methodHandle linktime_resolve_virtual_method_or_null  (KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access);
-  static methodHandle linktime_resolve_interface_method_or_null(KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access);
+  static methodHandle linktime_resolve_virtual_method_or_null  (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
+  static methodHandle linktime_resolve_interface_method_or_null(KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
 
   // runtime resolving from constant pool
   static void resolve_invokestatic   (CallInfo& result,              constantPoolHandle pool, int index, TRAPS);
--- a/src/share/vm/interpreter/rewriter.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/rewriter.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -221,7 +221,7 @@
       // call to calculate the length.
       bc_length = Bytecodes::length_for(c);
       if (bc_length == 0) {
-        bc_length = Bytecodes::length_at(bcp);
+        bc_length = Bytecodes::length_at(method, bcp);
 
         // length_at will put us at the bytecode after the one modified
         // by 'wide'. We don't currently examine any of the bytecodes
@@ -238,9 +238,9 @@
         case Bytecodes::_lookupswitch   : {
 #ifndef CC_INTERP
           if (!UseC1X) {
-            Bytecode_lookupswitch* bc = Bytecode_lookupswitch_at(bcp);
+            Bytecode_lookupswitch bc(method, bcp);
             (*bcp) = (
-              bc->number_of_pairs() < BinarySwitchThreshold
+              bc.number_of_pairs() < BinarySwitchThreshold
               ? Bytecodes::_fast_linearswitch
               : Bytecodes::_fast_binaryswitch
             );
--- a/src/share/vm/interpreter/templateInterpreter.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/interpreter/templateInterpreter.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -592,7 +592,7 @@
 //       that do not return "Interpreter::deopt_entry(vtos, 0)"
 address TemplateInterpreter::deopt_reexecute_entry(methodOop method, address bcp) {
   assert(method->contains(bcp), "just checkin'");
-  Bytecodes::Code code   = Bytecodes::java_code_at(bcp);
+  Bytecodes::Code code   = Bytecodes::java_code_at(method, bcp);
   if (code == Bytecodes::_return) {
     // This is used for deopt during registration of finalizers
     // during Object.<init>.  We simply need to resume execution at
--- a/src/share/vm/memory/classify.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/classify.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -68,8 +68,6 @@
     type = typeArray_type;
   } else if (obj->is_objArray()) {
     type = objArray_type;
-  } else if (obj->is_symbol()) {
-    type = symbol_type;
   } else if (obj->is_klass()) {
     Klass* k = ((klassOop)obj)->klass_part();
     if (k->oop_is_instance()) {
@@ -158,8 +156,6 @@
           name = "_typeArrayKlassKlassObj";
         } else if (obj == Universe::instanceKlassKlassObj()) {
           name = "_instanceKlassKlassObj";
-        } else if (obj == Universe::symbolKlassObj()) {
-          name = "_symbolKlassObj";
         } else if (obj == Universe::methodKlassObj()) {
           name = "_methodKlassObj";
         } else if (obj == Universe::constMethodKlassObj()) {
--- a/src/share/vm/memory/compactingPermGenGen.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/compactingPermGenGen.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -95,17 +95,11 @@
 // their stack to the class without having added the class to the
 // dictionary yet. This means the class will be marked during phase 1
 // but will not be unmarked during the application of the
-// RecursiveAdjustSharedObjectClosure to the SystemDictionary. Note
-// that we must not call find_shared_class with non-read-only symbols
-// as doing so can cause hash codes to be computed, destroying
-// forwarding pointers.
-class TraversePlaceholdersClosure : public OopClosure {
- protected:
-  template <class T> inline void do_oop_work(T* p) {
-    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
-    if (obj->klass() == Universe::symbolKlassObj() &&
-        obj->is_shared_readonly()) {
-      symbolHandle sym((symbolOop) obj);
+// RecursiveAdjustSharedObjectClosure to the SystemDictionary.
+class TraversePlaceholdersClosure {
+ public:
+  static void placeholders_do(Symbol* sym, oop loader) {
+    if (CompactingPermGenGen::is_shared(sym)) {
       oop k = SystemDictionary::find_shared_class(sym);
       if (k != NULL) {
         RecursiveAdjustSharedObjectClosure clo;
@@ -113,13 +107,8 @@
       }
     }
   }
- public:
-  virtual void do_oop(oop* p)       { TraversePlaceholdersClosure::do_oop_work(p); }
-  virtual void do_oop(narrowOop* p) { TraversePlaceholdersClosure::do_oop_work(p); }
-
 };
 
-
 void CompactingPermGenGen::initialize_performance_counters() {
 
   const char* gen_name = "perm";
@@ -335,8 +324,7 @@
       Universe::oops_do(&blk);
       StringTable::oops_do(&blk);
       SystemDictionary::always_strong_classes_do(&blk);
-      TraversePlaceholdersClosure tpc;
-      SystemDictionary::placeholders_do(&tpc);
+      SystemDictionary::placeholders_do(TraversePlaceholdersClosure::placeholders_do);
     }
   }
 }
@@ -490,5 +478,3 @@
   }
   return true;
 }
-
-void** CompactingPermGenGen::_vtbl_list;
--- a/src/share/vm/memory/compactingPermGenGen.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/compactingPermGenGen.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -96,9 +96,6 @@
   static HeapWord* misccode_end;
   static HeapWord* shared_end;
 
-  // List of klassOops whose vtbl entries are used to patch others.
-  static void**        _vtbl_list;
-
   // Performance Counters
   GenerationCounters*  _gen_counters;
   CSpaceCounters*      _space_counters;
@@ -153,32 +150,25 @@
   VirtualSpace*           mc_space()       { return &_mc_vs; }
   ContiguousSpace* unshared_space() const { return _the_space; }
 
-  static bool inline is_shared(const oopDesc* p) {
-    return (HeapWord*)p >= shared_bottom && (HeapWord*)p < shared_end;
+  static bool inline is_shared(const void* p) {
+    return p >= shared_bottom && p < shared_end;
   }
   // RedefineClasses note: this tester is used to check residence of
   // the specified oop in the shared readonly space and not whether
   // the oop is readonly.
-  static bool inline is_shared_readonly(const oopDesc* p) {
-    return (HeapWord*)p >= readonly_bottom && (HeapWord*)p < readonly_end;
+  static bool inline is_shared_readonly(const void* p) {
+    return p >= readonly_bottom && p < readonly_end;
   }
   // RedefineClasses note: this tester is used to check residence of
   // the specified oop in the shared readwrite space and not whether
   // the oop is readwrite.
-  static bool inline is_shared_readwrite(const oopDesc* p) {
-    return (HeapWord*)p >= readwrite_bottom && (HeapWord*)p < readwrite_end;
+  static bool inline is_shared_readwrite(const void* p) {
+    return p >= readwrite_bottom && p < readwrite_end;
   }
 
-  bool is_in_unshared(const void* p) const {
-    return OneContigSpaceCardGeneration::is_in(p);
-  }
-
-  bool is_in_shared(const void* p) const {
-   return p >= shared_bottom && p < shared_end;
-   }
-
+  // Checks if the pointer is either in unshared space or in shared space
   inline bool is_in(const void* p) const {
-    return is_in_unshared(p) || is_in_shared(p);
+    return OneContigSpaceCardGeneration::is_in(p) || is_shared(p);
   }
 
   inline PermanentGenerationSpec* spec() const { return _spec; }
@@ -236,6 +226,9 @@
                                       void** vtable,
                                       char** md_top, char* md_end,
                                       char** mc_top, char* mc_end);
+  static void* find_matching_vtbl_ptr(void** vtbl_list,
+                                      void* new_vtable_start,
+                                      void* obj);
 
   void verify(bool allow_dirty);
 
--- a/src/share/vm/memory/dump.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/dump.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -133,6 +133,69 @@
   return false;
 }
 
+
+class MoveSymbols : public SymbolClosure {
+private:
+  char* _start;
+  char* _end;
+  char* _top;
+  int _count;
+
+  bool in_shared_space(Symbol* sym) const {
+    return (char*)sym >= _start && (char*)sym < _end;
+  }
+
+  Symbol* get_shared_copy(Symbol* sym) {
+    return sym->refcount() > 0 ? NULL : (Symbol*)(_start - sym->refcount());
+  }
+
+  Symbol* make_shared_copy(Symbol* sym) {
+    Symbol* new_sym = (Symbol*)_top;
+    int size = sym->object_size();
+    _top += size * HeapWordSize;
+    if (_top <= _end) {
+      Copy::disjoint_words((HeapWord*)sym, (HeapWord*)new_sym, size);
+      // Encode a reference to the copy as a negative distance from _start
+      // When a symbol is being copied to a shared space
+      // during CDS archive creation, the original symbol is marked
+      // as relocated by putting a negative value to its _refcount field,
+      // This value is also used to find where exactly the shared copy is
+      // (see MoveSymbols::get_shared_copy), so that the other references
+      // to this symbol could be changed to point to the shared copy.
+      sym->_refcount = (int)(_start - (char*)new_sym);
+      // Mark the symbol in the shared archive as immortal so it is read only
+      // and not refcounted.
+      new_sym->_refcount = -1;
+      _count++;
+    } else {
+      report_out_of_shared_space(SharedMiscData);
+    }
+    return new_sym;
+  }
+
+public:
+  MoveSymbols(char* top, char* end) :
+    _start(top), _end(end), _top(top), _count(0) { }
+
+  char* get_top() const { return _top; }
+  int count()     const { return _count; }
+
+  void do_symbol(Symbol** p) {
+    Symbol* sym = load_symbol(p);
+    if (sym != NULL && !in_shared_space(sym)) {
+      Symbol* new_sym = get_shared_copy(sym);
+      if (new_sym == NULL) {
+        // The symbol has not been relocated yet; copy it to _top address
+        assert(sym->refcount() > 0, "should have positive reference count");
+        new_sym = make_shared_copy(sym);
+      }
+      // Make the reference point to the shared copy of the symbol
+      store_symbol(p, new_sym);
+    }
+  }
+};
+
+
 // Closure:  mark objects closure.
 
 class MarkObjectsOopClosure : public OopClosure {
@@ -164,7 +227,7 @@
 }
 
 
-// Closure:  mark common read-only objects, excluding symbols
+// Closure:  mark common read-only objects
 
 class MarkCommonReadOnly : public ObjectClosure {
 private:
@@ -216,54 +279,52 @@
 };
 
 
-// Closure:  mark common symbols
+// Closure:  find symbol references in Java Heap objects
 
-class MarkCommonSymbols : public ObjectClosure {
+class CommonSymbolsClosure : public ObjectClosure {
 private:
-  MarkObjectsOopClosure mark_all;
+  SymbolClosure* _closure;
 public:
+  CommonSymbolsClosure(SymbolClosure* closure) : _closure(closure) { }
+
   void do_object(oop obj) {
 
-    // Mark symbols refered to by method objects.
+    // Traverse symbols referenced by method objects.
 
     if (obj->is_method()) {
       methodOop m = methodOop(obj);
-      mark_object(m->name());
-      mark_object(m->signature());
+      constantPoolOop constants = m->constants();
+      _closure->do_symbol(constants->symbol_at_addr(m->name_index()));
+      _closure->do_symbol(constants->symbol_at_addr(m->signature_index()));
     }
 
-    // Mark symbols referenced by klass objects which are read-only.
+    // Traverse symbols referenced by klass objects which are read-only.
 
     else if (obj->is_klass()) {
+      Klass* k = Klass::cast((klassOop)obj);
+      k->shared_symbols_iterate(_closure);
 
       if (obj->blueprint()->oop_is_instanceKlass()) {
         instanceKlass* ik = instanceKlass::cast((klassOop)obj);
-        mark_object(ik->name());
-        mark_object(ik->generic_signature());
-        mark_object(ik->source_file_name());
-        mark_object(ik->source_debug_extension());
-
         typeArrayOop inner_classes = ik->inner_classes();
         if (inner_classes != NULL) {
-          int length = inner_classes->length();
-          for (int i = 0;
-                   i < length;
-                   i += instanceKlass::inner_class_next_offset) {
+          constantPoolOop constants = ik->constants();
+          int n = inner_classes->length();
+          for (int i = 0; i < n; i += instanceKlass::inner_class_next_offset) {
             int ioff = i + instanceKlass::inner_class_inner_name_offset;
             int index = inner_classes->ushort_at(ioff);
             if (index != 0) {
-              mark_object(ik->constants()->symbol_at(index));
+              _closure->do_symbol(constants->symbol_at_addr(index));
             }
           }
         }
-        ik->field_names_and_sigs_iterate(&mark_all);
       }
     }
 
-    // Mark symbols referenced by other constantpool entries.
+    // Traverse symbols referenced by other constantpool entries.
 
-    if (obj->is_constantPool()) {
-      constantPoolOop(obj)->shared_symbols_iterate(&mark_all);
+    else if (obj->is_constantPool()) {
+      constantPoolOop(obj)->shared_symbols_iterate(_closure);
     }
   }
 };
@@ -404,18 +465,7 @@
       int s = obj->size();
       oop sh_obj = (oop)_space->allocate(s);
       if (sh_obj == NULL) {
-        if (_read_only) {
-          warning("\nThe permanent generation read only space is not large "
-                  "enough to \npreload requested classes.  Use "
-                  "-XX:SharedReadOnlySize= to increase \nthe initial "
-                  "size of the read only space.\n");
-        } else {
-          warning("\nThe permanent generation read write space is not large "
-                  "enough to \npreload requested classes.  Use "
-                  "-XX:SharedReadWriteSize= to increase \nthe initial "
-                  "size of the read write space.\n");
-        }
-        exit(2);
+        report_out_of_shared_space(_read_only ? SharedReadOnly : SharedReadWrite);
       }
       if (PrintSharedSpaces && Verbose && WizardMode) {
         tty->print_cr("\nMoveMarkedObjects: " PTR_FORMAT " -> " PTR_FORMAT " %s", obj, sh_obj,
@@ -459,8 +509,6 @@
       instanceKlass* ik = instanceKlass::cast((klassOop)obj);
       int i;
 
-      mark_and_move_for_policy(OP_favor_startup, ik->name(), _move_ro);
-
       if (ik->super() != NULL) {
         do_object(ik->super());
       }
@@ -469,7 +517,6 @@
       mark_and_move_for_policy(OP_favor_startup, interfaces, _move_ro);
       for(i = 0; i < interfaces->length(); i++) {
         klassOop k = klassOop(interfaces->obj_at(i));
-        mark_and_move_for_policy(OP_favor_startup, k->klass_part()->name(), _move_ro);
         do_object(k);
       }
 
@@ -479,14 +526,6 @@
         mark_and_move_for_policy(OP_favor_startup, m->constMethod(), _move_ro);
         mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->exception_table(), _move_ro);
         mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->stackmap_data(), _move_ro);
-
-        // We don't move the name symbolOop here because it may invalidate
-        // method ordering, which is dependent on the address of the name
-        // symbolOop.  It will get promoted later with the other symbols.
-        // Method name is rarely accessed during classloading anyway.
-        // mark_and_move_for_policy(OP_balanced, m->name(), _move_ro);
-
-        mark_and_move_for_policy(OP_favor_startup, m->signature(), _move_ro);
       }
 
       mark_and_move_for_policy(OP_favor_startup, ik->transitive_interfaces(), _move_ro);
@@ -574,45 +613,43 @@
 };
 
 
-void sort_methods(instanceKlass* ik, TRAPS) {
-  klassOop super = ik->super();
-  if (super != NULL) {
-    sort_methods(instanceKlass::cast(super), THREAD);
-  }
-
-  // The methods array must be ordered by symbolOop address. (See
-  // classFileParser.cpp where methods in a class are originally
-  // sorted.)  Since objects have just be reordered, this must be
-  // corrected.
-  methodOopDesc::sort_methods(ik->methods(),
-                              ik->methods_annotations(),
-                              ik->methods_parameter_annotations(),
-                              ik->methods_default_annotations(),
-                              true /* idempotent, slow */);
-
-  // Itable indices are calculated based on methods array order
-  // (see klassItable::compute_itable_index()).  Must reinitialize.
-  // We assume that since checkconstraints is false, this method
-  // cannot throw an exception.  An exception here would be
-  // problematic since this is the VMThread, not a JavaThread.
-  ik->itable()->initialize_itable(false, THREAD);
-}
-
-// Sort methods if the oop is an instanceKlass.
+// The methods array must be reordered by Symbol* address.
+// (See classFileParser.cpp where methods in a class are originally
+// sorted). The addresses of symbols have been changed as a result
+// of moving to the shared space.
 
 class SortMethodsClosure: public ObjectClosure {
+public:
+  void do_object(oop obj) {
+    if (obj->blueprint()->oop_is_instanceKlass()) {
+      instanceKlass* ik = instanceKlass::cast((klassOop)obj);
+      methodOopDesc::sort_methods(ik->methods(),
+                                  ik->methods_annotations(),
+                                  ik->methods_parameter_annotations(),
+                                  ik->methods_default_annotations(),
+                                  true /* idempotent, slow */);
+    }
+  }
+};
+
+// Itable indices are calculated based on methods array order
+// (see klassItable::compute_itable_index()).  Must reinitialize
+// after ALL methods of ALL classes have been reordered.
+// We assume that since checkconstraints is false, this method
+// cannot throw an exception.  An exception here would be
+// problematic since this is the VMThread, not a JavaThread.
+
+class ReinitializeItables: public ObjectClosure {
 private:
   Thread* _thread;
 
 public:
-  SortMethodsClosure(Thread* thread) : _thread(thread) {}
+  ReinitializeItables(Thread* thread) : _thread(thread) {}
 
   void do_object(oop obj) {
-    // instanceKlass objects need some adjustment.
     if (obj->blueprint()->oop_is_instanceKlass()) {
       instanceKlass* ik = instanceKlass::cast((klassOop)obj);
-
-      sort_methods(ik, _thread);
+      ik->itable()->initialize_itable(false, _thread);
     }
   }
 };
@@ -673,18 +710,9 @@
   oop* top;
   char* end;
 
-  void out_of_space() {
-    warning("\nThe shared miscellaneous data space is not large "
-            "enough to \npreload requested classes.  Use "
-            "-XX:SharedMiscDataSize= to increase \nthe initial "
-            "size of the miscellaneous data space.\n");
-    exit(2);
-  }
-
-
   inline void check_space() {
     if ((char*)top + sizeof(oop) > end) {
-      out_of_space();
+      report_out_of_shared_space(SharedMiscData);
     }
   }
 
@@ -737,7 +765,7 @@
 
   void do_region(u_char* start, size_t size) {
     if ((char*)top + size > end) {
-      out_of_space();
+      report_out_of_shared_space(SharedMiscData);
     }
     assert((intptr_t)start % sizeof(oop) == 0, "bad alignment");
     assert(size % sizeof(oop) == 0, "bad size");
@@ -870,46 +898,53 @@
 
 class PatchKlassVtables: public ObjectClosure {
 private:
-  void*         _vtbl_ptr;
-  VirtualSpace* _md_vs;
   GrowableArray<klassOop>* _klass_objects;
 
 public:
-
-  PatchKlassVtables(void* vtbl_ptr, VirtualSpace* md_vs) {
-    _vtbl_ptr = vtbl_ptr;
-    _md_vs = md_vs;
+  PatchKlassVtables() {
     _klass_objects = new GrowableArray<klassOop>();
   }
 
-
   void do_object(oop obj) {
     if (obj->is_klass()) {
       _klass_objects->append(klassOop(obj));
     }
   }
 
-
-  void patch(void** vtbl_list, int vtbl_list_size) {
-    for (int i = 0; i < _klass_objects->length(); ++i) {
+  void patch(void** vtbl_list, void* new_vtable_start) {
+    int n = _klass_objects->length();
+    for (int i = 0; i < n; i++) {
       klassOop obj = (klassOop)_klass_objects->at(i);
       Klass* k = obj->klass_part();
-      void* v =  *(void**)k;
-
-      int n;
-      for (n = 0; n < vtbl_list_size; ++n) {
-        *(void**)k = NULL;
-        if (vtbl_list[n] == v) {
-          *(void**)k = (void**)_vtbl_ptr +
-                                 (n * CompactingPermGenGen::num_virtuals);
-          break;
-        }
-      }
-      guarantee(n < vtbl_list_size, "unable to find matching vtbl pointer");
+      *(void**)k = CompactingPermGenGen::find_matching_vtbl_ptr(
+                     vtbl_list, new_vtable_start, k);
     }
   }
 };
 
+// Walk through all symbols and patch their vtable pointers.
+// Note that symbols have vtable pointers only in non-product builds
+// (see allocation.hpp).
+
+#ifndef PRODUCT
+class PatchSymbolVtables: public SymbolClosure {
+private:
+  void* _new_vtbl_ptr;
+
+public:
+  PatchSymbolVtables(void** vtbl_list, void* new_vtable_start) {
+    Symbol s;
+    _new_vtbl_ptr = CompactingPermGenGen::find_matching_vtbl_ptr(
+                      vtbl_list, new_vtable_start, &s);
+  }
+
+  void do_symbol(Symbol** p) {
+    Symbol* sym = load_symbol(p);
+    *(void**)sym = _new_vtbl_ptr;
+  }
+};
+#endif
+
 
 // Populate the shared space.
 
@@ -969,7 +1004,6 @@
 
     MarkObjectsOopClosure mark_all;
     MarkCommonReadOnly mark_common_ro;
-    MarkCommonSymbols mark_common_symbols;
     MarkStringValues mark_string_values;
     MarkReadWriteObjects mark_rw;
     MarkStringObjects mark_strings;
@@ -1013,112 +1047,6 @@
     MarkAndMoveOrderedReadOnly  mark_and_move_ordered_ro(&move_ro);
     MarkAndMoveOrderedReadWrite mark_and_move_ordered_rw(&move_rw);
 
-    // Phase 1a: move commonly used read-only objects to the read-only space.
-
-    if (SharedOptimizeColdStart) {
-      tty->print("Moving pre-ordered read-only objects to shared space at " PTR_FORMAT " ... ",
-                 _ro_space->top());
-      for (int i = 0; i < _class_promote_order->length(); i++) {
-        oop obj = _class_promote_order->at(i);
-        mark_and_move_ordered_ro.do_object(obj);
-      }
-      tty->print_cr("done. ");
-    }
-
-    tty->print("Moving read-only objects to shared space at " PTR_FORMAT " ... ",
-               _ro_space->top());
-    gch->object_iterate(&mark_common_ro);
-    gch->object_iterate(&move_ro);
-    tty->print_cr("done. ");
-
-    // Phase 1b: move commonly used symbols to the read-only space.
-
-    tty->print("Moving common symbols to shared space at " PTR_FORMAT " ... ",
-               _ro_space->top());
-    gch->object_iterate(&mark_common_symbols);
-    gch->object_iterate(&move_ro);
-    tty->print_cr("done. ");
-
-    // Phase 1c: move remaining symbols to the read-only space
-    // (e.g. String initializers).
-
-    tty->print("Moving remaining symbols to shared space at " PTR_FORMAT " ... ",
-               _ro_space->top());
-    vmSymbols::oops_do(&mark_all, true);
-    gch->object_iterate(&move_ro);
-    tty->print_cr("done. ");
-
-    // Phase 1d: move String character arrays to the read-only space.
-
-    tty->print("Moving string char arrays to shared space at " PTR_FORMAT " ... ",
-               _ro_space->top());
-    gch->object_iterate(&mark_string_values);
-    gch->object_iterate(&move_ro);
-    tty->print_cr("done. ");
-
-    // Phase 2: move all remaining symbols to the read-only space.  The
-    // remaining symbols are assumed to be string initializers no longer
-    // referenced.
-
-    void* extra_symbols = _ro_space->top();
-    tty->print("Moving additional symbols to shared space at " PTR_FORMAT " ... ",
-               _ro_space->top());
-    SymbolTable::oops_do(&mark_all);
-    gch->object_iterate(&move_ro);
-    tty->print_cr("done. ");
-    tty->print_cr("Read-only space ends at " PTR_FORMAT ", %d bytes.",
-                  _ro_space->top(), _ro_space->used());
-
-    // Phase 3: move read-write objects to the read-write space, except
-    // Strings.
-
-    if (SharedOptimizeColdStart) {
-      tty->print("Moving pre-ordered read-write objects to shared space at " PTR_FORMAT " ... ",
-                 _rw_space->top());
-      for (int i = 0; i < _class_promote_order->length(); i++) {
-        oop obj = _class_promote_order->at(i);
-        mark_and_move_ordered_rw.do_object(obj);
-      }
-      tty->print_cr("done. ");
-    }
-    tty->print("Moving read-write objects to shared space at " PTR_FORMAT " ... ",
-               _rw_space->top());
-    Universe::oops_do(&mark_all, true);
-    SystemDictionary::oops_do(&mark_all);
-    oop tmp = Universe::arithmetic_exception_instance();
-    mark_object(java_lang_Throwable::message(tmp));
-    gch->object_iterate(&mark_rw);
-    gch->object_iterate(&move_rw);
-    tty->print_cr("done. ");
-
-    // Phase 4: move String objects to the read-write space.
-
-    tty->print("Moving String objects to shared space at " PTR_FORMAT " ... ",
-               _rw_space->top());
-    StringTable::oops_do(&mark_all);
-    gch->object_iterate(&mark_strings);
-    gch->object_iterate(&move_rw);
-    tty->print_cr("done. ");
-    tty->print_cr("Read-write space ends at " PTR_FORMAT ", %d bytes.",
-                  _rw_space->top(), _rw_space->used());
-
-#ifdef DEBUG
-    // Check: scan for objects which were not moved.
-
-    CheckRemainingObjects check_objects;
-    gch->object_iterate(&check_objects);
-    check_objects.status();
-#endif
-
-    // Resolve forwarding in objects and saved C++ structures
-    tty->print("Updating references to shared objects ... ");
-    ResolveForwardingClosure resolve;
-    Universe::oops_do(&resolve);
-    SystemDictionary::oops_do(&resolve);
-    StringTable::oops_do(&resolve);
-    SymbolTable::oops_do(&resolve);
-    vmSymbols::oops_do(&resolve);
-
     // Set up the share data and shared code segments.
 
     char* md_top = _md_vs->low();
@@ -1144,6 +1072,122 @@
                                                   &md_top, md_end,
                                                   &mc_top, mc_end);
 
+    // Reserve space for the total size and the number of stored symbols.
+
+    md_top += sizeof(intptr_t) * 2;
+
+    MoveSymbols move_symbols(md_top, md_end);
+    CommonSymbolsClosure traverse_common_symbols(&move_symbols);
+
+    // Phase 1a: remove symbols with _refcount == 0
+
+    SymbolTable::unlink();
+
+    // Phase 1b: move commonly used symbols referenced by oop fields.
+
+    tty->print("Moving common symbols to metadata section at " PTR_FORMAT " ... ",
+               move_symbols.get_top());
+    gch->object_iterate(&traverse_common_symbols);
+    tty->print_cr("done. ");
+
+    // Phase 1c: move known names and signatures.
+
+    tty->print("Moving vmSymbols to metadata section at " PTR_FORMAT " ... ",
+               move_symbols.get_top());
+    vmSymbols::symbols_do(&move_symbols);
+    tty->print_cr("done. ");
+
+    // Phase 1d: move the remaining symbols by scanning the whole SymbolTable.
+
+    void* extra_symbols = move_symbols.get_top();
+    tty->print("Moving the remaining symbols to metadata section at " PTR_FORMAT " ... ",
+               move_symbols.get_top());
+    SymbolTable::symbols_do(&move_symbols);
+    tty->print_cr("done. ");
+
+    // Record the total length of all symbols at the beginning of the block.
+    ((intptr_t*)md_top)[-2] = move_symbols.get_top() - md_top;
+    ((intptr_t*)md_top)[-1] = move_symbols.count();
+    tty->print_cr("Moved %d symbols, %d bytes.",
+                  move_symbols.count(), move_symbols.get_top() - md_top);
+    // Advance the pointer to the end of symbol store.
+    md_top = move_symbols.get_top();
+
+
+    // Phase 2: move commonly used read-only objects to the read-only space.
+
+    if (SharedOptimizeColdStart) {
+      tty->print("Moving pre-ordered read-only objects to shared space at " PTR_FORMAT " ... ",
+                 _ro_space->top());
+      for (int i = 0; i < _class_promote_order->length(); i++) {
+        oop obj = _class_promote_order->at(i);
+        mark_and_move_ordered_ro.do_object(obj);
+      }
+      tty->print_cr("done. ");
+    }
+
+    tty->print("Moving read-only objects to shared space at " PTR_FORMAT " ... ",
+               _ro_space->top());
+    gch->object_iterate(&mark_common_ro);
+    gch->object_iterate(&move_ro);
+    tty->print_cr("done. ");
+
+    // Phase 3: move String character arrays to the read-only space.
+
+    tty->print("Moving string char arrays to shared space at " PTR_FORMAT " ... ",
+               _ro_space->top());
+    gch->object_iterate(&mark_string_values);
+    gch->object_iterate(&move_ro);
+    tty->print_cr("done. ");
+
+    // Phase 4: move read-write objects to the read-write space, except
+    // Strings.
+
+    if (SharedOptimizeColdStart) {
+      tty->print("Moving pre-ordered read-write objects to shared space at " PTR_FORMAT " ... ",
+                 _rw_space->top());
+      for (int i = 0; i < _class_promote_order->length(); i++) {
+        oop obj = _class_promote_order->at(i);
+        mark_and_move_ordered_rw.do_object(obj);
+      }
+      tty->print_cr("done. ");
+    }
+    tty->print("Moving read-write objects to shared space at " PTR_FORMAT " ... ",
+               _rw_space->top());
+    Universe::oops_do(&mark_all, true);
+    SystemDictionary::oops_do(&mark_all);
+    oop tmp = Universe::arithmetic_exception_instance();
+    mark_object(java_lang_Throwable::message(tmp));
+    gch->object_iterate(&mark_rw);
+    gch->object_iterate(&move_rw);
+    tty->print_cr("done. ");
+
+    // Phase 5: move String objects to the read-write space.
+
+    tty->print("Moving String objects to shared space at " PTR_FORMAT " ... ",
+               _rw_space->top());
+    StringTable::oops_do(&mark_all);
+    gch->object_iterate(&mark_strings);
+    gch->object_iterate(&move_rw);
+    tty->print_cr("done. ");
+    tty->print_cr("Read-write space ends at " PTR_FORMAT ", %d bytes.",
+                  _rw_space->top(), _rw_space->used());
+
+#ifdef DEBUG
+    // Check: scan for objects which were not moved.
+
+    CheckRemainingObjects check_objects;
+    gch->object_iterate(&check_objects);
+    check_objects.status();
+#endif
+
+    // Resolve forwarding in objects and saved C++ structures
+    tty->print("Updating references to shared objects ... ");
+    ResolveForwardingClosure resolve;
+    Universe::oops_do(&resolve);
+    SystemDictionary::oops_do(&resolve);
+    StringTable::oops_do(&resolve);
+
     // Fix (forward) all of the references in these shared objects (which
     // are required to point ONLY to objects in the shared spaces).
     // Also, create a list of all objects which might later contain a
@@ -1166,9 +1210,13 @@
     // pointer resolution, so that methods can be promoted in any order
     // with respect to their holder classes.
 
-    SortMethodsClosure sort(THREAD);
+    SortMethodsClosure sort;
     gen->ro_space()->object_iterate(&sort);
     gen->rw_space()->object_iterate(&sort);
+
+    ReinitializeItables reinit_itables(THREAD);
+    gen->ro_space()->object_iterate(&reinit_itables);
+    gen->rw_space()->object_iterate(&reinit_itables);
     tty->print_cr("done. ");
     tty->cr();
 
@@ -1233,9 +1281,16 @@
     // Update the vtable pointers in all of the Klass objects in the
     // heap. They should point to newly generated vtable.
 
-    PatchKlassVtables pkvt(vtable, _md_vs);
+    PatchKlassVtables pkvt;
     _rw_space->object_iterate(&pkvt);
-    pkvt.patch(vtbl_list, vtbl_list_size);
+    pkvt.patch(vtbl_list, vtable);
+
+#ifndef PRODUCT
+    // Update the vtable pointers in all symbols,
+    // but only in non-product builds where symbols DO have virtual methods.
+    PatchSymbolVtables psvt(vtbl_list, vtable);
+    SymbolTable::symbols_do(&psvt);
+#endif
 
     char* saved_vtbl = (char*)malloc(vtbl_list_size * sizeof(void*));
     memmove(saved_vtbl, vtbl_list, vtbl_list_size * sizeof(void*));
@@ -1304,6 +1359,19 @@
   return JNI_OK;
 }
 
+void* CompactingPermGenGen::find_matching_vtbl_ptr(void** vtbl_list,
+                                                   void* new_vtable_start,
+                                                   void* obj) {
+  void* old_vtbl_ptr = *(void**)obj;
+  for (int i = 0; i < vtbl_list_size; i++) {
+    if (vtbl_list[i] == old_vtbl_ptr) {
+      return (void**)new_vtable_start + i * num_virtuals;
+    }
+  }
+  ShouldNotReachHere();
+  return NULL;
+}
+
 
 class LinkClassesClosure : public ObjectClosure {
  private:
@@ -1431,8 +1499,7 @@
       computed_jsum = jsum(computed_jsum, class_name, (const int)name_len - 1);
 
       // Got a class name - load it.
-      symbolHandle class_name_symbol = oopFactory::new_symbol(class_name,
-                                                              THREAD);
+      TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name, THREAD);
       guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
       klassOop klass = SystemDictionary::resolve_or_null(class_name_symbol,
                                                          THREAD);
--- a/src/share/vm/memory/genCollectedHeap.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/genCollectedHeap.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -875,10 +875,7 @@
 
 void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) {
   if (_preloading_shared_classes) {
-    warning("\nThe permanent generation is not large enough to preload "
-            "requested classes.\nUse -XX:PermSize= to increase the initial "
-            "size of the permanent generation.\n");
-    vm_exit(2);
+    report_out_of_shared_space(SharedPermGen);
   }
   // Read the GC count while holding the Heap_lock
   unsigned int gc_count_before      = total_collections();
--- a/src/share/vm/memory/genMarkSweep.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/genMarkSweep.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -158,6 +158,7 @@
 
   Threads::gc_epilogue();
   CodeCache::gc_epilogue();
+  JvmtiExport::gc_epilogue();
 
   if (PrintGC && !PrintGCDetails) {
     gch->print_heap_change(gch_prev_used);
@@ -295,9 +296,10 @@
   follow_mdo_weak_refs();
   assert(_marking_stack.is_empty(), "just drained");
 
-  // Visit symbol and interned string tables and delete unmarked oops
-  SymbolTable::unlink(&is_alive);
+  // Visit interned string tables and delete unmarked oops
   StringTable::unlink(&is_alive);
+  // Clean up unreferenced symbols in symbol table.
+  SymbolTable::unlink();
 
   assert(_marking_stack.is_empty(), "stack should be empty by now");
 }
--- a/src/share/vm/memory/heapInspection.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/heapInspection.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -56,7 +56,6 @@
     if (_klass == Universe::objArrayKlassKlassObj())     name = "<objArrayKlassKlass>";     else
     if (_klass == Universe::instanceKlassKlassObj())     name = "<instanceKlassKlass>";     else
     if (_klass == Universe::typeArrayKlassKlassObj())    name = "<typeArrayKlassKlass>";    else
-    if (_klass == Universe::symbolKlassObj())            name = "<symbolKlass>";            else
     if (_klass == Universe::boolArrayKlassObj())         name = "<boolArrayKlass>";         else
     if (_klass == Universe::charArrayKlassObj())         name = "<charArrayKlass>";         else
     if (_klass == Universe::singleArrayKlassObj())       name = "<singleArrayKlass>";       else
--- a/src/share/vm/memory/iterator.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/iterator.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -290,6 +290,22 @@
   virtual void do_tag(int tag) = 0;
 };
 
+class SymbolClosure : public StackObj {
+ public:
+  virtual void do_symbol(Symbol**) = 0;
+
+  // Clear LSB in symbol address; it can be set by CPSlot.
+  static Symbol* load_symbol(Symbol** p) {
+    return (Symbol*)(intptr_t(*p) & ~1);
+  }
+
+  // Store symbol, adjusting new pointer if the original pointer was adjusted
+  // (symbol references in constant pool slots have their LSB set to 1).
+  static void store_symbol(Symbol** p, Symbol* sym) {
+    *p = (Symbol*)(intptr_t(sym) | (intptr_t(*p) & 1));
+  }
+};
+
 #ifdef ASSERT
 // This class is used to flag phases of a collection that
 // can unload classes and which should override the
--- a/src/share/vm/memory/oopFactory.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/oopFactory.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -64,34 +64,6 @@
 
   static typeArrayOop    new_typeArray(BasicType type, int length, TRAPS);
 
-  // Symbols
-  static symbolOop new_symbol(const char* utf8_buffer, int length, TRAPS) {
-    assert(utf8_buffer != NULL, "just checking");
-    return SymbolTable::lookup(utf8_buffer, length, CHECK_NULL);
-  }
-  static void new_symbols(constantPoolHandle cp, int names_count,
-                          const char** name, int* lengths,
-                          int* cp_indices, unsigned int* hashValues,
-                          TRAPS) {
-    SymbolTable::add(cp, names_count, name, lengths, cp_indices,
-                     hashValues, CHECK);
-  }
-
-  static symbolOop       new_symbol(char* name, TRAPS) { return new_symbol(name, (int)strlen(name), CHECK_NULL); }
-  static symbolOop       new_symbol(const char* name, TRAPS) { return new_symbol(name, (int)strlen(name), CHECK_NULL); }
-  static symbolOop       new_symbol(symbolHandle sym, int begin, int end, TRAPS) {
-    assert(begin <= end && end <= sym->utf8_length(), "just checking");
-    return SymbolTable::lookup(sym, begin, end, CHECK_NULL);
-  }
-
-  // Create symbols as above but return a handle
-  static symbolHandle    new_symbol_handle(const char* name, int length, TRAPS) {
-    symbolOop sym = new_symbol(name, length, THREAD);
-    return symbolHandle(THREAD, sym);
-  }
-  static symbolHandle    new_symbol_handle(char* name, TRAPS) { return new_symbol_handle(name, (int)strlen(name), CHECK_(symbolHandle())); }
-  static symbolHandle    new_symbol_handle(const char* name, TRAPS) { return new_symbol_handle(name, (int)strlen(name), CHECK_(symbolHandle())); }
-
   // Constant pools
   static constantPoolOop      new_constantPool     (int length,
                                                     bool is_conc_safe,
--- a/src/share/vm/memory/restore.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/restore.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -107,15 +107,23 @@
   // Skip over (reserve space for) a list of addresses of C++ vtables
   // for Klass objects.  They get filled in later.
 
+  void** vtbl_list = (void**)buffer;
+  buffer += vtbl_list_size * sizeof(void*);
+  Universe::init_self_patching_vtbl_list(vtbl_list, vtbl_list_size);
+
   // Skip over (reserve space for) dummy C++ vtables Klass objects.
   // They are used as is.
 
-  void** vtbl_list = (void**)buffer;
-  buffer += vtbl_list_size * sizeof(void*);
   intptr_t vtable_size = *(intptr_t*)buffer;
   buffer += sizeof(intptr_t);
   buffer += vtable_size;
 
+  // Skip the recorded symbols.
+
+  intptr_t total_symbol_size = *(intptr_t*)buffer;
+  buffer += sizeof(intptr_t) * 2;
+  buffer += total_symbol_size;
+
   // Create the symbol table using the bucket array at this spot in the
   // misc data space.  Since the symbol table is often modified, this
   // region (of mapped pages) will be copy-on-write.
--- a/src/share/vm/memory/serialize.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/serialize.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -61,7 +61,7 @@
   soc->do_tag(sizeof(constantPoolCacheOopDesc));
   soc->do_tag(objArrayOopDesc::base_offset_in_bytes());
   soc->do_tag(typeArrayOopDesc::base_offset_in_bytes(T_BYTE));
-  soc->do_tag(sizeof(symbolOopDesc));
+  soc->do_tag(sizeof(Symbol));
   soc->do_tag(sizeof(klassOopDesc));
   soc->do_tag(sizeof(markOopDesc));
   soc->do_tag(sizeof(compiledICHolderOopDesc));
@@ -83,8 +83,12 @@
   // Dump/restore miscellaneous oops.
   Universe::oops_do(soc, true);
   soc->do_tag(--tag);
+  CodeCache::oops_do(soc);
+  soc->do_tag(--tag);
 
-  vmSymbols::oops_do(soc, true);               soc->do_tag(--tag);
-  CodeCache::oops_do(soc);                     soc->do_tag(--tag);
+  // Dump/restore references to commonly used names and signatures.
+  vmSymbols::serialize(soc);
+  soc->do_tag(--tag);
+
   soc->do_tag(666);
 }
--- a/src/share/vm/memory/sharedHeap.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/sharedHeap.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -46,7 +46,6 @@
   SH_PS_Management_oops_do,
   SH_PS_SystemDictionary_oops_do,
   SH_PS_jvmti_oops_do,
-  SH_PS_vmSymbols_oops_do,
   SH_PS_SymbolTable_oops_do,
   SH_PS_StringTable_oops_do,
   SH_PS_CodeCache_oops_do,
@@ -169,11 +168,6 @@
   }
 
   if (!_process_strong_tasks->is_task_claimed(SH_PS_SymbolTable_oops_do)) {
-    if (so & SO_Symbols) {
-      SymbolTable::oops_do(roots);
-    }
-    // Verify if the symbol table contents are in the perm gen
-    NOT_PRODUCT(SymbolTable::oops_do(&assert_is_perm_closure));
   }
 
   if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) {
@@ -210,20 +204,6 @@
     NOT_PRODUCT(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_perm));
   }
 
-  // Roots that should point only into permanent generation.
-  {
-    OopClosure* blk = NULL;
-    if (collecting_perm_gen) {
-      blk = roots;
-    } else {
-      debug_only(blk = &assert_is_perm_closure);
-    }
-    if (blk != NULL) {
-      if (!_process_strong_tasks->is_task_claimed(SH_PS_vmSymbols_oops_do))
-        vmSymbols::oops_do(blk);
-    }
-  }
-
   if (!collecting_perm_gen) {
     // All threads perform this; coordination is handled internally.
 
@@ -273,7 +253,6 @@
   JNIHandles::weak_oops_do(&always_true, root_closure);
 
   CodeCache::blobs_do(code_roots);
-  SymbolTable::oops_do(root_closure);
   if (UseSharedSpaces && !DumpSharedSpaces) {
     SkipAdjustingSharedStrings skip_closure(root_closure);
     StringTable::oops_do(&skip_closure);
--- a/src/share/vm/memory/universe.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/universe.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -59,7 +59,6 @@
 #include "oops/methodKlass.hpp"
 #include "oops/objArrayKlassKlass.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolKlass.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "oops/typeArrayKlassKlass.hpp"
 #include "prims/jvmtiRedefineClassesTrace.hpp"
@@ -108,7 +107,6 @@
 klassOop Universe::_doubleArrayKlassObj               = NULL;
 klassOop Universe::_typeArrayKlassObjs[T_VOID+1]      = { NULL /*, NULL...*/ };
 klassOop Universe::_objectArrayKlassObj               = NULL;
-klassOop Universe::_symbolKlassObj                    = NULL;
 klassOop Universe::_methodKlassObj                    = NULL;
 klassOop Universe::_constMethodKlassObj               = NULL;
 klassOop Universe::_methodDataKlassObj                = NULL;
@@ -155,7 +153,6 @@
 oop Universe::_arithmetic_exception_instance          = NULL;
 oop Universe::_virtual_machine_error_instance         = NULL;
 oop Universe::_vm_exception                           = NULL;
-oop Universe::_emptySymbol                            = NULL;
 
 // These variables are guarded by FullGCALot_lock.
 debug_only(objArrayOop Universe::_fullgc_alot_dummy_array = NULL;)
@@ -190,7 +187,6 @@
 
 
 void Universe::system_classes_do(void f(klassOop)) {
-  f(symbolKlassObj());
   f(methodKlassObj());
   f(constMethodKlassObj());
   f(methodDataKlassObj());
@@ -242,7 +238,6 @@
       }
     }
   }
-  f->do_oop((oop*)&_symbolKlassObj);
   f->do_oop((oop*)&_methodKlassObj);
   f->do_oop((oop*)&_constMethodKlassObj);
   f->do_oop((oop*)&_methodDataKlassObj);
@@ -279,7 +274,6 @@
   f->do_oop((oop*)&_main_thread_group);
   f->do_oop((oop*)&_system_thread_group);
   f->do_oop((oop*)&_vm_exception);
-  f->do_oop((oop*)&_emptySymbol);
   debug_only(f->do_oop((oop*)&_fullgc_alot_dummy_array);)
 }
 
@@ -312,10 +306,6 @@
         _instanceKlassKlassObj  = instanceKlassKlass::create_klass(CHECK);
         _typeArrayKlassKlassObj = typeArrayKlassKlass::create_klass(CHECK);
 
-        _symbolKlassObj         = symbolKlass::create_klass(CHECK);
-
-        _emptySymbol            = oopFactory::new_symbol("", CHECK);
-
         _boolArrayKlassObj      = typeArrayKlass::create_klass(T_BOOLEAN, sizeof(jboolean), CHECK);
         _charArrayKlassObj      = typeArrayKlass::create_klass(T_CHAR,    sizeof(jchar),    CHECK);
         _singleArrayKlassObj    = typeArrayKlass::create_klass(T_FLOAT,   sizeof(jfloat),   CHECK);
@@ -349,13 +339,6 @@
         _the_empty_system_obj_array = oopFactory::new_system_objArray(0, CHECK);
 
         _the_array_interfaces_array = oopFactory::new_system_objArray(2, CHECK);
-        _vm_exception               = oopFactory::new_symbol("vm exception holder", CHECK);
-      } else {
-        FileMapInfo *mapinfo = FileMapInfo::current_info();
-        char* buffer = mapinfo->region_base(CompactingPermGenGen::md);
-        void** vtbl_list = (void**)buffer;
-        init_self_patching_vtbl_list(vtbl_list,
-                                     CompactingPermGenGen::vtbl_list_size);
       }
     }
 
@@ -449,15 +432,15 @@
   if (JDK_Version::is_partially_initialized()) {
     uint8_t jdk_version;
     klassOop k = SystemDictionary::resolve_or_null(
-        vmSymbolHandles::java_lang_management_MemoryUsage(), THREAD);
+        vmSymbols::java_lang_management_MemoryUsage(), THREAD);
     CLEAR_PENDING_EXCEPTION; // ignore exceptions
     if (k == NULL) {
       k = SystemDictionary::resolve_or_null(
-          vmSymbolHandles::java_lang_CharSequence(), THREAD);
+          vmSymbols::java_lang_CharSequence(), THREAD);
       CLEAR_PENDING_EXCEPTION; // ignore exceptions
       if (k == NULL) {
         k = SystemDictionary::resolve_or_null(
-            vmSymbolHandles::java_lang_Shutdown(), THREAD);
+            vmSymbols::java_lang_Shutdown(), THREAD);
         CLEAR_PENDING_EXCEPTION; // ignore exceptions
         if (k == NULL) {
           jdk_version = 2;
@@ -520,11 +503,16 @@
 }
 
 
-static inline void add_vtable(void** list, int* n, Klass* o, int count) {
-  list[(*n)++] = *(void**)&o->vtbl_value();
-  guarantee((*n) <= count, "vtable list too small.");
+static inline void* dereference(void* addr) {
+  return *(void**)addr;
 }
 
+static inline void add_vtable(void** list, int* n, void* o, int count) {
+  guarantee((*n) < count, "vtable list too small");
+  void* vtable = dereference(o);
+  assert(dereference(vtable) != NULL, "invalid vtable");
+  list[(*n)++] = vtable;
+}
 
 void Universe::init_self_patching_vtbl_list(void** list, int count) {
   int n = 0;
@@ -535,7 +523,6 @@
   { instanceKlass o;          add_vtable(list, &n, &o, count); }
   { instanceRefKlass o;       add_vtable(list, &n, &o, count); }
   { typeArrayKlassKlass o;    add_vtable(list, &n, &o, count); }
-  { symbolKlass o;            add_vtable(list, &n, &o, count); }
   { typeArrayKlass o;         add_vtable(list, &n, &o, count); }
   { methodKlass o;            add_vtable(list, &n, &o, count); }
   { constMethodKlass o;       add_vtable(list, &n, &o, count); }
@@ -544,6 +531,11 @@
   { objArrayKlass o;          add_vtable(list, &n, &o, count); }
   { methodDataKlass o;        add_vtable(list, &n, &o, count); }
   { compiledICHolderKlass o;  add_vtable(list, &n, &o, count); }
+#ifndef PRODUCT
+  // In non-product builds CHeapObj is derived from AllocatedObj,
+  // so symbols in CDS archive should have their vtable pointer patched.
+  { Symbol o;                 add_vtable(list, &n, &o, count); }
+#endif
 }
 
 
@@ -633,8 +625,8 @@
     JavaCalls::call_static(
       &result,
       finalizer_klass,
-      vmSymbolHandles::run_finalizers_on_exit_name(),
-      vmSymbolHandles::void_method_signature(),
+      vmSymbols::run_finalizers_on_exit_name(),
+      vmSymbols::void_method_signature(),
       THREAD
     );
     // Ignore any pending exceptions
@@ -1037,7 +1029,7 @@
     // Setup preallocated empty java.lang.Class array
     Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false);
     // Setup preallocated OutOfMemoryError errors
-    k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_OutOfMemoryError(), true, CHECK_false);
+    k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false);
     k_h = instanceKlassHandle(THREAD, k);
     Universe::_out_of_memory_error_java_heap = k_h->allocate_permanent_instance(CHECK_false);
     Universe::_out_of_memory_error_perm_gen = k_h->allocate_permanent_instance(CHECK_false);
@@ -1047,15 +1039,15 @@
 
     // Setup preallocated NullPointerException
     // (this is currently used for a cheap & dirty solution in compiler exception handling)
-    k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_NullPointerException(), true, CHECK_false);
+    k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_NullPointerException(), true, CHECK_false);
     Universe::_null_ptr_exception_instance = instanceKlass::cast(k)->allocate_permanent_instance(CHECK_false);
     // Setup preallocated ArithmeticException
     // (this is currently used for a cheap & dirty solution in compiler exception handling)
-    k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_ArithmeticException(), true, CHECK_false);
+    k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ArithmeticException(), true, CHECK_false);
     Universe::_arithmetic_exception_instance = instanceKlass::cast(k)->allocate_permanent_instance(CHECK_false);
     // Virtual Machine Error for when we get into a situation we can't resolve
     k = SystemDictionary::resolve_or_fail(
-      vmSymbolHandles::java_lang_VirtualMachineError(), true, CHECK_false);
+      vmSymbols::java_lang_VirtualMachineError(), true, CHECK_false);
     bool linked = instanceKlass::cast(k)->link_class_or_fail(CHECK_false);
     if (!linked) {
       tty->print_cr("Unable to link/verify VirtualMachineError class");
@@ -1063,6 +1055,9 @@
     }
     Universe::_virtual_machine_error_instance =
       instanceKlass::cast(k)->allocate_permanent_instance(CHECK_false);
+
+    Universe::_vm_exception               = instanceKlass::cast(k)->allocate_permanent_instance(CHECK_false);
+
   }
   if (!DumpSharedSpaces) {
     // These are the only Java fields that are currently set during shared space dumping.
@@ -1117,7 +1112,7 @@
   // Note: No race-condition here, since a resolve will always return the same result
 
   // Setup method for security checks
-  k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_reflect_Method(), true, CHECK_false);
+  k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_reflect_Method(), true, CHECK_false);
   k_h = instanceKlassHandle(THREAD, k);
   k_h->link_class(CHECK_false);
   m = k_h->find_method(vmSymbols::invoke_name(), vmSymbols::object_object_array_object_signature());
--- a/src/share/vm/memory/universe.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/memory/universe.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -139,7 +139,6 @@
 
   static klassOop _objectArrayKlassObj;
 
-  static klassOop _symbolKlassObj;
   static klassOop _methodKlassObj;
   static klassOop _constMethodKlassObj;
   static klassOop _methodDataKlassObj;
@@ -198,8 +197,6 @@
   // the vm thread.
   static oop          _vm_exception;
 
-  static oop          _emptySymbol;                   // Canonical empty string ("") symbol
-
   // The particular choice of collected heap.
   static CollectedHeap* _collectedHeap;
 
@@ -273,7 +270,6 @@
     return _typeArrayKlassObjs[t];
   }
 
-  static klassOop symbolKlassObj()                    { return _symbolKlassObj;            }
   static klassOop methodKlassObj()                    { return _methodKlassObj;            }
   static klassOop constMethodKlassObj()               { return _constMethodKlassObj;         }
   static klassOop methodDataKlassObj()                { return _methodDataKlassObj;        }
@@ -287,9 +283,8 @@
   static klassOop compiledICHolderKlassObj()          { return _compiledICHolderKlassObj;  }
   static klassOop systemObjArrayKlassObj()            { return _systemObjArrayKlassObj;    }
 
-  // Known objects in tbe VM
-  static oop int_mirror()                   { return check_mirror(_int_mirror);
-}
+  // Known objects in the VM
+  static oop int_mirror()                   { return check_mirror(_int_mirror); }
   static oop float_mirror()                 { return check_mirror(_float_mirror); }
   static oop double_mirror()                { return check_mirror(_double_mirror); }
   static oop byte_mirror()                  { return check_mirror(_byte_mirror); }
@@ -327,7 +322,6 @@
   static oop          arithmetic_exception_instance() { return _arithmetic_exception_instance; }
   static oop          virtual_machine_error_instance() { return _virtual_machine_error_instance; }
   static oop          vm_exception()                  { return _vm_exception; }
-  static oop          emptySymbol()                   { return _emptySymbol; }
 
   // OutOfMemoryError support. Returns an error with the required message. The returned error
   // may or may not have a backtrace. If error has a backtrace then the stack trace is already
--- a/src/share/vm/oops/arrayKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/arrayKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -64,7 +64,7 @@
   return NULL;
 }
 
-methodOop arrayKlass::uncached_lookup_method(symbolOop name, symbolOop signature) const {
+methodOop arrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
   // There are no methods in an array klass but the super class (Object) has some
   assert(super(), "super klass must be present");
   return Klass::cast(super())->uncached_lookup_method(name, signature);
--- a/src/share/vm/oops/arrayKlass.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/arrayKlass.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,8 +36,8 @@
   friend class VMStructs;
  private:
   int      _dimension;         // This is n'th-dimensional array.
-  klassOop _higher_dimension;  // Refers the (n+1)'th-dimensional array (if present).
-  klassOop _lower_dimension;   // Refers the (n-1)'th-dimensional array (if present).
+  volatile klassOop _higher_dimension;  // Refers the (n+1)'th-dimensional array (if present).
+  volatile klassOop _lower_dimension;   // Refers the (n-1)'th-dimensional array (if present).
   int      _vtable_len;        // size of vtable for this klass
   juint    _alloc_size;        // allocation profiling support
   oop      _component_mirror;  // component type, as a java/lang/Class
@@ -84,7 +84,7 @@
   objArrayOop allocate_arrayArray(int n, int length, TRAPS);
 
   // Lookup operations
-  methodOop uncached_lookup_method(symbolOop name, symbolOop signature) const;
+  methodOop uncached_lookup_method(Symbol* name, Symbol* signature) const;
 
   // Casting from klassOop
   static arrayKlass* cast(klassOop k) {
--- a/src/share/vm/oops/arrayOop.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/arrayOop.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -26,6 +26,6 @@
 #include "oops/arrayOop.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 
 // <<this page is intentionally left blank>>
--- a/src/share/vm/oops/constantPoolKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/constantPoolKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -33,7 +33,7 @@
 #include "oops/constantPoolOop.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.inline2.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 #ifdef TARGET_OS_FAMILY_linux
 # include "thread_linux.inline.hpp"
@@ -388,8 +388,12 @@
       case JVM_CONSTANT_UnresolvedClass :               // fall-through
       case JVM_CONSTANT_UnresolvedClassInError: {
         // unresolved_klass_at requires lock or safe world.
-        oop entry = *cp->obj_at_addr(index);
-        entry->print_value_on(st);
+        CPSlot entry = cp->slot_at(index);
+        if (entry.is_oop()) {
+          entry.get_oop()->print_value_on(st);
+        } else {
+          entry.get_symbol()->print_value_on(st);
+        }
         }
         break;
       case JVM_CONSTANT_MethodHandle :
@@ -450,36 +454,43 @@
   constantPoolOop cp = constantPoolOop(obj);
   guarantee(cp->is_perm(), "should be in permspace");
   if (!cp->partially_loaded()) {
-    oop* base = (oop*)cp->base();
     for (int i = 0; i< cp->length();  i++) {
+      CPSlot entry = cp->slot_at(i);
       if (cp->tag_at(i).is_klass()) {
-        guarantee((*base)->is_perm(),     "should be in permspace");
-        guarantee((*base)->is_klass(),    "should be klass");
+        if (entry.is_oop()) {
+          guarantee(entry.get_oop()->is_perm(),     "should be in permspace");
+          guarantee(entry.get_oop()->is_klass(),    "should be klass");
+        }
       }
       if (cp->tag_at(i).is_unresolved_klass()) {
-        guarantee((*base)->is_perm(),     "should be in permspace");
-        guarantee((*base)->is_symbol() || (*base)->is_klass(),
-                  "should be symbol or klass");
+        if (entry.is_oop()) {
+          guarantee(entry.get_oop()->is_perm(),     "should be in permspace");
+          guarantee(entry.get_oop()->is_klass(),    "should be klass");
+        }
       }
       if (cp->tag_at(i).is_symbol()) {
-        guarantee((*base)->is_perm(),     "should be in permspace");
-        guarantee((*base)->is_symbol(),   "should be symbol");
+        guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count");
       }
       if (cp->tag_at(i).is_unresolved_string()) {
-        guarantee((*base)->is_perm(),     "should be in permspace");
-        guarantee((*base)->is_symbol() || (*base)->is_instance(),
-                  "should be symbol or instance");
+        if (entry.is_oop()) {
+          guarantee(entry.get_oop()->is_perm(),     "should be in permspace");
+          guarantee(entry.get_oop()->is_instance(), "should be instance");
+        }
+        else {
+          guarantee(entry.get_symbol()->refcount() != 0, "should have nonzero reference count");
+        }
       }
       if (cp->tag_at(i).is_string()) {
         if (!cp->has_pseudo_string()) {
-          guarantee((*base)->is_perm(),   "should be in permspace");
-          guarantee((*base)->is_instance(), "should be instance");
+          if (entry.is_oop()) {
+            guarantee(entry.get_oop()->is_perm(),   "should be in permspace");
+            guarantee(entry.get_oop()->is_instance(), "should be instance");
+          }
         } else {
           // can be non-perm, can be non-instance (array)
         }
       }
       // FIXME: verify JSR 292 tags JVM_CONSTANT_MethodHandle, etc.
-      base++;
     }
     guarantee(cp->tags()->is_perm(),         "should be in permspace");
     guarantee(cp->tags()->is_typeArray(),    "should be type array");
--- a/src/share/vm/oops/constantPoolOop.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/constantPoolOop.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -52,13 +52,14 @@
 }
 
 klassOop constantPoolOopDesc::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
-  // A resolved constantPool entry will contain a klassOop, otherwise a symbolOop.
+  // A resolved constantPool entry will contain a klassOop, otherwise a Symbol*.
   // It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
   // tag is not updated atomicly.
-  oop entry = *(this_oop->obj_at_addr(which));
-  if (entry->is_klass()) {
+  CPSlot entry = this_oop->slot_at(which);
+  if (entry.is_oop()) {
+    assert(entry.get_oop()->is_klass(), "must be");
     // Already resolved - return entry.
-    return (klassOop)entry;
+    return (klassOop)entry.get_oop();
   }
 
   // Acquire lock on constant oop while doing update. After we get the lock, we check if another object
@@ -67,7 +68,7 @@
   bool do_resolve = false;
   bool in_error = false;
 
-  symbolHandle name;
+  Symbol* name = NULL;
   Handle       loader;
   { ObjectLocker ol(this_oop, THREAD);
 
@@ -76,7 +77,7 @@
         in_error = true;
       } else {
         do_resolve = true;
-        name   = symbolHandle(THREAD, this_oop->unresolved_klass_at(which));
+        name   = this_oop->unresolved_klass_at(which);
         loader = Handle(THREAD, instanceKlass::cast(this_oop->pool_holder())->class_loader());
       }
     }
@@ -86,8 +87,8 @@
   // The original attempt to resolve this constant pool entry failed so find the
   // original error and throw it again (JVMS 5.4.3).
   if (in_error) {
-    symbolOop error = SystemDictionary::find_resolution_error(this_oop, which);
-    guarantee(error != (symbolOop)NULL, "tag mismatch with resolution error table");
+    Symbol* error = SystemDictionary::find_resolution_error(this_oop, which);
+    guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table");
     ResourceMark rm;
     // exception text will be the class name
     const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
@@ -110,7 +111,7 @@
     // to resolve this constant pool entry fail with the same error (JVMS 5.4.3).
     if (HAS_PENDING_EXCEPTION) {
       ResourceMark rm;
-      symbolHandle error(PENDING_EXCEPTION->klass()->klass_part()->name());
+      Symbol* error = PENDING_EXCEPTION->klass()->klass_part()->name();
 
       bool throw_orig_error = false;
       {
@@ -120,7 +121,7 @@
         if (this_oop->tag_at(which).is_klass()) {
           CLEAR_PENDING_EXCEPTION;
           entry = this_oop->resolved_klass_at(which);
-          return (klassOop)entry;
+          return (klassOop)entry.get_oop();
         }
 
         if (!PENDING_EXCEPTION->
@@ -135,8 +136,8 @@
           this_oop->tag_at_put(which, JVM_CONSTANT_UnresolvedClassInError);
         } else {
           // some other thread has put the class in error state.
-          error = symbolHandle(SystemDictionary::find_resolution_error(this_oop, which));
-          assert(!error.is_null(), "checking");
+          error = SystemDictionary::find_resolution_error(this_oop, which);
+          assert(error != NULL, "checking");
           throw_orig_error = true;
         }
       } // unlocked
@@ -162,7 +163,7 @@
         vframeStream vfst(JavaThread::current());
         if (!vfst.at_end()) {
           line_number = vfst.method()->line_number_from_bci(vfst.bci());
-          symbolOop s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name();
+          Symbol* s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name();
           if (s != NULL) {
             source_file = s->as_C_string();
           }
@@ -192,8 +193,8 @@
   }
 
   entry = this_oop->resolved_klass_at(which);
-  assert(entry->is_klass(), "must be resolved at this point");
-  return (klassOop)entry;
+  assert(entry.is_oop() && entry.get_oop()->is_klass(), "must be resolved at this point");
+  return (klassOop)entry.get_oop();
 }
 
 
@@ -202,13 +203,14 @@
 // instanceof operations. Returns NULL if the class has not been loaded or
 // if the verification of constant pool failed
 klassOop constantPoolOopDesc::klass_at_if_loaded(constantPoolHandle this_oop, int which) {
-  oop entry = *this_oop->obj_at_addr(which);
-  if (entry->is_klass()) {
-    return (klassOop)entry;
+  CPSlot entry = this_oop->slot_at(which);
+  if (entry.is_oop()) {
+    assert(entry.get_oop()->is_klass(), "must be");
+    return (klassOop)entry.get_oop();
   } else {
-    assert(entry->is_symbol(), "must be either symbol or klass");
+    assert(entry.is_metadata(), "must be either symbol or klass");
     Thread *thread = Thread::current();
-    symbolHandle name (thread, (symbolOop)entry);
+    Symbol* name = entry.get_symbol();
     oop loader = instanceKlass::cast(this_oop->pool_holder())->class_loader();
     oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
     Handle h_prot (thread, protection_domain);
@@ -244,12 +246,13 @@
 // Note: We cannot update the ConstantPool from the vm_thread.
 klassOop constantPoolOopDesc::klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int index, TRAPS) {
   int which = this_oop->klass_ref_index_at(index);
-  oop entry = *this_oop->obj_at_addr(which);
-  if (entry->is_klass()) {
-    return (klassOop)entry;
+  CPSlot entry = this_oop->slot_at(which);
+  if (entry.is_oop()) {
+    assert(entry.get_oop()->is_klass(), "must be");
+    return (klassOop)entry.get_oop();
   } else {
-    assert(entry->is_symbol(), "must be either symbol or klass");
-    symbolHandle name (THREAD, (symbolOop)entry);
+    assert(entry.is_metadata(), "must be either symbol or klass");
+    Symbol*  name  = entry.get_symbol();
     oop loader = instanceKlass::cast(this_oop->pool_holder())->class_loader();
     oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
     Handle h_loader(THREAD, loader);
@@ -263,13 +266,13 @@
 }
 
 
-symbolOop constantPoolOopDesc::impl_name_ref_at(int which, bool uncached) {
+Symbol* constantPoolOopDesc::impl_name_ref_at(int which, bool uncached) {
   int name_index = name_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
   return symbol_at(name_index);
 }
 
 
-symbolOop constantPoolOopDesc::impl_signature_ref_at(int which, bool uncached) {
+Symbol* constantPoolOopDesc::impl_signature_ref_at(int which, bool uncached) {
   int signature_index = signature_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
   return symbol_at(signature_index);
 }
@@ -361,39 +364,40 @@
 }
 
 
-symbolOop constantPoolOopDesc::klass_name_at(int which) {
+Symbol* constantPoolOopDesc::klass_name_at(int which) {
   assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(),
          "Corrupted constant pool");
-  // A resolved constantPool entry will contain a klassOop, otherwise a symbolOop.
+  // A resolved constantPool entry will contain a klassOop, otherwise a Symbol*.
   // It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
   // tag is not updated atomicly.
-  oop entry = *(obj_at_addr(which));
-  if (entry->is_klass()) {
+  CPSlot entry = slot_at(which);
+  if (entry.is_oop()) {
     // Already resolved - return entry's name.
-    return klassOop(entry)->klass_part()->name();
+    assert(entry.get_oop()->is_klass(), "must be");
+    return klassOop(entry.get_oop())->klass_part()->name();
   } else {
-    assert(entry->is_symbol(), "must be either symbol or klass");
-    return (symbolOop)entry;
+    assert(entry.is_metadata(), "must be either symbol or klass");
+    return entry.get_symbol();
   }
 }
 
-symbolOop constantPoolOopDesc::klass_ref_at_noresolve(int which) {
+Symbol* constantPoolOopDesc::klass_ref_at_noresolve(int which) {
   jint ref_index = klass_ref_index_at(which);
   return klass_at_noresolve(ref_index);
 }
 
-symbolOop constantPoolOopDesc::uncached_klass_ref_at_noresolve(int which) {
+Symbol* constantPoolOopDesc::uncached_klass_ref_at_noresolve(int which) {
   jint ref_index = uncached_klass_ref_index_at(which);
   return klass_at_noresolve(ref_index);
 }
 
 char* constantPoolOopDesc::string_at_noresolve(int which) {
   // Test entry type in case string is resolved while in here.
-  oop entry = *(obj_at_addr(which));
-  if (entry->is_symbol()) {
-    return ((symbolOop)entry)->as_C_string();
-  } else if (java_lang_String::is_instance(entry)) {
-    return java_lang_String::as_utf8_string(entry);
+  CPSlot entry = slot_at(which);
+  if (entry.is_metadata()) {
+    return (entry.get_symbol())->as_C_string();
+  } else if (java_lang_String::is_instance(entry.get_oop())) {
+    return java_lang_String::as_utf8_string(entry.get_oop());
   } else {
     return (char*)"<pseudo-string>";
   }
@@ -498,8 +502,8 @@
     {
       int ref_kind                 = this_oop->method_handle_ref_kind_at(index);
       int callee_index             = this_oop->method_handle_klass_index_at(index);
-      symbolHandle name(THREAD,      this_oop->method_handle_name_ref_at(index));
-      symbolHandle signature(THREAD, this_oop->method_handle_signature_ref_at(index));
+      Symbol*  name =      this_oop->method_handle_name_ref_at(index);
+      Symbol*  signature = this_oop->method_handle_signature_ref_at(index);
       if (PrintMiscellaneous)
         tty->print_cr("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s",
                       ref_kind, index, this_oop->method_handle_index_at(index),
@@ -524,7 +528,7 @@
 
   case JVM_CONSTANT_MethodType:
     {
-      symbolHandle signature(THREAD, this_oop->method_type_signature_at(index));
+      Symbol*  signature = this_oop->method_type_signature_at(index);
       if (PrintMiscellaneous)
         tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s",
                       index, this_oop->method_type_index_at(index),
@@ -605,30 +609,33 @@
 }
 
 oop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
-  oop entry = *(this_oop->obj_at_addr(which));
-  if (entry->is_symbol()) {
+  oop str = NULL;
+  CPSlot entry = this_oop->slot_at(which);
+  if (entry.is_metadata()) {
     ObjectLocker ol(this_oop, THREAD);
     if (this_oop->tag_at(which).is_unresolved_string()) {
       // Intern string
-      symbolOop sym = this_oop->unresolved_string_at(which);
-      entry = StringTable::intern(sym, CHECK_(constantPoolOop(NULL)));
-      this_oop->string_at_put(which, entry);
+      Symbol* sym = this_oop->unresolved_string_at(which);
+      str = StringTable::intern(sym, CHECK_(constantPoolOop(NULL)));
+      this_oop->string_at_put(which, str);
     } else {
       // Another thread beat us and interned string, read string from constant pool
-      entry = this_oop->resolved_string_at(which);
+      str = this_oop->resolved_string_at(which);
     }
+  } else {
+    str = entry.get_oop();
   }
-  assert(java_lang_String::is_instance(entry), "must be string");
-  return entry;
+  assert(java_lang_String::is_instance(str), "must be string");
+  return str;
 }
 
 
 bool constantPoolOopDesc::is_pseudo_string_at(int which) {
-  oop entry = *(obj_at_addr(which));
-  if (entry->is_symbol())
+  CPSlot entry = slot_at(which);
+  if (entry.is_metadata())
     // Not yet resolved, but it will resolve to a string.
     return false;
-  else if (java_lang_String::is_instance(entry))
+  else if (java_lang_String::is_instance(entry.get_oop()))
     return false; // actually, it might be a non-interned or non-perm string
   else
     // truly pseudo
@@ -638,8 +645,8 @@
 
 bool constantPoolOopDesc::klass_name_at_matches(instanceKlassHandle k,
                                                 int which) {
-  // Names are interned, so we can compare symbolOops directly
-  symbolOop cp_name = klass_name_at(which);
+  // Names are interned, so we can compare Symbol*s directly
+  Symbol* cp_name = klass_name_at(which);
   return (cp_name == k->name());
 }
 
@@ -650,7 +657,7 @@
   for (int index = 1; index < tags()->length(); index++) { // Index 0 is unused
     if (tag_at(index).is_unresolved_string()) {
       // Intern string
-      symbolOop sym = unresolved_string_at(index);
+      Symbol* sym = unresolved_string_at(index);
       oop entry = StringTable::intern(sym, CHECK_(-1));
       string_at_put(index, entry);
     }
@@ -658,23 +665,39 @@
   return count;
 }
 
+// Iterate over symbols and decrement ones which are Symbol*s.
+// This is done during GC so do not need to lock constantPool unless we
+// have per-thread safepoints.
+// Only decrement the UTF8 symbols. Unresolved classes and strings point to
+// these symbols but didn't increment the reference count.
+void constantPoolOopDesc::unreference_symbols() {
+  for (int index = 1; index < length(); index++) { // Index 0 is unused
+    constantTag tag = tag_at(index);
+    if (tag.is_symbol()) {
+      symbol_at(index)->decrement_refcount();
+    }
+  }
+}
 
 // Iterate over symbols which are used as class, field, method names and
 // signatures (in preparation for writing to the shared archive).
 
-void constantPoolOopDesc::shared_symbols_iterate(OopClosure* closure) {
+void constantPoolOopDesc::shared_symbols_iterate(SymbolClosure* closure) {
   for (int index = 1; index < length(); index++) { // Index 0 is unused
     switch (tag_at(index).value()) {
 
     case JVM_CONSTANT_UnresolvedClass:
-      closure->do_oop(obj_at_addr(index));
+    case JVM_CONSTANT_UnresolvedString:
+    case JVM_CONSTANT_Utf8:
+      assert(slot_at(index).is_metadata(), "must be symbol");
+      closure->do_symbol(symbol_at_addr(index));
       break;
 
     case JVM_CONSTANT_NameAndType:
       {
         int i = *int_at_addr(index);
-        closure->do_oop(obj_at_addr((unsigned)i >> 16));
-        closure->do_oop(obj_at_addr((unsigned)i & 0xffff));
+        closure->do_symbol(symbol_at_addr((unsigned)i >> 16));
+        closure->do_symbol(symbol_at_addr((unsigned)i & 0xffff));
       }
       break;
 
@@ -692,12 +715,6 @@
       // Do nothing!  Not a symbol.
       break;
 
-    case JVM_CONSTANT_UnresolvedString:
-    case JVM_CONSTANT_Utf8:
-      // These constants are symbols, but unless these symbols are
-      // actually to be used for something, we don't want to mark them.
-      break;
-
     case JVM_CONSTANT_Long:
     case JVM_CONSTANT_Double:
       // Do nothing!  Not an oop. (But takes two pool entries.)
@@ -744,7 +761,7 @@
       break;
 
     case JVM_CONSTANT_String:
-      closure->do_oop(obj_at_addr(index));
+      closure->do_oop(obj_at_addr_raw(index));
       break;
 
     case JVM_CONSTANT_UnresolvedString:
@@ -904,8 +921,8 @@
 
   case JVM_CONSTANT_UnresolvedClass:
   {
-    symbolOop k1 = unresolved_klass_at(index1);
-    symbolOop k2 = cp2->unresolved_klass_at(index2);
+    Symbol* k1 = unresolved_klass_at(index1);
+    Symbol* k2 = cp2->unresolved_klass_at(index2);
     if (k1 == k2) {
       return true;
     }
@@ -960,8 +977,8 @@
 
   case JVM_CONSTANT_UnresolvedString:
   {
-    symbolOop s1 = unresolved_string_at(index1);
-    symbolOop s2 = cp2->unresolved_string_at(index2);
+    Symbol* s1 = unresolved_string_at(index1);
+    Symbol* s2 = cp2->unresolved_string_at(index2);
     if (s1 == s2) {
       return true;
     }
@@ -969,8 +986,8 @@
 
   case JVM_CONSTANT_Utf8:
   {
-    symbolOop s1 = symbol_at(index1);
-    symbolOop s2 = cp2->symbol_at(index2);
+    Symbol* s1 = symbol_at(index1);
+    Symbol* s2 = cp2->symbol_at(index2);
     if (s1 == s2) {
       return true;
     }
@@ -1158,13 +1175,13 @@
 
   case JVM_CONSTANT_UnresolvedClass:
   {
-    symbolOop k = from_cp->unresolved_klass_at(from_i);
+    Symbol* k = from_cp->unresolved_klass_at(from_i);
     to_cp->unresolved_klass_at_put(to_i, k);
   } break;
 
   case JVM_CONSTANT_UnresolvedClassInError:
   {
-    symbolOop k = from_cp->unresolved_klass_at(from_i);
+    Symbol* k = from_cp->unresolved_klass_at(from_i);
     to_cp->unresolved_klass_at_put(to_i, k);
     to_cp->tag_at_put(to_i, JVM_CONSTANT_UnresolvedClassInError);
   } break;
@@ -1172,14 +1189,16 @@
 
   case JVM_CONSTANT_UnresolvedString:
   {
-    symbolOop s = from_cp->unresolved_string_at(from_i);
+    Symbol* s = from_cp->unresolved_string_at(from_i);
     to_cp->unresolved_string_at_put(to_i, s);
   } break;
 
   case JVM_CONSTANT_Utf8:
   {
-    symbolOop s = from_cp->symbol_at(from_i);
+    Symbol* s = from_cp->symbol_at(from_i);
     to_cp->symbol_at_put(to_i, s);
+    // This constantPool has the same lifetime as the original, so don't
+    // increase reference counts for the copy.
   } break;
 
   case JVM_CONSTANT_MethodType:
@@ -1453,7 +1472,7 @@
 
     switch(tag) {
       case JVM_CONSTANT_Utf8: {
-        symbolOop sym = symbol_at(idx);
+        Symbol* sym = symbol_at(idx);
         symmap->add_entry(sym, idx);
         DBG(printf("adding symbol entry %s = %d\n", sym->as_utf8(), idx));
         break;
@@ -1461,7 +1480,7 @@
       case JVM_CONSTANT_Class:
       case JVM_CONSTANT_UnresolvedClass:
       case JVM_CONSTANT_UnresolvedClassInError: {
-        symbolOop sym = klass_name_at(idx);
+        Symbol* sym = klass_name_at(idx);
         classmap->add_entry(sym, idx);
         DBG(printf("adding class entry %s = %d\n", sym->as_utf8(), idx));
         break;
@@ -1509,7 +1528,7 @@
         break;
       }
       case JVM_CONSTANT_Utf8: {
-        symbolOop sym = symbol_at(idx);
+        Symbol* sym = symbol_at(idx);
         char*     str = sym->as_utf8();
         // Warning! It's crashing on x86 with len = sym->utf8_length()
         int       len = (int) strlen(str);
@@ -1546,7 +1565,7 @@
       case JVM_CONSTANT_UnresolvedClass:
       case JVM_CONSTANT_UnresolvedClassInError: {
         *bytes = JVM_CONSTANT_Class;
-        symbolOop sym = klass_name_at(idx);
+        Symbol* sym = klass_name_at(idx);
         idx1 = tbl->symbol_to_value(sym);
         assert(idx1 != 0, "Have not found a hashtable entry");
         Bytes::put_Java_u2((address) (bytes+1), idx1);
@@ -1556,19 +1575,19 @@
       case JVM_CONSTANT_String: {
         unsigned int hash;
         char *str = string_at_noresolve(idx);
-        symbolOop sym = SymbolTable::lookup_only(str, (int) strlen(str), hash);
+        TempNewSymbol sym = SymbolTable::lookup_only(str, (int) strlen(str), hash);
         if (sym == NULL) {
           // sym can be NULL if string refers to incorrectly encoded JVM_CONSTANT_Utf8
           // this can happen with JVM TI; see CR 6839599 for more details
-          oop string = *(obj_at_addr(idx));
+          oop string = *(obj_at_addr_raw(idx));
           assert(java_lang_String::is_instance(string),"Not a String");
           DBG(printf("Error #%03hd tag=%03hd\n", idx, tag));
           idx1 = 0;
           for (int j = 0; j < tbl->table_size() && idx1 == 0; j++) {
             for (SymbolHashMapEntry* cur = tbl->bucket(j); cur != NULL; cur = cur->next()) {
               int length;
-              sym = cur->symbol();
-              jchar* chars = sym->as_unicode(length);
+              Symbol* s = cur->symbol();
+              jchar* chars = s->as_unicode(length);
               if (java_lang_String::equals(string, chars, length)) {
                 idx1 = cur->value();
                 DBG(printf("Index found: %d\n",idx1));
@@ -1586,7 +1605,7 @@
       }
       case JVM_CONSTANT_UnresolvedString: {
         *bytes = JVM_CONSTANT_String;
-        symbolOop sym = unresolved_string_at(idx);
+        Symbol* sym = unresolved_string_at(idx);
         idx1 = tbl->symbol_to_value(sym);
         assert(idx1 != 0, "Have not found a hashtable entry");
         Bytes::put_Java_u2((address) (bytes+1), idx1);
@@ -1666,7 +1685,7 @@
 } /* end copy_cpool_bytes */
 
 
-void SymbolHashMap::add_entry(symbolOop sym, u2 value) {
+void SymbolHashMap::add_entry(Symbol* sym, u2 value) {
   char *str = sym->as_utf8();
   unsigned int hash = compute_hash(str, sym->utf8_length());
   unsigned int index = hash % table_size();
@@ -1687,7 +1706,7 @@
   assert(entry->symbol() != NULL, "SymbolHashMapEntry symbol is NULL");
 }
 
-SymbolHashMapEntry* SymbolHashMap::find_entry(symbolOop sym) {
+SymbolHashMapEntry* SymbolHashMap::find_entry(Symbol* sym) {
   assert(sym != NULL, "SymbolHashMap::find_entry - symbol is NULL");
   char *str = sym->as_utf8();
   int   len = sym->utf8_length();
--- a/src/share/vm/oops/constantPoolOop.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/constantPoolOop.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -27,6 +27,7 @@
 
 #include "oops/arrayOop.hpp"
 #include "oops/cpCacheOop.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayOop.hpp"
 #include "utilities/constantTag.hpp"
 #ifdef TARGET_ARCH_x86
@@ -47,10 +48,32 @@
 // modified when the entry is resolved.  If a klass or string constant pool
 // entry is read without a lock, only the resolved state guarantees that
 // the entry in the constant pool is a klass or String object and
-// not a symbolOop.
+// not a Symbol*.
 
 class SymbolHashMap;
 
+class CPSlot VALUE_OBJ_CLASS_SPEC {
+  intptr_t _ptr;
+ public:
+  CPSlot(intptr_t ptr): _ptr(ptr) {}
+  CPSlot(void* ptr): _ptr((intptr_t)ptr) {}
+  CPSlot(oop ptr): _ptr((intptr_t)ptr) {}
+  CPSlot(Symbol* ptr): _ptr((intptr_t)ptr | 1) {}
+
+  intptr_t value()   { return _ptr; }
+  bool is_oop()      { return (_ptr & 1) == 0; }
+  bool is_metadata() { return (_ptr & 1) == 1; }
+
+  oop get_oop() {
+    assert(is_oop(), "bad call");
+    return oop(_ptr);
+  }
+  Symbol* get_symbol() {
+    assert(is_metadata(), "bad call");
+    return (Symbol*)(_ptr & ~1);
+  }
+};
+
 class constantPoolOopDesc : public oopDesc {
   friend class VMStructs;
   friend class BytecodeInterpreter;  // Directly extracts an oop in the pool for fast instanceof/checkcast
@@ -89,11 +112,41 @@
   oop* cache_addr()      { return (oop*)&_cache; }
   oop* operands_addr()   { return (oop*)&_operands; }
 
-  oop* obj_at_addr(int which) const {
+  CPSlot slot_at(int which) {
+    assert(is_within_bounds(which), "index out of bounds");
+    // There's a transitional value of zero when converting from
+    // Symbol->0->Klass for G1 when resolving classes and strings.
+    // wait for the value to be non-zero (this is temporary)
+    volatile intptr_t adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which));
+    if (adr == 0 && which != 0) {
+      constantTag t = tag_at(which);
+      if (t.is_unresolved_klass() || t.is_klass() ||
+          t.is_unresolved_string() || t.is_string()) {
+        while ((adr = (intptr_t)OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))) == 0);
+      }
+    }
+    return CPSlot(adr);
+  }
+
+  void slot_at_put(int which, CPSlot s) const {
+    assert(is_within_bounds(which), "index out of bounds");
+    *(intptr_t*)&base()[which] = s.value();
+  }
+  oop* obj_at_addr_raw(int which) const {
     assert(is_within_bounds(which), "index out of bounds");
     return (oop*) &base()[which];
   }
 
+  void obj_at_put_without_check(int which, oop o) {
+    assert(is_within_bounds(which), "index out of bounds");
+    oop_store_without_check((volatile oop *)obj_at_addr_raw(which), o);
+  }
+
+  void obj_at_put(int which, oop o) const {
+    assert(is_within_bounds(which), "index out of bounds");
+    oop_store((volatile oop*)obj_at_addr_raw(which), o);
+  }
+
   jint* int_at_addr(int which) const {
     assert(is_within_bounds(which), "index out of bounds");
     return (jint*) &base()[which];
@@ -141,15 +194,20 @@
   // Storing constants
 
   void klass_at_put(int which, klassOop k) {
-    oop_store_without_check((volatile oop *)obj_at_addr(which), oop(k));
+    // Overwrite the old index with a GC friendly value so
+    // that if G1 looks during the transition during oop_store it won't
+    // assert the symbol is not an oop.
+    *obj_at_addr_raw(which) = NULL;
+    assert(k != NULL, "resolved class shouldn't be null");
+    obj_at_put_without_check(which, k);
     // The interpreter assumes when the tag is stored, the klass is resolved
-    // and the klassOop is a klass rather than a symbolOop, so we need
+    // and the klassOop is a klass rather than a Symbol*, so we need
     // hardware store ordering here.
     release_tag_at_put(which, JVM_CONSTANT_Class);
     if (UseConcMarkSweepGC) {
       // In case the earlier card-mark was consumed by a concurrent
       // marking thread before the tag was updated, redirty the card.
-      oop_store_without_check((volatile oop *)obj_at_addr(which), oop(k));
+      obj_at_put_without_check(which, k);
     }
   }
 
@@ -160,13 +218,9 @@
   }
 
   // Temporary until actual use
-  void unresolved_klass_at_put(int which, symbolOop s) {
-    // Overwrite the old index with a GC friendly value so
-    // that if GC looks during the transition it won't try
-    // to treat a small integer as oop.
-    *obj_at_addr(which) = NULL;
+  void unresolved_klass_at_put(int which, Symbol* s) {
     release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass);
-    oop_store_without_check(obj_at_addr(which), oop(s));
+    slot_at_put(which, s);
   }
 
   void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
@@ -191,10 +245,9 @@
   }
 
   // Temporary until actual use
-  void unresolved_string_at_put(int which, symbolOop s) {
-    *obj_at_addr(which) = NULL;
+  void unresolved_string_at_put(int which, Symbol* s) {
     release_tag_at_put(which, JVM_CONSTANT_UnresolvedString);
-    oop_store_without_check(obj_at_addr(which), oop(s));
+    slot_at_put(which, s);
   }
 
   void int_at_put(int which, jint i) {
@@ -220,28 +273,39 @@
     Bytes::put_native_u8((address) double_at_addr(which), *((u8*) &d));
   }
 
-  void symbol_at_put(int which, symbolOop s) {
+  Symbol** symbol_at_addr(int which) const {
+    assert(is_within_bounds(which), "index out of bounds");
+    return (Symbol**) &base()[which];
+  }
+
+  void symbol_at_put(int which, Symbol* s) {
+    assert(s->refcount() != 0, "should have nonzero refcount");
     tag_at_put(which, JVM_CONSTANT_Utf8);
-    oop_store_without_check(obj_at_addr(which), oop(s));
+    slot_at_put(which, s);
   }
 
   void string_at_put(int which, oop str) {
-    oop_store((volatile oop*)obj_at_addr(which), str);
+    // Overwrite the old index with a GC friendly value so
+    // that if G1 looks during the transition during oop_store it won't
+    // assert the symbol is not an oop.
+    *obj_at_addr_raw(which) = NULL;
+    assert(str != NULL, "resolved string shouldn't be null");
+    obj_at_put(which, str);
     release_tag_at_put(which, JVM_CONSTANT_String);
     if (UseConcMarkSweepGC) {
       // In case the earlier card-mark was consumed by a concurrent
       // marking thread before the tag was updated, redirty the card.
-      oop_store_without_check((volatile oop *)obj_at_addr(which), str);
+      obj_at_put_without_check(which, str);
     }
   }
 
   void object_at_put(int which, oop str) {
-    oop_store((volatile oop*) obj_at_addr(which), str);
+    obj_at_put(which, str);
     release_tag_at_put(which, JVM_CONSTANT_Object);
     if (UseConcMarkSweepGC) {
       // In case the earlier card-mark was consumed by a concurrent
       // marking thread before the tag was updated, redirty the card.
-      oop_store_without_check((volatile oop*) obj_at_addr(which), str);
+      obj_at_put_without_check(which, str);
     }
   }
 
@@ -279,13 +343,19 @@
   bool is_pointer_entry(int which) {
     constantTag tag = tag_at(which);
     return tag.is_klass() ||
-      tag.is_unresolved_klass() ||
-      tag.is_symbol() ||
-      tag.is_unresolved_string() ||
       tag.is_string() ||
       tag.is_object();
   }
 
+  // Whether the entry points to an object for ldc (resolved or not)
+  bool is_object_entry(int which) {
+    constantTag tag = tag_at(which);
+    return is_pointer_entry(which) ||
+      tag.is_unresolved_klass() ||
+      tag.is_unresolved_string() ||
+      tag.is_symbol();
+  }
+
   // Fetching constants
 
   klassOop klass_at(int which, TRAPS) {
@@ -293,25 +363,25 @@
     return klass_at_impl(h_this, which, CHECK_NULL);
   }
 
-  symbolOop klass_name_at(int which);  // Returns the name, w/o resolving.
+  Symbol* klass_name_at(int which);  // Returns the name, w/o resolving.
 
   klassOop resolved_klass_at(int which) {  // Used by Compiler
     guarantee(tag_at(which).is_klass(), "Corrupted constant pool");
     // Must do an acquire here in case another thread resolved the klass
     // behind our back, lest we later load stale values thru the oop.
-    return klassOop((oop)OrderAccess::load_ptr_acquire(obj_at_addr(which)));
+    return klassOop(CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_oop());
   }
 
   // This method should only be used with a cpool lock or during parsing or gc
-  symbolOop unresolved_klass_at(int which) {     // Temporary until actual use
-    symbolOop s = symbolOop((oop)OrderAccess::load_ptr_acquire(obj_at_addr(which)));
+  Symbol* unresolved_klass_at(int which) {     // Temporary until actual use
+    Symbol* s = CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_symbol();
     // check that the klass is still unresolved.
     assert(tag_at(which).is_unresolved_klass(), "Corrupted constant pool");
     return s;
   }
 
   // RedefineClasses() API support:
-  symbolOop klass_at_noresolve(int which) { return klass_name_at(which); }
+  Symbol* klass_at_noresolve(int which) { return klass_name_at(which); }
 
   jint int_at(int which) {
     assert(tag_at(which).is_int(), "Corrupted constant pool");
@@ -336,9 +406,9 @@
     return *((jdouble*)&tmp);
   }
 
-  symbolOop symbol_at(int which) {
+  Symbol* symbol_at(int which) {
     assert(tag_at(which).is_utf8(), "Corrupted constant pool");
-    return symbolOop(*obj_at_addr(which));
+    return slot_at(which).get_symbol();
   }
 
   oop string_at(int which, TRAPS) {
@@ -348,7 +418,7 @@
 
   oop object_at(int which) {
     assert(tag_at(which).is_object(), "Corrupted constant pool");
-    return *obj_at_addr(which);
+    return slot_at(which).get_oop();
   }
 
   // A "pseudo-string" is an non-string oop that has found is way into
@@ -362,7 +432,7 @@
 
   oop pseudo_string_at(int which) {
     assert(tag_at(which).is_string(), "Corrupted constant pool");
-    return *obj_at_addr(which);
+    return slot_at(which).get_oop();
   }
 
   void pseudo_string_at_put(int which, oop x) {
@@ -378,12 +448,12 @@
     assert(tag_at(which).is_string(), "Corrupted constant pool");
     // Must do an acquire here in case another thread resolved the klass
     // behind our back, lest we later load stale values thru the oop.
-    return (oop)OrderAccess::load_ptr_acquire(obj_at_addr(which));
+    return CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_oop();
   }
 
   // This method should only be used with a cpool lock or during parsing or gc
-  symbolOop unresolved_string_at(int which) {    // Temporary until actual use
-    symbolOop s = symbolOop((oop)OrderAccess::load_ptr_acquire(obj_at_addr(which)));
+  Symbol* unresolved_string_at(int which) {    // Temporary until actual use
+    Symbol* s = CPSlot(OrderAccess::load_ptr_acquire(obj_at_addr_raw(which))).get_symbol();
     // check that the string is still unresolved.
     assert(tag_at(which).is_unresolved_string(), "Corrupted constant pool");
     return s;
@@ -391,7 +461,7 @@
 
   // Returns an UTF8 for a CONSTANT_String entry at a given index.
   // UTF8 char* representation was chosen to avoid conversion of
-  // java_lang_Strings at resolved entries into symbolOops
+  // java_lang_Strings at resolved entries into Symbol*s
   // or vice versa.
   // Caller is responsible for checking for pseudo-strings.
   char* string_at_noresolve(int which);
@@ -414,11 +484,11 @@
     return *int_at_addr(which);
   }
   // Derived queries:
-  symbolOop method_handle_name_ref_at(int which) {
+  Symbol* method_handle_name_ref_at(int which) {
     int member = method_handle_index_at(which);
     return impl_name_ref_at(member, true);
   }
-  symbolOop method_handle_signature_ref_at(int which) {
+  Symbol* method_handle_signature_ref_at(int which) {
     int member = method_handle_index_at(which);
     return impl_signature_ref_at(member, true);
   }
@@ -426,7 +496,7 @@
     int member = method_handle_index_at(which);
     return impl_klass_ref_index_at(member, true);
   }
-  symbolOop method_type_signature_at(int which) {
+  Symbol* method_type_signature_at(int which) {
     int sym = method_type_index_at(which);
     return symbol_at(sym);
   }
@@ -534,9 +604,9 @@
 
   // Lookup for entries consisting of (klass_index, name_and_type index)
   klassOop klass_ref_at(int which, TRAPS);
-  symbolOop klass_ref_at_noresolve(int which);
-  symbolOop name_ref_at(int which)                { return impl_name_ref_at(which, false); }
-  symbolOop signature_ref_at(int which)           { return impl_signature_ref_at(which, false); }
+  Symbol* klass_ref_at_noresolve(int which);
+  Symbol* name_ref_at(int which)                { return impl_name_ref_at(which, false); }
+  Symbol* signature_ref_at(int which)           { return impl_signature_ref_at(which, false); }
 
   int klass_ref_index_at(int which)               { return impl_klass_ref_index_at(which, false); }
   int name_and_type_ref_index_at(int which)       { return impl_name_and_type_ref_index_at(which, false); }
@@ -605,15 +675,15 @@
   // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
   // future by other Java code. These take constant pool indices rather than
   // constant pool cache indices as do the peer methods above.
-  symbolOop uncached_klass_ref_at_noresolve(int which);
-  symbolOop uncached_name_ref_at(int which)                 { return impl_name_ref_at(which, true); }
-  symbolOop uncached_signature_ref_at(int which)            { return impl_signature_ref_at(which, true); }
+  Symbol* uncached_klass_ref_at_noresolve(int which);
+  Symbol* uncached_name_ref_at(int which)                 { return impl_name_ref_at(which, true); }
+  Symbol* uncached_signature_ref_at(int which)            { return impl_signature_ref_at(which, true); }
   int       uncached_klass_ref_index_at(int which)          { return impl_klass_ref_index_at(which, true); }
   int       uncached_name_and_type_ref_index_at(int which)  { return impl_name_and_type_ref_index_at(which, true); }
 
   // Sharing
   int pre_resolve_shared_klasses(TRAPS);
-  void shared_symbols_iterate(OopClosure* closure0);
+  void shared_symbols_iterate(SymbolClosure* closure0);
   void shared_tags_iterate(OopClosure* closure0);
   void shared_strings_iterate(OopClosure* closure0);
 
@@ -628,8 +698,8 @@
 
  private:
 
-  symbolOop impl_name_ref_at(int which, bool uncached);
-  symbolOop impl_signature_ref_at(int which, bool uncached);
+  Symbol* impl_name_ref_at(int which, bool uncached);
+  Symbol* impl_signature_ref_at(int which, bool uncached);
   int       impl_klass_ref_index_at(int which, bool uncached);
   int       impl_name_and_type_ref_index_at(int which, bool uncached);
 
@@ -672,6 +742,9 @@
   int  orig_length() const                { return _orig_length; }
   void set_orig_length(int orig_length)   { _orig_length = orig_length; }
 
+  // Decrease ref counts of symbols that are in the constant pool
+  // when the holder class is unloaded
+  void unreference_symbols();
 
   // JVMTI accesss - GetConstantPool, RetransformClasses, ...
   friend class JvmtiConstantPoolReconstituter;
@@ -694,7 +767,7 @@
  private:
   unsigned int        _hash;   // 32-bit hash for item
   SymbolHashMapEntry* _next;   // Next element in the linked list for this bucket
-  symbolOop           _symbol; // 1-st part of the mapping: symbol => value
+  Symbol*             _symbol; // 1-st part of the mapping: symbol => value
   u2                  _value;  // 2-nd part of the mapping: symbol => value
 
  public:
@@ -704,13 +777,13 @@
   SymbolHashMapEntry* next() const        { return _next;   }
   void set_next(SymbolHashMapEntry* next) { _next = next;   }
 
-  symbolOop  symbol() const               { return _symbol; }
-  void       set_symbol(symbolOop sym)    { _symbol = sym;  }
+  Symbol*    symbol() const               { return _symbol; }
+  void       set_symbol(Symbol* sym)      { _symbol = sym;  }
 
   u2         value() const                {  return _value; }
   void       set_value(u2 value)          { _value = value; }
 
-  SymbolHashMapEntry(unsigned int hash, symbolOop symbol, u2 value)
+  SymbolHashMapEntry(unsigned int hash, Symbol* symbol, u2 value)
     : _hash(hash), _symbol(symbol), _value(value), _next(NULL) {}
 
 }; // End SymbolHashMapEntry class
@@ -769,10 +842,10 @@
     return _buckets[i].entry();
   }
 
-  void add_entry(symbolOop sym, u2 value);
-  SymbolHashMapEntry* find_entry(symbolOop sym);
+  void add_entry(Symbol* sym, u2 value);
+  SymbolHashMapEntry* find_entry(Symbol* sym);
 
-  u2 symbol_to_value(symbolOop sym) {
+  u2 symbol_to_value(Symbol* sym) {
     SymbolHashMapEntry *entry = find_entry(sym);
     return (entry == NULL) ? 0 : entry->value();
   }
--- a/src/share/vm/oops/generateOopMap.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/generateOopMap.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
 #include "interpreter/bytecodeStream.hpp"
 #include "oops/generateOopMap.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/relocator.hpp"
@@ -123,7 +123,7 @@
                                            set(CellTypeState::value); }
 
 public:
-  ComputeCallStack(symbolOop signature) : SignatureIterator(signature) {};
+  ComputeCallStack(Symbol* signature) : SignatureIterator(signature) {};
 
   // Compute methods
   int compute_for_parameters(bool is_static, CellTypeState *effect) {
@@ -177,7 +177,7 @@
                                           set(CellTypeState::value); }
 
 public:
-  ComputeEntryStack(symbolOop signature) : SignatureIterator(signature) {};
+  ComputeEntryStack(Symbol* signature) : SignatureIterator(signature) {};
 
   // Compute methods
   int compute_for_parameters(bool is_static, CellTypeState *effect) {
@@ -535,23 +535,23 @@
       (*jmpFct)(this, bcs->dest_w(), data);
       break;
     case Bytecodes::_tableswitch:
-      { Bytecode_tableswitch *tableswitch = Bytecode_tableswitch_at(bcs->bcp());
-        int len = tableswitch->length();
+      { Bytecode_tableswitch tableswitch(method(), bcs->bcp());
+        int len = tableswitch.length();
 
-        (*jmpFct)(this, bci + tableswitch->default_offset(), data); /* Default. jump address */
+        (*jmpFct)(this, bci + tableswitch.default_offset(), data); /* Default. jump address */
         while (--len >= 0) {
-          (*jmpFct)(this, bci + tableswitch->dest_offset_at(len), data);
+          (*jmpFct)(this, bci + tableswitch.dest_offset_at(len), data);
         }
         break;
       }
 
     case Bytecodes::_lookupswitch:
-      { Bytecode_lookupswitch *lookupswitch = Bytecode_lookupswitch_at(bcs->bcp());
-        int npairs = lookupswitch->number_of_pairs();
-        (*jmpFct)(this, bci + lookupswitch->default_offset(), data); /* Default. */
+      { Bytecode_lookupswitch lookupswitch(method(), bcs->bcp());
+        int npairs = lookupswitch.number_of_pairs();
+        (*jmpFct)(this, bci + lookupswitch.default_offset(), data); /* Default. */
         while(--npairs >= 0) {
-          LookupswitchPair *pair = lookupswitch->pair_at(npairs);
-          (*jmpFct)(this, bci + pair->offset(), data);
+          LookupswitchPair pair = lookupswitch.pair_at(npairs);
+          (*jmpFct)(this, bci + pair.offset(), data);
         }
         break;
       }
@@ -660,7 +660,7 @@
   _monitor_top = 0;
 }
 
-int GenerateOopMap::methodsig_to_effect(symbolOop signature, bool is_static, CellTypeState* effect) {
+int GenerateOopMap::methodsig_to_effect(Symbol* signature, bool is_static, CellTypeState* effect) {
   ComputeEntryStack ces(signature);
   return ces.compute_for_parameters(is_static, effect);
 }
@@ -977,7 +977,7 @@
 #ifdef ASSERT
     if (blockNum + 1 < bbNo) {
       address bcp = _method->bcp_from(bb->_end_bci);
-      int bc_len = Bytecodes::java_length_at(bcp);
+      int bc_len = Bytecodes::java_length_at(_method(), bcp);
       assert(bb->_end_bci + bc_len == bb[1]._bci, "unmatched bci info in basicblock");
     }
 #endif
@@ -985,7 +985,7 @@
 #ifdef ASSERT
   { BasicBlock *bb = &_basic_blocks[bbNo-1];
     address bcp = _method->bcp_from(bb->_end_bci);
-    int bc_len = Bytecodes::java_length_at(bcp);
+    int bc_len = Bytecodes::java_length_at(_method(), bcp);
     assert(bb->_end_bci + bc_len == _method->code_size(), "wrong end bci");
   }
 #endif
@@ -1265,7 +1265,7 @@
         constantPoolOop cp    = method()->constants();
         int nameAndTypeIdx    = cp->name_and_type_ref_index_at(idx);
         int signatureIdx      = cp->signature_ref_index_at(nameAndTypeIdx);
-        symbolOop signature   = cp->symbol_at(signatureIdx);
+        Symbol* signature     = cp->symbol_at(signatureIdx);
         os->print("%s", signature->as_C_string());
     }
     os->cr();
@@ -1297,7 +1297,7 @@
         constantPoolOop cp    = method()->constants();
         int nameAndTypeIdx    = cp->name_and_type_ref_index_at(idx);
         int signatureIdx      = cp->signature_ref_index_at(nameAndTypeIdx);
-        symbolOop signature   = cp->symbol_at(signatureIdx);
+        Symbol* signature     = cp->symbol_at(signatureIdx);
         os->print("%s", signature->as_C_string());
     }
     os->cr();
@@ -1837,14 +1837,14 @@
 
 
 void GenerateOopMap::do_ldc(int bci) {
-  Bytecode_loadconstant* ldc = Bytecode_loadconstant_at(method(), bci);
+  Bytecode_loadconstant ldc(method(), bci);
   constantPoolOop cp  = method()->constants();
-  BasicType       bt  = ldc->result_type();
+  BasicType       bt  = ldc.result_type();
   CellTypeState   cts = (bt == T_OBJECT) ? CellTypeState::make_line_ref(bci) : valCTS;
   // Make sure bt==T_OBJECT is the same as old code (is_pointer_entry).
   // Note that CONSTANT_MethodHandle entries are u2 index pairs, not pointer-entries,
   // and they are processed by _fast_aldc and the CP cache.
-  assert((ldc->has_cache_index() || cp->is_pointer_entry(ldc->pool_index()))
+  assert((ldc.has_cache_index() || cp->is_object_entry(ldc.pool_index()))
          ? (bt == T_OBJECT) : true, "expected object type");
   ppush1(cts);
 }
@@ -1884,7 +1884,7 @@
   constantPoolOop cp     = method()->constants();
   int nameAndTypeIdx     = cp->name_and_type_ref_index_at(idx);
   int signatureIdx       = cp->signature_ref_index_at(nameAndTypeIdx);
-  symbolOop signature    = cp->symbol_at(signatureIdx);
+  Symbol* signature      = cp->symbol_at(signatureIdx);
 
   // Parse signature (espcially simple for fields)
   assert(signature->utf8_length() > 0, "field signatures cannot have zero length");
@@ -1912,7 +1912,7 @@
 void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci) {
  // Dig up signature for field in constant pool
   constantPoolOop cp  = _method->constants();
-  symbolOop signature = cp->signature_ref_at(idx);
+  Symbol* signature   = cp->signature_ref_at(idx);
 
   // Parse method signature
   CellTypeState out[4];
@@ -2343,7 +2343,7 @@
 bool GenerateOopMap::rewrite_load_or_store(BytecodeStream *bcs, Bytecodes::Code bcN, Bytecodes::Code bc0, unsigned int varNo) {
   assert(bcN == Bytecodes::_astore   || bcN == Bytecodes::_aload,   "wrong argument (bcN)");
   assert(bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0, "wrong argument (bc0)");
-  int ilen = Bytecodes::length_at(bcs->bcp());
+  int ilen = Bytecodes::length_at(_method(), bcs->bcp());
   int newIlen;
 
   if (ilen == 4) {
--- a/src/share/vm/oops/generateOopMap.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/generateOopMap.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -323,7 +323,7 @@
   // Cell type methods
   void            init_state();
   void            make_context_uninitialized ();
-  int             methodsig_to_effect        (symbolOop signature, bool isStatic, CellTypeState* effect);
+  int             methodsig_to_effect        (Symbol* signature, bool isStatic, CellTypeState* effect);
   bool            merge_local_state_vectors  (CellTypeState* cts, CellTypeState* bbts);
   bool            merge_monitor_state_vectors(CellTypeState* cts, CellTypeState* bbts);
   void            copy_state                 (CellTypeState *dst, CellTypeState *src);
--- a/src/share/vm/oops/instanceKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -41,7 +41,7 @@
 #include "oops/methodOop.hpp"
 #include "oops/objArrayKlassKlass.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/jvmtiRedefineClassesTrace.hpp"
 #include "runtime/fieldDescriptor.hpp"
@@ -96,7 +96,7 @@
   {                                                              \
     char* data = NULL;                                           \
     int len = 0;                                                 \
-    symbolOop name = (clss)->name();                             \
+    Symbol* name = (clss)->name();                               \
     if (name != NULL) {                                          \
       data = (char*)name->bytes();                               \
       len = name->utf8_length();                                 \
@@ -109,7 +109,7 @@
   {                                                              \
     char* data = NULL;                                           \
     int len = 0;                                                 \
-    symbolOop name = (clss)->name();                             \
+    Symbol* name = (clss)->name();                               \
     if (name != NULL) {                                          \
       data = (char*)name->bytes();                               \
       len = name->utf8_length();                                 \
@@ -266,7 +266,7 @@
       ResourceMark rm(THREAD);
       Exceptions::fthrow(
         THREAD_AND_LOCATION,
-        vmSymbolHandles::java_lang_IncompatibleClassChangeError(),
+        vmSymbols::java_lang_IncompatibleClassChangeError(),
         "class %s has interface %s as super class",
         this_oop->external_name(),
         super->external_name()
@@ -500,8 +500,8 @@
       THROW_OOP(e());
     } else {
       JavaCallArguments args(e);
-      THROW_ARG(vmSymbolHandles::java_lang_ExceptionInInitializerError(),
-                vmSymbolHandles::throwable_void_signature(),
+      THROW_ARG(vmSymbols::java_lang_ExceptionInInitializerError(),
+                vmSymbols::throwable_void_signature(),
                 &args);
     }
   }
@@ -772,13 +772,13 @@
 }
 
 
-bool instanceKlass::find_local_field(symbolOop name, symbolOop sig, fieldDescriptor* fd) const {
+bool instanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
   const int n = fields()->length();
   for (int i = 0; i < n; i += next_offset ) {
     int name_index = fields()->ushort_at(i + name_index_offset);
     int sig_index  = fields()->ushort_at(i + signature_index_offset);
-    symbolOop f_name = constants()->symbol_at(name_index);
-    symbolOop f_sig  = constants()->symbol_at(sig_index);
+    Symbol* f_name = constants()->symbol_at(name_index);
+    Symbol* f_sig  = constants()->symbol_at(sig_index);
     if (f_name == name && f_sig == sig) {
       fd->initialize(as_klassOop(), i);
       return true;
@@ -788,21 +788,23 @@
 }
 
 
-void instanceKlass::field_names_and_sigs_iterate(OopClosure* closure) {
+void instanceKlass::shared_symbols_iterate(SymbolClosure* closure) {
+  Klass::shared_symbols_iterate(closure);
+  closure->do_symbol(&_generic_signature);
+  closure->do_symbol(&_source_file_name);
+  closure->do_symbol(&_source_debug_extension);
+
   const int n = fields()->length();
   for (int i = 0; i < n; i += next_offset ) {
     int name_index = fields()->ushort_at(i + name_index_offset);
-    symbolOop name = constants()->symbol_at(name_index);
-    closure->do_oop((oop*)&name);
-
+    closure->do_symbol(constants()->symbol_at_addr(name_index));
     int sig_index  = fields()->ushort_at(i + signature_index_offset);
-    symbolOop sig = constants()->symbol_at(sig_index);
-    closure->do_oop((oop*)&sig);
+    closure->do_symbol(constants()->symbol_at_addr(sig_index));
   }
 }
 
 
-klassOop instanceKlass::find_interface_field(symbolOop name, symbolOop sig, fieldDescriptor* fd) const {
+klassOop instanceKlass::find_interface_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
   const int n = local_interfaces()->length();
   for (int i = 0; i < n; i++) {
     klassOop intf1 = klassOop(local_interfaces()->obj_at(i));
@@ -821,7 +823,7 @@
 }
 
 
-klassOop instanceKlass::find_field(symbolOop name, symbolOop sig, fieldDescriptor* fd) const {
+klassOop instanceKlass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
   // search order according to newest JVM spec (5.4.3.2, p.167).
   // 1) search for field in current klass
   if (find_local_field(name, sig, fd)) {
@@ -840,7 +842,7 @@
 }
 
 
-klassOop instanceKlass::find_field(symbolOop name, symbolOop sig, bool is_static, fieldDescriptor* fd) const {
+klassOop instanceKlass::find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const {
   // search order according to newest JVM spec (5.4.3.2, p.167).
   // 1) search for field in current klass
   if (find_local_field(name, sig, fd)) {
@@ -967,7 +969,7 @@
 }
 
 #ifdef ASSERT
-static int linear_search(objArrayOop methods, symbolOop name, symbolOop signature) {
+static int linear_search(objArrayOop methods, Symbol* name, Symbol* signature) {
   int len = methods->length();
   for (int index = 0; index < len; index++) {
     methodOop m = (methodOop)(methods->obj_at(index));
@@ -980,11 +982,11 @@
 }
 #endif
 
-methodOop instanceKlass::find_method(symbolOop name, symbolOop signature) const {
+methodOop instanceKlass::find_method(Symbol* name, Symbol* signature) const {
   return instanceKlass::find_method(methods(), name, signature);
 }
 
-methodOop instanceKlass::find_method(objArrayOop methods, symbolOop name, symbolOop signature) {
+methodOop instanceKlass::find_method(objArrayOop methods, Symbol* name, Symbol* signature) {
   int len = methods->length();
   // methods are sorted, so do binary search
   int l = 0;
@@ -1032,7 +1034,7 @@
   return NULL;
 }
 
-methodOop instanceKlass::uncached_lookup_method(symbolOop name, symbolOop signature) const {
+methodOop instanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
   klassOop klass = as_klassOop();
   while (klass != NULL) {
     methodOop method = instanceKlass::cast(klass)->find_method(name, signature);
@@ -1043,8 +1045,8 @@
 }
 
 // lookup a method in all the interfaces that this class implements
-methodOop instanceKlass::lookup_method_in_all_interfaces(symbolOop name,
-                                                         symbolOop signature) const {
+methodOop instanceKlass::lookup_method_in_all_interfaces(Symbol* name,
+                                                         Symbol* signature) const {
   objArrayOop all_ifs = instanceKlass::cast(as_klassOop())->transitive_interfaces();
   int num_ifs = all_ifs->length();
   instanceKlass *ik = NULL;
@@ -1992,6 +1994,26 @@
     _cached_class_file_bytes = NULL;
     _cached_class_file_len = 0;
   }
+
+  // Decrement symbol reference counts associated with the unloaded class.
+  if (_name != NULL) _name->decrement_refcount();
+  // unreference array name derived from this class name (arrays of an unloaded
+  // class can't be referenced anymore).
+  if (_array_name != NULL)  _array_name->decrement_refcount();
+  if (_source_file_name != NULL) _source_file_name->decrement_refcount();
+  if (_source_debug_extension != NULL) _source_debug_extension->decrement_refcount();
+  // walk constant pool and decrement symbol reference counts
+  _constants->unreference_symbols();
+}
+
+void instanceKlass::set_source_file_name(Symbol* n) {
+  _source_file_name = n;
+  if (_source_file_name != NULL) _source_file_name->increment_refcount();
+}
+
+void instanceKlass::set_source_debug_extension(Symbol* n) {
+  _source_debug_extension = n;
+  if (_source_debug_extension != NULL) _source_debug_extension->increment_refcount();
 }
 
 const char* instanceKlass::signature_name() const {
@@ -2013,7 +2035,7 @@
 bool instanceKlass::is_same_class_package(klassOop class2) {
   klassOop class1 = as_klassOop();
   oop classloader1 = instanceKlass::cast(class1)->class_loader();
-  symbolOop classname1 = Klass::cast(class1)->name();
+  Symbol* classname1 = Klass::cast(class1)->name();
 
   if (Klass::cast(class2)->oop_is_objArray()) {
     class2 = objArrayKlass::cast(class2)->bottom_klass();
@@ -2025,16 +2047,16 @@
     assert(Klass::cast(class2)->oop_is_typeArray(), "should be type array");
     classloader2 = NULL;
   }
-  symbolOop classname2 = Klass::cast(class2)->name();
+  Symbol* classname2 = Klass::cast(class2)->name();
 
   return instanceKlass::is_same_class_package(classloader1, classname1,
                                               classloader2, classname2);
 }
 
-bool instanceKlass::is_same_class_package(oop classloader2, symbolOop classname2) {
+bool instanceKlass::is_same_class_package(oop classloader2, Symbol* classname2) {
   klassOop class1 = as_klassOop();
   oop classloader1 = instanceKlass::cast(class1)->class_loader();
-  symbolOop classname1 = Klass::cast(class1)->name();
+  Symbol* classname1 = Klass::cast(class1)->name();
 
   return instanceKlass::is_same_class_package(classloader1, classname1,
                                               classloader2, classname2);
@@ -2042,8 +2064,8 @@
 
 // return true if two classes are in the same package, classloader
 // and classname information is enough to determine a class's package
-bool instanceKlass::is_same_class_package(oop class_loader1, symbolOop class_name1,
-                                          oop class_loader2, symbolOop class_name2) {
+bool instanceKlass::is_same_class_package(oop class_loader1, Symbol* class_name1,
+                                          oop class_loader2, Symbol* class_name2) {
   if (class_loader1 != class_loader2) {
     return false;
   } else if (class_name1 == class_name2) {
@@ -2051,14 +2073,14 @@
   } else {
     ResourceMark rm;
 
-    // The symbolOop's are in UTF8 encoding. Since we only need to check explicitly
+    // The Symbol*'s are in UTF8 encoding. Since we only need to check explicitly
     // for ASCII characters ('/', 'L', '['), we can keep them in UTF8 encoding.
     // Otherwise, we just compare jbyte values between the strings.
-    jbyte *name1 = class_name1->base();
-    jbyte *name2 = class_name2->base();
-
-    jbyte *last_slash1 = UTF8::strrchr(name1, class_name1->utf8_length(), '/');
-    jbyte *last_slash2 = UTF8::strrchr(name2, class_name2->utf8_length(), '/');
+    const jbyte *name1 = class_name1->base();
+    const jbyte *name2 = class_name2->base();
+
+    const jbyte *last_slash1 = UTF8::strrchr(name1, class_name1->utf8_length(), '/');
+    const jbyte *last_slash2 = UTF8::strrchr(name2, class_name2->utf8_length(), '/');
 
     if ((last_slash1 == NULL) || (last_slash2 == NULL)) {
       // One of the two doesn't have a package.  Only return true
@@ -2099,7 +2121,7 @@
 // Assumes name-signature match
 // "this" is instanceKlass of super_method which must exist
 // note that the instanceKlass of the method in the targetclassname has not always been created yet
-bool instanceKlass::is_override(methodHandle super_method, Handle targetclassloader, symbolHandle targetclassname, TRAPS) {
+bool instanceKlass::is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS) {
    // Private methods can not be overridden
    if (super_method->is_private()) {
      return false;
@@ -2111,12 +2133,12 @@
    }
    // Package-private methods are not inherited outside of package
    assert(super_method->is_package_private(), "must be package private");
-   return(is_same_class_package(targetclassloader(), targetclassname()));
+   return(is_same_class_package(targetclassloader(), targetclassname));
 }
 
 /* defined for now in jvm.cpp, for historical reasons *--
 klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle self,
-                                                     symbolOop& simple_name_result, TRAPS) {
+                                                     Symbol*& simple_name_result, TRAPS) {
   ...
 }
 */
@@ -2187,7 +2209,7 @@
 
       // only look at classes that are already loaded
       // since we are looking for the flags for our self.
-      symbolOop inner_name = ik->constants()->klass_name_at(ioff);
+      Symbol* inner_name = ik->constants()->klass_name_at(ioff);
       if ((ik->name() == inner_name)) {
         // This is really a member class.
         access = inner_class_list_h->ushort_at(i + instanceKlass::inner_class_access_flags_offset);
@@ -2226,7 +2248,7 @@
     // If the interface isn't implemented by the receiver class,
     // the VM should throw IncompatibleClassChangeError.
     if (cnt >= nof_interfaces) {
-      THROW_OOP_0(vmSymbols::java_lang_IncompatibleClassChangeError());
+      THROW_0(vmSymbols::java_lang_IncompatibleClassChangeError());
     }
 
     klassOop ik = ioe->interface_klass();
@@ -2236,7 +2258,7 @@
   itableMethodEntry* ime = ioe->first_method_entry(as_klassOop());
   methodOop m = ime[index].method();
   if (m == NULL) {
-    THROW_OOP_0(vmSymbols::java_lang_AbstractMethodError());
+    THROW_0(vmSymbols::java_lang_AbstractMethodError());
   }
   return m;
 }
@@ -2723,8 +2745,8 @@
       if (!emcp_methods->at(i)) {
         // only obsolete methods are interesting
         methodOop old_method = (methodOop) old_methods->obj_at(i);
-        symbolOop m_name = old_method->name();
-        symbolOop m_signature = old_method->signature();
+        Symbol* m_name = old_method->name();
+        Symbol* m_signature = old_method->signature();
 
         // skip the last entry since we just added it
         for (int j = _previous_versions->length() - 2; j >= 0; j--) {
--- a/src/share/vm/oops/instanceKlass.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/instanceKlass.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -189,16 +189,10 @@
   klassOop        _host_klass;
   // Class signers.
   objArrayOop     _signers;
-  // Name of source file containing this klass, NULL if not specified.
-  symbolOop       _source_file_name;
-  // the source debug extension for this klass, NULL if not specified.
-  symbolOop       _source_debug_extension;
   // inner_classes attribute.
   typeArrayOop    _inner_classes;
   // Implementors of this interface (not valid if it overflows)
   klassOop        _implementors[implementors_limit];
-  // Generic signature, or null if none.
-  symbolOop       _generic_signature;
   // invokedynamic bootstrap method (a java.dyn.MethodHandle)
   oop             _bootstrap_method;
   // Annotations for this class, or null if none.
@@ -222,6 +216,16 @@
   // End of the oop block.
   //
 
+  // Name of source file containing this klass, NULL if not specified.
+  Symbol*         _source_file_name;
+  // the source debug extension for this klass, NULL if not specified.
+  Symbol*         _source_debug_extension;
+  // Generic signature, or null if none.
+  Symbol*         _generic_signature;
+  // Array name derived from this class which needs unreferencing
+  // if this class is unloaded.
+  Symbol*         _array_name;
+
   // Number of heapOopSize words used by non-static fields in this klass
   // (including inherited fields but after header_size()).
   int             _nonstatic_field_size;
@@ -343,12 +347,12 @@
   };
 
   // method override check
-  bool is_override(methodHandle super_method, Handle targetclassloader, symbolHandle targetclassname, TRAPS);
+  bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
 
   // package
   bool is_same_class_package(klassOop class2);
-  bool is_same_class_package(oop classloader2, symbolOop classname2);
-  static bool is_same_class_package(oop class_loader1, symbolOop class_name1, oop class_loader2, symbolOop class_name2);
+  bool is_same_class_package(oop classloader2, Symbol* classname2);
+  static bool is_same_class_package(oop class_loader1, Symbol* class_name1, oop class_loader2, Symbol* class_name2);
 
   // find an enclosing class (defined where original code was, in jvm.cpp!)
   klassOop compute_enclosing_class(bool* inner_is_member, TRAPS) {
@@ -402,13 +406,13 @@
   void set_reference_type(ReferenceType t) { _reference_type = t; }
 
   // find local field, returns true if found
-  bool find_local_field(symbolOop name, symbolOop sig, fieldDescriptor* fd) const;
+  bool find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const;
   // find field in direct superinterfaces, returns the interface in which the field is defined
-  klassOop find_interface_field(symbolOop name, symbolOop sig, fieldDescriptor* fd) const;
+  klassOop find_interface_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const;
   // find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined
-  klassOop find_field(symbolOop name, symbolOop sig, fieldDescriptor* fd) const;
+  klassOop find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const;
   // find instance or static fields according to JVM spec 5.4.3.2, returns the klass in which the field is defined
-  klassOop find_field(symbolOop name, symbolOop sig, bool is_static, fieldDescriptor* fd) const;
+  klassOop find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const;
 
   // find a non-static or static field given its offset within the class.
   bool contains_field_offset(int offset) {
@@ -419,15 +423,15 @@
   bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
 
   // find a local method (returns NULL if not found)
-  methodOop find_method(symbolOop name, symbolOop signature) const;
-  static methodOop find_method(objArrayOop methods, symbolOop name, symbolOop signature);
+  methodOop find_method(Symbol* name, Symbol* signature) const;
+  static methodOop find_method(objArrayOop methods, Symbol* name, Symbol* signature);
 
   // lookup operation (returns NULL if not found)
-  methodOop uncached_lookup_method(symbolOop name, symbolOop signature) const;
+  methodOop uncached_lookup_method(Symbol* name, Symbol* signature) const;
 
   // lookup a method in all the interfaces that this class implements
   // (returns NULL if not found)
-  methodOop lookup_method_in_all_interfaces(symbolOop name, symbolOop signature) const;
+  methodOop lookup_method_in_all_interfaces(Symbol* name, Symbol* signature) const;
 
   // constant pool
   constantPoolOop constants() const        { return _constants; }
@@ -451,8 +455,8 @@
   void set_signers(objArrayOop s)          { oop_store((oop*) &_signers, oop(s)); }
 
   // source file name
-  symbolOop source_file_name() const       { return _source_file_name; }
-  void set_source_file_name(symbolOop n)   { oop_store_without_check((oop*) &_source_file_name, (oop) n); }
+  Symbol* source_file_name() const         { return _source_file_name; }
+  void set_source_file_name(Symbol* n);
 
   // minor and major version numbers of class file
   u2 minor_version() const                 { return _minor_version; }
@@ -461,8 +465,12 @@
   void set_major_version(u2 major_version) { _major_version = major_version; }
 
   // source debug extension
-  symbolOop source_debug_extension() const    { return _source_debug_extension; }
-  void set_source_debug_extension(symbolOop n){ oop_store_without_check((oop*) &_source_debug_extension, (oop) n); }
+  Symbol* source_debug_extension() const   { return _source_debug_extension; }
+  void set_source_debug_extension(Symbol* n);
+
+  // symbol unloading support (refcount already added)
+  Symbol* array_name()                     { return _array_name; }
+  void set_array_name(Symbol* name)        { assert(_array_name == NULL, "name already created"); _array_name = name; }
 
   // nonstatic oop-map blocks
   static int nonstatic_oop_map_size(unsigned int oop_map_count) {
@@ -511,8 +519,9 @@
   void set_initial_method_idnum(u2 value)             { _idnum_allocated_count = value; }
 
   // generics support
-  symbolOop generic_signature() const                 { return _generic_signature; }
-  void set_generic_signature(symbolOop sig)           { oop_store_without_check((oop*)&_generic_signature, (oop)sig); }
+  Symbol* generic_signature() const                   { return _generic_signature; }
+  void set_generic_signature(Symbol* sig)             { _generic_signature = sig; }
+
   u2 enclosing_method_class_index() const             { return _enclosing_method_class_index; }
   u2 enclosing_method_method_index() const            { return _enclosing_method_method_index; }
   void set_enclosing_method_indices(u2 class_index,
@@ -807,11 +816,8 @@
   oop* adr_protection_domain() const { return (oop*)&this->_protection_domain;}
   oop* adr_host_klass() const        { return (oop*)&this->_host_klass;}
   oop* adr_signers() const           { return (oop*)&this->_signers;}
-  oop* adr_source_file_name() const  { return (oop*)&this->_source_file_name;}
-  oop* adr_source_debug_extension() const { return (oop*)&this->_source_debug_extension;}
   oop* adr_inner_classes() const     { return (oop*)&this->_inner_classes;}
   oop* adr_implementors() const      { return (oop*)&this->_implementors[0];}
-  oop* adr_generic_signature() const { return (oop*)&this->_generic_signature;}
   oop* adr_bootstrap_method() const  { return (oop*)&this->_bootstrap_method;}
   oop* adr_methods_jmethod_ids() const             { return (oop*)&this->_methods_jmethod_ids;}
   oop* adr_methods_cached_itable_indices() const   { return (oop*)&this->_methods_cached_itable_indices;}
@@ -843,7 +849,7 @@
 public:
   // sharing support
   virtual void remove_unshareable_info();
-  void field_names_and_sigs_iterate(OopClosure* closure);
+  virtual void shared_symbols_iterate(SymbolClosure* closure);
 
   // jvm support
   jint compute_modifier_flags(TRAPS) const;
--- a/src/share/vm/oops/instanceKlassKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/instanceKlassKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -37,7 +37,7 @@
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.inline2.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayOop.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/fieldDescriptor.hpp"
@@ -101,13 +101,10 @@
   MarkSweep::mark_and_push(ik->adr_fields());
   MarkSweep::mark_and_push(ik->adr_constants());
   MarkSweep::mark_and_push(ik->adr_class_loader());
-  MarkSweep::mark_and_push(ik->adr_source_file_name());
-  MarkSweep::mark_and_push(ik->adr_source_debug_extension());
   MarkSweep::mark_and_push(ik->adr_inner_classes());
   MarkSweep::mark_and_push(ik->adr_protection_domain());
   MarkSweep::mark_and_push(ik->adr_host_klass());
   MarkSweep::mark_and_push(ik->adr_signers());
-  MarkSweep::mark_and_push(ik->adr_generic_signature());
   MarkSweep::mark_and_push(ik->adr_bootstrap_method());
   MarkSweep::mark_and_push(ik->adr_class_annotations());
   MarkSweep::mark_and_push(ik->adr_fields_annotations());
@@ -142,13 +139,10 @@
   PSParallelCompact::mark_and_push(cm, ik->adr_fields());
   PSParallelCompact::mark_and_push(cm, ik->adr_constants());
   PSParallelCompact::mark_and_push(cm, ik->adr_class_loader());
-  PSParallelCompact::mark_and_push(cm, ik->adr_source_file_name());
-  PSParallelCompact::mark_and_push(cm, ik->adr_source_debug_extension());
   PSParallelCompact::mark_and_push(cm, ik->adr_inner_classes());
   PSParallelCompact::mark_and_push(cm, ik->adr_protection_domain());
   PSParallelCompact::mark_and_push(cm, ik->adr_host_klass());
   PSParallelCompact::mark_and_push(cm, ik->adr_signers());
-  PSParallelCompact::mark_and_push(cm, ik->adr_generic_signature());
   PSParallelCompact::mark_and_push(cm, ik->adr_bootstrap_method());
   PSParallelCompact::mark_and_push(cm, ik->adr_class_annotations());
   PSParallelCompact::mark_and_push(cm, ik->adr_fields_annotations());
@@ -189,13 +183,10 @@
   blk->do_oop(ik->adr_protection_domain());
   blk->do_oop(ik->adr_host_klass());
   blk->do_oop(ik->adr_signers());
-  blk->do_oop(ik->adr_source_file_name());
-  blk->do_oop(ik->adr_source_debug_extension());
   blk->do_oop(ik->adr_inner_classes());
   for (int i = 0; i < instanceKlass::implementors_limit; i++) {
     blk->do_oop(&ik->adr_implementors()[i]);
   }
-  blk->do_oop(ik->adr_generic_signature());
   blk->do_oop(ik->adr_bootstrap_method());
   blk->do_oop(ik->adr_class_annotations());
   blk->do_oop(ik->adr_fields_annotations());
@@ -245,18 +236,12 @@
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_signers();
   if (mr.contains(adr)) blk->do_oop(adr);
-  adr = ik->adr_source_file_name();
-  if (mr.contains(adr)) blk->do_oop(adr);
-  adr = ik->adr_source_debug_extension();
-  if (mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_inner_classes();
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_implementors();
   for (int i = 0; i < instanceKlass::implementors_limit; i++) {
     if (mr.contains(&adr[i])) blk->do_oop(&adr[i]);
   }
-  adr = ik->adr_generic_signature();
-  if (mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_bootstrap_method();
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_class_annotations();
@@ -296,13 +281,10 @@
   MarkSweep::adjust_pointer(ik->adr_protection_domain());
   MarkSweep::adjust_pointer(ik->adr_host_klass());
   MarkSweep::adjust_pointer(ik->adr_signers());
-  MarkSweep::adjust_pointer(ik->adr_source_file_name());
-  MarkSweep::adjust_pointer(ik->adr_source_debug_extension());
   MarkSweep::adjust_pointer(ik->adr_inner_classes());
   for (int i = 0; i < instanceKlass::implementors_limit; i++) {
     MarkSweep::adjust_pointer(&ik->adr_implementors()[i]);
   }
-  MarkSweep::adjust_pointer(ik->adr_generic_signature());
   MarkSweep::adjust_pointer(ik->adr_bootstrap_method());
   MarkSweep::adjust_pointer(ik->adr_class_annotations());
   MarkSweep::adjust_pointer(ik->adr_fields_annotations());
@@ -452,6 +434,8 @@
     ik->set_signers(NULL);
     ik->set_source_file_name(NULL);
     ik->set_source_debug_extension(NULL);
+    ik->set_source_debug_extension(NULL);
+    ik->set_array_name(NULL);
     ik->set_inner_classes(NULL);
     ik->set_static_oop_field_size(0);
     ik->set_nonstatic_field_size(0);
@@ -667,7 +651,7 @@
 #endif
     // Verify that klass is present in SystemDictionary
     if (ik->is_loaded() && !ik->is_anonymous()) {
-      symbolHandle h_name (thread, ik->name());
+      Symbol* h_name = ik->name();
       Handle h_loader (thread, ik->class_loader());
       Handle h_obj(thread, obj);
       SystemDictionary::verify_obj_klass_present(h_obj, h_name, h_loader);
@@ -793,14 +777,6 @@
     guarantee(ik->constants()->is_constantPool(),    "should be constant pool");
     guarantee(ik->inner_classes()->is_perm(),        "should be in permspace");
     guarantee(ik->inner_classes()->is_typeArray(),   "should be type array");
-    if (ik->source_file_name() != NULL) {
-      guarantee(ik->source_file_name()->is_perm(),   "should be in permspace");
-      guarantee(ik->source_file_name()->is_symbol(), "should be symbol");
-    }
-    if (ik->source_debug_extension() != NULL) {
-      guarantee(ik->source_debug_extension()->is_perm(),   "should be in permspace");
-      guarantee(ik->source_debug_extension()->is_symbol(), "should be symbol");
-    }
     if (ik->protection_domain() != NULL) {
       guarantee(ik->protection_domain()->is_oop(),  "should be oop");
     }
@@ -810,10 +786,6 @@
     if (ik->signers() != NULL) {
       guarantee(ik->signers()->is_objArray(),       "should be obj array");
     }
-    if (ik->generic_signature() != NULL) {
-      guarantee(ik->generic_signature()->is_perm(),   "should be in permspace");
-      guarantee(ik->generic_signature()->is_symbol(), "should be symbol");
-    }
     if (ik->class_annotations() != NULL) {
       guarantee(ik->class_annotations()->is_typeArray(), "should be type array");
     }
--- a/src/share/vm/oops/klass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/klass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -35,6 +35,10 @@
 #include "oops/oop.inline2.hpp"
 #include "runtime/atomic.hpp"
 
+void Klass::set_name(Symbol* n) {
+  _name = n;
+  if (_name != NULL) _name->increment_refcount();
+}
 
 bool Klass::is_subclass_of(klassOop k) const {
   // Run up the super chain and check
@@ -115,7 +119,7 @@
 }
 
 
-methodOop Klass::uncached_lookup_method(symbolOop name, symbolOop signature) const {
+methodOop Klass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
 #ifdef ASSERT
   tty->print_cr("Error: uncached_lookup_method called on a klass oop."
                 " Likely error: reflection method does not correctly"
@@ -455,6 +459,11 @@
 }
 
 
+void Klass::shared_symbols_iterate(SymbolClosure* closure) {
+  closure->do_symbol(&_name);
+}
+
+
 klassOop Klass::array_klass_or_null(int rank) {
   EXCEPTION_MARK;
   // No exception can be thrown by array_klass_impl when called with or_null == true.
--- a/src/share/vm/oops/klass.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/klass.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -212,6 +212,10 @@
   // secondary supers, else is &_primary_supers[depth()].
   juint       _super_check_offset;
 
+  // Class name.  Instance classes: java/lang/String, etc.  Array classes: [I,
+  // [Ljava/lang/String;, etc.  Set to zero for all other kinds of classes.
+  Symbol*     _name;
+
  public:
   oop* oop_block_beg() const { return adr_secondary_super_cache(); }
   oop* oop_block_end() const { return adr_next_sibling() + 1; }
@@ -237,9 +241,6 @@
   oop       _c1x_mirror;
   // Superclass
   klassOop  _super;
-  // Class name.  Instance classes: java/lang/String, etc.  Array classes: [I,
-  // [Ljava/lang/String;, etc.  Set to zero for all other kinds of classes.
-  symbolOop _name;
   // First subclass (NULL if none); _subklass->next_sibling() is next one
   klassOop _subklass;
   // Sibling link (or NULL); links all subklasses of a klass
@@ -368,7 +369,6 @@
   oop* adr_secondary_supers()const { return (oop*)&_secondary_supers;  }
   oop* adr_java_mirror()     const { return (oop*)&_java_mirror;       }
   oop* adr_c1x_mirror()      const { return (oop*)&_c1x_mirror;        }
-  oop* adr_name()            const { return (oop*)&_name;              }
   oop* adr_subklass()        const { return (oop*)&_subklass;          }
   oop* adr_next_sibling()    const { return (oop*)&_next_sibling;      }
 
@@ -518,9 +518,9 @@
   virtual void initialize(TRAPS);
   // lookup operation for MethodLookupCache
   friend class MethodLookupCache;
-  virtual methodOop uncached_lookup_method(symbolOop name, symbolOop signature) const;
+  virtual methodOop uncached_lookup_method(Symbol* name, Symbol* signature) const;
  public:
-  methodOop lookup_method(symbolOop name, symbolOop signature) const {
+  methodOop lookup_method(Symbol* name, Symbol* signature) const {
     return uncached_lookup_method(name, signature);
   }
 
@@ -544,6 +544,7 @@
 
  public:
   virtual void remove_unshareable_info();
+  virtual void shared_symbols_iterate(SymbolClosure* closure);
 
  protected:
   // computes the subtype relationship
@@ -586,7 +587,6 @@
   virtual bool oop_is_instanceRef()         const { return false; }
   virtual bool oop_is_array()               const { return false; }
   virtual bool oop_is_objArray_slow()       const { return false; }
-  virtual bool oop_is_symbol()              const { return false; }
   virtual bool oop_is_klass()               const { return false; }
   virtual bool oop_is_thread()              const { return false; }
   virtual bool oop_is_method()              const { return false; }
@@ -788,8 +788,8 @@
   Klass *up_cast_abstract();
 
   // klass name
-  symbolOop name() const                   { return _name; }
-  void set_name(symbolOop n)               { oop_store_without_check((oop*) &_name, (oop) n); }
+  Symbol* name() const                   { return _name; }
+  void set_name(Symbol* n);
 
   friend class klassKlass;
 
--- a/src/share/vm/oops/klassKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/klassKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -37,8 +37,7 @@
 #include "oops/objArrayKlass.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.inline2.hpp"
-#include "oops/symbolKlass.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "runtime/handles.inline.hpp"
 #ifndef SERIALGC
@@ -71,7 +70,6 @@
   MarkSweep::mark_and_push(k->adr_secondary_supers());
   MarkSweep::mark_and_push(k->adr_java_mirror());
   MarkSweep::mark_and_push(k->adr_c1x_mirror());
-  MarkSweep::mark_and_push(k->adr_name());
   // We follow the subklass and sibling links at the end of the
   // marking phase, since otherwise following them will prevent
   // class unloading (all classes are transitively linked from
@@ -92,7 +90,6 @@
   PSParallelCompact::mark_and_push(cm, k->adr_secondary_supers());
   PSParallelCompact::mark_and_push(cm, k->adr_java_mirror());
   PSParallelCompact::mark_and_push(cm, k->adr_c1x_mirror());
-  PSParallelCompact::mark_and_push(cm, k->adr_name());
   // We follow the subklass and sibling links at the end of the
   // marking phase, since otherwise following them will prevent
   // class unloading (all classes are transitively linked from
@@ -113,7 +110,6 @@
   blk->do_oop(k->adr_secondary_supers());
   blk->do_oop(k->adr_java_mirror());
   blk->do_oop(k->adr_c1x_mirror());
-  blk->do_oop(k->adr_name());
   // The following are in the perm gen and are treated
   // specially in a later phase of a perm gen collection; ...
   assert(oop(k)->is_perm(), "should be in perm");
@@ -149,8 +145,6 @@
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = k->adr_c1x_mirror();
   if (mr.contains(adr)) blk->do_oop(adr);
-  adr = k->adr_name();
-  if (mr.contains(adr)) blk->do_oop(adr);
   // The following are "weak links" in the perm gen and are
   // treated specially in a later phase of a perm gen collection.
   assert(oop(k)->is_perm(), "should be in perm");
@@ -180,7 +174,6 @@
   MarkSweep::adjust_pointer(k->adr_secondary_supers());
   MarkSweep::adjust_pointer(k->adr_java_mirror());
   MarkSweep::adjust_pointer(k->adr_c1x_mirror());
-  MarkSweep::adjust_pointer(k->adr_name());
   MarkSweep::adjust_pointer(k->adr_subklass());
   MarkSweep::adjust_pointer(k->adr_next_sibling());
   return size;
@@ -262,9 +255,4 @@
     guarantee(k->java_mirror()->is_perm(),       "should be in permspace");
     guarantee(k->java_mirror()->is_instance(),   "should be instance");
   }
-  if (k->name() != NULL) {
-    guarantee(Universe::heap()->is_in_permanent(k->name()),
-              "should be in permspace");
-    guarantee(k->name()->is_symbol(), "should be symbol");
-  }
 }
--- a/src/share/vm/oops/klassVtable.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/klassVtable.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -61,7 +61,7 @@
                                                        objArrayOop methods,
                                                        AccessFlags class_flags,
                                                        Handle classloader,
-                                                       symbolHandle classname,
+                                                       Symbol* classname,
                                                        objArrayOop local_interfaces,
                                                        TRAPS
                                                        ) {
@@ -210,7 +210,7 @@
 // the superclass's method, but might indirectly override a super-super class's vtable entry
 // If none found, return a null superk, else return the superk of the method this does override
 instanceKlass* klassVtable::find_transitive_override(instanceKlass* initialsuper, methodHandle target_method,
-                            int vtable_index, Handle target_loader, symbolHandle target_classname, Thread * THREAD) {
+                            int vtable_index, Handle target_loader, Symbol* target_classname, Thread * THREAD) {
   instanceKlass* superk = initialsuper;
   while (superk != NULL && superk->super() != NULL) {
     instanceKlass* supersuperklass = instanceKlass::cast(superk->super());
@@ -218,9 +218,9 @@
     if (vtable_index < ssVtable->length()) {
       methodOop super_method = ssVtable->method_at(vtable_index);
 #ifndef PRODUCT
-      symbolHandle name(THREAD,target_method()->name());
-      symbolHandle signature(THREAD,target_method()->signature());
-      assert(super_method->name() == name() && super_method->signature() == signature(), "vtable entry name/sig mismatch");
+      Symbol* name= target_method()->name();
+      Symbol* signature = target_method()->signature();
+      assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch");
 #endif
       if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) {
 #ifndef PRODUCT
@@ -294,14 +294,14 @@
   // which can block for gc, once we are in this loop, use handles
   // For classfiles built with >= jdk7, we now look for transitive overrides
 
-  symbolHandle name(THREAD,target_method()->name());
-  symbolHandle signature(THREAD,target_method()->signature());
+  Symbol* name = target_method()->name();
+  Symbol* signature = target_method()->signature();
   Handle target_loader(THREAD, _klass->class_loader());
-  symbolHandle target_classname(THREAD, _klass->name());
+  Symbol*  target_classname = _klass->name();
   for(int i = 0; i < super_vtable_len; i++) {
     methodOop super_method = method_at(i);
     // Check if method name matches
-    if (super_method->name() == name() && super_method->signature() == signature()) {
+    if (super_method->name() == name && super_method->signature() == signature) {
 
       // get super_klass for method_holder for the found method
       instanceKlass* super_klass =  instanceKlass::cast(super_method->method_holder());
@@ -406,7 +406,7 @@
 bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
                                          klassOop super,
                                          Handle classloader,
-                                         symbolHandle classname,
+                                         Symbol* classname,
                                          AccessFlags class_flags,
                                          TRAPS) {
   if ((class_flags.is_final() || target_method()->is_final()) ||
@@ -436,8 +436,8 @@
   // search through the super class hierarchy to see if we need
   // a new entry
   ResourceMark rm;
-  symbolOop name = target_method()->name();
-  symbolOop signature = target_method()->signature();
+  Symbol* name = target_method()->name();
+  Symbol* signature = target_method()->signature();
   klassOop k = super;
   methodOop super_method = NULL;
   instanceKlass *holder = NULL;
@@ -485,7 +485,7 @@
 // Support for miranda methods
 
 // get the vtable index of a miranda method with matching "name" and "signature"
-int klassVtable::index_of_miranda(symbolOop name, symbolOop signature) {
+int klassVtable::index_of_miranda(Symbol* name, Symbol* signature) {
   // search from the bottom, might be faster
   for (int i = (length() - 1); i >= 0; i--) {
     methodOop m = table()[i].method();
@@ -516,9 +516,8 @@
 // check if a method is a miranda method, given a class's methods table and it's super
 // the caller must make sure that the method belongs to an interface implemented by the class
 bool klassVtable::is_miranda(methodOop m, objArrayOop class_methods, klassOop super) {
-  symbolOop name = m->name();
-  symbolOop signature = m->signature();
-
+  Symbol* name = m->name();
+  Symbol* signature = m->signature();
   if (instanceKlass::find_method(class_methods, name, signature) == NULL) {
     // did not find it in the method table of the current class
     if (super == NULL) {
@@ -929,8 +928,8 @@
   // methods needs a handle in case of gc from check_signature_loaders
   for(; i < nof_methods; i++) {
     methodOop m = (methodOop)methods()->obj_at(i);
-    symbolOop method_name = m->name();
-    symbolOop method_signature = m->signature();
+    Symbol* method_name = m->name();
+    Symbol* method_signature = m->signature();
 
     // This is same code as in Linkresolver::lookup_instance_method_in_klasses
     methodOop target = klass->uncached_lookup_method(method_name, method_signature);
--- a/src/share/vm/oops/klassVtable.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/klassVtable.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -71,7 +71,7 @@
 
   // searching; all methods return -1 if not found
   int index_of(methodOop m) const                         { return index_of(m, _length); }
-  int index_of_miranda(symbolOop name, symbolOop signature);
+  int index_of_miranda(Symbol* name, Symbol* signature);
 
   void initialize_vtable(bool checkconstraints, TRAPS);   // initialize vtable of a new klass
 
@@ -79,7 +79,7 @@
   static void compute_vtable_size_and_num_mirandas(int &vtable_length, int &num_miranda_methods,
                                                    klassOop super, objArrayOop methods,
                                                    AccessFlags class_flags, Handle classloader,
-                                                   symbolHandle classname, objArrayOop local_interfaces,
+                                                   Symbol* classname, objArrayOop local_interfaces,
                                                    TRAPS);
 
   // RedefineClasses() API support:
@@ -125,11 +125,11 @@
   int  initialize_from_super(KlassHandle super);
   int  index_of(methodOop m, int len) const; // same as index_of, but search only up to len
   void put_method_at(methodOop m, int index);
-  static bool needs_new_vtable_entry(methodHandle m, klassOop super, Handle classloader, symbolHandle classname, AccessFlags access_flags, TRAPS);
+  static bool needs_new_vtable_entry(methodHandle m, klassOop super, Handle classloader, Symbol* classname, AccessFlags access_flags, TRAPS);
 
   bool update_inherited_vtable(instanceKlass* klass, methodHandle target_method, int super_vtable_len, bool checkconstraints, TRAPS);
  instanceKlass* find_transitive_override(instanceKlass* initialsuper, methodHandle target_method, int vtable_index,
-                                         Handle target_loader, symbolHandle target_classname, Thread* THREAD);
+                                         Handle target_loader, Symbol* target_classname, Thread* THREAD);
 
   // support for miranda methods
   bool is_miranda_entry_at(int i);
--- a/src/share/vm/oops/markOop.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/markOop.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -118,14 +118,7 @@
   };
 
   // The biased locking code currently requires that the age bits be
-  // contiguous to the lock bits. Class data sharing would prefer the
-  // hash bits to be lower down to provide more random hash codes for
-  // shared read-only symbolOop objects, because these objects' mark
-  // words are set to their own address with marked_value in the lock
-  // bit, and using lower bits would make their identity hash values
-  // more random. However, the performance decision was made in favor
-  // of the biased locking code.
-
+  // contiguous to the lock bits.
   enum { lock_shift               = 0,
          biased_lock_shift        = lock_bits,
          age_shift                = lock_bits + biased_lock_bits,
--- a/src/share/vm/oops/methodDataOop.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/methodDataOop.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -417,11 +417,11 @@
 int MultiBranchData::compute_cell_count(BytecodeStream* stream) {
   int cell_count = 0;
   if (stream->code() == Bytecodes::_tableswitch) {
-    Bytecode_tableswitch* sw = Bytecode_tableswitch_at(stream->bcp());
-    cell_count = 1 + per_case_cell_count * (1 + sw->length()); // 1 for default
+    Bytecode_tableswitch sw(stream->method()(), stream->bcp());
+    cell_count = 1 + per_case_cell_count * (1 + sw.length()); // 1 for default
   } else {
-    Bytecode_lookupswitch* sw = Bytecode_lookupswitch_at(stream->bcp());
-    cell_count = 1 + per_case_cell_count * (sw->number_of_pairs() + 1); // 1 for default
+    Bytecode_lookupswitch sw(stream->method()(), stream->bcp());
+    cell_count = 1 + per_case_cell_count * (sw.number_of_pairs() + 1); // 1 for default
   }
   return cell_count;
 }
@@ -434,35 +434,35 @@
   int target_di;
   int offset;
   if (stream->code() == Bytecodes::_tableswitch) {
-    Bytecode_tableswitch* sw = Bytecode_tableswitch_at(stream->bcp());
-    int len = sw->length();
+    Bytecode_tableswitch sw(stream->method()(), stream->bcp());
+    int len = sw.length();
     assert(array_len() == per_case_cell_count * (len + 1), "wrong len");
     for (int count = 0; count < len; count++) {
-      target = sw->dest_offset_at(count) + bci();
+      target = sw.dest_offset_at(count) + bci();
       my_di = mdo->dp_to_di(dp());
       target_di = mdo->bci_to_di(target);
       offset = target_di - my_di;
       set_displacement_at(count, offset);
     }
-    target = sw->default_offset() + bci();
+    target = sw.default_offset() + bci();
     my_di = mdo->dp_to_di(dp());
     target_di = mdo->bci_to_di(target);
     offset = target_di - my_di;
     set_default_displacement(offset);
 
   } else {
-    Bytecode_lookupswitch* sw = Bytecode_lookupswitch_at(stream->bcp());
-    int npairs = sw->number_of_pairs();
+    Bytecode_lookupswitch sw(stream->method()(), stream->bcp());
+    int npairs = sw.number_of_pairs();
     assert(array_len() == per_case_cell_count * (npairs + 1), "wrong len");
     for (int count = 0; count < npairs; count++) {
-      LookupswitchPair *pair = sw->pair_at(count);
-      target = pair->offset() + bci();
+      LookupswitchPair pair = sw.pair_at(count);
+      target = pair.offset() + bci();
       my_di = mdo->dp_to_di(dp());
       target_di = mdo->bci_to_di(target);
       offset = target_di - my_di;
       set_displacement_at(count, offset);
     }
-    target = sw->default_offset() + bci();
+    target = sw.default_offset() + bci();
     my_di = mdo->dp_to_di(dp());
     target_di = mdo->bci_to_di(target);
     offset = target_di - my_di;
--- a/src/share/vm/oops/methodKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/methodKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -36,7 +36,7 @@
 #include "oops/methodKlass.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.inline2.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 
 klassOop methodKlass::create_klass(TRAPS) {
@@ -353,10 +353,6 @@
   if (!obj->partially_loaded()) {
     methodOop m = methodOop(obj);
     guarantee(m->is_perm(),  "should be in permspace");
-    guarantee(m->name()->is_perm(), "should be in permspace");
-    guarantee(m->name()->is_symbol(), "should be symbol");
-    guarantee(m->signature()->is_perm(), "should be in permspace");
-    guarantee(m->signature()->is_symbol(), "should be symbol");
     guarantee(m->constants()->is_perm(), "should be in permspace");
     guarantee(m->constants()->is_constantPool(), "should be constant pool");
     guarantee(m->constMethod()->is_constMethod(), "should be constMethodOop");
--- a/src/share/vm/oops/methodOop.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/methodOop.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
 #include "oops/methodDataOop.hpp"
 #include "oops/methodOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/methodHandleWalk.hpp"
 #include "prims/nativeLookup.hpp"
@@ -77,7 +77,7 @@
   return name_and_sig_as_C_string(Klass::cast(constants()->pool_holder()), name(), signature(), buf, size);
 }
 
-char* methodOopDesc::name_and_sig_as_C_string(Klass* klass, symbolOop method_name, symbolOop signature) {
+char* methodOopDesc::name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature) {
   const char* klass_name = klass->external_name();
   int klass_name_len  = (int)strlen(klass_name);
   int method_name_len = method_name->utf8_length();
@@ -91,8 +91,8 @@
   return dest;
 }
 
-char* methodOopDesc::name_and_sig_as_C_string(Klass* klass, symbolOop method_name, symbolOop signature, char* buf, int size) {
-  symbolOop klass_name = klass->name();
+char* methodOopDesc::name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature, char* buf, int size) {
+  Symbol* klass_name = klass->name();
   klass_name->as_klass_external_name(buf, size);
   int len = (int)strlen(buf);
 
@@ -150,17 +150,6 @@
   return -1;
 }
 
-methodOop methodOopDesc::method_from_bcp(address bcp) {
-  debug_only(static int count = 0; count++);
-  assert(Universe::heap()->is_in_permanent(bcp), "bcp not in perm_gen");
-  // TO DO: this may be unsafe in some configurations
-  HeapWord* p = Universe::heap()->block_start(bcp);
-  assert(Universe::heap()->block_is_obj(p), "must be obj");
-  assert(oop(p)->is_constMethod(), "not a method");
-  return constMethodOop(p)->method();
-}
-
-
 void methodOopDesc::mask_for(int bci, InterpreterOopMap* mask) {
 
   Thread* myThread    = Thread::current();
@@ -232,7 +221,7 @@
 }
 
 
-symbolOop methodOopDesc::klass_name() const {
+Symbol* methodOopDesc::klass_name() const {
   klassOop k = method_holder();
   assert(k->is_klass(), "must be klass");
   instanceKlass* ik = (instanceKlass*) k->klass_part();
@@ -344,8 +333,7 @@
 
 
 void methodOopDesc::compute_size_of_parameters(Thread *thread) {
-  symbolHandle h_signature(thread, signature());
-  ArgumentSizeComputer asc(h_signature);
+  ArgumentSizeComputer asc(signature());
   set_size_of_parameters(asc.size() + (is_static() ? 0 : 1));
 }
 
@@ -469,11 +457,10 @@
 bool methodOopDesc::is_accessor() const {
   if (code_size() != 5) return false;
   if (size_of_parameters() != 1) return false;
-  methodOop m = (methodOop)this;  // pass to code_at() to avoid method_from_bcp
-  if (Bytecodes::java_code_at(code_base()+0, m) != Bytecodes::_aload_0 ) return false;
-  if (Bytecodes::java_code_at(code_base()+1, m) != Bytecodes::_getfield) return false;
-  if (Bytecodes::java_code_at(code_base()+4, m) != Bytecodes::_areturn &&
-      Bytecodes::java_code_at(code_base()+4, m) != Bytecodes::_ireturn ) return false;
+  if (java_code_at(0) != Bytecodes::_aload_0 ) return false;
+  if (java_code_at(1) != Bytecodes::_getfield) return false;
+  if (java_code_at(4) != Bytecodes::_areturn &&
+      java_code_at(4) != Bytecodes::_ireturn ) return false;
   return true;
 }
 
@@ -532,7 +519,7 @@
 bool methodOopDesc::is_klass_loaded_by_klass_index(int klass_index) const {
   if( _constants->tag_at(klass_index).is_unresolved_klass() ) {
     Thread *thread = Thread::current();
-    symbolHandle klass_name(thread, _constants->klass_name_at(klass_index));
+    Symbol* klass_name = _constants->klass_name_at(klass_index);
     Handle loader(thread, instanceKlass::cast(method_holder())->class_loader());
     Handle prot  (thread, Klass::cast(method_holder())->protection_domain());
     return SystemDictionary::find(klass_name, loader, prot, thread) != NULL;
@@ -864,7 +851,7 @@
 // Constant pool structure for invoke methods:
 enum {
   _imcp_invoke_name = 1,        // utf8: 'invokeExact' or 'invokeGeneric'
-  _imcp_invoke_signature,       // utf8: (variable symbolOop)
+  _imcp_invoke_signature,       // utf8: (variable Symbol*)
   _imcp_method_type_value,      // string: (variable java/dyn/MethodType, sic)
   _imcp_limit
 };
@@ -907,8 +894,8 @@
 }
 
 methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
-                                               symbolHandle name,
-                                               symbolHandle signature,
+                                               Symbol* name,
+                                               Symbol* signature,
                                                Handle method_type, TRAPS) {
   methodHandle empty;
 
@@ -926,9 +913,9 @@
     constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty));
     cp = constantPoolHandle(THREAD, cp_oop);
   }
-  cp->symbol_at_put(_imcp_invoke_name,       name());
-  cp->symbol_at_put(_imcp_invoke_signature,  signature());
-  cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature());
+  cp->symbol_at_put(_imcp_invoke_name,       name);
+  cp->symbol_at_put(_imcp_invoke_signature,  signature);
+  cp->string_at_put(_imcp_method_type_value, Universe::the_null_string());
   cp->set_pool_holder(holder());
 
   // set up the fancy stuff:
@@ -944,7 +931,7 @@
   m->set_name_index(_imcp_invoke_name);
   m->set_signature_index(_imcp_invoke_signature);
   assert(is_method_handle_invoke_name(m->name()), "");
-  assert(m->signature() == signature(), "");
+  assert(m->signature() == signature, "");
   assert(m->is_method_handle_invoke(), "");
 #ifdef CC_INTERP
   ResultTypeFinder rtf(signature());
@@ -1059,7 +1046,7 @@
     return vmSymbols::NO_SID;   // regardless of name, no intrinsics here
 
   // see if the klass name is well-known:
-  symbolOop klass_name = instanceKlass::cast(holder)->name();
+  Symbol* klass_name = instanceKlass::cast(holder)->name();
   return vmSymbols::find_sid(klass_name);
 }
 
@@ -1135,11 +1122,12 @@
   bool sig_is_loaded = true;
   Handle class_loader(THREAD, instanceKlass::cast(m->method_holder())->class_loader());
   Handle protection_domain(THREAD, Klass::cast(m->method_holder())->protection_domain());
-  symbolHandle signature(THREAD, m->signature());
+  ResourceMark rm(THREAD);
+  Symbol*  signature = m->signature();
   for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
     if (ss.is_object()) {
-      symbolOop sym = ss.as_symbol(CHECK_(false));
-      symbolHandle name (THREAD, sym);
+      Symbol* sym = ss.as_symbol(CHECK_(false));
+      Symbol*  name  = sym;
       klassOop klass = SystemDictionary::resolve_or_null(name, class_loader,
                                              protection_domain, THREAD);
       // We are loading classes eagerly. If a ClassNotFoundException or
@@ -1161,11 +1149,12 @@
 bool methodOopDesc::has_unloaded_classes_in_signature(methodHandle m, TRAPS) {
   Handle class_loader(THREAD, instanceKlass::cast(m->method_holder())->class_loader());
   Handle protection_domain(THREAD, Klass::cast(m->method_holder())->protection_domain());
-  symbolHandle signature(THREAD, m->signature());
+  ResourceMark rm(THREAD);
+  Symbol*  signature = m->signature();
   for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
     if (ss.type() == T_OBJECT) {
-      symbolHandle name(THREAD, ss.as_symbol_or_null());
-      if (name() == NULL) return true;
+      Symbol* name = ss.as_symbol_or_null();
+      if (name == NULL) return true;
       klassOop klass = SystemDictionary::find(name, class_loader, protection_domain, THREAD);
       if (klass == NULL) return true;
     }
@@ -1329,7 +1318,7 @@
   }
 
  public:
-  SignatureTypePrinter(symbolHandle signature, outputStream* st) : SignatureTypeNames(signature) {
+  SignatureTypePrinter(Symbol* signature, outputStream* st) : SignatureTypeNames(signature) {
     _st = st;
     _use_separator = false;
   }
@@ -1414,7 +1403,7 @@
 }
 
 
-Bytecodes::Code methodOopDesc::orig_bytecode_at(int bci) {
+Bytecodes::Code methodOopDesc::orig_bytecode_at(int bci) const {
   BreakpointInfo* bp = instanceKlass::cast(method_holder())->breakpoints();
   for (; bp != NULL; bp = bp->next()) {
     if (bp->match(this, bci)) {
--- a/src/share/vm/oops/methodOop.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/methodOop.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -161,17 +161,17 @@
   void set_access_flags(AccessFlags flags)       { _access_flags = flags; }
 
   // name
-  symbolOop name() const                         { return _constants->symbol_at(name_index()); }
+  Symbol* name() const                           { return _constants->symbol_at(name_index()); }
   int name_index() const                         { return constMethod()->name_index();         }
   void set_name_index(int index)                 { constMethod()->set_name_index(index);       }
 
   // signature
-  symbolOop signature() const                    { return _constants->symbol_at(signature_index()); }
+  Symbol* signature() const                      { return _constants->symbol_at(signature_index()); }
   int signature_index() const                    { return constMethod()->signature_index();         }
   void set_signature_index(int index)            { constMethod()->set_signature_index(index);       }
 
   // generics support
-  symbolOop generic_signature() const            { int idx = generic_signature_index(); return ((idx != 0) ? _constants->symbol_at(idx) : (symbolOop)NULL); }
+  Symbol* generic_signature() const              { int idx = generic_signature_index(); return ((idx != 0) ? _constants->symbol_at(idx) : (Symbol*)NULL); }
   int generic_signature_index() const            { return constMethod()->generic_signature_index(); }
   void set_generic_signature_index(int index)    { constMethod()->set_generic_signature_index(index); }
 
@@ -193,11 +193,18 @@
   char* name_and_sig_as_C_string(char* buf, int size);
 
   // Static routine in the situations we don't have a methodOop
-  static char* name_and_sig_as_C_string(Klass* klass, symbolOop method_name, symbolOop signature);
-  static char* name_and_sig_as_C_string(Klass* klass, symbolOop method_name, symbolOop signature, char* buf, int size);
+  static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature);
+  static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature, char* buf, int size);
+
+  Bytecodes::Code java_code_at(int bci) const {
+    return Bytecodes::java_code_at(this, bcp_from(bci));
+  }
+  Bytecodes::Code code_at(int bci) const {
+    return Bytecodes::code_at(this, bcp_from(bci));
+  }
 
   // JVMTI breakpoints
-  Bytecodes::Code orig_bytecode_at(int bci);
+  Bytecodes::Code orig_bytecode_at(int bci) const;
   void        set_orig_bytecode_at(int bci, Bytecodes::Code code);
   void set_breakpoint(int bci);
   void clear_breakpoint(int bci);
@@ -426,7 +433,7 @@
   klassOop method_holder() const                 { return _constants->pool_holder(); }
 
   void compute_size_of_parameters(Thread *thread); // word size of parameters (receiver if any + arguments)
-  symbolOop klass_name() const;                  // returns the name of the method holder
+  Symbol* klass_name() const;                    // returns the name of the method holder
   BasicType result_type() const;                 // type of the method result
   int result_type_index() const;                 // type index of the method result
   bool is_returning_oop() const                  { BasicType r = result_type(); return (r == T_OBJECT || r == T_ARRAY); }
@@ -557,15 +564,15 @@
   // JSR 292 support
   bool is_method_handle_invoke() const              { return access_flags().is_method_handle_invoke(); }
   static bool is_method_handle_invoke_name(vmSymbols::SID name_sid);
-  static bool is_method_handle_invoke_name(symbolOop name) {
+  static bool is_method_handle_invoke_name(Symbol* name) {
     return is_method_handle_invoke_name(vmSymbols::find_sid(name));
   }
   // Tests if this method is an internal adapter frame from the
   // MethodHandleCompiler.
   bool is_method_handle_adapter() const;
   static methodHandle make_invoke_method(KlassHandle holder,
-                                         symbolHandle name, //invokeExact or invokeGeneric
-                                         symbolHandle signature, //anything at all
+                                         Symbol* name, //invokeExact or invokeGeneric
+                                         Symbol* signature, //anything at all
                                          Handle method_type,
                                          TRAPS);
   // these operate only on invoke methods:
@@ -655,8 +662,6 @@
   void set_queued_for_compilation()    { _access_flags.set_queued_for_compilation();     }
   void clear_queued_for_compilation()  { _access_flags.clear_queued_for_compilation();   }
 
-  static methodOop method_from_bcp(address bcp);
-
   // Resolve all classes in signature, return 'true' if successful
   static bool load_signature_classes(methodHandle m, TRAPS);
 
@@ -787,11 +792,11 @@
   void                 set_next(BreakpointInfo* n)    { _next = n; }
 
   // helps for searchers
-  bool match(methodOop m, int bci) {
+  bool match(const methodOopDesc* m, int bci) {
     return bci == _bci && match(m);
   }
 
-  bool match(methodOop m) {
+  bool match(const methodOopDesc* m) {
     return _name_index == m->name_index() &&
       _signature_index == m->signature_index();
   }
--- a/src/share/vm/oops/objArrayKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/objArrayKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.inline2.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "utilities/copy.hpp"
@@ -235,8 +235,9 @@
           objArrayKlassKlass::cast(Universe::objArrayKlassKlassObj())->
           allocate_objArray_klass(dimension + 1, this_oop, CHECK_NULL);
         ak = objArrayKlassHandle(THREAD, new_klass);
+        ak->set_lower_dimension(this_oop());
+        OrderAccess::storestore();
         this_oop->set_higher_dimension(ak());
-        ak->set_lower_dimension(this_oop());
         assert(ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
       }
     }
--- a/src/share/vm/oops/objArrayKlassKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/objArrayKlassKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -110,14 +110,11 @@
     }
   }
 
-  // Create type name for klass (except for symbol arrays, since symbolKlass
-  // does not have a name).  This will potentially allocate an object, cause
-  // GC, and all other kinds of things.  Hence, this must be done before we
-  // get a handle to the new objArrayKlass we want to construct.  We cannot
-  // block while holding a handling to a partly initialized object.
-  symbolHandle name = symbolHandle();
+  // Create type name for klass.
+  Symbol* name = NULL;
+  if (!element_klass->oop_is_instance() ||
+      (name = instanceKlass::cast(element_klass())->array_name()) == NULL) {
 
-  if (!element_klass->oop_is_symbol()) {
     ResourceMark rm(THREAD);
     char *name_str = element_klass->name()->as_C_string();
     int len = element_klass->name()->utf8_length();
@@ -133,7 +130,11 @@
       new_str[idx++] = ';';
     }
     new_str[idx++] = '\0';
-    name = oopFactory::new_symbol_handle(new_str, CHECK_0);
+    name = SymbolTable::new_symbol(new_str, CHECK_0);
+    if (element_klass->oop_is_instance()) {
+      instanceKlass* ik = instanceKlass::cast(element_klass());
+      ik->set_array_name(name);
+    }
   }
 
   objArrayKlass o;
@@ -142,12 +143,15 @@
                                                           this_oop,
                                                            CHECK_0);
 
-
   // Initialize instance variables
   objArrayKlass* oak = objArrayKlass::cast(k());
   oak->set_dimension(n);
   oak->set_element_klass(element_klass());
-  oak->set_name(name());
+  oak->set_name(name);
+  // decrement refcount because object arrays are not explicitly freed.  The
+  // instanceKlass array_name() keeps the name counted while the klass is
+  // loaded.
+  name->decrement_refcount();
 
   klassOop bk;
   if (element_klass->oop_is_objArray()) {
--- a/src/share/vm/oops/oop.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/oop.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -127,7 +127,6 @@
   bool is_instanceRef()        const;
   bool is_array()              const;
   bool is_objArray()           const;
-  bool is_symbol()             const;
   bool is_klass()              const;
   bool is_thread()             const;
   bool is_method()             const;
--- a/src/share/vm/oops/oop.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/oop.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -140,7 +140,6 @@
 inline bool oopDesc::is_objArray()           const { return blueprint()->oop_is_objArray(); }
 inline bool oopDesc::is_typeArray()          const { return blueprint()->oop_is_typeArray(); }
 inline bool oopDesc::is_javaArray()          const { return blueprint()->oop_is_javaArray(); }
-inline bool oopDesc::is_symbol()             const { return blueprint()->oop_is_symbol(); }
 inline bool oopDesc::is_klass()              const { return blueprint()->oop_is_klass(); }
 inline bool oopDesc::is_thread()             const { return blueprint()->oop_is_thread(); }
 inline bool oopDesc::is_method()             const { return blueprint()->oop_is_method(); }
--- a/src/share/vm/oops/oopsHierarchy.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/oopsHierarchy.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -49,7 +49,6 @@
 typedef class     typeArrayOopDesc*            typeArrayOop;
 typedef class   constantPoolOopDesc*            constantPoolOop;
 typedef class   constantPoolCacheOopDesc*   constantPoolCacheOop;
-typedef class   symbolOopDesc*                    symbolOop;
 typedef class   klassOopDesc*                    klassOop;
 typedef class   markOopDesc*                    markOop;
 typedef class   compiledICHolderOopDesc*    compiledICHolderOop;
@@ -166,7 +165,6 @@
 DEF_OOP(constantPoolCache);
 DEF_OOP(objArray);
 DEF_OOP(typeArray);
-DEF_OOP(symbol);
 DEF_OOP(klass);
 DEF_OOP(compiledICHolder);
 
@@ -190,7 +188,6 @@
 class     typeArrayKlass;
 class   constantPoolKlass;
 class   constantPoolCacheKlass;
-class   symbolKlass;
 class   compiledICHolderKlass;
 
 #endif // SHARE_VM_OOPS_OOPSHIERARCHY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/oops/symbol.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+
+#include "precompiled.hpp"
+#include "oops/oop.inline.hpp"
+#include "oops/symbol.hpp"
+#include "runtime/os.hpp"
+#include "memory/allocation.inline.hpp"
+
+Symbol::Symbol(const u1* name, int length) : _refcount(0), _length(length) {
+  _identity_hash = os::random();
+  for (int i = 0; i < _length; i++) {
+    byte_at_put(i, name[i]);
+  }
+}
+
+void* Symbol::operator new(size_t size, int len) {
+  return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol");
+}
+
+// ------------------------------------------------------------------
+// Symbol::equals
+//
+// Compares the symbol with a string of the given length.
+bool Symbol::equals(const char* str, int len) const {
+  int l = utf8_length();
+  if (l != len) return false;
+  while (l-- > 0) {
+    if (str[l] != (char) byte_at(l))
+      return false;
+  }
+  assert(l == -1, "we should be at the beginning");
+  return true;
+}
+
+
+// ------------------------------------------------------------------
+// Symbol::starts_with
+//
+// Tests if the symbol starts with the specified prefix of the given
+// length.
+bool Symbol::starts_with(const char* prefix, int len) const {
+  if (len > utf8_length()) return false;
+  while (len-- > 0) {
+    if (prefix[len] != (char) byte_at(len))
+      return false;
+  }
+  assert(len == -1, "we should be at the beginning");
+  return true;
+}
+
+
+// ------------------------------------------------------------------
+// Symbol::index_of
+//
+// Finds if the given string is a substring of this symbol's utf8 bytes.
+// Return -1 on failure.  Otherwise return the first index where str occurs.
+int Symbol::index_of_at(int i, const char* str, int len) const {
+  assert(i >= 0 && i <= utf8_length(), "oob");
+  if (len <= 0)  return 0;
+  char first_char = str[0];
+  address bytes = (address) ((Symbol*)this)->base();
+  address limit = bytes + utf8_length() - len;  // inclusive limit
+  address scan = bytes + i;
+  if (scan > limit)
+    return -1;
+  for (;;) {
+    scan = (address) memchr(scan, first_char, (limit + 1 - scan));
+    if (scan == NULL)
+      return -1;  // not found
+    assert(scan >= bytes+i && scan <= limit, "scan oob");
+    if (memcmp(scan, str, len) == 0)
+      return (int)(scan - bytes);
+  }
+}
+
+
+char* Symbol::as_C_string(char* buf, int size) const {
+  if (size > 0) {
+    int len = MIN2(size - 1, utf8_length());
+    for (int i = 0; i < len; i++) {
+      buf[i] = byte_at(i);
+    }
+    buf[len] = '\0';
+  }
+  return buf;
+}
+
+char* Symbol::as_C_string() const {
+  int len = utf8_length();
+  char* str = NEW_RESOURCE_ARRAY(char, len + 1);
+  return as_C_string(str, len + 1);
+}
+
+char* Symbol::as_C_string_flexible_buffer(Thread* t,
+                                                 char* buf, int size) const {
+  char* str;
+  int len = utf8_length();
+  int buf_len = len + 1;
+  if (size < buf_len) {
+    str = NEW_RESOURCE_ARRAY(char, buf_len);
+  } else {
+    str = buf;
+  }
+  return as_C_string(str, buf_len);
+}
+
+void Symbol::print_symbol_on(outputStream* st) const {
+  st = st ? st : tty;
+  int length = UTF8::unicode_length((const char*)bytes(), utf8_length());
+  const char *ptr = (const char *)bytes();
+  jchar value;
+  for (int index = 0; index < length; index++) {
+    ptr = UTF8::next(ptr, &value);
+    if (value >= 32 && value < 127 || value == '\'' || value == '\\') {
+      st->put(value);
+    } else {
+      st->print("\\u%04x", value);
+    }
+  }
+}
+
+jchar* Symbol::as_unicode(int& length) const {
+  Symbol* this_ptr = (Symbol*)this;
+  length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length());
+  jchar* result = NEW_RESOURCE_ARRAY(jchar, length);
+  if (length > 0) {
+    UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length);
+  }
+  return result;
+}
+
+const char* Symbol::as_klass_external_name(char* buf, int size) const {
+  if (size > 0) {
+    char* str    = as_C_string(buf, size);
+    int   length = (int)strlen(str);
+    // Turn all '/'s into '.'s (also for array klasses)
+    for (int index = 0; index < length; index++) {
+      if (str[index] == '/') {
+        str[index] = '.';
+      }
+    }
+    return str;
+  } else {
+    return buf;
+  }
+}
+
+const char* Symbol::as_klass_external_name() const {
+  char* str    = as_C_string();
+  int   length = (int)strlen(str);
+  // Turn all '/'s into '.'s (also for array klasses)
+  for (int index = 0; index < length; index++) {
+    if (str[index] == '/') {
+      str[index] = '.';
+    }
+  }
+  return str;
+}
+
+
+void Symbol::print_on(outputStream* st) const {
+  if (this == NULL) {
+    st->print_cr("NULL");
+  } else {
+    st->print("Symbol: '");
+    print_symbol_on(st);
+    st->print("'");
+    st->print(" count %d", refcount());
+  }
+}
+
+// The print_value functions are present in all builds, to support the
+// disassembler and error reporting.
+void Symbol::print_value_on(outputStream* st) const {
+  if (this == NULL) {
+    st->print("NULL");
+  } else {
+    st->print("'");
+    for (int i = 0; i < utf8_length(); i++) {
+      st->print("%c", byte_at(i));
+    }
+    st->print("'");
+  }
+}
+
+void Symbol::increment_refcount() {
+  // Only increment the refcount if positive.  If negative either
+  // overflow has occurred or it is a permanent symbol in a read only
+  // shared archive.
+  if (_refcount >= 0) {
+    Atomic::inc(&_refcount);
+    NOT_PRODUCT(Atomic::inc(&_total_count);)
+  }
+}
+
+void Symbol::decrement_refcount() {
+  if (_refcount >= 0) {
+    Atomic::dec(&_refcount);
+#ifdef ASSERT
+    if (_refcount < 0) {
+      print();
+      assert(false, "reference count underflow for symbol");
+    }
+#endif
+  }
+}
+
+NOT_PRODUCT(int Symbol::_total_count = 0;)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/oops/symbol.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_OOPS_SYMBOL_HPP
+#define SHARE_VM_OOPS_SYMBOL_HPP
+
+#include "utilities/utf8.hpp"
+#include "memory/allocation.hpp"
+
+// A Symbol is a canonicalized string.
+// All Symbols reside in global SymbolTable and are reference counted.
+
+// Reference counting
+//
+// All Symbols are allocated and added to the SymbolTable.
+// When a class is unloaded, the reference counts of the Symbol pointers in
+// the ConstantPool and in instanceKlass (see release_C_heap_structures) are
+// decremented.  When the reference count for a Symbol goes to 0, the garbage
+// collector can free the Symbol and remove it from the SymbolTable.
+//
+// 0) Symbols need to be reference counted when a pointer to the Symbol is
+// saved in persistent storage.  This does not include the pointer
+// in the SymbolTable bucket (the _literal field in HashtableEntry)
+// that points to the Symbol.  All other stores of a Symbol*
+// to a field of a persistent variable (e.g., the _name filed in
+// FieldAccessInfo or _ptr in a CPSlot) is reference counted.
+//
+// 1) The lookup of a "name" in the SymbolTable either creates a Symbol F for
+// "name" and returns a pointer to F or finds a pre-existing Symbol F for
+// "name" and returns a pointer to it. In both cases the reference count for F
+// is incremented under the assumption that a pointer to F will be created from
+// the return value. Thus the increment of the reference count is on the lookup
+// and not on the assignment to the new Symbol*.  That is
+//    Symbol* G = lookup()
+//                ^ increment on lookup()
+// and not
+//    Symbol* G = lookup()
+//              ^ increment on assignmnet
+// The reference count must be decremented manually when the copy of the
+// pointer G is destroyed.
+//
+// 2) For a local Symbol* A that is a copy of an existing Symbol* B, the
+// reference counting is elided when the scope of B is greater than the scope
+// of A.  For example, in the code fragment
+// below "klass" is passed as a parameter to the method.  Symbol* "kn"
+// is a copy of the name in "klass".
+//
+//   Symbol*  kn = klass->name();
+//   unsigned int d_hash = dictionary()->compute_hash(kn, class_loader);
+//
+// The scope of "klass" is greater than the scope of "kn" so the reference
+// counting for "kn" is elided.
+//
+// Symbol* copied from ConstantPool entries are good candidates for reference
+// counting elision.  The ConstantPool entries for a class C exist until C is
+// unloaded.  If a Symbol* is copied out of the ConstantPool into Symbol* X,
+// the Symbol* in the ConstantPool will in general out live X so the reference
+// counting on X can be elided.
+//
+// For cases where the scope of A is not greater than the scope of B,
+// the reference counting is explicitly done.  See ciSymbol,
+// ResolutionErrorEntry and ClassVerifier for examples.
+//
+// 3) When a Symbol K is created for temporary use, generally for substrings of
+// an existing symbol or to create a new symbol, assign it to a
+// TempNewSymbol. The SymbolTable methods new_symbol(), lookup()
+// and probe() all potentially return a pointer to a new Symbol.
+// The allocation (or lookup) of K increments the reference count for K
+// and the destructor decrements the reference count.
+//
+// Another example of TempNewSymbol usage is parsed_name used in
+// ClassFileParser::parseClassFile() where parsed_name is used in the cleanup
+// after a failed attempt to load a class.  Here parsed_name is a
+// TempNewSymbol (passed in as a parameter) so the reference count on its symbol
+// will be decremented when it goes out of scope.
+
+class Symbol : public CHeapObj {
+  friend class VMStructs;
+  friend class SymbolTable;
+  friend class MoveSymbols;
+ private:
+  volatile int   _refcount;
+  int            _identity_hash;
+  unsigned short _length; // number of UTF8 characters in the symbol
+  jbyte _body[1];
+
+  enum {
+    // max_symbol_length is constrained by type of _length
+    max_symbol_length = (1 << 16) -1
+  };
+
+  static int object_size(int length) {
+    size_t size = heap_word_size(sizeof(Symbol) + length);
+    return align_object_size(size);
+  }
+
+  void byte_at_put(int index, int value) {
+    assert(index >=0 && index < _length, "symbol index overflow");
+    _body[index] = value;
+  }
+
+  Symbol(const u1* name, int length);
+  void* operator new(size_t size, int len);
+
+ public:
+  // Low-level access (used with care, since not GC-safe)
+  const jbyte* base() const { return &_body[0]; }
+
+  int object_size() { return object_size(utf8_length()); }
+
+  // Returns the largest size symbol we can safely hold.
+  static int max_length() {
+    return max_symbol_length;
+  }
+
+  int identity_hash() {
+    return _identity_hash;
+  }
+
+  // Reference counting.  See comments above this class for when to use.
+  int refcount() const { return _refcount; }
+  void increment_refcount();
+  void decrement_refcount();
+
+  int byte_at(int index) const {
+    assert(index >=0 && index < _length, "symbol index overflow");
+    return base()[index];
+  }
+
+  const jbyte* bytes() const { return base(); }
+
+  int utf8_length() const { return _length; }
+
+  // Compares the symbol with a string.
+  bool equals(const char* str, int len) const;
+  bool equals(const char* str) const { return equals(str, (int) strlen(str)); }
+
+  // Tests if the symbol starts with the given prefix.
+  bool starts_with(const char* prefix, int len) const;
+  bool starts_with(const char* prefix) const {
+    return starts_with(prefix, (int) strlen(prefix));
+  }
+
+  // Tests if the symbol starts with the given prefix.
+  int index_of_at(int i, const char* str, int len) const;
+  int index_of_at(int i, const char* str) const {
+    return index_of_at(i, str, (int) strlen(str));
+  }
+
+  // Three-way compare for sorting; returns -1/0/1 if receiver is </==/> than arg
+  // note that the ordering is not alfabetical
+  inline int fast_compare(Symbol* other) const;
+
+  // Returns receiver converted to null-terminated UTF-8 string; string is
+  // allocated in resource area, or in the char buffer provided by caller.
+  char* as_C_string() const;
+  char* as_C_string(char* buf, int size) const;
+  // Use buf if needed buffer length is <= size.
+  char* as_C_string_flexible_buffer(Thread* t, char* buf, int size) const;
+
+
+  // Returns a null terminated utf8 string in a resource array
+  char* as_utf8() const { return as_C_string(); }
+  char* as_utf8_flexible_buffer(Thread* t, char* buf, int size) const {
+    return as_C_string_flexible_buffer(t, buf, size);
+  }
+
+  jchar* as_unicode(int& length) const;
+
+  // Treating this symbol as a class name, returns the Java name for the class.
+  // String is allocated in resource area if buffer is not provided.
+  // See Klass::external_name()
+  const char* as_klass_external_name() const;
+  const char* as_klass_external_name(char* buf, int size) const;
+
+  // Printing
+  void print_symbol_on(outputStream* st = NULL) const;
+  void print_on(outputStream* st) const;         // First level print
+  void print_value_on(outputStream* st) const;   // Second level print.
+
+  // printing on default output stream
+  void print()         { print_on(tty);       }
+  void print_value()   { print_value_on(tty); }
+
+#ifndef PRODUCT
+  // Empty constructor to create a dummy symbol object on stack
+  // only for getting its vtable pointer.
+  Symbol() { }
+
+  static int _total_count;
+#endif
+};
+
+// Note: this comparison is used for vtable sorting only; it doesn't matter
+// what order it defines, as long as it is a total, time-invariant order
+// Since Symbol*s are in C_HEAP, their relative order in memory never changes,
+// so use address comparison for speed
+int Symbol::fast_compare(Symbol* other) const {
+ return (((uintptr_t)this < (uintptr_t)other) ? -1
+   : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1);
+}
+#endif // SHARE_VM_OOPS_SYMBOL_HPP
--- a/src/share/vm/oops/symbolKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,230 +0,0 @@
-/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "classfile/symbolTable.hpp"
-#include "memory/gcLocker.hpp"
-#include "oops/oop.inline.hpp"
-#include "oops/symbolKlass.hpp"
-#include "oops/symbolOop.hpp"
-#include "runtime/handles.inline.hpp"
-
-symbolOop symbolKlass::allocate_symbol(u1* name, int len, TRAPS) {
-  // Don't allow symbol oops to be created which cannot fit in a symbolOop.
-  if (len > symbolOopDesc::max_length()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(),
-                "name is too long to represent");
-  }
-  int size = symbolOopDesc::object_size(len);
-  symbolKlassHandle h_k(THREAD, as_klassOop());
-  symbolOop sym = (symbolOop)
-    CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_NULL);
-  assert(!sym->is_parsable(), "not expecting parsability yet.");
-  No_Safepoint_Verifier no_safepoint;
-  sym->set_utf8_length(len);
-  for (int i = 0; i < len; i++) {
-    sym->byte_at_put(i, name[i]);
-  }
-  // Let the first emptySymbol be created and
-  // ensure only one is ever created.
-  assert(sym->is_parsable() || Universe::emptySymbol() == NULL,
-         "should be parsable here.");
-  return sym;
-}
-
-bool symbolKlass::allocate_symbols(int names_count, const char** names,
-                                   int* lengths, symbolOop* sym_oops, TRAPS) {
-  if (UseConcMarkSweepGC || UseParallelGC) {
-    // Concurrent GC needs to mark all the allocated symbol oops after
-    // the remark phase which isn't done below (except the first symbol oop).
-    // So return false which will let the symbols be allocated one by one.
-    // The parallel collector uses an object start array to find the
-    // start of objects on a dirty card.  The object start array is not
-    // updated for the start of each symbol so is not precise.  During
-    // object array verification this causes a verification failure.
-    // In a product build this causes extra searching for the start of
-    // a symbol.  As with the concurrent collector a return of false will
-    // cause each symbol to be allocated separately and in the case
-    // of the parallel collector will cause the object
-    // start array to be updated.
-    return false;
-  }
-
-  assert(names_count > 0, "can't allocate 0 symbols");
-
-  int total_size = 0;
-  int i, sizes[SymbolTable::symbol_alloc_batch_size];
-  for (i=0; i<names_count; i++) {
-    int len = lengths[i];
-    if (len > symbolOopDesc::max_length()) {
-      return false;
-    }
-    int sz = symbolOopDesc::object_size(len);
-    sizes[i] = sz * HeapWordSize;
-    total_size += sz;
-  }
-  symbolKlassHandle h_k(THREAD, as_klassOop());
-  HeapWord* base = Universe::heap()->permanent_mem_allocate(total_size);
-  if (base == NULL) {
-    return false;
-  }
-
-  // CAN'T take any safepoint during the initialization of the symbol oops !
-  No_Safepoint_Verifier nosafepoint;
-
-  klassOop sk = h_k();
-  int pos = 0;
-  for (i=0; i<names_count; i++) {
-    symbolOop s = (symbolOop) (((char*)base) + pos);
-    s->set_mark(markOopDesc::prototype());
-    s->set_klass(sk);
-    s->set_utf8_length(lengths[i]);
-    const char* name = names[i];
-    for (int j=0; j<lengths[i]; j++) {
-      s->byte_at_put(j, name[j]);
-    }
-
-    assert(s->is_parsable(), "should be parsable here.");
-
-    sym_oops[i] = s;
-    pos += sizes[i];
-  }
-  return true;
-}
-
-klassOop symbolKlass::create_klass(TRAPS) {
-  symbolKlass o;
-  KlassHandle h_this_klass(THREAD, Universe::klassKlassObj());
-  KlassHandle k = base_create_klass(h_this_klass, header_size(), o.vtbl_value(), CHECK_NULL);
-  // Make sure size calculation is right
-  assert(k()->size() == align_object_size(header_size()), "wrong size for object");
-//  java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror
-  return k();
-}
-
-int symbolKlass::oop_size(oop obj) const {
-  assert(obj->is_symbol(),"must be a symbol");
-  symbolOop s = symbolOop(obj);
-  int size = s->object_size();
-  return size;
-}
-
-bool symbolKlass::oop_is_parsable(oop obj) const {
-  assert(obj->is_symbol(),"must be a symbol");
-  symbolOop s = symbolOop(obj);
-  return s->object_is_parsable();
-}
-
-void symbolKlass::oop_follow_contents(oop obj) {
-  assert (obj->is_symbol(), "object must be symbol");
-  // Performance tweak: We skip iterating over the klass pointer since we
-  // know that Universe::symbolKlassObj never moves.
-  // Note: do not follow next link here (see SymbolTable::follow_contents)
-}
-
-#ifndef SERIALGC
-void symbolKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) {
-  assert (obj->is_symbol(), "object must be symbol");
-  // Performance tweak: We skip iterating over the klass pointer since we
-  // know that Universe::symbolKlassObj never moves.
-  // Note: do not follow next link here (see SymbolTable::follow_contents)
-}
-#endif // SERIALGC
-
-int symbolKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
-  assert(obj->is_symbol(), "object must be symbol");
-  symbolOop s = symbolOop(obj);
-  // Get size before changing pointers.
-  // Don't call size() or oop_size() since that is a virtual call.
-  int size = s->object_size();
-  // Performance tweak: We skip iterating over the klass pointer since we
-  // know that Universe::symbolKlassObj never moves.
-  return size;
-}
-
-
-int symbolKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) {
-  assert(obj->is_symbol(), "object must be symbol");
-  symbolOop s = symbolOop(obj);
-  // Get size before changing pointers.
-  // Don't call size() or oop_size() since that is a virtual call.
-  int size = s->object_size();
-  // Performance tweak: We skip iterating over the klass pointer since we
-  // know that Universe::symbolKlassObj never moves.
-  return size;
-}
-
-
-int symbolKlass::oop_adjust_pointers(oop obj) {
-  assert(obj->is_symbol(), "should be symbol");
-  symbolOop s = symbolOop(obj);
-  // Get size before changing pointers.
-  // Don't call size() or oop_size() since that is a virtual call.
-  int size = s->object_size();
-  // Performance tweak: We skip iterating over the klass pointer since we
-  // know that Universe::symbolKlassObj never moves.
-  return size;
-}
-
-
-#ifndef SERIALGC
-void symbolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
-  assert(obj->is_symbol(), "should be symbol");
-}
-
-int symbolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
-  assert(obj->is_symbol(), "should be symbol");
-  return symbolOop(obj)->object_size();
-}
-
-int symbolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
-                                     HeapWord* beg_addr, HeapWord* end_addr) {
-  assert(obj->is_symbol(), "should be symbol");
-  return symbolOop(obj)->object_size();
-}
-#endif // SERIALGC
-
-#ifndef PRODUCT
-// Printing
-
-void symbolKlass::oop_print_on(oop obj, outputStream* st) {
-  st->print("Symbol: '");
-  symbolOop(obj)->print_symbol_on(st);
-  st->print("'");
-}
-
-#endif //PRODUCT
-
-void symbolKlass::oop_print_value_on(oop obj, outputStream* st) {
-  symbolOop sym = symbolOop(obj);
-  st->print("'");
-  for (int i = 0; i < sym->utf8_length(); i++) {
-    st->print("%c", sym->byte_at(i));
-  }
-  st->print("'");
-}
-
-const char* symbolKlass::internal_name() const {
-  return "{symbol}";
-}
--- a/src/share/vm/oops/symbolKlass.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_OOPS_SYMBOLKLASS_HPP
-#define SHARE_VM_OOPS_SYMBOLKLASS_HPP
-
-#include "oops/typeArrayKlass.hpp"
-
-// a symbolKlass is the klass for a symbolOop
-
-class symbolKlass : public Klass {
-  friend class VMStructs;
- private:
-  juint    _alloc_size;        // allocation profiling support
- public:
-  // Allocation
-  DEFINE_ALLOCATE_PERMANENT(symbolKlass);
-  static klassOop create_klass(TRAPS);
-  symbolOop allocate_symbol(u1* name, int len, TRAPS);   // Assumes no characters larger than 0x7F
-  bool allocate_symbols(int names_count, const char** names, int* lengths, symbolOop* sym_oops, TRAPS);
-
-  // Test operation
-  bool oop_is_symbol() const { return true; }
-
-  // Casting from klassOop
-  static symbolKlass* cast(klassOop k) {
-    assert(k->klass_part()->oop_is_symbol(), "cast to symbolKlass");
-    return (symbolKlass*) k->klass_part();
-  }
-
-  static int header_size()       { return oopDesc::header_size() + sizeof(symbolKlass)/HeapWordSize; }
-  int oop_size(oop obj) const;
-  int klass_oop_size() const     { return object_size(); }
-  int object_size() const        { return align_object_size(header_size()); }
-
-    // Garbage collection
-  void oop_follow_contents(oop obj);
-  int  oop_adjust_pointers(oop obj);
-  bool oop_is_parsable(oop obj) const;
-
-  // Parallel Scavenge and Parallel Old
-  PARALLEL_GC_DECLS
-
-  // Allocation profiling support
-  juint alloc_size() const              { return _alloc_size; }
-  void set_alloc_size(juint n)          { _alloc_size = n; }
-
-  // Iterators
-  int  oop_oop_iterate(oop obj, OopClosure* blk);
-  int  oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr);
-
-  // Printing
-  void oop_print_value_on(oop obj, outputStream* st);
-#ifndef PRODUCT
-  void oop_print_on(oop obj, outputStream* st);
-#endif //PRODUCT
-  const char* internal_name() const;
-};
-
-#endif // SHARE_VM_OOPS_SYMBOLKLASS_HPP
--- a/src/share/vm/oops/symbolOop.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
-
-
-// ------------------------------------------------------------------
-// symbolOopDesc::equals
-//
-// Compares the symbol with a string of the given length.
-bool symbolOopDesc::equals(const char* str, int len) const {
-  int l = utf8_length();
-  if (l != len) return false;
-  while (l-- > 0) {
-    if (str[l] != (char) byte_at(l))
-      return false;
-  }
-  assert(l == -1, "we should be at the beginning");
-  return true;
-}
-
-
-// ------------------------------------------------------------------
-// symbolOopDesc::starts_with
-//
-// Tests if the symbol starts with the specified prefix of the given
-// length.
-bool symbolOopDesc::starts_with(const char* prefix, int len) const {
-  if (len > utf8_length()) return false;
-  while (len-- > 0) {
-    if (prefix[len] != (char) byte_at(len))
-      return false;
-  }
-  assert(len == -1, "we should be at the beginning");
-  return true;
-}
-
-
-// ------------------------------------------------------------------
-// symbolOopDesc::index_of
-//
-// Finds if the given string is a substring of this symbol's utf8 bytes.
-// Return -1 on failure.  Otherwise return the first index where str occurs.
-int symbolOopDesc::index_of_at(int i, const char* str, int len) const {
-  assert(i >= 0 && i <= utf8_length(), "oob");
-  if (len <= 0)  return 0;
-  char first_char = str[0];
-  address bytes = (address) ((symbolOopDesc*)this)->base();
-  address limit = bytes + utf8_length() - len;  // inclusive limit
-  address scan = bytes + i;
-  if (scan > limit)
-    return -1;
-  for (;;) {
-    scan = (address) memchr(scan, first_char, (limit + 1 - scan));
-    if (scan == NULL)
-      return -1;  // not found
-    assert(scan >= bytes+i && scan <= limit, "scan oob");
-    if (memcmp(scan, str, len) == 0)
-      return (int)(scan - bytes);
-  }
-}
-
-
-char* symbolOopDesc::as_C_string(char* buf, int size) const {
-  if (size > 0) {
-    int len = MIN2(size - 1, utf8_length());
-    for (int i = 0; i < len; i++) {
-      buf[i] = byte_at(i);
-    }
-    buf[len] = '\0';
-  }
-  return buf;
-}
-
-char* symbolOopDesc::as_C_string() const {
-  int len = utf8_length();
-  char* str = NEW_RESOURCE_ARRAY(char, len + 1);
-  return as_C_string(str, len + 1);
-}
-
-char* symbolOopDesc::as_C_string_flexible_buffer(Thread* t,
-                                                 char* buf, int size) const {
-  char* str;
-  int len = utf8_length();
-  int buf_len = len + 1;
-  if (size < buf_len) {
-    str = NEW_RESOURCE_ARRAY(char, buf_len);
-  } else {
-    str = buf;
-  }
-  return as_C_string(str, buf_len);
-}
-
-void symbolOopDesc::print_symbol_on(outputStream* st) {
-  st = st ? st : tty;
-  int length = UTF8::unicode_length((const char*)bytes(), utf8_length());
-  const char *ptr = (const char *)bytes();
-  jchar value;
-  for (int index = 0; index < length; index++) {
-    ptr = UTF8::next(ptr, &value);
-    if (value >= 32 && value < 127 || value == '\'' || value == '\\') {
-      st->put(value);
-    } else {
-      st->print("\\u%04x", value);
-    }
-  }
-}
-
-jchar* symbolOopDesc::as_unicode(int& length) const {
-  symbolOopDesc* this_ptr = (symbolOopDesc*)this;
-  length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length());
-  jchar* result = NEW_RESOURCE_ARRAY(jchar, length);
-  if (length > 0) {
-    UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length);
-  }
-  return result;
-}
-
-const char* symbolOopDesc::as_klass_external_name(char* buf, int size) const {
-  if (size > 0) {
-    char* str    = as_C_string(buf, size);
-    int   length = (int)strlen(str);
-    // Turn all '/'s into '.'s (also for array klasses)
-    for (int index = 0; index < length; index++) {
-      if (str[index] == '/') {
-        str[index] = '.';
-      }
-    }
-    return str;
-  } else {
-    return buf;
-  }
-}
-
-const char* symbolOopDesc::as_klass_external_name() const {
-  char* str    = as_C_string();
-  int   length = (int)strlen(str);
-  // Turn all '/'s into '.'s (also for array klasses)
-  for (int index = 0; index < length; index++) {
-    if (str[index] == '/') {
-      str[index] = '.';
-    }
-  }
-  return str;
-}
--- a/src/share/vm/oops/symbolOop.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_OOPS_SYMBOLOOP_HPP
-#define SHARE_VM_OOPS_SYMBOLOOP_HPP
-
-#include "oops/typeArrayOop.hpp"
-#include "utilities/utf8.hpp"
-
-// A symbolOop is a canonicalized string.
-// All symbolOops reside in global symbolTable.
-// See oopFactory::new_symbol for how to allocate a symbolOop
-
-class symbolOopDesc : public oopDesc {
-  friend class VMStructs;
- private:
-  unsigned short _length; // number of UTF8 characters in the symbol
-  jbyte _body[1];
-
-  enum {
-    // max_symbol_length is constrained by type of _length
-    max_symbol_length = (1 << 16) -1
-  };
- public:
-
-  // Low-level access (used with care, since not GC-safe)
-  jbyte* base() { return &_body[0]; }
-
-
-  // Returns the largest size symbol we can safely hold.
-  static int max_length() {
-    return max_symbol_length;
-  }
-
-  static int object_size(int length) {
-    int size = header_size() + (sizeof(unsigned short) + length + HeapWordSize - 1) / HeapWordSize;
-    return align_object_size(size);
-  }
-
-  int object_size() { return object_size(utf8_length()); }
-
-  int byte_at(int index) const {
-    assert(index >=0 && index < _length, "symbol index overflow");
-    return ((symbolOopDesc*)this)->base()[index];
-  }
-
-  void byte_at_put(int index, int value) {
-    assert(index >=0 && index < _length, "symbol index overflow");
-    ((symbolOopDesc*)this)->base()[index] = value;
-  }
-
-  jbyte* bytes() { return base(); }
-
-  int utf8_length() const { return _length; }
-
-  void set_utf8_length(int len) { _length = len; }
-
-  // Compares the symbol with a string.
-  bool equals(const char* str, int len) const;
-  bool equals(const char* str) const { return equals(str, (int) strlen(str)); }
-
-  // Tests if the symbol starts with the given prefix.
-  bool starts_with(const char* prefix, int len) const;
-  bool starts_with(const char* prefix) const {
-    return starts_with(prefix, (int) strlen(prefix));
-  }
-
-  // Tests if the symbol starts with the given prefix.
-  int index_of_at(int i, const char* str, int len) const;
-  int index_of_at(int i, const char* str) const {
-    return index_of_at(i, str, (int) strlen(str));
-  }
-
-  // Three-way compare for sorting; returns -1/0/1 if receiver is </==/> than arg
-  // note that the ordering is not alfabetical
-  inline int fast_compare(symbolOop other) const;
-
-  // Returns receiver converted to null-terminated UTF-8 string; string is
-  // allocated in resource area, or in the char buffer provided by caller.
-  char* as_C_string() const;
-  char* as_C_string(char* buf, int size) const;
-  // Use buf if needed buffer length is <= size.
-  char* as_C_string_flexible_buffer(Thread* t, char* buf, int size) const;
-
-
-  // Returns a null terminated utf8 string in a resource array
-  char* as_utf8() const { return as_C_string(); }
-  char* as_utf8_flexible_buffer(Thread* t, char* buf, int size) const {
-    return as_C_string_flexible_buffer(t, buf, size);
-  }
-
-  jchar* as_unicode(int& length) const;
-
-  // Treating this symbol as a class name, returns the Java name for the class.
-  // String is allocated in resource area if buffer is not provided.
-  // See Klass::external_name()
-  const char* as_klass_external_name() const;
-  const char* as_klass_external_name(char* buf, int size) const;
-
-  bool object_is_parsable() const {
-    return (utf8_length() > 0 || (oop)this == Universe::emptySymbol());
-  }
-
-  // Printing
-  void print_symbol_on(outputStream* st = NULL);
-};
-
-
-// Note: this comparison is used for vtable sorting only; it doesn't matter
-// what order it defines, as long as it is a total, time-invariant order
-// Since symbolOops are in permSpace, their relative order in memory never changes,
-// so use address comparison for speed
-int symbolOopDesc::fast_compare(symbolOop other) const {
- return (((uintptr_t)this < (uintptr_t)other) ? -1
-   : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1);
-}
-
-#endif // SHARE_VM_OOPS_SYMBOLOOP_HPP
--- a/src/share/vm/oops/typeArrayKlass.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/oops/typeArrayKlass.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,16 +53,15 @@
                                       const char* name_str, TRAPS) {
   typeArrayKlass o;
 
-  symbolHandle sym(symbolOop(NULL));
-  // bootstrapping: don't create sym if symbolKlass not created yet
-  if (Universe::symbolKlassObj() != NULL && name_str != NULL) {
-    sym = oopFactory::new_symbol_handle(name_str, CHECK_NULL);
+  Symbol* sym = NULL;
+  if (name_str != NULL) {
+    sym = SymbolTable::new_symbol(name_str, CHECK_NULL);
   }
   KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj());
 
   arrayKlassHandle k = base_create_array_klass(o.vtbl_value(), header_size(), klassklass, CHECK_NULL);
   typeArrayKlass* ak = typeArrayKlass::cast(k());
-  ak->set_name(sym());
+  ak->set_name(sym);
   ak->set_layout_helper(array_layout_helper(type));
   assert(scale == (1 << ak->log2_element_size()), "scale must check out");
   assert(ak->oop_is_javaArray(), "sanity");
@@ -179,6 +178,7 @@
           dimension + 1, h_this, CHECK_NULL);
         h_ak = objArrayKlassHandle(THREAD, oak);
         h_ak->set_lower_dimension(h_this());
+        OrderAccess::storestore();
         h_this->set_higher_dimension(h_ak());
         assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
       }
--- a/src/share/vm/opto/runtime.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/opto/runtime.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -477,7 +477,7 @@
 const TypeFunc *OptoRuntime::uncommon_trap_Type() {
   // create input type (domain)
   const Type **fields = TypeTuple::fields(1);
-  // symbolOop name of class to be loaded
+  // Symbol* name of class to be loaded
   fields[TypeFunc::Parms+0] = TypeInt::INT;
   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
 
@@ -586,7 +586,7 @@
 const TypeFunc *OptoRuntime::Math_D_D_Type() {
   // create input type (domain)
   const Type **fields = TypeTuple::fields(2);
-  // symbolOop name of class to be loaded
+  // Symbol* name of class to be loaded
   fields[TypeFunc::Parms+0] = Type::DOUBLE;
   fields[TypeFunc::Parms+1] = Type::HALF;
   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
--- a/src/share/vm/opto/type.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/opto/type.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2187,8 +2187,11 @@
   case TypePtr::NotNull:
     return this;
   case TypePtr::Null:
-  case TypePtr::Constant:
-    return make( _bits+offset );
+  case TypePtr::Constant: {
+    address bits = _bits+offset;
+    if ( bits == 0 ) return TypePtr::NULL_PTR;
+    return make( bits );
+  }
   default:  ShouldNotReachHere();
   }
   return NULL;                  // Lint noise
--- a/src/share/vm/precompiled.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/precompiled.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -169,7 +169,7 @@
 # include "oops/oop.inline.hpp"
 # include "oops/oop.inline2.hpp"
 # include "oops/oopsHierarchy.hpp"
-# include "oops/symbolOop.hpp"
+# include "oops/symbol.hpp"
 # include "oops/typeArrayKlass.hpp"
 # include "oops/typeArrayOop.hpp"
 # include "prims/jni.h"
--- a/src/share/vm/prims/jni.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jni.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -40,7 +40,7 @@
 #include "oops/objArrayKlass.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "oops/typeArrayOop.hpp"
 #include "prims/jni.h"
@@ -338,16 +338,15 @@
 
   // Since exceptions can be thrown, class initialization can take place
   // if name is NULL no check for class name in .class stream has to be made.
-  symbolHandle class_name;
   if (name != NULL) {
     const int str_len = (int)strlen(name);
-    if (str_len > symbolOopDesc::max_length()) {
+    if (str_len > Symbol::max_length()) {
       // It's impossible to create this class;  the name cannot fit
       // into the constant pool.
       THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
     }
-    class_name = oopFactory::new_symbol_handle(name, str_len, CHECK_NULL);
   }
+  TempNewSymbol class_name = SymbolTable::new_symbol(name, THREAD);
 
   ResourceMark rm(THREAD);
   ClassFileStream st((u1*) buf, bufLen, NULL);
@@ -394,7 +393,7 @@
 
   // Sanity check the name:  it cannot be null or larger than the maximum size
   // name we can fit in the constant pool.
-  if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
+  if (name == NULL || (int)strlen(name) > Symbol::max_length()) {
     THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
   }
 
@@ -411,8 +410,8 @@
         k->name() == vmSymbols::java_lang_ClassLoader_NativeLibrary()) {
       JavaValue result(T_OBJECT);
       JavaCalls::call_static(&result, k,
-                                      vmSymbolHandles::getFromClass_name(),
-                                      vmSymbolHandles::void_class_signature(),
+                                      vmSymbols::getFromClass_name(),
+                                      vmSymbols::void_class_signature(),
                                       thread);
       if (HAS_PENDING_EXCEPTION) {
         Handle ex(thread, thread->pending_exception());
@@ -430,7 +429,7 @@
     loader = Handle(THREAD, SystemDictionary::java_system_loader());
   }
 
-  symbolHandle sym = oopFactory::new_symbol_handle(name, CHECK_NULL);
+  TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL);
   result = find_class_from_class_loader(env, sym, true, loader,
                                         protection_domain, true, thread);
 
@@ -609,7 +608,7 @@
   DT_RETURN_MARK(ThrowNew, jint, (const jint&)ret);
 
   instanceKlass* k = instanceKlass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz)));
-  symbolHandle name = symbolHandle(THREAD, k->name());
+  Symbol*  name = k->name();
   Handle class_loader (THREAD,  k->class_loader());
   Handle protection_domain (THREAD, k->protection_domain());
   THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK);
@@ -663,8 +662,8 @@
                                 ex,
                                 KlassHandle(THREAD,
                                   SystemDictionary::Throwable_klass()),
-                                vmSymbolHandles::printStackTrace_name(),
-                                vmSymbolHandles::void_method_signature(),
+                                vmSymbols::printStackTrace_name(),
+                                vmSymbols::void_method_signature(),
                                 THREAD);
         // If an exception is thrown in the call it gets thrown away. Not much
         // we can do with it. The native code that calls this, does not check
@@ -838,8 +837,7 @@
   virtual void get_double () = 0;
   virtual void get_object () = 0;
 
-  JNI_ArgumentPusher(Thread *thread, symbolOop signature)
-       : SignatureIterator(thread, signature) {
+  JNI_ArgumentPusher(Symbol* signature) : SignatureIterator(signature) {
     this->_return_type = T_ILLEGAL;
     _arguments = NULL;
   }
@@ -895,12 +893,12 @@
   }
 
  public:
-  JNI_ArgumentPusherVaArg(Thread *thread, symbolOop signature, va_list rap)
-       : JNI_ArgumentPusher(thread, signature) {
+  JNI_ArgumentPusherVaArg(Symbol* signature, va_list rap)
+       : JNI_ArgumentPusher(signature) {
     set_ap(rap);
   }
-  JNI_ArgumentPusherVaArg(Thread *thread, jmethodID method_id, va_list rap)
-      : JNI_ArgumentPusher(thread, JNIHandles::resolve_jmethod_id(method_id)->signature()) {
+  JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
+      : JNI_ArgumentPusher(JNIHandles::resolve_jmethod_id(method_id)->signature()) {
     set_ap(rap);
   }
 
@@ -966,12 +964,12 @@
   inline void set_ap(const jvalue *rap) { _ap = rap; }
 
  public:
-  JNI_ArgumentPusherArray(Thread *thread, symbolOop signature, const jvalue *rap)
-       : JNI_ArgumentPusher(thread, signature) {
+  JNI_ArgumentPusherArray(Symbol* signature, const jvalue *rap)
+       : JNI_ArgumentPusher(signature) {
     set_ap(rap);
   }
-  JNI_ArgumentPusherArray(Thread *thread, jmethodID method_id, const jvalue *rap)
-      : JNI_ArgumentPusher(thread, JNIHandles::resolve_jmethod_id(method_id)->signature()) {
+  JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
+      : JNI_ArgumentPusher(JNIHandles::resolve_jmethod_id(method_id)->signature()) {
     set_ap(rap);
   }
 
@@ -1038,8 +1036,8 @@
   KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc)
   if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass());
   KlassHandle spec_klass (THREAD, method->method_holder());
-  symbolHandle name (THREAD, method->name());
-  symbolHandle signature (THREAD, method->signature());
+  Symbol*  name  = method->name();
+  Symbol*  signature  = method->signature();
   CallInfo info;
   LinkResolver::resolve_interface_call(info, recv, recv_klass,  spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle()));
   return info.selected_method();
@@ -1051,8 +1049,8 @@
   KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc)
   if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass());
   KlassHandle spec_klass (THREAD, method->method_holder());
-  symbolHandle name (THREAD, method->name());
-  symbolHandle signature (THREAD, method->signature());
+  Symbol*  name  = method->name();
+  Symbol*  signature  = method->signature();
   CallInfo info;
   LinkResolver::resolve_virtual_call(info, recv, recv_klass,  spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle()));
   return info.selected_method();
@@ -1073,7 +1071,7 @@
   assert(method->is_static(), "method should be static");
 
   // Fill out JavaCallArguments object
-  args->iterate( Fingerprinter(THREAD, method).fingerprint() );
+  args->iterate( Fingerprinter(method).fingerprint() );
   // Initialize result type
   result->set_type(args->get_ret_type());
 
@@ -1149,7 +1147,7 @@
   args->push_receiver(h_recv); // Push jobject handle
 
   // Fill out JavaCallArguments object
-  args->iterate( Fingerprinter(THREAD, method).fingerprint() );
+  args->iterate( Fingerprinter(method).fingerprint() );
   // Initialize result type
   result->set_type(args->get_ret_type());
 
@@ -1196,7 +1194,7 @@
   instanceOop i = alloc_object(clazz, CHECK_NULL);
   obj = JNIHandles::make_local(env, i);
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherArray ap(THREAD, methodID, args);
+  JNI_ArgumentPusherArray ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
   return obj;
 JNI_END
@@ -1212,7 +1210,7 @@
   instanceOop i = alloc_object(clazz, CHECK_NULL);
   obj = JNIHandles::make_local(env, i);
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args);
+  JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
   return obj;
 JNI_END
@@ -1230,7 +1228,7 @@
   va_list args;
   va_start(args, methodID);
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args);
+  JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
   va_end(args);
   return obj;
@@ -1271,16 +1269,13 @@
   // The class should have been loaded (we have an instance of the class
   // passed in) so the method and signature should already be in the symbol
   // table.  If they're not there, the method doesn't exist.
-  symbolHandle signature =
-           symbolHandle(THREAD, SymbolTable::probe(sig, (int)strlen(sig)));
-  symbolHandle name;
-  if (name_str == NULL) {
-    name = vmSymbolHandles::object_initializer_name();
-  } else {
-    name = symbolHandle(THREAD,
-                        SymbolTable::probe(name_str, (int)strlen(name_str)));
-  }
-  if (name.is_null() || signature.is_null()) {
+  const char *name_to_probe = (name_str == NULL)
+                        ? vmSymbols::object_initializer_name()->as_C_string()
+                        : name_str;
+  TempNewSymbol name = SymbolTable::probe(name_to_probe, (int)strlen(name_to_probe));
+  TempNewSymbol signature = SymbolTable::probe(sig, (int)strlen(sig));
+
+  if (name == NULL || signature == NULL) {
     THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
   }
 
@@ -1298,20 +1293,20 @@
   Klass::cast(klass())->initialize(CHECK_NULL);
 
   methodOop m;
-  if (name() == vmSymbols::object_initializer_name() ||
-      name() == vmSymbols::class_initializer_name()) {
+  if (name == vmSymbols::object_initializer_name() ||
+      name == vmSymbols::class_initializer_name()) {
     // Never search superclasses for constructors
     if (klass->oop_is_instance()) {
-      m = instanceKlass::cast(klass())->find_method(name(), signature());
+      m = instanceKlass::cast(klass())->find_method(name, signature);
     } else {
       m = NULL;
     }
   } else {
-    m = klass->lookup_method(name(), signature());
+    m = klass->lookup_method(name, signature);
     // Look up interfaces
     if (m == NULL && klass->oop_is_instance()) {
-      m = instanceKlass::cast(klass())->lookup_method_in_all_interfaces(name(),
-                                                                   signature());
+      m = instanceKlass::cast(klass())->lookup_method_in_all_interfaces(name,
+                                                                   signature);
     }
   }
   if (m == NULL || (m->is_static() != is_static)) {
@@ -1365,7 +1360,7 @@
   va_list args; \
   va_start(args, methodID); \
   JavaValue jvalue(Tag); \
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args); \
+  JNI_ArgumentPusherVaArg ap(methodID, args); \
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
   va_end(args); \
   ret = jvalue.get_##ResultType(); \
@@ -1383,7 +1378,7 @@
                      (const ResultType&)ret);\
 \
   JavaValue jvalue(Tag); \
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args); \
+  JNI_ArgumentPusherVaArg ap(methodID, args); \
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
   ret = jvalue.get_##ResultType(); \
   return ret;\
@@ -1399,7 +1394,7 @@
                      (const ResultType&)ret);\
 \
   JavaValue jvalue(Tag); \
-  JNI_ArgumentPusherArray ap(THREAD, methodID, args); \
+  JNI_ArgumentPusherArray ap(methodID, args); \
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
   ret = jvalue.get_##ResultType(); \
   return ret;\
@@ -1429,7 +1424,7 @@
   va_list args;
   va_start(args, methodID);
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args);
+  JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);
   va_end(args);
 JNI_END
@@ -1441,7 +1436,7 @@
   DT_VOID_RETURN_MARK(CallVoidMethodV);
 
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args);
+  JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);
 JNI_END
 
@@ -1452,7 +1447,7 @@
   DT_VOID_RETURN_MARK(CallVoidMethodA);
 
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherArray ap(THREAD, methodID, args);
+  JNI_ArgumentPusherArray ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);
 JNI_END
 
@@ -1475,7 +1470,7 @@
   va_list args; \
   va_start(args, methodID); \
   JavaValue jvalue(Tag); \
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args); \
+  JNI_ArgumentPusherVaArg ap(methodID, args); \
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
   va_end(args); \
   ret = jvalue.get_##ResultType(); \
@@ -1491,7 +1486,7 @@
                      (const ResultType&)ret);\
 \
   JavaValue jvalue(Tag); \
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args); \
+  JNI_ArgumentPusherVaArg ap(methodID, args); \
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
   ret = jvalue.get_##ResultType(); \
   return ret;\
@@ -1506,7 +1501,7 @@
                      (const ResultType&)ret);\
 \
   JavaValue jvalue(Tag); \
-  JNI_ArgumentPusherArray ap(THREAD, methodID, args); \
+  JNI_ArgumentPusherArray ap(methodID, args); \
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
   ret = jvalue.get_##ResultType(); \
   return ret;\
@@ -1539,7 +1534,7 @@
   va_list args;
   va_start(args, methodID);
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args);
+  JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);
   va_end(args);
 JNI_END
@@ -1553,7 +1548,7 @@
   DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodV);
 
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args);
+  JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);
 JNI_END
 
@@ -1564,7 +1559,7 @@
                 env, obj, cls, methodID);
   DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodA);
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherArray ap(THREAD, methodID, args);
+  JNI_ArgumentPusherArray ap(methodID, args);
   jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);
 JNI_END
 
@@ -1587,7 +1582,7 @@
   va_list args; \
   va_start(args, methodID); \
   JavaValue jvalue(Tag); \
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args); \
+  JNI_ArgumentPusherVaArg ap(methodID, args); \
   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
   va_end(args); \
   ret = jvalue.get_##ResultType(); \
@@ -1603,7 +1598,7 @@
                      (const ResultType&)ret);\
 \
   JavaValue jvalue(Tag); \
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args); \
+  JNI_ArgumentPusherVaArg ap(methodID, args); \
   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
   ret = jvalue.get_##ResultType(); \
   return ret;\
@@ -1618,7 +1613,7 @@
                      (const ResultType&)ret);\
 \
   JavaValue jvalue(Tag); \
-  JNI_ArgumentPusherArray ap(THREAD, methodID, args); \
+  JNI_ArgumentPusherArray ap(methodID, args); \
   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
   ret = jvalue.get_##ResultType(); \
   return ret;\
@@ -1649,7 +1644,7 @@
   va_list args;
   va_start(args, methodID);
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args);
+  JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);
   va_end(args);
 JNI_END
@@ -1661,7 +1656,7 @@
   DT_VOID_RETURN_MARK(CallStaticVoidMethodV);
 
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherVaArg ap(THREAD, methodID, args);
+  JNI_ArgumentPusherVaArg ap(methodID, args);
   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);
 JNI_END
 
@@ -1672,7 +1667,7 @@
   DT_VOID_RETURN_MARK(CallStaticVoidMethodA);
 
   JavaValue jvalue(T_VOID);
-  JNI_ArgumentPusherArray ap(THREAD, methodID, args);
+  JNI_ArgumentPusherArray ap(methodID, args);
   jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);
 JNI_END
 
@@ -1694,11 +1689,9 @@
   // The class should have been loaded (we have an instance of the class
   // passed in) so the field and signature should already be in the symbol
   // table.  If they're not there, the field doesn't exist.
-  symbolHandle fieldname =
-            symbolHandle(THREAD, SymbolTable::probe(name, (int)strlen(name)));
-  symbolHandle signame   =
-            symbolHandle(THREAD, SymbolTable::probe(sig, (int)strlen(sig)));
-  if (fieldname.is_null() || signame.is_null()) {
+  TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
+  TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
+  if (fieldname == NULL || signame == NULL) {
     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
   }
   KlassHandle k(THREAD,
@@ -1708,7 +1701,7 @@
 
   fieldDescriptor fd;
   if (!Klass::cast(k())->oop_is_instance() ||
-      !instanceKlass::cast(k())->find_field(fieldname(), signame(), false, &fd)) {
+      !instanceKlass::cast(k())->find_field(fieldname, signame, false, &fd)) {
     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
   }
 
@@ -1893,11 +1886,9 @@
   // The class should have been loaded (we have an instance of the class
   // passed in) so the field and signature should already be in the symbol
   // table.  If they're not there, the field doesn't exist.
-  symbolHandle fieldname =
-           symbolHandle(THREAD, SymbolTable::probe(name, (int)strlen(name)));
-  symbolHandle signame   =
-           symbolHandle(THREAD, SymbolTable::probe(sig, (int)strlen(sig)));
-  if (fieldname.is_null() || signame.is_null()) {
+  TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
+  TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
+  if (fieldname == NULL || signame == NULL) {
     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
   }
   KlassHandle k(THREAD,
@@ -1907,7 +1898,7 @@
 
   fieldDescriptor fd;
   if (!Klass::cast(k())->oop_is_instance() ||
-      !instanceKlass::cast(k())->find_field(fieldname(), signame(), true, &fd)) {
+      !instanceKlass::cast(k())->find_field(fieldname, signame, true, &fd)) {
     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
   }
 
@@ -2389,7 +2380,7 @@
 // to see if the native method is now wrapped with the prefixes.  See the
 // SetNativeMethodPrefix(es) functions in the JVM TI Spec for details.
 static methodOop find_prefixed_native(KlassHandle k,
-                                      symbolHandle name, symbolHandle signature, TRAPS) {
+                                      Symbol* name, Symbol* signature, TRAPS) {
   ResourceMark rm(THREAD);
   methodOop method;
   int name_len = name->utf8_length();
@@ -2405,11 +2396,11 @@
     char* trial_name_str = NEW_RESOURCE_ARRAY(char, trial_len + 1);
     strcpy(trial_name_str, prefix);
     strcat(trial_name_str, name_str);
-    symbolHandle trial_name(THREAD, SymbolTable::probe(trial_name_str, trial_len));
-    if (trial_name.is_null()) {
+    TempNewSymbol trial_name = SymbolTable::probe(trial_name_str, trial_len);
+    if (trial_name == NULL) {
       continue; // no such symbol, so this prefix wasn't used, try the next prefix
     }
-    method = Klass::cast(k())->lookup_method(trial_name(), signature());
+    method = Klass::cast(k())->lookup_method(trial_name, signature);
     if (method == NULL) {
       continue; // signature doesn't match, try the next prefix
     }
@@ -2424,13 +2415,13 @@
   return NULL; // not found
 }
 
-static bool register_native(KlassHandle k, symbolHandle name, symbolHandle signature, address entry, TRAPS) {
-  methodOop method = Klass::cast(k())->lookup_method(name(), signature());
+static bool register_native(KlassHandle k, Symbol* name, Symbol* signature, address entry, TRAPS) {
+  methodOop method = Klass::cast(k())->lookup_method(name, signature);
   if (method == NULL) {
     ResourceMark rm;
     stringStream st;
     st.print("Method %s name or signature does not match",
-             methodOopDesc::name_and_sig_as_C_string(Klass::cast(k()), name(), signature()));
+             methodOopDesc::name_and_sig_as_C_string(Klass::cast(k()), name, signature));
     THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
   }
   if (!method->is_native()) {
@@ -2440,7 +2431,7 @@
       ResourceMark rm;
       stringStream st;
       st.print("Method %s is not declared as native",
-               methodOopDesc::name_and_sig_as_C_string(Klass::cast(k()), name(), signature()));
+               methodOopDesc::name_and_sig_as_C_string(Klass::cast(k()), name, signature));
       THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
     }
   }
@@ -2480,10 +2471,10 @@
     // The class should have been loaded (we have an instance of the class
     // passed in) so the method and signature should already be in the symbol
     // table.  If they're not there, the method doesn't exist.
-    symbolHandle name(THREAD, SymbolTable::probe(meth_name, meth_name_len));
-    symbolHandle signature(THREAD, SymbolTable::probe(meth_sig, (int)strlen(meth_sig)));
-
-    if (name.is_null() || signature.is_null()) {
+    TempNewSymbol  name = SymbolTable::probe(meth_name, meth_name_len);
+    TempNewSymbol  signature = SymbolTable::probe(meth_sig, (int)strlen(meth_sig));
+
+    if (name == NULL || signature == NULL) {
       ResourceMark rm;
       stringStream st;
       st.print("Method %s.%s%s not found", Klass::cast(h_k())->external_name(), meth_name, meth_sig);
@@ -2717,7 +2708,7 @@
   Handle loader;            // null (bootstrap) loader
   Handle protection_domain; // null protection domain
 
-  symbolHandle sym = oopFactory::new_symbol_handle(name, CHECK_NULL);
+  TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL);
   jclass result =  find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL);
 
   if (TraceClassResolution && result != NULL) {
--- a/src/share/vm/prims/jniCheck.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jniCheck.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -27,7 +27,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jni.h"
 #include "prims/jniCheck.hpp"
 #include "prims/jvm_misc.hpp"
--- a/src/share/vm/prims/jvm.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvm.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -124,9 +124,9 @@
     vframeStream vfst(jthread);
 
     // scan up the stack skipping ClassLoader, AccessController and PrivilegedAction frames
-    symbolHandle access_controller = oopFactory::new_symbol_handle("java/security/AccessController", CHECK);
+    TempNewSymbol access_controller = SymbolTable::new_symbol("java/security/AccessController", CHECK);
     klassOop access_controller_klass = SystemDictionary::resolve_or_fail(access_controller, false, CHECK);
-    symbolHandle privileged_action = oopFactory::new_symbol_handle("java/security/PrivilegedAction", CHECK);
+    TempNewSymbol privileged_action = SymbolTable::new_symbol("java/security/PrivilegedAction", CHECK);
     klassOop privileged_action_klass = SystemDictionary::resolve_or_fail(privileged_action, false, CHECK);
 
     methodOop last_caller = NULL;
@@ -175,7 +175,7 @@
         // show method name if it's a native method
         trace = vfst.method()->name_and_sig_as_C_string();
       }
-      symbolOop s = instanceKlass::cast(caller)->source_file_name();
+      Symbol* s = instanceKlass::cast(caller)->source_file_name();
       if (s != NULL) {
         source_file = s->as_C_string();
       }
@@ -311,8 +311,8 @@
   JavaCalls::call_virtual(&r,
                           props,
                           KlassHandle(THREAD, SystemDictionary::Properties_klass()),
-                          vmSymbolHandles::put_name(),
-                          vmSymbolHandles::object_object_object_signature(),
+                          vmSymbols::put_name(),
+                          vmSymbols::object_object_object_signature(),
                           key_str,
                           value_str,
                           THREAD);
@@ -716,13 +716,13 @@
   JVMWrapper2("JVM_FindClassFromBootLoader %s", name);
 
   // Java libraries should ensure that name is never null...
-  if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
+  if (name == NULL || (int)strlen(name) > Symbol::max_length()) {
     // It's impossible to create this class;  the name cannot fit
     // into the constant pool.
     return NULL;
   }
 
-  symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_NULL);
+  TempNewSymbol h_name = SymbolTable::new_symbol(name, CHECK_NULL);
   klassOop k = SystemDictionary::resolve_or_null(h_name, CHECK_NULL);
   if (k == NULL) {
     return NULL;
@@ -740,7 +740,7 @@
   JVMWrapper3("JVM_FindClassFromClassLoader %s throw %s", name,
                throwError ? "error" : "exception");
   // Java libraries should ensure that name is never null...
-  if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
+  if (name == NULL || (int)strlen(name) > Symbol::max_length()) {
     // It's impossible to create this class;  the name cannot fit
     // into the constant pool.
     if (throwError) {
@@ -749,7 +749,7 @@
       THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name);
     }
   }
-  symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_NULL);
+  TempNewSymbol h_name = SymbolTable::new_symbol(name, CHECK_NULL);
   Handle h_loader(THREAD, JNIHandles::resolve(loader));
   jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
                                                Handle(), throwError, THREAD);
@@ -764,12 +764,12 @@
 JVM_ENTRY(jclass, JVM_FindClassFromClass(JNIEnv *env, const char *name,
                                          jboolean init, jclass from))
   JVMWrapper2("JVM_FindClassFromClass %s", name);
-  if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
+  if (name == NULL || (int)strlen(name) > Symbol::max_length()) {
     // It's impossible to create this class;  the name cannot fit
     // into the constant pool.
     THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
   }
-  symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_NULL);
+  TempNewSymbol h_name = SymbolTable::new_symbol(name, CHECK_NULL);
   oop from_class_oop = JNIHandles::resolve(from);
   klassOop from_class = (from_class_oop == NULL)
                            ? (klassOop)NULL
@@ -838,15 +838,15 @@
 
   // Since exceptions can be thrown, class initialization can take place
   // if name is NULL no check for class name in .class stream has to be made.
-  symbolHandle class_name;
+  TempNewSymbol class_name = NULL;
   if (name != NULL) {
     const int str_len = (int)strlen(name);
-    if (str_len > symbolOopDesc::max_length()) {
+    if (str_len > Symbol::max_length()) {
       // It's impossible to create this class;  the name cannot fit
       // into the constant pool.
       THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
     }
-    class_name = oopFactory::new_symbol_handle(name, str_len, CHECK_NULL);
+    class_name = SymbolTable::new_symbol(name, str_len, CHECK_NULL);
   }
 
   ResourceMark rm(THREAD);
@@ -905,12 +905,12 @@
   if (str == NULL) return NULL;
 
   const int str_len = (int)strlen(str);
-  if (str_len > symbolOopDesc::max_length()) {
+  if (str_len > Symbol::max_length()) {
     // It's impossible to create this class;  the name cannot fit
     // into the constant pool.
     return NULL;
   }
-  symbolHandle klass_name = oopFactory::new_symbol_handle(str, str_len,CHECK_NULL);
+  TempNewSymbol klass_name = SymbolTable::new_symbol(str, str_len, CHECK_NULL);
 
   // Security Note:
   //   The Java level wrapper will perform the necessary security check allowing
@@ -1155,8 +1155,8 @@
         !pending_exception->is_a(SystemDictionary::RuntimeException_klass())) {
       // Throw a java.security.PrivilegedActionException(Exception e) exception
       JavaCallArguments args(pending_exception);
-      THROW_ARG_0(vmSymbolHandles::java_security_PrivilegedActionException(),
-                  vmSymbolHandles::exception_void_signature(),
+      THROW_ARG_0(vmSymbols::java_security_PrivilegedActionException(),
+                  vmSymbols::exception_void_signature(),
                   &args);
     }
   }
@@ -1452,8 +1452,8 @@
   if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
     klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve(cls));
     if (Klass::cast(k)->oop_is_instance()) {
-      symbolHandle sym = symbolHandle(THREAD, instanceKlass::cast(k)->generic_signature());
-      if (sym.is_null()) return NULL;
+      Symbol* sym = instanceKlass::cast(k)->generic_signature();
+      if (sym == NULL) return NULL;
       Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
       return (jstring) JNIHandles::make_local(env, str());
     }
@@ -1842,8 +1842,8 @@
     if (k_o == NULL) return NULL;
   }
   instanceKlassHandle k(THREAD, k_o);
-  symbolOop name = cp->uncached_name_ref_at(index);
-  symbolOop sig  = cp->uncached_signature_ref_at(index);
+  Symbol* name = cp->uncached_name_ref_at(index);
+  Symbol* sig  = cp->uncached_signature_ref_at(index);
   methodHandle m (THREAD, k->find_method(name, sig));
   if (m.is_null()) {
     THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up method in target class");
@@ -1893,8 +1893,8 @@
     if (k_o == NULL) return NULL;
   }
   instanceKlassHandle k(THREAD, k_o);
-  symbolOop name = cp->uncached_name_ref_at(index);
-  symbolOop sig  = cp->uncached_signature_ref_at(index);
+  Symbol* name = cp->uncached_name_ref_at(index);
+  Symbol* sig  = cp->uncached_signature_ref_at(index);
   fieldDescriptor fd;
   klassOop target_klass = k->find_field(name, sig, &fd);
   if (target_klass == NULL) {
@@ -1937,9 +1937,9 @@
     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
   }
   int klass_ref = cp->uncached_klass_ref_index_at(index);
-  symbolHandle klass_name (THREAD, cp->klass_name_at(klass_ref));
-  symbolHandle member_name(THREAD, cp->uncached_name_ref_at(index));
-  symbolHandle member_sig (THREAD, cp->uncached_signature_ref_at(index));
+  Symbol*  klass_name  = cp->klass_name_at(klass_ref);
+  Symbol*  member_name = cp->uncached_name_ref_at(index);
+  Symbol*  member_sig  = cp->uncached_signature_ref_at(index);
   objArrayOop  dest_o = oopFactory::new_objArray(SystemDictionary::String_klass(), 3, CHECK_NULL);
   objArrayHandle dest(THREAD, dest_o);
   Handle str = java_lang_String::create_from_symbol(klass_name, CHECK_NULL);
@@ -2028,8 +2028,7 @@
   if (!tag.is_symbol()) {
     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
   }
-  symbolOop sym_o = cp->symbol_at(index);
-  symbolHandle sym(THREAD, sym_o);
+  Symbol* sym = cp->symbol_at(index);
   Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
   return (jstring) JNIHandles::make_local(str());
 }
@@ -2356,7 +2355,7 @@
   klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls));
   k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
   constantPoolOop cp = instanceKlass::cast(k)->constants();
-  symbolOop classname = cp->klass_name_at(cp_index);
+  Symbol* classname = cp->klass_name_at(cp_index);
   return classname->as_utf8();
 JVM_END
 
@@ -2369,7 +2368,7 @@
   switch (cp->tag_at(cp_index).value()) {
     case JVM_CONSTANT_Fieldref: {
       int class_index = cp->uncached_klass_ref_index_at(cp_index);
-      symbolOop classname = cp->klass_name_at(class_index);
+      Symbol* classname = cp->klass_name_at(class_index);
       return classname->as_utf8();
     }
     default:
@@ -2389,7 +2388,7 @@
     case JVM_CONSTANT_Methodref:
     case JVM_CONSTANT_InterfaceMethodref: {
       int class_index = cp->uncached_klass_ref_index_at(cp_index);
-      symbolOop classname = cp->klass_name_at(class_index);
+      Symbol* classname = cp->klass_name_at(class_index);
       return classname->as_utf8();
     }
     default:
@@ -2410,8 +2409,8 @@
   constantPoolOop cp_called = instanceKlass::cast(k_called)->constants();
   switch (cp->tag_at(cp_index).value()) {
     case JVM_CONSTANT_Fieldref: {
-      symbolOop name      = cp->uncached_name_ref_at(cp_index);
-      symbolOop signature = cp->uncached_signature_ref_at(cp_index);
+      Symbol* name      = cp->uncached_name_ref_at(cp_index);
+      Symbol* signature = cp->uncached_signature_ref_at(cp_index);
       typeArrayOop fields = instanceKlass::cast(k_called)->fields();
       int fields_count = fields->length();
       for (int i = 0; i < fields_count; i += instanceKlass::next_offset) {
@@ -2440,8 +2439,8 @@
   switch (cp->tag_at(cp_index).value()) {
     case JVM_CONSTANT_Methodref:
     case JVM_CONSTANT_InterfaceMethodref: {
-      symbolOop name      = cp->uncached_name_ref_at(cp_index);
-      symbolOop signature = cp->uncached_signature_ref_at(cp_index);
+      Symbol* name      = cp->uncached_name_ref_at(cp_index);
+      Symbol* signature = cp->uncached_signature_ref_at(cp_index);
       objArrayOop methods = instanceKlass::cast(k_called)->methods();
       int methods_count = methods->length();
       for (int i = 0; i < methods_count; i++) {
@@ -2629,8 +2628,8 @@
   JavaCalls::call_virtual(&result,
                           obj,
                           KlassHandle(THREAD, SystemDictionary::Thread_klass()),
-                          vmSymbolHandles::run_method_name(),
-                          vmSymbolHandles::void_method_signature(),
+                          vmSymbols::run_method_name(),
+                          vmSymbols::void_method_signature(),
                           THREAD);
 }
 
@@ -2651,12 +2650,18 @@
     // we operate.
     MutexLocker mu(Threads_lock);
 
-    // Check to see if we're running a thread that's already exited or was
-    // stopped (is_stillborn) or is still active (thread is not NULL).
-    if (java_lang_Thread::is_stillborn(JNIHandles::resolve_non_null(jthread)) ||
-        java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
-        throw_illegal_thread_state = true;
+    // Since JDK 5 the java.lang.Thread threadStatus is used to prevent
+    // re-starting an already started thread, so we should usually find
+    // that the JavaThread is null. However for a JNI attached thread
+    // there is a small window between the Thread object being created
+    // (with its JavaThread set) and the update to its threadStatus, so we
+    // have to check for this
+    if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
+      throw_illegal_thread_state = true;
     } else {
+      // We could also check the stillborn flag to see if this thread was already stopped, but
+      // for historical reasons we let the thread detect that itself when it starts running
+
       jlong size =
              java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
       // Allocate the C++ Thread structure and create the native thread.  The
@@ -2704,7 +2709,7 @@
 // JVM_Stop is implemented using a VM_Operation, so threads are forced to safepoints
 // before the quasi-asynchronous exception is delivered.  This is a little obtrusive,
 // but is thought to be reliable and simple. In the case, where the receiver is the
-// save thread as the sender, no safepoint is needed.
+// same thread as the sender, no safepoint is needed.
 JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))
   JVMWrapper("JVM_StopThread");
 
@@ -2715,26 +2720,27 @@
   oop java_thread = JNIHandles::resolve_non_null(jthread);
   JavaThread* receiver = java_lang_Thread::thread(java_thread);
   Events::log("JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", receiver, (address)java_thread, throwable);
-  // First check if thread already exited
+  // First check if thread is alive
   if (receiver != NULL) {
     // Check if exception is getting thrown at self (use oop equality, since the
     // target object might exit)
     if (java_thread == thread->threadObj()) {
-      // This is a change from JDK 1.1, but JDK 1.2 will also do it:
-      // NOTE (from JDK 1.2): this is done solely to prevent stopped
-      // threads from being restarted.
-      // Fix for 4314342, 4145910, perhaps others: it now doesn't have
-      // any effect on the "liveness" of a thread; see
-      // JVM_IsThreadAlive, below.
-      if (java_throwable->is_a(SystemDictionary::ThreadDeath_klass())) {
-        java_lang_Thread::set_stillborn(java_thread);
-      }
       THROW_OOP(java_throwable);
     } else {
       // Enques a VM_Operation to stop all threads and then deliver the exception...
       Thread::send_async_exception(java_thread, JNIHandles::resolve(throwable));
     }
   }
+  else {
+    // Either:
+    // - target thread has not been started before being stopped, or
+    // - target thread already terminated
+    // We could read the threadStatus to determine which case it is
+    // but that is overkill as it doesn't matter. We must set the
+    // stillborn flag for the first case, and if the thread has already
+    // exited setting this flag has no affect
+    java_lang_Thread::set_stillborn(java_thread);
+  }
 JVM_END
 
 
@@ -3106,9 +3112,8 @@
   Handle class_name_str = java_lang_String::internalize_classname(h_name, CHECK_0);
 
   const char* str = java_lang_String::as_utf8_string(class_name_str());
-  symbolHandle class_name_sym =
-                symbolHandle(THREAD, SymbolTable::probe(str, (int)strlen(str)));
-  if (class_name_sym.is_null()) {
+  TempNewSymbol class_name_sym = SymbolTable::probe(str, (int)strlen(str));
+  if (class_name_sym == NULL) {
     return -1;
   }
 
@@ -3118,7 +3123,7 @@
     if (!vfst.method()->is_native()) {
       klassOop holder = vfst.method()->method_holder();
       assert(holder->is_klass(), "just checking");
-      if (instanceKlass::cast(holder)->name() == class_name_sym()) {
+      if (instanceKlass::cast(holder)->name() == class_name_sym) {
         return depth;
       }
       depth++;
@@ -3317,13 +3322,13 @@
 
   const char* str = java_lang_String::as_utf8_string(string());
 
-  if (str == NULL || (int)strlen(str) > symbolOopDesc::max_length()) {
+  if (str == NULL || (int)strlen(str) > Symbol::max_length()) {
     // It's impossible to create this class;  the name cannot fit
     // into the constant pool.
     THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), str);
   }
 
-  symbolHandle name = oopFactory::new_symbol_handle(str, CHECK_NULL);
+  TempNewSymbol name = SymbolTable::new_symbol(str, CHECK_NULL);
   Handle curr_klass (THREAD, JNIHandles::resolve(currClass));
   // Find the most recent class on the stack with a non-null classloader
   oop loader = NULL;
@@ -3966,7 +3971,7 @@
 
 // Shared JNI/JVM entry points //////////////////////////////////////////////////////////////
 
-jclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) {
+jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) {
   // Security Note:
   //   The Java level wrapper will perform the necessary security check allowing
   //   us to pass the NULL as the initiating class loader.
@@ -4062,14 +4067,13 @@
   Handle str (THREAD, JNIHandles::resolve_non_null(name));
 
   const char* cstr = java_lang_String::as_utf8_string(str());
-  symbolHandle field_name =
-           symbolHandle(THREAD, SymbolTable::probe(cstr, (int)strlen(cstr)));
-  if (field_name.is_null()) {
+  TempNewSymbol field_name = SymbolTable::probe(cstr, (int)strlen(cstr));
+  if (field_name == NULL) {
     THROW_0(vmSymbols::java_lang_NoSuchFieldException());
   }
 
   oop mirror = JNIHandles::resolve_non_null(cls);
-  oop result = Reflection::reflect_field(mirror, field_name(), which, CHECK_NULL);
+  oop result = Reflection::reflect_field(mirror, field_name, which, CHECK_NULL);
   if (result == NULL) {
     THROW_0(vmSymbols::java_lang_NoSuchFieldException());
   }
@@ -4086,9 +4090,8 @@
   Handle str (THREAD, JNIHandles::resolve_non_null(name));
 
   const char* cstr = java_lang_String::as_utf8_string(str());
-  symbolHandle method_name =
-          symbolHandle(THREAD, SymbolTable::probe(cstr, (int)strlen(cstr)));
-  if (method_name.is_null()) {
+  TempNewSymbol method_name = SymbolTable::probe(cstr, (int)strlen(cstr));
+  if (method_name == NULL) {
     THROW_0(vmSymbols::java_lang_NoSuchMethodException());
   }
 
@@ -4461,16 +4464,14 @@
   dest->obj_at_put(0, Klass::cast(enc_k)->java_mirror());
   int encl_method_method_idx = ik_h->enclosing_method_method_index();
   if (encl_method_method_idx != 0) {
-    symbolOop sym_o = ik_h->constants()->symbol_at(
+    Symbol* sym = ik_h->constants()->symbol_at(
                         extract_low_short_from_int(
                           ik_h->constants()->name_and_type_at(encl_method_method_idx)));
-    symbolHandle sym(THREAD, sym_o);
     Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
     dest->obj_at_put(1, str());
-    sym_o = ik_h->constants()->symbol_at(
+    sym = ik_h->constants()->symbol_at(
               extract_high_short_from_int(
                 ik_h->constants()->name_and_type_at(encl_method_method_idx)));
-    sym = symbolHandle(THREAD, sym_o);
     str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
     dest->obj_at_put(2, str());
   }
--- a/src/share/vm/prims/jvm.h	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvm.h	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1649,7 +1649,8 @@
      * the new bit is also added in the main/baseline.
      */
     unsigned int thread_park_blocker : 1;
-    unsigned int : 31;
+    unsigned int post_vm_init_hook_enabled : 1;
+    unsigned int : 30;
     unsigned int : 32;
     unsigned int : 32;
 } jdk_version_info;
--- a/src/share/vm/prims/jvm_misc.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvm_misc.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,7 +31,7 @@
 // Useful entry points shared by JNI and JVM interface.
 // We do not allow real JNI or JVM entry point to call each other.
 
-jclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS);
+jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS);
 
 void trace_class_resolution(klassOop to_class);
 
--- a/src/share/vm/prims/jvmti.xml	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmti.xml	Wed Feb 16 13:47:20 2011 +0100
@@ -13048,8 +13048,8 @@
   <event label="Garbage Collection Start"
 	 id="GarbageCollectionStart" const="JVMTI_EVENT_GARBAGE_COLLECTION_START" num="81">
     <description>
-      A Garbage Collection Start event is sent when a full cycle
-      garbage collection begins.
+      A Garbage Collection Start event is sent when a 
+      garbage collection pause begins.
       Only stop-the-world collections are reported--that is, collections during
       which all threads cease to modify the state of the Java virtual machine.
       This means that some collectors will never generate these events.
@@ -13075,8 +13075,8 @@
   <event label="Garbage Collection Finish"
 	 id="GarbageCollectionFinish" const="JVMTI_EVENT_GARBAGE_COLLECTION_FINISH" num="82">
     <description>
-      A Garbage Collection Finish event is sent when a full 
-      garbage collection cycle ends.
+      A Garbage Collection Finish event is sent when a
+      garbage collection pause ends.
       This event is sent while the VM is still stopped, thus
       the event handler must not use JNI functions and
       must not use <jvmti/> functions except those which
--- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -461,11 +461,11 @@
 // JVMSpec|     attribute_info attributes[attributes_count];
 void JvmtiClassFileReconstituter::write_class_attributes() {
   u2 inner_classes_length = inner_classes_attribute_length();
-  symbolHandle generic_signature(thread(), ikh()->generic_signature());
+  Symbol* generic_signature = ikh()->generic_signature();
   typeArrayHandle anno(thread(), ikh()->class_annotations());
 
   int attr_count = 0;
-  if (generic_signature() != NULL) {
+  if (generic_signature != NULL) {
     ++attr_count;
   }
   if (ikh()->source_file_name() != NULL) {
@@ -483,8 +483,8 @@
 
   write_u2(attr_count);
 
-  if (generic_signature() != NULL) {
-    write_signature_attribute(symbol_to_cpool_index(generic_signature()));
+  if (generic_signature != NULL) {
+    write_signature_attribute(symbol_to_cpool_index(generic_signature));
   }
   if (ikh()->source_file_name() != NULL) {
     write_source_file_attribute();
@@ -609,8 +609,7 @@
 }
 
 void JvmtiClassFileReconstituter::write_attribute_name_index(const char* name) {
-  unsigned int hash_ignored;
-  symbolOop sym = SymbolTable::lookup_only(name, (int)strlen(name), hash_ignored);
+  TempNewSymbol sym = SymbolTable::probe(name, (int)strlen(name));
   assert(sym != NULL, "attribute name symbol not found");
   u2 attr_name_index = symbol_to_cpool_index(sym);
   assert(attr_name_index != 0, "attribute name symbol not in constant pool");
--- a/src/share/vm/prims/jvmtiClassFileReconstituter.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiClassFileReconstituter.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -41,11 +41,11 @@
   instanceKlassHandle  ikh()     { return _ikh; };
   constantPoolHandle   cpool()   { return _cpool; };
 
-  u2 symbol_to_cpool_index(symbolOop sym) {
+  u2 symbol_to_cpool_index(Symbol* sym) {
     return _symmap->symbol_to_value(sym);
   }
 
-  u2 class_symbol_to_cpool_index(symbolOop sym) {
+  u2 class_symbol_to_cpool_index(Symbol* sym) {
     return _classmap->symbol_to_value(sym);
   }
 
--- a/src/share/vm/prims/jvmtiEnv.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiEnv.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -541,12 +541,12 @@
       JavaCalls::call_special(&res,
                               loader,
                               loader_ik,
-                              vmSymbolHandles::appendToClassPathForInstrumentation_name(),
-                              vmSymbolHandles::appendToClassPathForInstrumentation_signature(),
+                              vmSymbols::appendToClassPathForInstrumentation_name(),
+                              vmSymbols::appendToClassPathForInstrumentation_signature(),
                               path,
                               THREAD);
       if (HAS_PENDING_EXCEPTION) {
-        symbolOop ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
+        Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
         CLEAR_PENDING_EXCEPTION;
 
         if (ex_name == vmSymbols::java_lang_NoSuchMethodError()) {
@@ -2124,7 +2124,7 @@
   if (generic_ptr != NULL) {
     *generic_ptr = NULL;
     if (!isPrimitive && Klass::cast(k)->oop_is_instance()) {
-      symbolOop soo = instanceKlass::cast(k)->generic_signature();
+      Symbol* soo = instanceKlass::cast(k)->generic_signature();
       if (soo != NULL) {
         const char *gen_sig = soo->as_C_string();
         if (gen_sig != NULL) {
@@ -2176,7 +2176,7 @@
     return JVMTI_ERROR_ABSENT_INFORMATION;
   }
 
-  symbolOop sfnOop = instanceKlass::cast(k_klass)->source_file_name();
+  Symbol* sfnOop = instanceKlass::cast(k_klass)->source_file_name();
   NULL_CHECK(sfnOop, JVMTI_ERROR_ABSENT_INFORMATION);
   {
     JavaThread* current_thread  = JavaThread::current();
@@ -2539,7 +2539,7 @@
     if (!Klass::cast(k)->oop_is_instance()) {
       return JVMTI_ERROR_ABSENT_INFORMATION;
     }
-    symbolOop sdeOop = instanceKlass::cast(k)->source_debug_extension();
+    Symbol* sdeOop = instanceKlass::cast(k)->source_debug_extension();
     NULL_CHECK(sdeOop, JVMTI_ERROR_ABSENT_INFORMATION);
 
     {
@@ -2619,7 +2619,7 @@
   }
   if (generic_ptr != NULL) {
     *generic_ptr = NULL;
-    symbolOop soop = fdesc_ptr->generic_signature();
+    Symbol* soop = fdesc_ptr->generic_signature();
     if (soop != NULL) {
       const char* gen_sig = soop->as_C_string();
       if (gen_sig != NULL) {
@@ -2695,7 +2695,7 @@
 
   if (generic_ptr != NULL) {
     *generic_ptr = NULL;
-    symbolOop soop = method_oop->generic_signature();
+    Symbol* soop = method_oop->generic_signature();
     if (soop != NULL) {
       const char* gen_sig = soop->as_C_string();
       if (gen_sig != NULL) {
--- a/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1355,7 +1355,7 @@
   }
 
   // Get information about method return type
-  symbolHandle signature(current_thread, jvf->method()->signature());
+  Symbol* signature = jvf->method()->signature();
 
   ResultTypeFinder rtf(signature);
   TosState fr_tos = as_TosState(rtf.type());
--- a/src/share/vm/prims/jvmtiEventController.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiEventController.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -667,14 +667,13 @@
 JvmtiEventControllerPrivate::thread_ended(JavaThread *thread) {
   // Removes the JvmtiThreadState associated with the specified thread.
   // May be called after all environments have been disposed.
+  assert(JvmtiThreadState_lock->is_locked(), "sanity check");
 
   EC_TRACE(("JVMTI [%s] # thread ended", JvmtiTrace::safe_get_thread_name(thread)));
 
   JvmtiThreadState *state = thread->jvmti_thread_state();
-  if (state != NULL) {
-    MutexLocker mu(JvmtiThreadState_lock);
-    delete state;
-  }
+  assert(state != NULL, "else why are we here?");
+  delete state;
 }
 
 void JvmtiEventControllerPrivate::set_event_callbacks(JvmtiEnvBase *env,
--- a/src/share/vm/prims/jvmtiExport.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiExport.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -268,9 +268,9 @@
   jclass  _class_being_redefined;
 
 public:
-  JvmtiClassFileLoadEventMark(JavaThread *thread, symbolHandle name,
+  JvmtiClassFileLoadEventMark(JavaThread *thread, Symbol* name,
      Handle class_loader, Handle prot_domain, KlassHandle *class_being_redefined) : JvmtiThreadEventMark(thread) {
-      _class_name = name() != NULL? name->as_utf8() : NULL;
+      _class_name = name != NULL? name->as_utf8() : NULL;
       _jloader = (jobject)to_jobject(class_loader());
       _protection_domain = (jobject)to_jobject(prot_domain());
       if (class_being_redefined == NULL) {
@@ -506,7 +506,7 @@
 
 class JvmtiClassFileLoadHookPoster : public StackObj {
  private:
-  symbolHandle         _h_name;
+  Symbol*            _h_name;
   Handle               _class_loader;
   Handle               _h_protection_domain;
   unsigned char **     _data_ptr;
@@ -522,7 +522,7 @@
   JvmtiClassLoadKind   _load_kind;
 
  public:
-  inline JvmtiClassFileLoadHookPoster(symbolHandle h_name, Handle class_loader,
+  inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader,
                                       Handle h_protection_domain,
                                       unsigned char **data_ptr, unsigned char **end_ptr,
                                       unsigned char **cached_data_ptr,
@@ -597,7 +597,7 @@
 //    EVT_TRACE(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
 //     ("JVMTI [%s] class file load hook event sent %s  data_ptr = %d, data_len = %d",
 //               JvmtiTrace::safe_get_thread_name(_thread),
-//               _h_name.is_null() ? "NULL" : _h_name->as_utf8(),
+//               _h_name == NULL ? "NULL" : _h_name->as_utf8(),
 //               _curr_data, _curr_len ));
     JvmtiClassFileLoadEventMark jem(_thread, _h_name, _class_loader,
                                     _h_protection_domain,
@@ -655,7 +655,7 @@
 bool JvmtiExport::_should_post_class_file_load_hook = false;
 
 // this entry is for class file load hook on class load, redefine and retransform
-void JvmtiExport::post_class_file_load_hook(symbolHandle h_name,
+void JvmtiExport::post_class_file_load_hook(Symbol* h_name,
                                             Handle class_loader,
                                             Handle h_protection_domain,
                                             unsigned char **data_ptr,
@@ -2253,12 +2253,14 @@
 
 void JvmtiExport::cleanup_thread(JavaThread* thread) {
   assert(JavaThread::current() == thread, "thread is not current");
-
+  MutexLocker mu(JvmtiThreadState_lock);
 
-  // This has to happen after the thread state is removed, which is
-  // why it is not in post_thread_end_event like its complement
-  // Maybe both these functions should be rolled into the posts?
-  JvmtiEventController::thread_ended(thread);
+  if (thread->jvmti_thread_state() != NULL) {
+    // This has to happen after the thread state is removed, which is
+    // why it is not in post_thread_end_event like its complement
+    // Maybe both these functions should be rolled into the posts?
+    JvmtiEventController::thread_ended(thread);
+  }
 }
 
 void JvmtiExport::oops_do(OopClosure* f) {
@@ -2266,6 +2268,14 @@
   JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(f);
 }
 
+void JvmtiExport::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
+  JvmtiTagMap::weak_oops_do(is_alive, f);
+}
+
+void JvmtiExport::gc_epilogue() {
+  JvmtiCurrentBreakpoints::gc_epilogue();
+}
+
 // Onload raw monitor transition.
 void JvmtiExport::transition_pending_onload_raw_monitors() {
   JvmtiPendingMonitors::transition_raw_monitors();
@@ -2358,15 +2368,6 @@
 }
 #endif // SERVICES_KERNEL
 
-// CMS has completed referencing processing so may need to update
-// tag maps.
-void JvmtiExport::cms_ref_processing_epilogue() {
-  if (JvmtiEnv::environments_might_exist()) {
-    JvmtiTagMap::cms_ref_processing_epilogue();
-  }
-}
-
-
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
 // Setup current current thread for event collection.
@@ -2536,36 +2537,20 @@
   }
 };
 
-JvmtiGCMarker::JvmtiGCMarker(bool full) : _full(full), _invocation_count(0) {
-  assert(Thread::current()->is_VM_thread(), "wrong thread");
-
+JvmtiGCMarker::JvmtiGCMarker() {
   // if there aren't any JVMTI environments then nothing to do
   if (!JvmtiEnv::environments_might_exist()) {
     return;
   }
 
-  if (ForceFullGCJVMTIEpilogues) {
-    // force 'Full GC' was done semantics for JVMTI GC epilogues
-    _full = true;
-  }
-
-  // GarbageCollectionStart event posted from VM thread - okay because
-  // JVMTI is clear that the "world is stopped" and callback shouldn't
-  // try to call into the VM.
   if (JvmtiExport::should_post_garbage_collection_start()) {
     JvmtiExport::post_garbage_collection_start();
   }
 
-  // if "full" is false it probably means this is a scavenge of the young
-  // generation. However it could turn out that a "full" GC is required
-  // so we record the number of collections so that it can be checked in
-  // the destructor.
-  if (!_full) {
-    _invocation_count = Universe::heap()->total_full_collections();
+  if (SafepointSynchronize::is_at_safepoint()) {
+    // Do clean up tasks that need to be done at a safepoint
+    JvmtiEnvBase::check_for_periodic_clean_up();
   }
-
-  // Do clean up tasks that need to be done at a safepoint
-  JvmtiEnvBase::check_for_periodic_clean_up();
 }
 
 JvmtiGCMarker::~JvmtiGCMarker() {
@@ -2578,21 +2563,5 @@
   if (JvmtiExport::should_post_garbage_collection_finish()) {
     JvmtiExport::post_garbage_collection_finish();
   }
-
-  // we might have initially started out doing a scavenge of the young
-  // generation but could have ended up doing a "full" GC - check the
-  // GC count to see.
-  if (!_full) {
-    _full = (_invocation_count != Universe::heap()->total_full_collections());
-  }
-
-  // Full collection probably means the perm generation has been GC'ed
-  // so we clear the breakpoint cache.
-  if (_full) {
-    JvmtiCurrentBreakpoints::gc_epilogue();
-  }
-
-  // Notify heap/object tagging support
-  JvmtiTagMap::gc_epilogue(_full);
 }
 #endif // JVMTI_KERNEL
--- a/src/share/vm/prims/jvmtiExport.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiExport.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -306,7 +306,7 @@
   static bool _should_post_class_file_load_hook;
   inline static void set_should_post_class_file_load_hook(bool on)     { _should_post_class_file_load_hook = on;  }
   inline static bool should_post_class_file_load_hook()           { return _should_post_class_file_load_hook; }
-  static void post_class_file_load_hook(symbolHandle h_name, Handle class_loader,
+  static void post_class_file_load_hook(Symbol* h_name, Handle class_loader,
                                         Handle h_protection_domain,
                                         unsigned char **data_ptr, unsigned char **end_ptr,
                                         unsigned char **cached_data_ptr,
@@ -346,6 +346,8 @@
   static void cleanup_thread             (JavaThread* thread) KERNEL_RETURN;
 
   static void oops_do(OopClosure* f) KERNEL_RETURN;
+  static void weak_oops_do(BoolObjectClosure* b, OopClosure* f) KERNEL_RETURN;
+  static void gc_epilogue() KERNEL_RETURN;
 
   static void transition_pending_onload_raw_monitors() KERNEL_RETURN;
 
@@ -356,9 +358,6 @@
 
   // SetNativeMethodPrefix support
   static char** get_all_native_method_prefixes(int* count_ptr);
-
-  // call after CMS has completed referencing processing
-  static void cms_ref_processing_epilogue() KERNEL_RETURN;
 };
 
 // Support class used by JvmtiDynamicCodeEventCollector and others. It
@@ -492,55 +491,11 @@
 
 // Base class for reporting GC events to JVMTI.
 class JvmtiGCMarker : public StackObj {
- private:
-  bool _full;                           // marks a "full" GC
-  unsigned int _invocation_count;       // GC invocation count
- protected:
-  JvmtiGCMarker(bool full) KERNEL_RETURN;       // protected
-  ~JvmtiGCMarker() KERNEL_RETURN;               // protected
+ public:
+  JvmtiGCMarker() KERNEL_RETURN;
+  ~JvmtiGCMarker() KERNEL_RETURN;
 };
 
-
-// Support class used to report GC events to JVMTI. The class is stack
-// allocated and should be placed in the doit() implementation of all
-// vm operations that do a stop-the-world GC for failed allocation.
-//
-// Usage :-
-//
-// void VM_GenCollectForAllocation::doit() {
-//   JvmtiGCForAllocationMarker jgcm;
-//   :
-// }
-//
-// If jvmti is not enabled the constructor and destructor is essentially
-// a no-op (no overhead).
-//
-class JvmtiGCForAllocationMarker : public JvmtiGCMarker {
- public:
-  JvmtiGCForAllocationMarker() : JvmtiGCMarker(false) {
-  }
-};
-
-// Support class used to report GC events to JVMTI. The class is stack
-// allocated and should be placed in the doit() implementation of all
-// vm operations that do a "full" stop-the-world GC. This class differs
-// from JvmtiGCForAllocationMarker in that this class assumes that a
-// "full" GC will happen.
-//
-// Usage :-
-//
-// void VM_GenCollectFull::doit() {
-//   JvmtiGCFullMarker jgcm;
-//   :
-// }
-//
-class JvmtiGCFullMarker : public JvmtiGCMarker {
- public:
-  JvmtiGCFullMarker() : JvmtiGCMarker(true) {
-  }
-};
-
-
 // JvmtiHideSingleStepping is a helper class for hiding
 // internal single step events.
 class JvmtiHideSingleStepping : public StackObj {
--- a/src/share/vm/prims/jvmtiImpl.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiImpl.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -217,7 +217,6 @@
 
 void GrowableCache::gc_epilogue() {
   int len = _elements->length();
-  // recompute the new cache value after GC
   for (int i=0; i<len; i++) {
     _cache[i] = _elements->at(i)->getCacheValue();
   }
@@ -286,8 +285,8 @@
   // not saved in the PreviousVersionInfo.
   Thread *thread = Thread::current();
   instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder());
-  symbolOop m_name = _method->name();
-  symbolOop m_signature = _method->signature();
+  Symbol* m_name = _method->name();
+  Symbol* m_signature = _method->signature();
 
   {
     ResourceMark rm(thread);
@@ -401,7 +400,7 @@
   _bps.oops_do(f);
 }
 
-void  JvmtiBreakpoints::gc_epilogue() {
+void JvmtiBreakpoints::gc_epilogue() {
   _bps.gc_epilogue();
 }
 
@@ -540,7 +539,6 @@
   }
 }
 
-
 ///////////////////////////////////////////////////////////////
 //
 // class VM_GetOrSetLocal
@@ -630,22 +628,22 @@
     ty_sign++;
     len -= 2;
   }
-  symbolHandle ty_sym = oopFactory::new_symbol_handle(ty_sign, len, thread);
-  if (klass->name() == ty_sym()) {
+  TempNewSymbol ty_sym = SymbolTable::new_symbol(ty_sign, len, thread);
+  if (klass->name() == ty_sym) {
     return true;
   }
   // Compare primary supers
   int super_depth = klass->super_depth();
   int idx;
   for (idx = 0; idx < super_depth; idx++) {
-    if (Klass::cast(klass->primary_super_of_depth(idx))->name() == ty_sym()) {
+    if (Klass::cast(klass->primary_super_of_depth(idx))->name() == ty_sym) {
       return true;
     }
   }
   // Compare secondary supers
   objArrayOop sec_supers = klass->secondary_supers();
   for (idx = 0; idx < sec_supers->length(); idx++) {
-    if (Klass::cast((klassOop) sec_supers->obj_at(idx))->name() == ty_sym()) {
+    if (Klass::cast((klassOop) sec_supers->obj_at(idx))->name() == ty_sym) {
       return true;
     }
   }
@@ -692,7 +690,7 @@
     _result = JVMTI_ERROR_INVALID_SLOT;
     return false;       // Incorrect slot index
   }
-  symbolOop   sign_sym  = method_oop->constants()->symbol_at(signature_idx);
+  Symbol*   sign_sym  = method_oop->constants()->symbol_at(signature_idx);
   const char* signature = (const char *) sign_sym->as_utf8();
   BasicType slot_type = char2type(signature[0]);
 
--- a/src/share/vm/prims/jvmtiImpl.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiImpl.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -117,6 +117,7 @@
   void clear();
   // apply f to every element and update the cache
   void oops_do(OopClosure* f);
+  // update the cache after a full gc
   void gc_epilogue();
 };
 
@@ -278,13 +279,13 @@
 
   int length();
   void oops_do(OopClosure* f);
-  void gc_epilogue();
   void print();
 
   int  set(JvmtiBreakpoint& bp);
   int  clear(JvmtiBreakpoint& bp);
   void clearall_in_class_at_safepoint(klassOop klass);
   void clearall();
+  void gc_epilogue();
 };
 
 
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -235,7 +235,7 @@
     case JVM_CONSTANT_String:      // fall through
 
     // These were indirect CP entries, but they have been changed into
-    // symbolOops so these entries can be directly appended.
+    // Symbol*s so these entries can be directly appended.
     case JVM_CONSTANT_UnresolvedClass:  // fall through
     case JVM_CONSTANT_UnresolvedString:
     {
@@ -575,12 +575,12 @@
     // name and signature
     jshort name_index = k_old_fields->short_at(i + instanceKlass::name_index_offset);
     jshort sig_index = k_old_fields->short_at(i +instanceKlass::signature_index_offset);
-    symbolOop name_sym1 = the_class->constants()->symbol_at(name_index);
-    symbolOop sig_sym1 = the_class->constants()->symbol_at(sig_index);
+    Symbol* name_sym1 = the_class->constants()->symbol_at(name_index);
+    Symbol* sig_sym1 = the_class->constants()->symbol_at(sig_index);
     name_index = k_new_fields->short_at(i + instanceKlass::name_index_offset);
     sig_index = k_new_fields->short_at(i + instanceKlass::signature_index_offset);
-    symbolOop name_sym2 = scratch_class->constants()->symbol_at(name_index);
-    symbolOop sig_sym2 = scratch_class->constants()->symbol_at(sig_index);
+    Symbol* name_sym2 = scratch_class->constants()->symbol_at(name_index);
+    Symbol* sig_sym2 = scratch_class->constants()->symbol_at(sig_index);
     if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) {
       return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED;
     }
@@ -855,7 +855,7 @@
     }
     klassOop the_class_oop = java_lang_Class::as_klassOop(mirror);
     instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop);
-    symbolHandle the_class_sym = symbolHandle(THREAD, the_class->name());
+    Symbol*  the_class_sym = the_class->name();
 
     // RC_TRACE_WITH_THREAD macro has an embedded ResourceMark
     RC_TRACE_WITH_THREAD(0x00000001, THREAD,
@@ -886,7 +886,7 @@
     instanceKlassHandle scratch_class (THREAD, k);
 
     if (HAS_PENDING_EXCEPTION) {
-      symbolOop ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
+      Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
       // RC_TRACE_WITH_THREAD macro has an embedded ResourceMark
       RC_TRACE_WITH_THREAD(0x00000002, THREAD, ("parse_stream exception: '%s'",
         ex_name->as_C_string()));
@@ -912,7 +912,7 @@
     if (!the_class->is_linked()) {
       the_class->link_class(THREAD);
       if (HAS_PENDING_EXCEPTION) {
-        symbolOop ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
+        Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
         // RC_TRACE_WITH_THREAD macro has an embedded ResourceMark
         RC_TRACE_WITH_THREAD(0x00000002, THREAD, ("link_class exception: '%s'",
           ex_name->as_C_string()));
@@ -950,7 +950,7 @@
     }
 
     if (HAS_PENDING_EXCEPTION) {
-      symbolOop ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
+      Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
       // RC_TRACE_WITH_THREAD macro has an embedded ResourceMark
       RC_TRACE_WITH_THREAD(0x00000002, THREAD,
         ("verify_byte_codes exception: '%s'", ex_name->as_C_string()));
@@ -976,7 +976,7 @@
       }
 
       if (HAS_PENDING_EXCEPTION) {
-        symbolOop ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
+        Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
         // RC_TRACE_WITH_THREAD macro has an embedded ResourceMark
         RC_TRACE_WITH_THREAD(0x00000002, THREAD,
           ("verify_byte_codes post merge-CP exception: '%s'",
@@ -993,7 +993,7 @@
 
     Rewriter::rewrite(scratch_class, THREAD);
     if (HAS_PENDING_EXCEPTION) {
-      symbolOop ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
+      Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name();
       CLEAR_PENDING_EXCEPTION;
       if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) {
         return JVMTI_ERROR_OUT_OF_MEMORY;
@@ -1458,7 +1458,7 @@
     if (bc_length == 0) {
       // More complicated bytecodes report a length of zero so
       // we have to try again a slightly different way.
-      bc_length = Bytecodes::length_at(bcp);
+      bc_length = Bytecodes::length_at(method(), bcp);
     }
 
     assert(bc_length != 0, "impossible bytecode length");
@@ -2857,8 +2857,8 @@
   //    (2) with the prefix.
   // where 'prefix' is the prefix at that 'depth' (first prefix, second prefix,...)
   methodOop search_prefix_name_space(int depth, char* name_str, size_t name_len,
-                                     symbolOop signature) {
-    symbolOop name_symbol = SymbolTable::probe(name_str, (int)name_len);
+                                     Symbol* signature) {
+    TempNewSymbol name_symbol = SymbolTable::probe(name_str, (int)name_len);
     if (name_symbol != NULL) {
       methodOop method = Klass::cast(the_class())->lookup_method(name_symbol, signature);
       if (method != NULL) {
@@ -2897,7 +2897,7 @@
 
   // Return the method name with old prefixes stripped away.
   char* method_name_without_prefixes(methodOop method) {
-    symbolOop name = method->name();
+    Symbol* name = method->name();
     char* name_str = name->as_utf8();
 
     // Old prefixing may be defunct, strip prefixes, if any.
--- a/src/share/vm/prims/jvmtiRedefineClasses.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -223,8 +223,8 @@
 // JVM_CONSTANT_UnresolvedClass and JVM_CONSTANT_UnresolvedString
 // entries. During this conversion process, the UTF8 values that are
 // indirectly referenced by the JVM_CONSTANT_ClassIndex and
-// JVM_CONSTANT_StringIndex entries are changed into symbolOops and the
-// entries are modified to refer to the symbolOops. This optimization
+// JVM_CONSTANT_StringIndex entries are changed into Symbol*s and the
+// entries are modified to refer to the Symbol*s. This optimization
 // eliminates one level of indirection for those two CP entry types and
 // gets the entries ready for verification. During class file parsing
 // it is also possible for JVM_CONSTANT_UnresolvedString entries to be
--- a/src/share/vm/prims/jvmtiTagMap.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiTagMap.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -50,7 +50,7 @@
 
 // JvmtiTagHashmapEntry
 //
-// Each entry encapsulates a JNI weak reference to the tagged object
+// Each entry encapsulates a reference to the tagged object
 // and the tag value. In addition an entry includes a next pointer which
 // is used to chain entries together.
 
@@ -58,24 +58,25 @@
  private:
   friend class JvmtiTagMap;
 
-  jweak _object;                        // JNI weak ref to tagged object
+  oop _object;                          // tagged object
   jlong _tag;                           // the tag
   JvmtiTagHashmapEntry* _next;          // next on the list
 
-  inline void init(jweak object, jlong tag) {
+  inline void init(oop object, jlong tag) {
     _object = object;
     _tag = tag;
     _next = NULL;
   }
 
   // constructor
-  JvmtiTagHashmapEntry(jweak object, jlong tag)         { init(object, tag); }
+  JvmtiTagHashmapEntry(oop object, jlong tag)         { init(object, tag); }
 
  public:
 
   // accessor methods
-  inline jweak object() const                           { return _object; }
-  inline jlong tag() const                              { return _tag; }
+  inline oop object() const                           { return _object; }
+  inline oop* object_addr()                           { return &_object; }
+  inline jlong tag() const                            { return _tag; }
 
   inline void set_tag(jlong tag) {
     assert(tag != 0, "can't be zero");
@@ -92,9 +93,7 @@
 // A hashmap is essentially a table of pointers to entries. Entries
 // are hashed to a location, or position in the table, and then
 // chained from that location. The "key" for hashing is address of
-// the object, or oop. The "value" is the JNI weak reference to the
-// object and the tag value. Keys are not stored with the entry.
-// Instead the weak reference is resolved to obtain the key.
+// the object, or oop. The "value" is the tag value.
 //
 // A hashmap maintains a count of the number entries in the hashmap
 // and resizes if the number of entries exceeds a given threshold.
@@ -206,7 +205,7 @@
       JvmtiTagHashmapEntry* entry = _table[i];
       while (entry != NULL) {
         JvmtiTagHashmapEntry* next = entry->next();
-        oop key = JNIHandles::resolve(entry->object());
+        oop key = entry->object();
         assert(key != NULL, "jni weak reference cleared!!");
         unsigned int h = hash(key, new_size);
         JvmtiTagHashmapEntry* anchor = new_table[h];
@@ -299,14 +298,12 @@
     unsigned int h = hash(key);
     JvmtiTagHashmapEntry* entry = _table[h];
     while (entry != NULL) {
-      oop orig_key = JNIHandles::resolve(entry->object());
-      assert(orig_key != NULL, "jni weak reference cleared!!");
-      if (key == orig_key) {
-        break;
+      if (entry->object() == key) {
+         return entry;
       }
       entry = entry->next();
     }
-    return entry;
+    return NULL;
   }
 
 
@@ -343,9 +340,7 @@
     JvmtiTagHashmapEntry* entry = _table[h];
     JvmtiTagHashmapEntry* prev = NULL;
     while (entry != NULL) {
-      oop orig_key = JNIHandles::resolve(entry->object());
-      assert(orig_key != NULL, "jni weak reference cleared!!");
-      if (key == orig_key) {
+      if (key == entry->object()) {
         break;
       }
       prev = entry;
@@ -418,54 +413,6 @@
   }
 }
 
-// memory region for young generation
-MemRegion JvmtiTagMap::_young_gen;
-
-// get the memory region used for the young generation
-void JvmtiTagMap::get_young_generation() {
-  CollectedHeap* ch = Universe::heap();
-  switch (ch->kind()) {
-    case (CollectedHeap::GenCollectedHeap): {
-      _young_gen = ((GenCollectedHeap*)ch)->get_gen(0)->reserved();
-      break;
-    }
-#ifndef SERIALGC
-    case (CollectedHeap::ParallelScavengeHeap): {
-      _young_gen = ((ParallelScavengeHeap*)ch)->young_gen()->reserved();
-      break;
-    }
-    case (CollectedHeap::G1CollectedHeap): {
-      // Until a more satisfactory solution is implemented, all
-      // oops in the tag map will require rehash at each gc.
-      // This is a correct, if extremely inefficient solution.
-      // See RFE 6621729 for related commentary.
-      _young_gen = ch->reserved_region();
-      break;
-    }
-#endif  // !SERIALGC
-    default:
-      ShouldNotReachHere();
-  }
-}
-
-// returns true if oop is in the young generation
-inline bool JvmtiTagMap::is_in_young(oop o) {
-  assert(_young_gen.start() != NULL, "checking");
-  void* p = (void*)o;
-  bool in_young = _young_gen.contains(p);
-  return in_young;
-}
-
-// returns the appropriate hashmap for a given object
-inline JvmtiTagHashmap* JvmtiTagMap::hashmap_for(oop o) {
-  if (is_in_young(o)) {
-    return _hashmap[0];
-  } else {
-    return _hashmap[1];
-  }
-}
-
-
 // create a JvmtiTagMap
 JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
   _env(env),
@@ -476,13 +423,7 @@
   assert(JvmtiThreadState_lock->is_locked(), "sanity check");
   assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment");
 
-  // create the hashmaps
-  for (int i=0; i<n_hashmaps; i++) {
-    _hashmap[i] = new JvmtiTagHashmap();
-  }
-
-  // get the memory region used by the young generation
-  get_young_generation();
+  _hashmap = new JvmtiTagHashmap();
 
   // finally add us to the environment
   ((JvmtiEnvBase *)env)->set_tag_map(this);
@@ -496,25 +437,20 @@
   // also being destroryed.
   ((JvmtiEnvBase *)_env)->set_tag_map(NULL);
 
-  // iterate over the hashmaps and destroy each of the entries
-  for (int i=0; i<n_hashmaps; i++) {
-    JvmtiTagHashmap* hashmap = _hashmap[i];
-    JvmtiTagHashmapEntry** table = hashmap->table();
-    for (int j=0; j<hashmap->size(); j++) {
-      JvmtiTagHashmapEntry *entry = table[j];
-      while (entry != NULL) {
-        JvmtiTagHashmapEntry* next = entry->next();
-        jweak ref = entry->object();
-        JNIHandles::destroy_weak_global(ref);
-        delete entry;
-        entry = next;
-      }
+  JvmtiTagHashmapEntry** table = _hashmap->table();
+  for (int j = 0; j < _hashmap->size(); j++) {
+    JvmtiTagHashmapEntry* entry = table[j];
+    while (entry != NULL) {
+      JvmtiTagHashmapEntry* next = entry->next();
+      delete entry;
+      entry = next;
     }
-
-    // finally destroy the hashmap
-    delete hashmap;
   }
 
+  // finally destroy the hashmap
+  delete _hashmap;
+  _hashmap = NULL;
+
   // remove any entries on the free list
   JvmtiTagHashmapEntry* entry = _free_entries;
   while (entry != NULL) {
@@ -522,12 +458,13 @@
     delete entry;
     entry = next;
   }
+  _free_entries = NULL;
 }
 
 // create a hashmap entry
 // - if there's an entry on the (per-environment) free list then this
 // is returned. Otherwise an new entry is allocated.
-JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(jweak ref, jlong tag) {
+JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(oop ref, jlong tag) {
   assert(Thread::current()->is_VM_thread() || is_locked(), "checking");
   JvmtiTagHashmapEntry* entry;
   if (_free_entries == NULL) {
@@ -558,10 +495,10 @@
 // returns the tag map for the given environments. If the tag map
 // doesn't exist then it is created.
 JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
-  JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
+  JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map();
   if (tag_map == NULL) {
     MutexLocker mu(JvmtiThreadState_lock);
-    tag_map = ((JvmtiEnvBase *)env)->tag_map();
+    tag_map = ((JvmtiEnvBase*)env)->tag_map();
     if (tag_map == NULL) {
       tag_map = new JvmtiTagMap(env);
     }
@@ -573,17 +510,13 @@
 
 // iterate over all entries in the tag map.
 void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) {
-  for (int i=0; i<n_hashmaps; i++) {
-    JvmtiTagHashmap* hashmap = _hashmap[i];
-    hashmap->entry_iterate(closure);
-  }
+  hashmap()->entry_iterate(closure);
 }
 
 // returns true if the hashmaps are empty
 bool JvmtiTagMap::is_empty() {
   assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");
-  assert(n_hashmaps == 2, "not implemented");
-  return ((_hashmap[0]->entry_count() == 0) && (_hashmap[1]->entry_count() == 0));
+  return hashmap()->entry_count() == 0;
 }
 
 
@@ -591,7 +524,7 @@
 // not tagged
 //
 static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) {
-  JvmtiTagHashmapEntry* entry = tag_map->hashmap_for(o)->find(o);
+  JvmtiTagHashmapEntry* entry = tag_map->hashmap()->find(o);
   if (entry == NULL) {
     return 0;
   } else {
@@ -655,7 +588,7 @@
 
     // record the context
     _tag_map = tag_map;
-    _hashmap = tag_map->hashmap_for(_o);
+    _hashmap = tag_map->hashmap();
     _entry = _hashmap->find(_o);
 
     // get object tag
@@ -694,23 +627,18 @@
     if (obj_tag != 0) {
       // callback has tagged the object
       assert(Thread::current()->is_VM_thread(), "must be VMThread");
-      HandleMark hm;
-      Handle h(o);
-      jweak ref = JNIHandles::make_weak_global(h);
-      entry = tag_map()->create_entry(ref, obj_tag);
+      entry = tag_map()->create_entry(o, obj_tag);
       hashmap->add(o, entry);
     }
   } else {
     // object was previously tagged - the callback may have untagged
     // the object or changed the tag value
     if (obj_tag == 0) {
-      jweak ref = entry->object();
 
       JvmtiTagHashmapEntry* entry_removed = hashmap->remove(o);
       assert(entry_removed == entry, "checking");
       tag_map()->destroy_entry(entry);
 
-      JNIHandles::destroy_weak_global(ref);
     } else {
       if (obj_tag != entry->tag()) {
          entry->set_tag(obj_tag);
@@ -760,7 +688,7 @@
       // for Classes the klassOop is tagged
       _referrer = klassOop_if_java_lang_Class(referrer);
       // record the context
-      _referrer_hashmap = tag_map->hashmap_for(_referrer);
+      _referrer_hashmap = tag_map->hashmap();
       _referrer_entry = _referrer_hashmap->find(_referrer);
 
       // get object tag
@@ -796,8 +724,7 @@
 //
 // This function is performance critical. If many threads attempt to tag objects
 // around the same time then it's possible that the Mutex associated with the
-// tag map will be a hot lock. Eliminating this lock will not eliminate the issue
-// because creating a JNI weak reference requires acquiring a global lock also.
+// tag map will be a hot lock.
 void JvmtiTagMap::set_tag(jobject object, jlong tag) {
   MutexLocker ml(lock());
 
@@ -808,22 +735,14 @@
   o = klassOop_if_java_lang_Class(o);
 
   // see if the object is already tagged
-  JvmtiTagHashmap* hashmap = hashmap_for(o);
+  JvmtiTagHashmap* hashmap = _hashmap;
   JvmtiTagHashmapEntry* entry = hashmap->find(o);
 
   // if the object is not already tagged then we tag it
   if (entry == NULL) {
     if (tag != 0) {
-      HandleMark hm;
-      Handle h(o);
-      jweak ref = JNIHandles::make_weak_global(h);
-
-      // the object may have moved because make_weak_global may
-      // have blocked - thus it is necessary resolve the handle
-      // and re-hash the object.
-      o = h();
-      entry = create_entry(ref, tag);
-      hashmap_for(o)->add(o, entry);
+      entry = create_entry(o, tag);
+      hashmap->add(o, entry);
     } else {
       // no-op
     }
@@ -831,13 +750,9 @@
     // if the object is already tagged then we either update
     // the tag (if a new tag value has been provided)
     // or remove the object if the new tag value is 0.
-    // Removing the object requires that we also delete the JNI
-    // weak ref to the object.
     if (tag == 0) {
-      jweak ref = entry->object();
       hashmap->remove(o);
       destroy_entry(entry);
-      JNIHandles::destroy_weak_global(ref);
     } else {
       entry->set_tag(tag);
     }
@@ -1626,8 +1541,8 @@
   void do_entry(JvmtiTagHashmapEntry* entry) {
     for (int i=0; i<_tag_count; i++) {
       if (_tags[i] == entry->tag()) {
-        oop o = JNIHandles::resolve(entry->object());
-        assert(o != NULL && o != JNIHandles::deleted_handle(), "sanity check");
+        oop o = entry->object();
+        assert(o != NULL, "sanity check");
 
         // the mirror is tagged
         if (o->is_klass()) {
@@ -2690,7 +2605,7 @@
     }
 
     // some objects are ignored - in the case of simple
-    // roots it's mostly symbolOops that we are skipping
+    // roots it's mostly Symbol*s that we are skipping
     // here.
     if (!ServiceUtil::visible_oop(o)) {
       return;
@@ -3374,62 +3289,25 @@
 }
 
 
-// called post-GC
-// - for each JVMTI environment with an object tag map, call its rehash
-// function to re-sync with the new object locations.
-void JvmtiTagMap::gc_epilogue(bool full) {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
+void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
+  // No locks during VM bring-up (0 threads) and no safepoints after main
+  // thread creation and before VMThread creation (1 thread); initial GC
+  // verification can happen in that window which gets to here.
+  assert(Threads::number_of_threads() <= 1 ||
+         SafepointSynchronize::is_at_safepoint(),
+         "must be executed at a safepoint");
   if (JvmtiEnv::environments_might_exist()) {
-    // re-obtain the memory region for the young generation (might
-    // changed due to adaptive resizing policy)
-    get_young_generation();
-
     JvmtiEnvIterator it;
     for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
       JvmtiTagMap* tag_map = env->tag_map();
       if (tag_map != NULL && !tag_map->is_empty()) {
-        TraceTime t(full ? "JVMTI Full Rehash " : "JVMTI Rehash ", TraceJVMTIObjectTagging);
-        if (full) {
-          tag_map->rehash(0, n_hashmaps);
-        } else {
-          tag_map->rehash(0, 0);        // tag map for young gen only
-        }
+        tag_map->do_weak_oops(is_alive, f);
       }
     }
   }
 }
 
-// CMS has completed referencing processing so we may have JNI weak refs
-// to objects in the CMS generation that have been GC'ed.
-void JvmtiTagMap::cms_ref_processing_epilogue() {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
-  assert(UseConcMarkSweepGC, "should only be used with CMS");
-  if (JvmtiEnv::environments_might_exist()) {
-    JvmtiEnvIterator it;
-    for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
-      JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
-      if (tag_map != NULL && !tag_map->is_empty()) {
-        TraceTime t("JVMTI Rehash (CMS) ", TraceJVMTIObjectTagging);
-        tag_map->rehash(1, n_hashmaps);    // assume CMS not used in young gen
-      }
-    }
-  }
-}
-
-
-// For each entry in the hashmaps 'start' to 'end' :
-//
-// 1. resolve the JNI weak reference
-//
-// 2. If it resolves to NULL it means the object has been freed so the entry
-//    is removed, the weak reference destroyed, and the object free event is
-//    posted (if enabled).
-//
-// 3. If the weak reference resolves to an object then we re-hash the object
-//    to see if it has moved or has been promoted (from the young to the old
-//    generation for example).
-//
-void JvmtiTagMap::rehash(int start, int end) {
+void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
 
   // does this environment have the OBJECT_FREE event enabled
   bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE);
@@ -3437,143 +3315,98 @@
   // counters used for trace message
   int freed = 0;
   int moved = 0;
-  int promoted = 0;
-
-  // we assume there are two hashmaps - one for the young generation
-  // and the other for all other spaces.
-  assert(n_hashmaps == 2, "not implemented");
-  JvmtiTagHashmap* young_hashmap = _hashmap[0];
-  JvmtiTagHashmap* other_hashmap = _hashmap[1];
+
+  JvmtiTagHashmap* hashmap = this->hashmap();
 
   // reenable sizing (if disabled)
-  young_hashmap->set_resizing_enabled(true);
-  other_hashmap->set_resizing_enabled(true);
-
-  // when re-hashing the hashmap corresponding to the young generation we
-  // collect the entries corresponding to objects that have been promoted.
-  JvmtiTagHashmapEntry* promoted_entries = NULL;
-
-  if (end >= n_hashmaps) {
-    end = n_hashmaps - 1;
+  hashmap->set_resizing_enabled(true);
+
+  // if the hashmap is empty then we can skip it
+  if (hashmap->_entry_count == 0) {
+    return;
   }
 
-  for (int i=start; i <= end; i++) {
-    JvmtiTagHashmap* hashmap = _hashmap[i];
-
-    // if the hashmap is empty then we can skip it
-    if (hashmap->_entry_count == 0) {
-      continue;
-    }
-
-    // now iterate through each entry in the table
-
-    JvmtiTagHashmapEntry** table = hashmap->table();
-    int size = hashmap->size();
-
-    for (int pos=0; pos<size; pos++) {
-      JvmtiTagHashmapEntry* entry = table[pos];
-      JvmtiTagHashmapEntry* prev = NULL;
-
-      while (entry != NULL) {
-        JvmtiTagHashmapEntry* next = entry->next();
-
-        jweak ref = entry->object();
-        oop oop = JNIHandles::resolve(ref);
-
-        // has object been GC'ed
-        if (oop == NULL) {
-          // grab the tag
-          jlong tag = entry->tag();
-          guarantee(tag != 0, "checking");
-
-          // remove GC'ed entry from hashmap and return the
-          // entry to the free list
-          hashmap->remove(prev, pos, entry);
-          destroy_entry(entry);
-
-          // destroy the weak ref
-          JNIHandles::destroy_weak_global(ref);
-
-          // post the event to the profiler
-          if (post_object_free) {
-            JvmtiExport::post_object_free(env(), tag);
+  // now iterate through each entry in the table
+
+  JvmtiTagHashmapEntry** table = hashmap->table();
+  int size = hashmap->size();
+
+  JvmtiTagHashmapEntry* delayed_add = NULL;
+
+  for (int pos = 0; pos < size; ++pos) {
+    JvmtiTagHashmapEntry* entry = table[pos];
+    JvmtiTagHashmapEntry* prev = NULL;
+
+    while (entry != NULL) {
+      JvmtiTagHashmapEntry* next = entry->next();
+
+      oop* obj = entry->object_addr();
+
+      // has object been GC'ed
+      if (!is_alive->do_object_b(entry->object())) {
+        // grab the tag
+        jlong tag = entry->tag();
+        guarantee(tag != 0, "checking");
+
+        // remove GC'ed entry from hashmap and return the
+        // entry to the free list
+        hashmap->remove(prev, pos, entry);
+        destroy_entry(entry);
+
+        // post the event to the profiler
+        if (post_object_free) {
+          JvmtiExport::post_object_free(env(), tag);
+        }
+
+        ++freed;
+      } else {
+        f->do_oop(entry->object_addr());
+        oop new_oop = entry->object();
+
+        // if the object has moved then re-hash it and move its
+        // entry to its new location.
+        unsigned int new_pos = JvmtiTagHashmap::hash(new_oop, size);
+        if (new_pos != (unsigned int)pos) {
+          if (prev == NULL) {
+            table[pos] = next;
+          } else {
+            prev->set_next(next);
           }
-
-          freed++;
-          entry = next;
-          continue;
-        }
-
-        // if this is the young hashmap then the object is either promoted
-        // or moved.
-        // if this is the other hashmap then the object is moved.
-
-        bool same_gen;
-        if (i == 0) {
-          assert(hashmap == young_hashmap, "checking");
-          same_gen = is_in_young(oop);
-        } else {
-          same_gen = true;
-        }
-
-
-        if (same_gen) {
-          // if the object has moved then re-hash it and move its
-          // entry to its new location.
-          unsigned int new_pos = JvmtiTagHashmap::hash(oop, size);
-          if (new_pos != (unsigned int)pos) {
-            if (prev == NULL) {
-              table[pos] = next;
-            } else {
-              prev->set_next(next);
-            }
+          if (new_pos < (unsigned int)pos) {
             entry->set_next(table[new_pos]);
             table[new_pos] = entry;
-            moved++;
           } else {
-            // object didn't move
-            prev = entry;
+            // Delay adding this entry to it's new position as we'd end up
+            // hitting it again during this iteration.
+            entry->set_next(delayed_add);
+            delayed_add = entry;
           }
+          moved++;
         } else {
-          // object has been promoted so remove the entry from the
-          // young hashmap
-          assert(hashmap == young_hashmap, "checking");
-          hashmap->remove(prev, pos, entry);
-
-          // move the entry to the promoted list
-          entry->set_next(promoted_entries);
-          promoted_entries = entry;
+          // object didn't move
+          prev = entry;
         }
-
-        entry = next;
       }
+
+      entry = next;
     }
   }
 
-
-  // add the entries, corresponding to the promoted objects, to the
-  // other hashmap.
-  JvmtiTagHashmapEntry* entry = promoted_entries;
-  while (entry != NULL) {
-    oop o = JNIHandles::resolve(entry->object());
-    assert(hashmap_for(o) == other_hashmap, "checking");
-    JvmtiTagHashmapEntry* next = entry->next();
-    other_hashmap->add(o, entry);
-    entry = next;
-    promoted++;
+  // Re-add all the entries which were kept aside
+  while (delayed_add != NULL) {
+    JvmtiTagHashmapEntry* next = delayed_add->next();
+    unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object(), size);
+    delayed_add->set_next(table[pos]);
+    table[pos] = delayed_add;
+    delayed_add = next;
   }
 
   // stats
   if (TraceJVMTIObjectTagging) {
-    int total_moves = promoted + moved;
-
-    int post_total = 0;
-    for (int i=0; i<n_hashmaps; i++) {
-      post_total += _hashmap[i]->_entry_count;
-    }
+    int post_total = hashmap->_entry_count;
     int pre_total = post_total + freed;
 
-    tty->print("(%d->%d, %d freed, %d promoted, %d total moves)",
-        pre_total, post_total, freed, promoted, total_moves);
+    tty->print_cr("(%d->%d, %d freed, %d total moves)",
+        pre_total, post_total, freed, moved);
   }
 }
--- a/src/share/vm/prims/jvmtiTagMap.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/jvmtiTagMap.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -45,17 +45,12 @@
  private:
 
   enum{
-    n_hashmaps = 2,                                 // encapsulates 2 hashmaps
-    max_free_entries = 4096                         // maximum number of free entries per env
+    max_free_entries = 4096         // maximum number of free entries per env
   };
 
-  // memory region for young generation
-  static MemRegion _young_gen;
-  static void get_young_generation();
-
   JvmtiEnv*             _env;                       // the jvmti environment
   Mutex                 _lock;                      // lock for this tag map
-  JvmtiTagHashmap*      _hashmap[n_hashmaps];       // the hashmaps
+  JvmtiTagHashmap*      _hashmap;                   // the hashmap
 
   JvmtiTagHashmapEntry* _free_entries;              // free list for this environment
   int _free_entries_count;                          // number of entries on the free list
@@ -67,11 +62,7 @@
   inline Mutex* lock()                      { return &_lock; }
   inline JvmtiEnv* env() const              { return _env; }
 
-  // rehash tags maps for generation start to end
-  void rehash(int start, int end);
-
-  // indicates if the object is in the young generation
-  static bool is_in_young(oop o);
+  void do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f);
 
   // iterate over all entries in this tag map
   void entry_iterate(JvmtiTagHashmapEntryClosure* closure);
@@ -81,11 +72,10 @@
   // indicates if this tag map is locked
   bool is_locked()                          { return lock()->is_locked(); }
 
-  // return the appropriate hashmap for a given object
-  JvmtiTagHashmap* hashmap_for(oop o);
+  JvmtiTagHashmap* hashmap() { return _hashmap; }
 
   // create/destroy entries
-  JvmtiTagHashmapEntry* create_entry(jweak ref, jlong tag);
+  JvmtiTagHashmapEntry* create_entry(oop ref, jlong tag);
   void destroy_entry(JvmtiTagHashmapEntry* entry);
 
   // returns true if the hashmaps are empty
@@ -134,11 +124,8 @@
                                    jint* count_ptr, jobject** object_result_ptr,
                                    jlong** tag_result_ptr);
 
-  // call post-GC to rehash the tag maps.
-  static void gc_epilogue(bool full);
-
-  // call after referencing processing has completed (CMS)
-  static void cms_ref_processing_epilogue();
+  static void weak_oops_do(
+      BoolObjectClosure* is_alive, OopClosure* f) KERNEL_RETURN;
 };
 
 #endif // SHARE_VM_PRIMS_JVMTITAGMAP_HPP
--- a/src/share/vm/prims/methodComparator.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/methodComparator.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jvmtiRedefineClassesTrace.hpp"
 #include "prims/methodComparator.hpp"
 #include "runtime/handles.inline.hpp"
@@ -194,10 +194,10 @@
 
   case Bytecodes::_ldc   : // fall through
   case Bytecodes::_ldc_w : {
-    Bytecode_loadconstant* ldc_old = Bytecode_loadconstant_at(_s_old->method(), _s_old->bci());
-    Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method(), _s_new->bci());
-    int cpi_old = ldc_old->pool_index();
-    int cpi_new = ldc_new->pool_index();
+    Bytecode_loadconstant ldc_old(_s_old->method(), _s_old->bci());
+    Bytecode_loadconstant ldc_new(_s_new->method(), _s_new->bci());
+    int cpi_old = ldc_old.pool_index();
+    int cpi_new = ldc_new.pool_index();
     if (!pool_constants_same(cpi_old, cpi_new))
       return false;
     break;
@@ -267,8 +267,8 @@
   case Bytecodes::_ifnonnull : // fall through
   case Bytecodes::_ifnull    : // fall through
   case Bytecodes::_jsr       : {
-    int old_ofs = _s_old->bytecode()->get_offset_s2(c_old);
-    int new_ofs = _s_new->bytecode()->get_offset_s2(c_new);
+    int old_ofs = _s_old->bytecode().get_offset_s2(c_old);
+    int new_ofs = _s_new->bytecode().get_offset_s2(c_new);
     if (_switchable_test) {
       int old_dest = _s_old->bci() + old_ofs;
       int new_dest = _s_new->bci() + new_ofs;
@@ -304,8 +304,8 @@
 
   case Bytecodes::_goto_w : // fall through
   case Bytecodes::_jsr_w  : {
-    int old_ofs = _s_old->bytecode()->get_offset_s4(c_old);
-    int new_ofs = _s_new->bytecode()->get_offset_s4(c_new);
+    int old_ofs = _s_old->bytecode().get_offset_s4(c_old);
+    int new_ofs = _s_new->bytecode().get_offset_s4(c_new);
     if (_switchable_test) {
       int old_dest = _s_old->bci() + old_ofs;
       int new_dest = _s_new->bci() + new_ofs;
--- a/src/share/vm/prims/methodHandleWalk.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/methodHandleWalk.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -120,6 +120,7 @@
       if (cur_slot == arg_slot)
         return T_OBJECT;
     }
+    ResourceMark rm(THREAD);
     for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) {
       BasicType bt = ss.type();
       cur_slot -= type2size[bt];
@@ -137,7 +138,6 @@
 
 
 void MethodHandleChain::lose(const char* msg, TRAPS) {
-  assert(false, "lose");
   _lose_message = msg;
   if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) {
     // throw a preallocated exception
@@ -962,9 +962,9 @@
     m = vmIntrinsics::method_for(iid);
   }
 
-  klassOop  klass     = m->method_holder();
-  symbolOop name      = m->name();
-  symbolOop signature = m->signature();
+  klassOop  klass   = m->method_holder();
+  Symbol* name      = m->name();
+  Symbol* signature = m->signature();
 
   if (tailcall) {
     // Actually, in order to make these methods more recognizable,
@@ -1142,7 +1142,7 @@
   for (int i = 1; i < _constants.length(); i++) {
     ConstantValue* cv = _constants.at(i);
     switch (cv->tag()) {
-    case JVM_CONSTANT_Utf8:        cpool->symbol_at_put(       i, cv->symbol_oop()                     ); break;
+    case JVM_CONSTANT_Utf8:        cpool->symbol_at_put(       i, cv->symbol()                         ); break;
     case JVM_CONSTANT_Integer:     cpool->int_at_put(          i, cv->get_jint()                       ); break;
     case JVM_CONSTANT_Float:       cpool->float_at_put(        i, cv->get_jfloat()                     ); break;
     case JVM_CONSTANT_Long:        cpool->long_at_put(         i, cv->get_jlong()                      ); break;
@@ -1332,7 +1332,7 @@
   virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid,
                                Bytecodes::Code op, bool tailcall,
                                int argc, ArgToken* argv, TRAPS) {
-    symbolOop name, sig;
+    Symbol* name, sig;
     if (m != NULL) {
       name = m->name();
       sig  = m->signature();
--- a/src/share/vm/prims/methodHandleWalk.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/methodHandleWalk.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -258,16 +258,20 @@
     int       _tag;   // Constant pool tag type.
     JavaValue _value;
     Handle    _handle;
+    Symbol*   _sym;
 
   public:
     // Constructor for oop types.
     ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
-      assert(tag == JVM_CONSTANT_Utf8   ||
-             tag == JVM_CONSTANT_Class  ||
+      assert(tag == JVM_CONSTANT_Class  ||
              tag == JVM_CONSTANT_String ||
              tag == JVM_CONSTANT_Object, "must be oop type");
     }
 
+    ConstantValue(int tag, Symbol* con) : _tag(tag), _sym(con) {
+      assert(tag == JVM_CONSTANT_Utf8, "must be symbol type");
+    }
+
     // Constructor for oop reference types.
     ConstantValue(int tag, int index) : _tag(tag) {
       assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type");
@@ -291,7 +295,7 @@
     }
 
     int       tag()          const { return _tag; }
-    symbolOop symbol_oop()   const { return (symbolOop) _handle(); }
+    Symbol*   symbol()       const { return _sym; }
     klassOop  klass_oop()    const { return (klassOop)  _handle(); }
     oop       object_oop()   const { return _handle(); }
     int       index()        const { return _value.get_jint(); }
@@ -336,6 +340,12 @@
     return _constants.append(cv);
   }
 
+  int cpool_symbol_put(int tag, Symbol* con) {
+    if (con == NULL)  return 0;
+    ConstantValue* cv = new ConstantValue(tag, con);
+    return _constants.append(cv);
+  }
+
   int cpool_oop_reference_put(int tag, int first_index, int second_index) {
     if (first_index == 0 && second_index == 0)  return 0;
     assert(first_index != 0 && second_index != 0, "no zero indexes");
@@ -365,8 +375,8 @@
   int cpool_object_put(Handle obj) {
     return cpool_oop_put(JVM_CONSTANT_Object, obj);
   }
-  int cpool_symbol_put(symbolOop sym) {
-    return cpool_oop_put(JVM_CONSTANT_Utf8, sym);
+  int cpool_symbol_put(Symbol* sym) {
+    return cpool_symbol_put(JVM_CONSTANT_Utf8, sym);
   }
   int cpool_klass_put(klassOop klass) {
     return cpool_oop_put(JVM_CONSTANT_Class, klass);
--- a/src/share/vm/prims/methodHandles.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/methodHandles.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -111,7 +111,7 @@
 //------------------------------------------------------------------------------
 // MethodHandles::generate_adapters
 //
-void MethodHandles::generate_adapters(TRAPS) {
+void MethodHandles::generate_adapters() {
   if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL)  return;
 
   assert(_adapter_code == NULL, "generate only once");
@@ -123,20 +123,20 @@
     vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters");
   CodeBuffer code(_adapter_code);
   MethodHandlesAdapterGenerator g(&code);
-  g.generate(CHECK);
+  g.generate();
 }
 
 
 //------------------------------------------------------------------------------
 // MethodHandlesAdapterGenerator::generate
 //
-void MethodHandlesAdapterGenerator::generate(TRAPS) {
+void MethodHandlesAdapterGenerator::generate() {
   // Generate generic method handle adapters.
   for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
        ek < MethodHandles::_EK_LIMIT;
        ek = MethodHandles::EntryKind(1 + (int)ek)) {
     StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
-    MethodHandles::generate_method_handle_stub(_masm, ek, CHECK);
+    MethodHandles::generate_method_handle_stub(_masm, ek);
   }
 }
 
@@ -278,7 +278,7 @@
   assert(m->is_method(), "");
   if (m->is_static()) {
     // check that signature begins '(L' or '([' (not '(I', '()', etc.)
-    symbolOop sig = m->signature();
+    Symbol* sig = m->signature();
     BasicType recv_bt = char2type(sig->byte_at(1));
     // Note: recv_bt might be T_ILLEGAL if byte_at(2) is ')'
     assert(sig->byte_at(0) == '(', "must be method sig");
@@ -438,6 +438,25 @@
   return m;
 }
 
+// convert the external string or reflective type to an internal signature
+Symbol* MethodHandles::convert_to_signature(oop type_str,
+                                            bool polymorphic,
+                                            TRAPS) {
+  if (java_dyn_MethodType::is_instance(type_str)) {
+    return java_dyn_MethodType::as_signature(type_str, polymorphic, CHECK_NULL);
+  } else if (java_lang_Class::is_instance(type_str)) {
+    return java_lang_Class::as_signature(type_str, false, CHECK_NULL);
+  } else if (java_lang_String::is_instance(type_str)) {
+    if (polymorphic) {
+      return java_lang_String::as_symbol(type_str, CHECK_NULL);
+    } else {
+      return java_lang_String::as_symbol_or_null(type_str);
+    }
+  } else {
+    THROW_MSG_(vmSymbols::java_lang_InternalError(), "unrecognized type", NULL);
+  }
+}
+
 // An unresolved member name is a mere symbolic reference.
 // Resolving it plants a vmtarget/vmindex in it,
 // which refers dirctly to JVM internals.
@@ -478,39 +497,24 @@
   defc->link_class(CHECK);
 
   // convert the external string name to an internal symbol
-  symbolHandle name(THREAD, java_lang_String::as_symbol_or_null(name_str));
-  if (name.is_null())  return;  // no such name
+  TempNewSymbol name = java_lang_String::as_symbol_or_null(name_str);
+  if (name == NULL)  return;  // no such name
   name_str = NULL;  // safety
 
   Handle polymorphic_method_type;
   bool polymorphic_signature = false;
   if ((flags & ALL_KINDS) == IS_METHOD &&
       (defc() == SystemDictionary::MethodHandle_klass() &&
-       methodOopDesc::is_method_handle_invoke_name(name())))
+       methodOopDesc::is_method_handle_invoke_name(name)))
     polymorphic_signature = true;
 
   // convert the external string or reflective type to an internal signature
-  symbolHandle type; {
-    symbolOop type_sym = NULL;
-    if (java_dyn_MethodType::is_instance(type_str)) {
-      type_sym = java_dyn_MethodType::as_signature(type_str, polymorphic_signature, CHECK);
-      if (polymorphic_signature)
-        polymorphic_method_type = Handle(THREAD, type_str);  //preserve exactly
-    } else if (java_lang_Class::is_instance(type_str)) {
-      type_sym = java_lang_Class::as_signature(type_str, false, CHECK);
-    } else if (java_lang_String::is_instance(type_str)) {
-      if (polymorphic_signature) {
-        type     = java_lang_String::as_symbol(type_str, CHECK);
-      } else {
-        type_sym = java_lang_String::as_symbol_or_null(type_str);
-      }
-    } else {
-      THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized type");
-    }
-    if (type_sym != NULL)
-      type = symbolHandle(THREAD, type_sym);
+  TempNewSymbol type = convert_to_signature(type_str, polymorphic_signature, CHECK);
+  if (java_dyn_MethodType::is_instance(type_str) && polymorphic_signature) {
+    polymorphic_method_type = Handle(THREAD, type_str);  //preserve exactly
   }
-  if (type.is_null())  return;  // no such signature exists in the VM
+
+  if (type == NULL)  return;  // no such signature exists in the VM
   type_str = NULL; // safety
 
   // Time to do the lookup.
@@ -566,7 +570,7 @@
       CallInfo result;
       {
         EXCEPTION_MARK;
-        if (name() == vmSymbols::object_initializer_name()) {
+        if (name == vmSymbols::object_initializer_name()) {
           LinkResolver::resolve_special_call(result,
                         defc, name, type, KlassHandle(), false, THREAD);
         } else {
@@ -594,7 +598,7 @@
     {
       // This is taken from LinkResolver::resolve_field, sans access checks.
       fieldDescriptor fd; // find_field initializes fd if found
-      KlassHandle sel_klass(THREAD, instanceKlass::cast(defc())->find_field(name(), type(), &fd));
+      KlassHandle sel_klass(THREAD, instanceKlass::cast(defc())->find_field(name, type, &fd));
       // check if field exists; i.e., if a klass containing the field def has been selected
       if (sel_klass.is_null())  return;
       oop vmtarget = sel_klass->as_klassOop();
@@ -725,7 +729,7 @@
 }
 
 int MethodHandles::find_MemberNames(klassOop k,
-                                    symbolOop name, symbolOop sig,
+                                    Symbol* name, Symbol* sig,
                                     int mflags, klassOop caller,
                                     int skip, objArrayOop results) {
   DEBUG_ONLY(No_Safepoint_Verifier nsv);
@@ -782,8 +786,8 @@
 
   if ((match_flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) {
     // watch out for these guys:
-    symbolOop init_name   = vmSymbols::object_initializer_name();
-    symbolOop clinit_name = vmSymbols::class_initializer_name();
+    Symbol* init_name   = vmSymbols::object_initializer_name();
+    Symbol* clinit_name = vmSymbols::class_initializer_name();
     if (name == clinit_name)  clinit_name = NULL; // hack for exposing <clinit>
     bool negate_name_test = false;
     // fix name so that it captures the intention of IS_CONSTRUCTOR
@@ -807,7 +811,7 @@
     }
     for (MethodStream st(k, local_only, !search_intfc); !st.eos(); st.next()) {
       methodOop m = st.method();
-      symbolOop m_name = m->name();
+      Symbol* m_name = m->name();
       if (m_name == clinit_name)
         continue;
       if (name != NULL && ((m_name != name) ^ negate_name_test))
@@ -928,7 +932,7 @@
   // Must be on the boot class path:
   if (ik->class_loader() != NULL)  return false;
   // Check the name.
-  symbolOop name = ik->name();
+  Symbol* name = ik->name();
   for (int i = 0; ; i++) {
     const char* test_name = always_null_names[i];
     if (test_name == NULL)  break;
@@ -1026,6 +1030,7 @@
   int pmax = ptypes->length();
   int mnum = 0;                 // method argument
   const char* err = NULL;
+  ResourceMark rm(THREAD);
   for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) {
     oop ptype_oop = NULL;
     if (ss.at_return_type()) {
@@ -1061,15 +1066,14 @@
       }
       KlassHandle pklass_handle(THREAD, pklass); pklass = NULL;
       // If we fail to resolve types at this point, we will throw an error.
-      symbolOop    name_oop = ss.as_symbol(CHECK);
-      symbolHandle name(THREAD, name_oop);
+      Symbol* name = ss.as_symbol(CHECK);
       instanceKlass* mk = instanceKlass::cast(m->method_holder());
       Handle loader(THREAD, mk->class_loader());
       Handle domain(THREAD, mk->protection_domain());
       mklass = SystemDictionary::resolve_or_null(name, loader, domain, CHECK);
       pklass = pklass_handle();
       if (mklass == NULL && pklass != NULL &&
-          Klass::cast(pklass)->name() == name() &&
+          Klass::cast(pklass)->name() == name &&
           m->is_method_handle_invoke()) {
         // Assume a match.  We can't really decode the signature of MH.invoke*.
         continue;
@@ -2288,7 +2292,8 @@
     tty->print("creating MethodType form ");
     if (WizardMode || Verbose) {   // Warning: this calls Java code on the MH!
       // call Object.toString()
-      symbolOop name = vmSymbols::toString_name(), sig = vmSymbols::void_string_signature();
+      Symbol* name = vmSymbols::toString_name();
+      Symbol* sig = vmSymbols::void_string_signature();
       JavaCallArguments args(Handle(THREAD, JNIHandles::resolve_non_null(erased_jh)));
       JavaValue result(T_OBJECT);
       JavaCalls::call_virtual(&result, SystemDictionary::Object_klass(), name, sig,
@@ -2452,7 +2457,8 @@
   objArrayOop results = (objArrayOop) JNIHandles::resolve(results_jh);
   if (results == NULL || !results->is_objArray())       return -1;
 
-  symbolOop name = NULL, sig = NULL;
+  TempNewSymbol name = NULL;
+  TempNewSymbol sig = NULL;
   if (name_jh != NULL) {
     name = java_lang_String::as_symbol_or_null(JNIHandles::resolve_non_null(name_jh));
     if (name == NULL)  return 0; // a match is not possible
@@ -2611,20 +2617,30 @@
   if (enable_MH) {
     KlassHandle MHI_klass = SystemDictionaryHandles::MethodHandleImpl_klass();
     if (MHI_klass.not_null()) {
-      symbolHandle raiseException_name = oopFactory::new_symbol_handle("raiseException", CHECK);
-      symbolHandle raiseException_sig  = oopFactory::new_symbol_handle("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK);
+      TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK);
+      TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK);
       methodOop raiseException_method  = instanceKlass::cast(MHI_klass->as_klassOop())
-                    ->find_method(raiseException_name(), raiseException_sig());
+                    ->find_method(raiseException_name, raiseException_sig);
       if (raiseException_method != NULL && raiseException_method->is_static()) {
         MethodHandles::set_raise_exception_method(raiseException_method);
       } else {
         warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
         enable_MH = false;
       }
+    } else {
+      enable_MH = false;
     }
   }
 
   if (enable_MH) {
+    // We need to link the MethodHandleImpl klass before we generate
+    // the method handle adapters as the _raise_exception adapter uses
+    // one of its methods (and its c2i-adapter).
+    KlassHandle    k  = SystemDictionaryHandles::MethodHandleImpl_klass();
+    instanceKlass* ik = instanceKlass::cast(k());
+    ik->link_class(CHECK);
+
+    MethodHandles::generate_adapters();
     MethodHandles::set_enabled(true);
   }
 
@@ -2645,10 +2661,5 @@
       MethodHandles::set_enabled(true);
     }
   }
-
-  // Generate method handles adapters if enabled.
-  if (MethodHandles::enabled()) {
-    MethodHandles::generate_adapters(CHECK);
-  }
 }
 JVM_END
--- a/src/share/vm/prims/methodHandles.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/methodHandles.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -287,18 +287,18 @@
   static void init_MemberName(oop mname_oop, oop target); // compute vmtarget/vmindex from target
   static void init_MemberName(oop mname_oop, methodOop m, bool do_dispatch = true);
   static void init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset);
-  static int find_MemberNames(klassOop k, symbolOop name, symbolOop sig,
+  static int find_MemberNames(klassOop k, Symbol* name, Symbol* sig,
                               int mflags, klassOop caller,
                               int skip, objArrayOop results);
   // bit values for suppress argument to expand_MemberName:
   enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
 
   // Generate MethodHandles adapters.
-  static void generate_adapters(TRAPS);
+  static void generate_adapters();
 
   // Called from InterpreterGenerator and MethodHandlesAdapterGenerator.
   static address generate_method_handle_interpreter_entry(MacroAssembler* _masm);
-  static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek, TRAPS);
+  static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek);
 
   // argument list parsing
   static int argument_slot(oop method_type, int arg);
@@ -466,6 +466,8 @@
                                Register temp_reg, Register temp2_reg, Register temp3_reg = noreg);
 
   static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
+
+  static Symbol* convert_to_signature(oop type_str, bool polymorphic, TRAPS);
 };
 
 
@@ -530,7 +532,7 @@
 public:
   MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {}
 
-  void generate(TRAPS);
+  void generate();
 };
 
 #endif // SHARE_VM_PRIMS_METHODHANDLES_HPP
--- a/src/share/vm/prims/nativeLookup.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/nativeLookup.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -32,7 +32,7 @@
 #include "oops/instanceKlass.hpp"
 #include "oops/methodOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jvm_misc.hpp"
 #include "prims/nativeLookup.hpp"
 #include "runtime/arguments.hpp"
@@ -51,7 +51,7 @@
 #endif
 
 
-static void mangle_name_on(outputStream* st, symbolOop name, int begin, int end) {
+static void mangle_name_on(outputStream* st, Symbol* name, int begin, int end) {
   char* bytes = (char*)name->bytes() + begin;
   char* end_bytes = (char*)name->bytes() + end;
   while (bytes < end_bytes) {
@@ -70,7 +70,7 @@
 }
 
 
-static void mangle_name_on(outputStream* st, symbolOop name) {
+static void mangle_name_on(outputStream* st, Symbol* name) {
   mangle_name_on(st, name, 0, name->utf8_length());
 }
 
@@ -91,7 +91,7 @@
 char* NativeLookup::long_jni_name(methodHandle method) {
   // Signature ignore the wrapping parenteses and the trailing return type
   stringStream st;
-  symbolOop signature = method->signature();
+  Symbol* signature = method->signature();
   st.print("__");
   // find ')'
   int end;
@@ -168,8 +168,8 @@
   JavaValue result(T_LONG);
   JavaCalls::call_static(&result,
                          klass,
-                         vmSymbolHandles::findNative_name(),
-                         vmSymbolHandles::classloader_string_long_signature(),
+                         vmSymbols::findNative_name(),
+                         vmSymbols::classloader_string_long_signature(),
                          // Arguments
                          loader,
                          name_arg,
@@ -249,10 +249,10 @@
   if (wrapper_name != in_name) {
     // we have a name for a wrapping method
     int wrapper_name_len = (int)strlen(wrapper_name);
-    symbolHandle wrapper_symbol(THREAD, SymbolTable::probe(wrapper_name, wrapper_name_len));
-    if (!wrapper_symbol.is_null()) {
+    TempNewSymbol wrapper_symbol = SymbolTable::probe(wrapper_name, wrapper_name_len);
+    if (wrapper_symbol != NULL) {
       KlassHandle kh(method->method_holder());
-      methodOop wrapper_method = Klass::cast(kh())->lookup_method(wrapper_symbol(),
+      methodOop wrapper_method = Klass::cast(kh())->lookup_method(wrapper_symbol,
                                                                   method->signature());
       if (wrapper_method != NULL && !wrapper_method->is_native()) {
         // we found a wrapper method, use its native entry
@@ -301,9 +301,9 @@
 address NativeLookup::base_library_lookup(const char* class_name, const char* method_name, const char* signature) {
   EXCEPTION_MARK;
   bool in_base_library = true;  // SharedRuntime inits some math methods.
-  symbolHandle c_name = oopFactory::new_symbol_handle(class_name,  CATCH);
-  symbolHandle m_name = oopFactory::new_symbol_handle(method_name, CATCH);
-  symbolHandle s_name = oopFactory::new_symbol_handle(signature,   CATCH);
+  TempNewSymbol c_name = SymbolTable::new_symbol(class_name,  CATCH);
+  TempNewSymbol m_name = SymbolTable::new_symbol(method_name, CATCH);
+  TempNewSymbol s_name = SymbolTable::new_symbol(signature,   CATCH);
 
   // Find the class
   klassOop k = SystemDictionary::resolve_or_fail(c_name, true, CATCH);
@@ -311,7 +311,7 @@
 
   // Find method and invoke standard lookup
   methodHandle method (THREAD,
-                       klass->uncached_lookup_method(m_name(), s_name()));
+                       klass->uncached_lookup_method(m_name, s_name));
   address result = lookup(method, in_base_library, CATCH);
   assert(in_base_library, "must be in basic library");
   guarantee(result != NULL, "must be non NULL");
--- a/src/share/vm/prims/unsafe.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/prims/unsafe.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -154,12 +154,11 @@
 
 #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
   oop p = JNIHandles::resolve(obj); \
-  volatile type_name v = *(volatile type_name*)index_oop_from_field_offset_long(p, offset)
+  volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset));
 
 #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
   oop p = JNIHandles::resolve(obj); \
-  *(volatile type_name*)index_oop_from_field_offset_long(p, offset) = x; \
-  OrderAccess::fence();
+  OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x);
 
 // Macros for oops that check UseCompressedOops
 
@@ -181,7 +180,8 @@
     v = oopDesc::decode_heap_oop(n);                               \
   } else {                            \
     v = *(volatile oop*)index_oop_from_field_offset_long(p, offset);       \
-  }
+  } \
+  OrderAccess::acquire();
 
 
 // Get/SetObject must be special-cased, since it works with handles.
@@ -248,14 +248,22 @@
   UnsafeWrapper("Unsafe_SetObjectVolatile");
   oop x = JNIHandles::resolve(x_h);
   oop p = JNIHandles::resolve(obj);
+  void* addr = index_oop_from_field_offset_long(p, offset);
+  OrderAccess::release();
   if (UseCompressedOops) {
-    oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
+    oop_store((narrowOop*)addr, x);
   } else {
-    oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
+    oop_store((oop*)addr, x);
   }
   OrderAccess::fence();
 UNSAFE_END
 
+#if defined(SPARC) || defined(X86)
+// Sparc and X86 have atomic jlong (8 bytes) instructions
+
+#else
+// Keep old code for platforms which may not have atomic jlong (8 bytes) instructions
+
 // Volatile long versions must use locks if !VM_Version::supports_cx8().
 // support_cx8 is a surrogate for 'supports atomic long memory ops'.
 
@@ -291,6 +299,7 @@
   }
 UNSAFE_END
 
+#endif // not SPARC and not X86
 
 #define DEFINE_GETSETOOP(jboolean, Boolean) \
  \
@@ -320,6 +329,16 @@
  \
 // END DEFINE_GETSETOOP.
 
+DEFINE_GETSETOOP(jboolean, Boolean)
+DEFINE_GETSETOOP(jbyte, Byte)
+DEFINE_GETSETOOP(jshort, Short);
+DEFINE_GETSETOOP(jchar, Char);
+DEFINE_GETSETOOP(jint, Int);
+DEFINE_GETSETOOP(jlong, Long);
+DEFINE_GETSETOOP(jfloat, Float);
+DEFINE_GETSETOOP(jdouble, Double);
+
+#undef DEFINE_GETSETOOP
 
 #define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \
  \
@@ -336,47 +355,49 @@
  \
 // END DEFINE_GETSETOOP_VOLATILE.
 
-DEFINE_GETSETOOP(jboolean, Boolean)
-DEFINE_GETSETOOP(jbyte, Byte)
-DEFINE_GETSETOOP(jshort, Short);
-DEFINE_GETSETOOP(jchar, Char);
-DEFINE_GETSETOOP(jint, Int);
-DEFINE_GETSETOOP(jlong, Long);
-DEFINE_GETSETOOP(jfloat, Float);
-DEFINE_GETSETOOP(jdouble, Double);
-
 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
 DEFINE_GETSETOOP_VOLATILE(jshort, Short);
 DEFINE_GETSETOOP_VOLATILE(jchar, Char);
 DEFINE_GETSETOOP_VOLATILE(jint, Int);
-// no long -- handled specially
 DEFINE_GETSETOOP_VOLATILE(jfloat, Float);
 DEFINE_GETSETOOP_VOLATILE(jdouble, Double);
 
-#undef DEFINE_GETSETOOP
+#if defined(SPARC) || defined(X86)
+// Sparc and X86 have atomic jlong (8 bytes) instructions
+DEFINE_GETSETOOP_VOLATILE(jlong, Long);
+#endif
+
+#undef DEFINE_GETSETOOP_VOLATILE
 
 // The non-intrinsified versions of setOrdered just use setVolatile
 
-UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) \
-  UnsafeWrapper("Unsafe_SetOrderedInt"); \
-  SET_FIELD_VOLATILE(obj, offset, jint, x); \
+UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x))
+  UnsafeWrapper("Unsafe_SetOrderedInt");
+  SET_FIELD_VOLATILE(obj, offset, jint, x);
 UNSAFE_END
 
 UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
   UnsafeWrapper("Unsafe_SetOrderedObject");
   oop x = JNIHandles::resolve(x_h);
   oop p = JNIHandles::resolve(obj);
+  void* addr = index_oop_from_field_offset_long(p, offset);
+  OrderAccess::release();
   if (UseCompressedOops) {
-    oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
+    oop_store((narrowOop*)addr, x);
   } else {
-    oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
+    oop_store((oop*)addr, x);
   }
   OrderAccess::fence();
 UNSAFE_END
 
 UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
   UnsafeWrapper("Unsafe_SetOrderedLong");
+#if defined(SPARC) || defined(X86)
+  // Sparc and X86 have atomic jlong (8 bytes) instructions
+  SET_FIELD_VOLATILE(obj, offset, jlong, x);
+#else
+  // Keep old code for platforms which may not have atomic long (8 bytes) instructions
   {
     if (VM_Version::supports_cx8()) {
       SET_FIELD_VOLATILE(obj, offset, jlong, x);
@@ -388,6 +409,7 @@
       *addr = x;
     }
   }
+#endif
 UNSAFE_END
 
 ////// Data in the C heap.
@@ -969,7 +991,7 @@
 
   instanceKlassHandle anon_klass;
   {
-    symbolHandle no_class_name;
+    Symbol* no_class_name = NULL;
     klassOop anonk = SystemDictionary::parse_stream(no_class_name,
                                                     host_loader, host_domain,
                                                     &st, host_klass, cp_patches,
--- a/src/share/vm/runtime/arguments.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -924,9 +924,7 @@
   } else if (strcmp(key, "sun.java.command") == 0) {
     _java_command = value;
 
-    // don't add this property to the properties exposed to the java application
-    FreeHeap(key);
-    return true;
+    // Record value in Arguments, but let it get passed to Java.
   } else if (strcmp(key, "sun.java.launcher.pid") == 0) {
     // launcher.pid property is private and is processed
     // in process_sun_java_launcher_properties();
@@ -1949,10 +1947,16 @@
     status = false;
   }
 
+#ifndef SERIALGC
   if (UseG1GC) {
     status = status && verify_percentage(InitiatingHeapOccupancyPercent,
                                          "InitiatingHeapOccupancyPercent");
+    status = status && verify_min_value(G1RefProcDrainInterval, 1,
+                                        "G1RefProcDrainInterval");
+    status = status && verify_min_value((intx)G1ConcMarkStepDurationMillis, 1,
+                                        "G1ConcMarkStepDurationMillis");
   }
+#endif
 
   status = status && verify_interval(RefDiscoveryPolicy,
                                      ReferenceProcessor::DiscoveryPolicyMin,
@@ -3073,15 +3077,6 @@
     }
     ScavengeRootsInCode = 1;
   }
-#ifdef COMPILER2
-  if (EnableInvokeDynamic && DoEscapeAnalysis) {
-    // TODO: We need to find rules for invokedynamic and EA.  For now,
-    // simply disable EA by default.
-    if (FLAG_IS_DEFAULT(DoEscapeAnalysis)) {
-      DoEscapeAnalysis = false;
-    }
-  }
-#endif
 
   if (PrintGCDetails) {
     // Turn on -verbose:gc options as well
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -399,8 +399,8 @@
   {
     HandleMark hm;
     methodHandle method(thread, array->element(0)->method());
-    Bytecode_invoke* invoke = Bytecode_invoke_at_check(method, array->element(0)->bci());
-    return_type = (invoke != NULL) ? invoke->result_type(thread) : T_ILLEGAL;
+    Bytecode_invoke invoke = Bytecode_invoke_check(method, array->element(0)->bci());
+    return_type = invoke.is_valid() ? invoke.result_type() : T_ILLEGAL;
   }
 
   // Compute information for handling adapters and adjusting the frame size of the caller.
@@ -604,8 +604,8 @@
           cur_code == Bytecodes::_invokespecial ||
           cur_code == Bytecodes::_invokestatic  ||
           cur_code == Bytecodes::_invokeinterface) {
-        Bytecode_invoke* invoke = Bytecode_invoke_at(mh, iframe->interpreter_frame_bci());
-        symbolHandle signature(thread, invoke->signature());
+        Bytecode_invoke invoke(mh, iframe->interpreter_frame_bci());
+        Symbol* signature = invoke.signature();
         ArgumentSizeComputer asc(signature);
         cur_invoke_parameter_size = asc.size();
         if (cur_code != Bytecodes::_invokestatic) {
@@ -967,7 +967,7 @@
       if (bci == SynchronizationEntryBCI) {
         code_name = "sync entry";
       } else {
-        Bytecodes::Code code = Bytecodes::code_at(vf->method(), bci);
+        Bytecodes::Code code = vf->method()->code_at(bci);
         code_name = Bytecodes::name(code);
       }
       tty->print(" - %s", code_name);
@@ -1159,7 +1159,7 @@
   if (!constant_pool->tag_at(index).is_symbol()) return;
 
   Handle class_loader (THREAD, instanceKlass::cast(constant_pool->pool_holder())->class_loader());
-  symbolHandle symbol (THREAD, constant_pool->symbol_at(index));
+  Symbol*  symbol  = constant_pool->symbol_at(index);
 
   // class name?
   if (symbol->byte_at(0) != '(') {
@@ -1169,10 +1169,10 @@
   }
 
   // then it must be a signature!
+  ResourceMark rm(THREAD);
   for (SignatureStream ss(symbol); !ss.is_done(); ss.next()) {
     if (ss.is_object()) {
-      symbolOop s = ss.as_symbol(CHECK);
-      symbolHandle class_name (THREAD, s);
+      Symbol* class_name = ss.as_symbol(CHECK);
       Handle protection_domain (THREAD, Klass::cast(constant_pool->pool_holder())->protection_domain());
       SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK);
     }
@@ -1227,7 +1227,7 @@
     ScopeDesc*      trap_scope  = cvf->scope();
     methodHandle    trap_method = trap_scope->method();
     int             trap_bci    = trap_scope->bci();
-    Bytecodes::Code trap_bc     = Bytecode_at(trap_method->bcp_from(trap_bci))->java_code();
+    Bytecodes::Code trap_bc     = trap_method->java_code_at(trap_bci);
 
     // Record this event in the histogram.
     gather_statistics(reason, action, trap_bc);
@@ -1249,19 +1249,17 @@
                          format_trap_request(buf, sizeof(buf), trap_request));
         nm->log_identity(xtty);
       }
-      symbolHandle class_name;
+      Symbol* class_name = NULL;
       bool unresolved = false;
       if (unloaded_class_index >= 0) {
         constantPoolHandle constants (THREAD, trap_method->constants());
         if (constants->tag_at(unloaded_class_index).is_unresolved_klass()) {
-          class_name = symbolHandle(THREAD,
-            constants->klass_name_at(unloaded_class_index));
+          class_name = constants->klass_name_at(unloaded_class_index);
           unresolved = true;
           if (xtty != NULL)
             xtty->print(" unresolved='1'");
         } else if (constants->tag_at(unloaded_class_index).is_symbol()) {
-          class_name = symbolHandle(THREAD,
-            constants->symbol_at(unloaded_class_index));
+          class_name = constants->symbol_at(unloaded_class_index);
         }
         if (xtty != NULL)
           xtty->name(class_name);
@@ -1297,7 +1295,7 @@
                    trap_reason_name(reason),
                    trap_action_name(action),
                    unloaded_class_index);
-        if (class_name.not_null()) {
+        if (class_name != NULL) {
           tty->print(unresolved ? " unresolved class: " : " symbol: ");
           class_name->print_symbol_on(tty);
         }
--- a/src/share/vm/runtime/fieldDescriptor.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/fieldDescriptor.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -28,7 +28,7 @@
 #include "oops/constantPoolOop.hpp"
 #include "oops/klassOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/fieldType.hpp"
 #include "utilities/accessFlags.hpp"
 #include "utilities/constantTag.hpp"
@@ -49,15 +49,15 @@
   constantPoolHandle  _cp;
 
  public:
-  symbolOop name() const               { return _cp->symbol_at(_name_index); }
-  symbolOop signature() const          { return _cp->symbol_at(_signature_index); }
+  Symbol* name() const                 { return _cp->symbol_at(_name_index); }
+  Symbol* signature() const            { return _cp->symbol_at(_signature_index); }
   klassOop field_holder() const        { return _cp->pool_holder(); }
   constantPoolOop constants() const    { return _cp(); }
   AccessFlags access_flags() const     { return _access_flags; }
   oop loader() const;
   // Offset (in words) of field from start of instanceOop / klassOop
   int offset() const                   { return _offset; }
-  symbolOop generic_signature() const  { return (_generic_signature_index > 0 ? _cp->symbol_at(_generic_signature_index) : (symbolOop)NULL); }
+  Symbol* generic_signature() const    { return (_generic_signature_index > 0 ? _cp->symbol_at(_generic_signature_index) : (Symbol*)NULL); }
   int index() const                    { return _index; }
   typeArrayOop annotations() const;
 
--- a/src/share/vm/runtime/fieldType.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/fieldType.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -30,7 +30,7 @@
 #include "runtime/fieldType.hpp"
 #include "runtime/signature.hpp"
 
-void FieldType::skip_optional_size(symbolOop signature, int* index) {
+void FieldType::skip_optional_size(Symbol* signature, int* index) {
   jchar c = signature->byte_at(*index);
   while (c >= '0' && c <= '9') {
     *index = *index + 1;
@@ -38,12 +38,12 @@
   }
 }
 
-BasicType FieldType::basic_type(symbolOop signature) {
+BasicType FieldType::basic_type(Symbol* signature) {
   return char2type(signature->byte_at(0));
 }
 
 // Check if it is a valid array signature
-bool FieldType::is_valid_array_signature(symbolOop sig) {
+bool FieldType::is_valid_array_signature(Symbol* sig) {
   assert(sig->utf8_length() > 1, "this should already have been checked");
   assert(sig->byte_at(0) == '[', "this should already have been checked");
   // The first character is already checked
@@ -73,7 +73,7 @@
 }
 
 
-BasicType FieldType::get_array_info(symbolOop signature, jint* dimension, symbolOop* object_key, TRAPS) {
+BasicType FieldType::get_array_info(Symbol* signature, FieldArrayInfo& fd, TRAPS) {
   assert(basic_type(signature) == T_ARRAY, "must be array");
   int index = 1;
   int dim   = 1;
@@ -84,14 +84,15 @@
     skip_optional_size(signature, &index);
   }
   ResourceMark rm;
-  symbolOop element = oopFactory::new_symbol(signature->as_C_string() + index, CHECK_(T_BYTE));
-  BasicType element_type = FieldType::basic_type(element);
+  char *element = signature->as_C_string() + index;
+  BasicType element_type = char2type(element[0]);
   if (element_type == T_OBJECT) {
-    char* object_type = element->as_C_string();
-    object_type[element->utf8_length() - 1] = '\0';
-    *object_key = oopFactory::new_symbol(object_type + 1, CHECK_(T_BYTE));
+    int len = (int)strlen(element);
+    assert(element[len-1] == ';', "last char should be a semicolon");
+    element[len-1] = '\0';        // chop off semicolon
+    fd._object_key = SymbolTable::new_symbol(element + 1, CHECK_(T_BYTE));
   }
   // Pass dimension back to caller
-  *dimension = dim;
+  fd._dimension = dim;
   return element_type;
 }
--- a/src/share/vm/runtime/fieldType.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/fieldType.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -26,26 +26,42 @@
 #define SHARE_VM_RUNTIME_FIELDTYPE_HPP
 
 #include "memory/allocation.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 
 // Note: FieldType should be based on the SignatureIterator (or vice versa).
 //       In any case, this structure should be re-thought at some point.
 
 // A FieldType is used to determine the type of a field from a signature string.
 
+// Information returned by get_array_info, which is scoped to decrement
+// reference count if a Symbol is created in the case of T_OBJECT
+class FieldArrayInfo : public StackObj {
+  friend class FieldType;  // field type can set these fields.
+  int       _dimension;
+  Symbol*   _object_key;
+ public:
+  int       dimension()    { return _dimension; }
+  Symbol*   object_key()   { return _object_key; }
+  // basic constructor
+  FieldArrayInfo() : _dimension(0), _object_key(NULL) {}
+  // destructor decrements object key's refcount if created
+  ~FieldArrayInfo() { if (_object_key != NULL) _object_key->decrement_refcount(); }
+};
+
+
 class FieldType: public AllStatic {
  private:
-  static void skip_optional_size(symbolOop signature, int* index);
-  static bool is_valid_array_signature(symbolOop signature);
+  static void skip_optional_size(Symbol* signature, int* index);
+  static bool is_valid_array_signature(Symbol* signature);
  public:
 
   // Return basic type
-  static BasicType basic_type(symbolOop signature);
+  static BasicType basic_type(Symbol* signature);
 
   // Testing
-  static bool is_array(symbolOop signature) { return signature->utf8_length() > 1 && signature->byte_at(0) == '[' && is_valid_array_signature(signature); }
+  static bool is_array(Symbol* signature) { return signature->utf8_length() > 1 && signature->byte_at(0) == '[' && is_valid_array_signature(signature); }
 
-  static bool is_obj(symbolOop signature) {
+  static bool is_obj(Symbol* signature) {
      int sig_length = signature->utf8_length();
      // Must start with 'L' and end with ';'
      return (sig_length >= 2 &&
@@ -54,7 +70,7 @@
   }
 
   // Parse field and extract array information. Works for T_ARRAY only.
-  static BasicType get_array_info(symbolOop signature, jint* dimension, symbolOop *object_key, TRAPS);
+  static BasicType get_array_info(Symbol* signature, FieldArrayInfo& ai, TRAPS);
 };
 
 #endif // SHARE_VM_RUNTIME_FIELDTYPE_HPP
--- a/src/share/vm/runtime/fprofiler.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/fprofiler.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,7 +31,7 @@
 #include "memory/universe.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.inline2.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fprofiler.hpp"
 #include "runtime/mutexLocker.hpp"
@@ -318,7 +318,7 @@
     int limit;
     int i;
     methodOop m = method();
-    symbolOop k = m->klass_name();
+    Symbol* k = m->klass_name();
     // Print the class name with dots instead of slashes
     limit = k->utf8_length();
     for (i = 0 ; i < limit ; i += 1) {
@@ -331,7 +331,7 @@
     if (limit > 0) {
       st->print(".");
     }
-    symbolOop n = m->name();
+    Symbol* n = m->name();
     limit = n->utf8_length();
     for (i = 0 ; i < limit ; i += 1) {
       char c = (char) n->byte_at(i);
@@ -339,7 +339,7 @@
     }
     if( Verbose ) {
       // Disambiguate overloaded methods
-      symbolOop sig = m->signature();
+      Symbol* sig = m->signature();
       sig->print_symbol_on(st);
     }
   }
--- a/src/share/vm/runtime/frame.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/frame.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -792,7 +792,7 @@
   }
 
  public:
-  InterpretedArgumentOopFinder(symbolHandle signature, bool has_receiver, frame* fr, OopClosure* f) : SignatureInfo(signature), _has_receiver(has_receiver) {
+  InterpretedArgumentOopFinder(Symbol* signature, bool has_receiver, frame* fr, OopClosure* f) : SignatureInfo(signature), _has_receiver(has_receiver) {
     // compute size of arguments
     int args_size = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0);
     assert(!fr->is_interpreted_frame() ||
@@ -846,7 +846,7 @@
   }
 
  public:
-   EntryFrameOopFinder(frame* frame, symbolHandle signature, bool is_static) : SignatureInfo(signature) {
+   EntryFrameOopFinder(frame* frame, Symbol* signature, bool is_static) : SignatureInfo(signature) {
      _f = NULL; // will be set later
      _fr = frame;
      _is_static = is_static;
@@ -861,7 +861,7 @@
 
 };
 
-oop* frame::interpreter_callee_receiver_addr(symbolHandle signature) {
+oop* frame::interpreter_callee_receiver_addr(Symbol* signature) {
   ArgumentSizeComputer asc(signature);
   int size = asc.size();
   return (oop *)interpreter_frame_tos_at(size);
@@ -922,7 +922,7 @@
 
   int max_locals = m->is_native() ? m->size_of_parameters() : m->max_locals();
 
-  symbolHandle signature;
+  Symbol* signature = NULL;
   bool has_receiver = false;
 
   // Process a callee's arguments if we are at a call site
@@ -930,10 +930,10 @@
   // This is used sometimes for calling into the VM, not for another
   // interpreted or compiled frame.
   if (!m->is_native()) {
-    Bytecode_invoke *call = Bytecode_invoke_at_check(m, bci);
-    if (call != NULL) {
-      signature = symbolHandle(thread, call->signature());
-      has_receiver = call->has_receiver();
+    Bytecode_invoke call = Bytecode_invoke_check(m, bci);
+    if (call.is_valid()) {
+      signature = call.signature();
+      has_receiver = call.has_receiver();
       if (map->include_argument_oops() &&
           interpreter_frame_expression_stack_size() > 0) {
         ResourceMark rm(thread);  // is this right ???
@@ -965,7 +965,7 @@
 }
 
 
-void frame::oops_interpreted_arguments_do(symbolHandle signature, bool has_receiver, OopClosure* f) {
+void frame::oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f) {
   InterpretedArgumentOopFinder finder(signature, has_receiver, this, f);
   finder.oops_do();
 }
@@ -1014,7 +1014,7 @@
   }
 
  public:
-  CompiledArgumentOopFinder(symbolHandle signature, bool has_receiver, OopClosure* f, frame fr,  const RegisterMap* reg_map)
+  CompiledArgumentOopFinder(Symbol* signature, bool has_receiver, OopClosure* f, frame fr,  const RegisterMap* reg_map)
     : SignatureInfo(signature) {
 
     // initialize CompiledArgumentOopFinder
@@ -1026,7 +1026,7 @@
     _arg_size  = ArgumentSizeComputer(signature).size() + (has_receiver ? 1 : 0);
 
     int arg_size;
-    _regs = SharedRuntime::find_callee_arguments(signature(), has_receiver, &arg_size);
+    _regs = SharedRuntime::find_callee_arguments(signature, has_receiver, &arg_size);
     assert(arg_size == _arg_size, "wrong arg size");
   }
 
@@ -1039,7 +1039,7 @@
   }
 };
 
-void frame::oops_compiled_arguments_do(symbolHandle signature, bool has_receiver, const RegisterMap* reg_map, OopClosure* f) {
+void frame::oops_compiled_arguments_do(Symbol* signature, bool has_receiver, const RegisterMap* reg_map, OopClosure* f) {
   ResourceMark rm;
   CompiledArgumentOopFinder finder(signature, has_receiver, f, *this, reg_map);
   finder.oops_do();
@@ -1099,8 +1099,7 @@
     // must collect argument oops, as nobody else is doing it
     Thread *thread = Thread::current();
     methodHandle m (thread, entry_frame_call_wrapper()->callee_method());
-    symbolHandle signature (thread, m->signature());
-    EntryFrameOopFinder finder(this, signature, m->is_static());
+    EntryFrameOopFinder finder(this, m->signature(), m->is_static());
     finder.arguments_do(f);
   }
   // Traverse the Handle Block saved in the entry frame
--- a/src/share/vm/runtime/frame.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/frame.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -261,10 +261,10 @@
 
   // Find receiver for an invoke when arguments are just pushed on stack (i.e., callee stack-frame is
   // not setup)
-  oop interpreter_callee_receiver(symbolHandle signature)     { return *interpreter_callee_receiver_addr(signature); }
+  oop interpreter_callee_receiver(Symbol* signature)     { return *interpreter_callee_receiver_addr(signature); }
 
 
-  oop* interpreter_callee_receiver_addr(symbolHandle signature);
+  oop* interpreter_callee_receiver_addr(Symbol* signature);
 
 
   // expression stack (may go up or down, direction == 1 or -1)
@@ -386,11 +386,11 @@
   oop* oopmapreg_to_location(VMReg reg, const RegisterMap* regmap) const;
 
   // Oops-do's
-  void oops_compiled_arguments_do(symbolHandle signature, bool has_receiver, const RegisterMap* reg_map, OopClosure* f);
+  void oops_compiled_arguments_do(Symbol* signature, bool has_receiver, const RegisterMap* reg_map, OopClosure* f);
   void oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache = true);
 
  private:
-  void oops_interpreted_arguments_do(symbolHandle signature, bool has_receiver, OopClosure* f);
+  void oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f);
 
   // Iteration of oops
   void oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache);
--- a/src/share/vm/runtime/globals.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/globals.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -607,6 +607,9 @@
   notproduct(bool, ZombieALot, false,                                       \
           "creates zombies (non-entrant) at exit from the runt. system")    \
                                                                             \
+  product(bool, UnlinkSymbolsALot, false,                                   \
+          "unlink unreferenced symbols from the symbol table at safepoints")\
+                                                                            \
   notproduct(bool, WalkStackALot, false,                                    \
           "trace stack (no print) at every exit from the runtime system")   \
                                                                             \
@@ -1201,9 +1204,6 @@
   product(ccstr, TraceJVMTI, NULL,                                          \
           "Trace flags for JVMTI functions and events")                     \
                                                                             \
-  product(bool, ForceFullGCJVMTIEpilogues, false,                           \
-          "Force 'Full GC' was done semantics for JVMTI GC epilogues")      \
-                                                                            \
   /* This option can change an EMCP method into an obsolete method. */      \
   /* This can affect tests that except specific methods to be EMCP. */      \
   /* This option should be used with caution. */                            \
--- a/src/share/vm/runtime/handles.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/handles.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -196,7 +196,6 @@
 DEF_HANDLE(constantPoolCache, is_constantPoolCache)
 DEF_HANDLE(objArray         , is_objArray         )
 DEF_HANDLE(typeArray        , is_typeArray        )
-DEF_HANDLE(symbol           , is_symbol           )
 
 //------------------------------------------------------------------------------------------------------------------------
 // Specific KlassHandles for different Klass types
@@ -233,7 +232,6 @@
 DEF_KLASS_HANDLE(arrayKlass            , oop_is_array         )
 DEF_KLASS_HANDLE(typeArrayKlass        , oop_is_typeArray_slow)
 DEF_KLASS_HANDLE(objArrayKlass         , oop_is_objArray_slow )
-DEF_KLASS_HANDLE(symbolKlass           , oop_is_symbol        )
 DEF_KLASS_HANDLE(constantPoolKlass     , oop_is_constantPool  )
 DEF_KLASS_HANDLE(constantPoolCacheKlass, oop_is_constantPool  )
 
--- a/src/share/vm/runtime/interfaceSupport.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/interfaceSupport.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -198,6 +198,11 @@
   }
 }
 
+void InterfaceSupport::unlinkSymbols() {
+  VM_UnlinkSymbols op;
+  VMThread::execute(&op);
+}
+
 void InterfaceSupport::deoptimizeAll() {
   if (is_init_completed() ) {
     if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) {
--- a/src/share/vm/runtime/interfaceSupport.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/interfaceSupport.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -97,6 +97,7 @@
 # endif
 
   static void zombieAll();
+  static void unlinkSymbols();
   static void deoptimizeAll();
   static void stress_derived_pointers();
   static void verify_stack();
@@ -375,6 +376,9 @@
     if (ZombieALot) {
       InterfaceSupport::zombieAll();
     }
+    if (UnlinkSymbolsALot) {
+      InterfaceSupport::unlinkSymbols();
+    }
     // do verification AFTER potential deoptimization
     if (VerifyStack) {
       InterfaceSupport::verify_stack();
--- a/src/share/vm/runtime/java.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/java.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
 #include "oops/methodOop.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "runtime/aprofiler.hpp"
 #include "runtime/arguments.hpp"
@@ -615,7 +615,7 @@
   vm_abort(false);
 }
 
-void vm_exit_during_initialization(symbolHandle ex, const char* message) {
+void vm_exit_during_initialization(Symbol* ex, const char* message) {
   ResourceMark rm;
   vm_notify_during_shutdown(ex->as_C_string(), message);
 
@@ -663,7 +663,8 @@
     }
     _current = JDK_Version(major, minor, micro, info.update_version,
                            info.special_update_version, build,
-                           info.thread_park_blocker == 1);
+                           info.thread_park_blocker == 1,
+                           info.post_vm_init_hook_enabled == 1);
   }
 }
 
--- a/src/share/vm/runtime/java.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/java.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,7 @@
 
 // VM exit if error occurs during initialization of VM
 extern void vm_exit_during_initialization(Handle exception);
-extern void vm_exit_during_initialization(symbolHandle exception_name, const char* message);
+extern void vm_exit_during_initialization(Symbol* exception_name, const char* message);
 extern void vm_exit_during_initialization(const char* error, const char* message = NULL);
 extern void vm_shutdown_during_initialization(const char* error, const char* message = NULL);
 
@@ -92,6 +92,7 @@
   bool _partially_initialized;
 
   bool _thread_park_blocker;
+  bool _post_vm_init_hook_enabled;
 
   bool is_valid() const {
     return (_major != 0 || _partially_initialized);
@@ -113,14 +114,15 @@
 
   JDK_Version() : _major(0), _minor(0), _micro(0), _update(0),
                   _special(0), _build(0), _partially_initialized(false),
-                  _thread_park_blocker(false) {}
+                  _thread_park_blocker(false), _post_vm_init_hook_enabled(false) {}
 
   JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0,
               uint8_t update = 0, uint8_t special = 0, uint8_t build = 0,
-              bool thread_park_blocker = false) :
+              bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false) :
       _major(major), _minor(minor), _micro(micro), _update(update),
       _special(special), _build(build), _partially_initialized(false),
-      _thread_park_blocker(thread_park_blocker) {}
+      _thread_park_blocker(thread_park_blocker),
+      _post_vm_init_hook_enabled(post_vm_init_hook_enabled) {}
 
   // Returns the current running JDK version
   static JDK_Version current() { return _current; }
@@ -144,6 +146,9 @@
   bool supports_thread_park_blocker() const {
     return _thread_park_blocker;
   }
+  bool post_vm_init_hook_enabled() const {
+    return _post_vm_init_hook_enabled;
+  }
 
   // Performs a full ordering comparison using all fields (update, build, etc.)
   int compare(const JDK_Version& other) const;
--- a/src/share/vm/runtime/javaCalls.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/javaCalls.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -218,7 +218,7 @@
 
 // ============ Virtual calls ============
 
-void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, symbolHandle name, symbolHandle signature, JavaCallArguments* args, TRAPS) {
+void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
   CallInfo callinfo;
   Handle receiver = args->receiver();
   KlassHandle recvrKlass(THREAD, receiver.is_null() ? (klassOop)NULL : receiver->klass());
@@ -233,13 +233,13 @@
 }
 
 
-void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, symbolHandle name, symbolHandle signature, TRAPS) {
+void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, TRAPS) {
   JavaCallArguments args(receiver); // One oop argument
   call_virtual(result, spec_klass, name, signature, &args, CHECK);
 }
 
 
-void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, symbolHandle name, symbolHandle signature, Handle arg1, TRAPS) {
+void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) {
   JavaCallArguments args(receiver); // One oop argument
   args.push_oop(arg1);
   call_virtual(result, spec_klass, name, signature, &args, CHECK);
@@ -247,7 +247,7 @@
 
 
 
-void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, symbolHandle name, symbolHandle signature, Handle arg1, Handle arg2, TRAPS) {
+void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) {
   JavaCallArguments args(receiver); // One oop argument
   args.push_oop(arg1);
   args.push_oop(arg2);
@@ -257,7 +257,7 @@
 
 // ============ Special calls ============
 
-void JavaCalls::call_special(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, JavaCallArguments* args, TRAPS) {
+void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
   CallInfo callinfo;
   LinkResolver::resolve_special_call(callinfo, klass, name, signature, KlassHandle(), false, CHECK);
   methodHandle method = callinfo.selected_method();
@@ -268,20 +268,20 @@
 }
 
 
-void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
+void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
   JavaCallArguments args(receiver); // One oop argument
   call_special(result, klass, name, signature, &args, CHECK);
 }
 
 
-void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, symbolHandle name, symbolHandle signature, Handle arg1, TRAPS) {
+void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) {
   JavaCallArguments args(receiver); // One oop argument
   args.push_oop(arg1);
   call_special(result, klass, name, signature, &args, CHECK);
 }
 
 
-void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, symbolHandle name, symbolHandle signature, Handle arg1, Handle arg2, TRAPS) {
+void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) {
   JavaCallArguments args(receiver); // One oop argument
   args.push_oop(arg1);
   args.push_oop(arg2);
@@ -291,7 +291,7 @@
 
 // ============ Static calls ============
 
-void JavaCalls::call_static(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, JavaCallArguments* args, TRAPS) {
+void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
   CallInfo callinfo;
   LinkResolver::resolve_static_call(callinfo, klass, name, signature, KlassHandle(), false, true, CHECK);
   methodHandle method = callinfo.selected_method();
@@ -302,19 +302,19 @@
 }
 
 
-void JavaCalls::call_static(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
+void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
   JavaCallArguments args; // No argument
   call_static(result, klass, name, signature, &args, CHECK);
 }
 
 
-void JavaCalls::call_static(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, Handle arg1, TRAPS) {
+void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) {
   JavaCallArguments args(arg1); // One oop argument
   call_static(result, klass, name, signature, &args, CHECK);
 }
 
 
-void JavaCalls::call_static(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, Handle arg1, Handle arg2, TRAPS) {
+void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) {
   JavaCallArguments args; // One oop argument
   args.push_oop(arg1);
   args.push_oop(arg2);
@@ -478,7 +478,7 @@
  public:
   bool _is_return;
 
-  SignatureChekker(symbolHandle signature, BasicType return_type, bool is_static, bool* is_oop, intptr_t* value, Thread* thread) : SignatureIterator(signature) {
+  SignatureChekker(Symbol* signature, BasicType return_type, bool is_static, bool* is_oop, intptr_t* value, Thread* thread) : SignatureIterator(signature) {
     _is_oop = is_oop;
     _is_return = false;
     _return_type = return_type;
@@ -569,7 +569,7 @@
   if (return_type == T_ARRAY) return_type = T_OBJECT;
 
   // Check that oop information is correct
-  symbolHandle signature (thread,  method->signature());
+  Symbol* signature = method->signature();
 
   SignatureChekker sc(signature, return_type, method->is_static(),_is_oop, _value, thread);
   sc.iterate_parameters();
--- a/src/share/vm/runtime/javaCalls.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/javaCalls.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -189,11 +189,11 @@
   // call_special
   // ------------
   // The receiver must be first oop in argument list
-  static void call_special(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, JavaCallArguments* args, TRAPS);
+  static void call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);
 
-  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); // No args
-  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, symbolHandle name, symbolHandle signature, Handle arg1, TRAPS);
-  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, symbolHandle name, symbolHandle signature, Handle arg1, Handle arg2, TRAPS);
+  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); // No args
+  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
+  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 
   // interface call
   // ------------
@@ -205,19 +205,19 @@
   // ------------
 
   // The receiver must be first oop in argument list
-  static void call_virtual(JavaValue* result, KlassHandle spec_klass, symbolHandle name, symbolHandle signature, JavaCallArguments* args, TRAPS);
+  static void call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);
 
-  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, symbolHandle name, symbolHandle signature, TRAPS); // No args
-  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, symbolHandle name, symbolHandle signature, Handle arg1, TRAPS);
-  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, symbolHandle name, symbolHandle signature, Handle arg1, Handle arg2, TRAPS);
+  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, TRAPS); // No args
+  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
+  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 
   // Static call
   // -----------
-  static void call_static(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, JavaCallArguments* args, TRAPS);
+  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);
 
-  static void call_static(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
-  static void call_static(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, Handle arg1, TRAPS);
-  static void call_static(JavaValue* result, KlassHandle klass, symbolHandle name, symbolHandle signature, Handle arg1, Handle arg2, TRAPS);
+  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
+  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
+  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 
   // Low-level interface
   static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS);
--- a/src/share/vm/runtime/jniHandles.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/jniHandles.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "oops/oop.inline.hpp"
+#include "prims/jvmtiExport.hpp"
 #include "runtime/jniHandles.hpp"
 #include "runtime/mutexLocker.hpp"
 #ifdef TARGET_OS_FAMILY_linux
@@ -428,6 +429,12 @@
       break;
     }
   }
+
+  /*
+   * JVMTI data structures may also contain weak oops.  The iteration of them
+   * is placed here so that we don't need to add it to each of the collectors.
+   */
+  JvmtiExport::weak_oops_do(is_alive, f);
 }
 
 
--- a/src/share/vm/runtime/mutexLocker.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/mutexLocker.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,8 +80,6 @@
 Monitor* iCMS_lock                    = NULL;
 Monitor* FullGCCount_lock             = NULL;
 Monitor* CMark_lock                   = NULL;
-Monitor* ZF_mon                       = NULL;
-Monitor* Cleanup_mon                  = NULL;
 Mutex*   CMRegionStack_lock           = NULL;
 Mutex*   SATB_Q_FL_lock               = NULL;
 Monitor* SATB_Q_CBL_mon               = NULL;
@@ -122,6 +120,9 @@
 Mutex*   PerfDataManager_lock         = NULL;
 Mutex*   OopMapCacheAlloc_lock        = NULL;
 
+Mutex*   FreeList_lock                = NULL;
+Monitor* SecondaryFreeList_lock       = NULL;
+Mutex*   OldSets_lock                 = NULL;
 Mutex*   MMUTracker_lock              = NULL;
 Mutex*   HotCardCache_lock            = NULL;
 
@@ -177,8 +178,6 @@
   }
   if (UseG1GC) {
     def(CMark_lock                 , Monitor, nonleaf,     true ); // coordinate concurrent mark thread
-    def(ZF_mon                     , Monitor, leaf,        true );
-    def(Cleanup_mon                , Monitor, nonleaf,     true );
     def(CMRegionStack_lock         , Mutex,   leaf,        true );
     def(SATB_Q_FL_lock             , Mutex  , special,     true );
     def(SATB_Q_CBL_mon             , Monitor, nonleaf,     true );
@@ -188,6 +187,9 @@
     def(DirtyCardQ_CBL_mon         , Monitor, nonleaf,     true );
     def(Shared_DirtyCardQ_lock     , Mutex,   nonleaf,     true );
 
+    def(FreeList_lock              , Mutex,   leaf     ,   true );
+    def(SecondaryFreeList_lock     , Monitor, leaf     ,   true );
+    def(OldSets_lock               , Mutex  , leaf     ,   true );
     def(MMUTracker_lock            , Mutex  , leaf     ,   true );
     def(HotCardCache_lock          , Mutex  , special  ,   true );
     def(EvacFailureStack_lock      , Mutex  , nonleaf  ,   true );
--- a/src/share/vm/runtime/mutexLocker.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/mutexLocker.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,8 +76,6 @@
 extern Monitor* iCMS_lock;                       // CMS incremental mode start/stop notification
 extern Monitor* FullGCCount_lock;                // in support of "concurrent" full gc
 extern Monitor* CMark_lock;                      // used for concurrent mark thread coordination
-extern Monitor* ZF_mon;                          // used for G1 conc zero-fill.
-extern Monitor* Cleanup_mon;                     // used for G1 conc cleanup.
 extern Mutex*   CMRegionStack_lock;              // used for protecting accesses to the CM region stack
 extern Mutex*   SATB_Q_FL_lock;                  // Protects SATB Q
                                                  // buffer free list.
@@ -125,6 +123,9 @@
 extern Mutex*   ParkerFreeList_lock;
 extern Mutex*   OopMapCacheAlloc_lock;           // protects allocation of oop_map caches
 
+extern Mutex*   FreeList_lock;                   // protects the free region list during safepoints
+extern Monitor* SecondaryFreeList_lock;          // protects the secondary free region list
+extern Mutex*   OldSets_lock;                    // protects the old region sets
 extern Mutex*   MMUTracker_lock;                 // protects the MMU
                                                  // tracker data structures
 extern Mutex*   HotCardCache_lock;               // protects the hot card cache
--- a/src/share/vm/runtime/objectMonitor.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/objectMonitor.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -79,7 +79,7 @@
   char* bytes = NULL;                                                      \
   int len = 0;                                                             \
   jlong jtid = SharedRuntime::get_java_tid(thread);                        \
-  symbolOop klassname = ((oop)(klassOop))->klass()->klass_part()->name();  \
+  Symbol* klassname = ((oop)(klassOop))->klass()->klass_part()->name();    \
   if (klassname != NULL) {                                                 \
     bytes = (char*)klassname->bytes();                                     \
     len = klassname->utf8_length();                                        \
--- a/src/share/vm/runtime/os.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/os.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -255,7 +255,7 @@
       default: {
         // Dispatch the signal to java
         HandleMark hm(THREAD);
-        klassOop k = SystemDictionary::resolve_or_null(vmSymbolHandles::sun_misc_Signal(), THREAD);
+        klassOop k = SystemDictionary::resolve_or_null(vmSymbols::sun_misc_Signal(), THREAD);
         KlassHandle klass (THREAD, k);
         if (klass.not_null()) {
           JavaValue result(T_VOID);
@@ -264,8 +264,8 @@
           JavaCalls::call_static(
             &result,
             klass,
-            vmSymbolHandles::dispatch_name(),
-            vmSymbolHandles::int_void_signature(),
+            vmSymbols::dispatch_name(),
+            vmSymbols::int_void_signature(),
             &args,
             THREAD
           );
@@ -298,7 +298,7 @@
   if (!ReduceSignalUsage) {
     // Setup JavaThread for processing signals
     EXCEPTION_MARK;
-    klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(), true, CHECK);
+    klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK);
     instanceKlassHandle klass (THREAD, k);
     instanceHandle thread_oop = klass->allocate_instance_handle(CHECK);
 
@@ -310,8 +310,8 @@
     JavaValue result(T_VOID);
     JavaCalls::call_special(&result, thread_oop,
                            klass,
-                           vmSymbolHandles::object_initializer_name(),
-                           vmSymbolHandles::threadgroup_string_void_signature(),
+                           vmSymbols::object_initializer_name(),
+                           vmSymbols::threadgroup_string_void_signature(),
                            thread_group,
                            string,
                            CHECK);
@@ -320,8 +320,8 @@
     JavaCalls::call_special(&result,
                             thread_group,
                             group,
-                            vmSymbolHandles::add_method_name(),
-                            vmSymbolHandles::thread_void_signature(),
+                            vmSymbols::add_method_name(),
+                            vmSymbols::thread_void_signature(),
                             thread_oop,         // ARG 1
                             CHECK);
 
--- a/src/share/vm/runtime/reflection.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/reflection.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -64,7 +64,7 @@
       // this frame is a likely suspect
       caller = vfst.method()->method_holder();
       line_number = vfst.method()->line_number_from_bci(vfst.bci());
-      symbolOop s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name();
+      Symbol* s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name();
       if (s != NULL) {
         source_file = s->as_C_string();
       }
@@ -622,7 +622,7 @@
   ResourceMark rm(THREAD);
   Exceptions::fthrow(
     THREAD_AND_LOCATION,
-    vmSymbolHandles::java_lang_IncompatibleClassChangeError(),
+    vmSymbols::java_lang_IncompatibleClassChangeError(),
     "%s and %s disagree on InnerClasses attribute",
     outer->external_name(),
     inner->external_name()
@@ -638,11 +638,11 @@
       return java_lang_Class::primitive_mirror(ss->type());
     case T_OBJECT:
     case T_ARRAY:
-      symbolOop name        = ss->as_symbol(CHECK_NULL);
+      Symbol* name        = ss->as_symbol(CHECK_NULL);
       oop loader            = instanceKlass::cast(method->method_holder())->class_loader();
       oop protection_domain = instanceKlass::cast(method->method_holder())->protection_domain();
       klassOop k = SystemDictionary::resolve_or_fail(
-                                       symbolHandle(THREAD, name),
+                                       name,
                                        Handle(THREAD, loader),
                                        Handle(THREAD, protection_domain),
                                        true, CHECK_NULL);
@@ -660,7 +660,8 @@
   objArrayHandle mirrors (THREAD, m);
   int index = 0;
   // Collect parameter types
-  symbolHandle signature (THREAD, method->signature());
+  ResourceMark rm(THREAD);
+  Symbol*  signature  = method->signature();
   SignatureStream ss(signature);
   while (!ss.at_return_type()) {
     oop mirror = get_mirror_from_signature(method, &ss, CHECK_(objArrayHandle()));
@@ -681,9 +682,9 @@
 }
 
 
-Handle Reflection::new_type(symbolHandle signature, KlassHandle k, TRAPS) {
+Handle Reflection::new_type(Symbol* signature, KlassHandle k, TRAPS) {
   // Basic types
-  BasicType type = vmSymbols::signature_type(signature());
+  BasicType type = vmSymbols::signature_type(signature);
   if (type != T_OBJECT) {
     return Handle(THREAD, Universe::java_mirror(type));
   }
@@ -714,7 +715,7 @@
   instanceKlassHandle holder (THREAD, method->method_holder());
   int slot = method->method_idnum();
 
-  symbolHandle signature (THREAD, method->signature());
+  Symbol*  signature  = method->signature();
   int parameter_count = ArgumentCount(signature).size();
   oop return_type_oop = NULL;
   objArrayHandle parameter_types = get_parameter_types(method, parameter_count, &return_type_oop, CHECK_NULL);
@@ -726,16 +727,16 @@
 
   if (exception_types.is_null()) return NULL;
 
-  symbolHandle method_name(THREAD, method->name());
+  Symbol*  method_name = method->name();
   Handle name;
   if (intern_name) {
     // intern_name is only true with UseNewReflection
-    oop name_oop = StringTable::intern(method_name(), CHECK_NULL);
+    oop name_oop = StringTable::intern(method_name, CHECK_NULL);
     name = Handle(THREAD, name_oop);
   } else {
     name = java_lang_String::create_from_symbol(method_name, CHECK_NULL);
   }
-  if (name.is_null()) return NULL;
+  if (name == NULL) return NULL;
 
   int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
 
@@ -751,7 +752,7 @@
   java_lang_reflect_Method::set_override(mh(), false);
   if (java_lang_reflect_Method::has_signature_field() &&
       method->generic_signature() != NULL) {
-    symbolHandle gs(THREAD, method->generic_signature());
+    Symbol*  gs = method->generic_signature();
     Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL);
     java_lang_reflect_Method::set_signature(mh(), sig());
   }
@@ -774,7 +775,7 @@
   instanceKlassHandle  holder (THREAD, method->method_holder());
   int slot = method->method_idnum();
 
-  symbolHandle signature (THREAD, method->signature());
+  Symbol*  signature  = method->signature();
   int parameter_count = ArgumentCount(signature).size();
   objArrayHandle parameter_types = get_parameter_types(method, parameter_count, NULL, CHECK_NULL);
   if (parameter_types.is_null()) return NULL;
@@ -794,7 +795,7 @@
   java_lang_reflect_Constructor::set_override(ch(), false);
   if (java_lang_reflect_Constructor::has_signature_field() &&
       method->generic_signature() != NULL) {
-    symbolHandle gs(THREAD, method->generic_signature());
+    Symbol*  gs = method->generic_signature();
     Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL);
     java_lang_reflect_Constructor::set_signature(ch(), sig());
   }
@@ -809,16 +810,16 @@
 
 
 oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) {
-  symbolHandle field_name(THREAD, fd->name());
+  Symbol*  field_name = fd->name();
   Handle name;
   if (intern_name) {
     // intern_name is only true with UseNewReflection
-    oop name_oop = StringTable::intern(field_name(), CHECK_NULL);
+    oop name_oop = StringTable::intern(field_name, CHECK_NULL);
     name = Handle(THREAD, name_oop);
   } else {
     name = java_lang_String::create_from_symbol(field_name, CHECK_NULL);
   }
-  symbolHandle signature (THREAD, fd->signature());
+  Symbol*  signature  = fd->signature();
   KlassHandle  holder    (THREAD, fd->field_holder());
   Handle type = new_type(signature, holder, CHECK_NULL);
   Handle rh  = java_lang_reflect_Field::create(CHECK_NULL);
@@ -832,7 +833,7 @@
   java_lang_reflect_Field::set_override(rh(), false);
   if (java_lang_reflect_Field::has_signature_field() &&
       fd->generic_signature() != NULL) {
-    symbolHandle gs(THREAD, fd->generic_signature());
+    Symbol*  gs = fd->generic_signature();
     Handle sig = java_lang_String::create_from_symbol(gs, CHECK_NULL);
     java_lang_reflect_Field::set_signature(rh(), sig());
   }
@@ -858,8 +859,8 @@
   assert(!method.is_null() , "method should not be null");
 
   CallInfo info;
-  symbolHandle signature (THREAD, method->signature());
-  symbolHandle name      (THREAD, method->name());
+  Symbol*  signature  = method->signature();
+  Symbol*  name       = method->name();
   LinkResolver::resolve_interface_call(info, receiver, recv_klass, klass,
                                        name, signature,
                                        KlassHandle(), false, true,
@@ -912,8 +913,8 @@
             oop resolution_exception = PENDING_EXCEPTION;
             CLEAR_PENDING_EXCEPTION;
             JavaCallArguments args(Handle(THREAD, resolution_exception));
-            THROW_ARG_0(vmSymbolHandles::java_lang_reflect_InvocationTargetException(),
-                vmSymbolHandles::throwable_void_signature(),
+            THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
+                vmSymbols::throwable_void_signature(),
                 &args);
           }
         } else {
@@ -941,8 +942,8 @@
                      method->name(),
                      method->signature()));
               JavaCallArguments args(h_origexception);
-              THROW_ARG_0(vmSymbolHandles::java_lang_reflect_InvocationTargetException(),
-                vmSymbolHandles::throwable_void_signature(),
+              THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
+                vmSymbols::throwable_void_signature(),
                 &args);
             } else {
               ResourceMark rm(THREAD);
@@ -1043,8 +1044,8 @@
     oop target_exception = PENDING_EXCEPTION;
     CLEAR_PENDING_EXCEPTION;
     JavaCallArguments args(Handle(THREAD, target_exception));
-    THROW_ARG_0(vmSymbolHandles::java_lang_reflect_InvocationTargetException(),
-                vmSymbolHandles::throwable_void_signature(),
+    THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(),
+                vmSymbols::throwable_void_signature(),
                 &args);
   } else {
     if (rtype == T_BOOLEAN || rtype == T_BYTE || rtype == T_CHAR || rtype == T_SHORT)
@@ -1097,9 +1098,9 @@
 
 
 oop Reflection::new_field(FieldStream* st, TRAPS) {
-  symbolHandle field_name(THREAD, st->name());
+  Symbol*  field_name = st->name();
   Handle name = java_lang_String::create_from_symbol(field_name, CHECK_NULL);
-  symbolHandle signature(THREAD, st->signature());
+  Symbol*  signature = st->signature();
   Handle type = new_type(signature, st->klass(), CHECK_NULL);
   Handle rh  = java_lang_reflect_Field::create(CHECK_NULL);
   oop result = rh();
@@ -1242,7 +1243,7 @@
     case T_ARRAY: {
       Handle obj(THREAD, (oop) value->l);
       if (obj.not_null()) {
-        symbolHandle signature(THREAD, fd->signature());
+        Symbol*  signature = fd->signature();
         Handle       loader   (THREAD, fd->loader());
         Handle       protect  (THREAD, Klass::cast(fd->field_holder())->protection_domain());
         klassOop k = SystemDictionary::resolve_or_fail(signature, loader, protect, true, CHECK); // may block
@@ -1259,7 +1260,7 @@
 }
 
 
-oop Reflection::reflect_field(oop mirror, symbolOop field_name, jint which, TRAPS) {
+oop Reflection::reflect_field(oop mirror, Symbol* field_name, jint which, TRAPS) {
   // Exclude primitive types and array types
   if (java_lang_Class::is_primitive(mirror))                             return NULL;
   if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) return NULL;
@@ -1287,7 +1288,7 @@
   // Exclude primitive types and array types
   if (java_lang_Class::is_primitive(mirror)
       || Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) {
-    symbolHandle name = vmSymbolHandles::java_lang_reflect_Field();
+    Symbol* name = vmSymbols::java_lang_reflect_Field();
     klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL);
     return oopFactory::new_objArray(klass, 0, CHECK_NULL);  // Return empty array
   }
@@ -1308,7 +1309,7 @@
   }
 
   // Allocate result
-  symbolHandle name = vmSymbolHandles::java_lang_reflect_Field();
+  Symbol* name = vmSymbols::java_lang_reflect_Field();
   klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL);
   objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL);
   objArrayHandle result (THREAD, r);
@@ -1327,7 +1328,7 @@
 }
 
 
-oop Reflection::reflect_method(oop mirror, symbolHandle method_name, objArrayHandle types, jint which, TRAPS) {
+oop Reflection::reflect_method(oop mirror, Symbol* method_name, objArrayHandle types, jint which, TRAPS) {
   if (java_lang_Class::is_primitive(mirror))  return NULL;
   klassOop klass = java_lang_Class::as_klassOop(mirror);
   if (Klass::cast(klass)->oop_is_array() && which == MEMBER_DECLARED)  return NULL;
@@ -1351,8 +1352,8 @@
         for (MethodStream st(h_k, false, false); !st.eos(); st.next()) {
           methodHandle m(THREAD, st.method());
           // For interfaces include static initializers since classic does that!
-          if (method_name() == m->name() && (include_clinit || (m->is_public() && !m->is_static() && !m->is_initializer()))) {
-            symbolHandle signature(THREAD, m->signature());
+          if (method_name == m->name() && (include_clinit || (m->is_public() && !m->is_static() && !m->is_initializer()))) {
+            Symbol*  signature = m->signature();
             bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL);
             if (parameter_match) {
               return new_method(m, false, false, THREAD);
@@ -1364,8 +1365,8 @@
       {
         for (MethodStream st(h_k, false, false); !st.eos(); st.next()) {
           methodHandle m(THREAD, st.method());
-          if (method_name() == m->name() && m->is_public() && m->is_static() && !m->is_initializer()) {
-            symbolHandle signature(THREAD, m->signature());
+          if (method_name == m->name() && m->is_public() && m->is_static() && !m->is_initializer()) {
+            Symbol*  signature = m->signature();
             bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL);
             if (parameter_match) {
               return new_method(m, false, false, THREAD);
@@ -1379,8 +1380,8 @@
       {
         for (MethodStream st(h_k, true, true); !st.eos(); st.next()) {
           methodHandle m(THREAD, st.method());
-          if (method_name() == m->name() && !m->is_initializer()) {
-            symbolHandle signature(THREAD, m->signature());
+          if (method_name == m->name() && !m->is_initializer()) {
+            Symbol*  signature = m->signature();
             bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL);
             if (parameter_match) {
               return new_method(m, false, false, THREAD);
@@ -1531,7 +1532,7 @@
   for (MethodStream st(h_k, true, true); !st.eos(); st.next()) {
     methodHandle m(THREAD, st.method());
     if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) {
-      symbolHandle signature(THREAD, m->signature());
+      Symbol*  signature = m->signature();
       bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL);
       if (parameter_match) {
         return new_constructor(m, THREAD);
@@ -1569,7 +1570,7 @@
   }
 
   // Allocate result
-  symbolHandle name = vmSymbolHandles::java_lang_reflect_Constructor();
+  Symbol* name = vmSymbols::java_lang_reflect_Constructor();
   klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL);
   objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL);
   objArrayHandle h_result (THREAD, r);
--- a/src/share/vm/runtime/reflection.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/reflection.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -55,7 +55,7 @@
   static objArrayHandle get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS);
   static objArrayHandle get_exception_types(methodHandle method, TRAPS);
   // Creating new java.lang.reflect.xxx wrappers
-  static Handle new_type(symbolHandle signature, KlassHandle k, TRAPS);
+  static Handle new_type(Symbol* signature, KlassHandle k, TRAPS);
 
  public:
   // Constants defined by java reflection api classes
@@ -157,11 +157,11 @@
   static void      field_set(jvalue* value, fieldDescriptor* fd, Handle receiver, BasicType value_type, TRAPS);
 
   // Reflective lookup of fields. Returns java.lang.reflect.Field instances.
-  static oop         reflect_field(oop mirror, symbolOop field_name, jint which, TRAPS);
+  static oop         reflect_field(oop mirror, Symbol* field_name, jint which, TRAPS);
   static objArrayOop reflect_fields(oop mirror, jint which, TRAPS);
 
   // Reflective lookup of methods. Returns java.lang.reflect.Method instances.
-  static oop         reflect_method(oop mirror, symbolHandle method_name, objArrayHandle types, jint which, TRAPS);
+  static oop         reflect_method(oop mirror, Symbol* method_name, objArrayHandle types, jint which, TRAPS);
   static objArrayOop reflect_methods(oop mirror, jint which, TRAPS);
 
   // Reflective lookup of constructors. Returns java.lang.reflect.Constructor instances.
--- a/src/share/vm/runtime/reflectionUtils.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/reflectionUtils.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -100,7 +100,7 @@
 // Usage:
 //
 //    for (FieldStream st(k, false, false); !st.eos(); st.next()) {
-//      symbolOop field_name = st.name();
+//      Symbol* field_name = st.name();
 //      ...
 //    }
 
@@ -126,11 +126,11 @@
     flags.set_flags(fields()->ushort_at(index() + instanceKlass::access_flags_offset));
     return flags;
   }
-  symbolOop name() const {
+  Symbol* name() const {
     int name_index = fields()->ushort_at(index() + instanceKlass::name_index_offset);
     return constants()->symbol_at(name_index);
   }
-  symbolOop signature() const {
+  Symbol* signature() const {
     int signature_index = fields()->ushort_at(index() +
                                        instanceKlass::signature_index_offset);
     return constants()->symbol_at(signature_index);
@@ -197,7 +197,7 @@
 // Usage:
 //
 //    for (FilteredFieldStream st(k, false, false); !st.eos(); st.next()) {
-//      symbolOop field_name = st.name();
+//      Symbol* field_name = st.name();
 //      ...
 //    }
 
--- a/src/share/vm/runtime/relocator.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/relocator.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -106,7 +106,7 @@
   // get the address of in the code_array
   inline char* addr_at(int bci) const             { return (char*) &code_array()[bci]; }
 
-  int  instruction_length_at(int bci)             { return Bytecodes::length_at(code_array() + bci); }
+  int  instruction_length_at(int bci)             { return Bytecodes::length_at(NULL, code_array() + bci); }
 
   // Helper methods
   int  align(int n) const                          { return (n+3) & ~3; }
--- a/src/share/vm/runtime/rframe.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/rframe.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -25,7 +25,7 @@
 #include "precompiled.hpp"
 #include "interpreter/interpreter.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/rframe.hpp"
 #include "runtime/vframe.hpp"
--- a/src/share/vm/runtime/safepoint.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/safepoint.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -34,7 +34,7 @@
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/frame.inline.hpp"
--- a/src/share/vm/runtime/sharedRuntime.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -527,7 +527,7 @@
 }
 
 
-oop SharedRuntime::retrieve_receiver( symbolHandle sig, frame caller ) {
+oop SharedRuntime::retrieve_receiver( Symbol* sig, frame caller ) {
   assert(caller.is_interpreted_frame(), "");
   int args_size = ArgumentSizeComputer(sig).size() + 1;
   assert(args_size <= caller.interpreter_frame_expression_stack_size(), "receiver must be on interpreter stack");
@@ -547,7 +547,7 @@
   Exceptions::_throw(thread, __FILE__, __LINE__, h_exception);
 }
 
-void SharedRuntime::throw_and_post_jvmti_exception(JavaThread *thread, symbolOop name, const char *message) {
+void SharedRuntime::throw_and_post_jvmti_exception(JavaThread *thread, Symbol* name, const char *message) {
   Handle h_exception = Exceptions::new_exception(thread, name, message);
   throw_and_post_jvmti_exception(thread, h_exception);
 }
@@ -892,7 +892,7 @@
   assert(DTraceAllocProbes, "wrong call");
   Klass* klass = o->blueprint();
   int size = o->size();
-  symbolOop name = klass->name();
+  Symbol* name = klass->name();
   HS_DTRACE_PROBE4(hotspot, object__alloc, get_java_tid(thread),
                    name->bytes(), name->utf8_length(), size * HeapWordSize);
   return 0;
@@ -901,9 +901,9 @@
 JRT_LEAF(int, SharedRuntime::dtrace_method_entry(
     JavaThread* thread, methodOopDesc* method))
   assert(DTraceMethodProbes, "wrong call");
-  symbolOop kname = method->klass_name();
-  symbolOop name = method->name();
-  symbolOop sig = method->signature();
+  Symbol* kname = method->klass_name();
+  Symbol* name = method->name();
+  Symbol* sig = method->signature();
   HS_DTRACE_PROBE7(hotspot, method__entry, get_java_tid(thread),
       kname->bytes(), kname->utf8_length(),
       name->bytes(), name->utf8_length(),
@@ -914,9 +914,9 @@
 JRT_LEAF(int, SharedRuntime::dtrace_method_exit(
     JavaThread* thread, methodOopDesc* method))
   assert(DTraceMethodProbes, "wrong call");
-  symbolOop kname = method->klass_name();
-  symbolOop name = method->name();
-  symbolOop sig = method->signature();
+  Symbol* kname = method->klass_name();
+  Symbol* name = method->name();
+  Symbol* sig = method->signature();
   HS_DTRACE_PROBE7(hotspot, method__return, get_java_tid(thread),
       kname->bytes(), kname->utf8_length(),
       name->bytes(), name->utf8_length(),
@@ -956,9 +956,9 @@
   int          bci    = vfst.bci();
 
   // Find bytecode
-  Bytecode_invoke* bytecode = Bytecode_invoke_at(caller, bci);
-  bc = bytecode->java_code();
-  int bytecode_index = bytecode->index();
+  Bytecode_invoke bytecode(caller, bci);
+  bc = bytecode.java_code();
+  int bytecode_index = bytecode.index();
 
   // Find receiver for non-static call
   if (bc != Bytecodes::_invokestatic) {
@@ -969,7 +969,7 @@
     // Caller-frame is a compiled frame
     frame callerFrame = stubFrame.sender(&reg_map2);
 
-    methodHandle callee = bytecode->static_target(CHECK_(nullHandle));
+    methodHandle callee = bytecode.static_target(CHECK_(nullHandle));
     if (callee.is_null()) {
       THROW_(vmSymbols::java_lang_NoSuchMethodException(), nullHandle);
     }
@@ -1686,10 +1686,9 @@
   // Get target class name from the checkcast instruction
   vframeStream vfst(thread, true);
   assert(!vfst.at_end(), "Java frame must exist");
-  Bytecode_checkcast* cc = Bytecode_checkcast_at(
-    vfst.method()->bcp_from(vfst.bci()));
+  Bytecode_checkcast cc(vfst.method(), vfst.method()->bcp_from(vfst.bci()));
   Klass* targetKlass = Klass::cast(vfst.method()->constants()->klass_at(
-    cc->index(), thread));
+    cc.index(), thread));
   return generate_class_cast_message(objName, targetKlass->external_name());
 }
 
@@ -1723,11 +1722,11 @@
     const char* targetType = "the required signature";
     vframeStream vfst(thread, true);
     if (!vfst.at_end()) {
-      Bytecode_invoke* call = Bytecode_invoke_at(vfst.method(), vfst.bci());
+      Bytecode_invoke call(vfst.method(), vfst.bci());
       methodHandle target;
       {
         EXCEPTION_MARK;
-        target = call->static_target(THREAD);
+        target = call.static_target(THREAD);
         if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; }
       }
       if (target.not_null()
@@ -2650,7 +2649,7 @@
   return regs.first();
 }
 
-VMRegPair *SharedRuntime::find_callee_arguments(symbolOop sig, bool has_receiver, int* arg_size) {
+VMRegPair *SharedRuntime::find_callee_arguments(Symbol* sig, bool has_receiver, int* arg_size) {
   // This method is returning a data structure allocating as a
   // ResourceObject, so do not put any ResourceMarks in here.
   char *s = sig->as_C_string();
--- a/src/share/vm/runtime/sharedRuntime.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -223,7 +223,7 @@
 
   // Helper routine for full-speed JVMTI exception throwing support
   static void throw_and_post_jvmti_exception(JavaThread *thread, Handle h_exception);
-  static void throw_and_post_jvmti_exception(JavaThread *thread, symbolOop name, const char *message = NULL);
+  static void throw_and_post_jvmti_exception(JavaThread *thread, Symbol* name, const char *message = NULL);
 
   // RedefineClasses() tracing support for obsolete method entry
   static int rc_trace_method_entry(JavaThread* thread, methodOopDesc* m);
@@ -237,7 +237,7 @@
   // Used to back off a spin lock that is under heavy contention
   static void yield_all(JavaThread* thread, int attempts = 0);
 
-  static oop retrieve_receiver( symbolHandle sig, frame caller );
+  static oop retrieve_receiver( Symbol* sig, frame caller );
 
   static void register_finalizer(JavaThread* thread, oopDesc* obj);
 
@@ -417,7 +417,7 @@
 
   // Convert a sig into a calling convention register layout
   // and find interesting things about it.
-  static VMRegPair* find_callee_arguments(symbolOop sig, bool has_receiver, int *arg_size);
+  static VMRegPair* find_callee_arguments(Symbol* sig, bool has_receiver, int *arg_size);
   static VMReg     name_for_receiver();
 
   // "Top of Stack" slots that may be unused by the calling convention but must
--- a/src/share/vm/runtime/signature.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/signature.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -28,7 +28,7 @@
 #include "memory/oopFactory.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "runtime/signature.hpp"
 
@@ -44,25 +44,11 @@
 // ClassName  = string.
 
 
-SignatureIterator::SignatureIterator(symbolHandle signature) {
-  assert(signature->is_symbol(), "not a symbol");
+SignatureIterator::SignatureIterator(Symbol* signature) {
   _signature       = signature;
   _parameter_index = 0;
 }
 
-// Overloaded version called without handle
-SignatureIterator::SignatureIterator(symbolOop signature) {
-  symbolHandle sh(Thread::current(), signature);
-  _signature       = sh;
-  _parameter_index = 0;
-}
-
-SignatureIterator::SignatureIterator(Thread *thread, symbolOop signature) {
-  symbolHandle sh(thread, signature);
-  _signature       = sh;
-  _parameter_index = 0;
-}
-
 void SignatureIterator::expect(char c) {
   if (_signature->byte_at(_index) != c) fatal(err_msg("expecting %c", c));
   _index++;
@@ -70,7 +56,7 @@
 
 
 void SignatureIterator::skip_optional_size() {
-  symbolOop sig = _signature();
+  Symbol* sig = _signature;
   char c = sig->byte_at(_index);
   while ('0' <= c && c <= '9') c = sig->byte_at(++_index);
 }
@@ -104,7 +90,7 @@
               _index++; size = T_VOID_size;  ; break;
     case 'L':
       { int begin = ++_index;
-        symbolOop sig = _signature();
+        Symbol* sig = _signature;
         while (sig->byte_at(_index++) != ';') ;
         do_object(begin, _index);
       }
@@ -114,7 +100,7 @@
     case '[':
       { int begin = ++_index;
         skip_optional_size();
-        symbolOop sig = _signature();
+        Symbol* sig = _signature;
         while (sig->byte_at(_index) == '[') {
           _index++;
           skip_optional_size();
@@ -237,7 +223,7 @@
   // Ignore parameters
   _index = 0;
   expect('(');
-  symbolOop sig = _signature();
+  Symbol* sig = _signature;
   while (sig->byte_at(_index) != ')') _index++;
   expect(')');
   // Parse return type
@@ -264,9 +250,22 @@
 
 
 // Implementation of SignatureStream
+SignatureStream::SignatureStream(Symbol* signature, bool is_method) :
+                   _signature(signature), _at_return_type(false) {
+  _begin = _end = (is_method ? 1 : 0);  // skip first '(' in method signatures
+  _names = new GrowableArray<Symbol*>(10);
+  next();
+}
+
+SignatureStream::~SignatureStream() {
+  // decrement refcount for names created during signature parsing
+  for (int i = 0; i < _names->length(); i++) {
+    _names->at(i)->decrement_refcount();
+  }
+}
 
 bool SignatureStream::is_done() const {
-  return _end > _signature()->utf8_length();
+  return _end > _signature->utf8_length();
 }
 
 
@@ -274,13 +273,13 @@
   switch (t) {
     case 'L': {
       _type = T_OBJECT;
-      symbolOop sig = _signature();
+      Symbol* sig = _signature;
       while (sig->byte_at(_end++) != ';');
       break;
     }
     case '[': {
       _type = T_ARRAY;
-      symbolOop sig = _signature();
+      Symbol* sig = _signature;
       char c = sig->byte_at(_end);
       while ('0' <= c && c <= '9') c = sig->byte_at(_end++);
       while (sig->byte_at(_end) == '[') {
@@ -319,25 +318,28 @@
   return _type == T_ARRAY;
 }
 
-symbolOop SignatureStream::as_symbol(TRAPS) {
+Symbol* SignatureStream::as_symbol(TRAPS) {
   // Create a symbol from for string _begin _end
   int begin = _begin;
   int end   = _end;
 
-  if (   _signature()->byte_at(_begin) == 'L'
-      && _signature()->byte_at(_end-1) == ';') {
+  if (   _signature->byte_at(_begin) == 'L'
+      && _signature->byte_at(_end-1) == ';') {
     begin++;
     end--;
   }
 
-  symbolOop result = oopFactory::new_symbol(_signature, begin, end, CHECK_NULL);
-  return result;
+  // Save names for cleaning up reference count at the end of
+  // SignatureStream scope.
+  Symbol* name = SymbolTable::new_symbol(_signature, begin, end, CHECK_NULL);
+  _names->push(name);  // save new symbol for decrementing later
+  return name;
 }
 
 klassOop SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
                                    FailureMode failure_mode, TRAPS) {
   if (!is_object())  return NULL;
-  symbolOop name = as_symbol(CHECK_NULL);
+  Symbol* name = as_symbol(CHECK_NULL);
   if (failure_mode == ReturnNull) {
     return SystemDictionary::resolve_or_null(name, class_loader, protection_domain, THREAD);
   } else {
@@ -355,28 +357,28 @@
   return Klass::cast(klass)->java_mirror();
 }
 
-symbolOop SignatureStream::as_symbol_or_null() {
+Symbol* SignatureStream::as_symbol_or_null() {
   // Create a symbol from for string _begin _end
   ResourceMark rm;
 
   int begin = _begin;
   int end   = _end;
 
-  if (   _signature()->byte_at(_begin) == 'L'
-      && _signature()->byte_at(_end-1) == ';') {
+  if (   _signature->byte_at(_begin) == 'L'
+      && _signature->byte_at(_end-1) == ';') {
     begin++;
     end--;
   }
 
   char* buffer = NEW_RESOURCE_ARRAY(char, end - begin);
   for (int index = begin; index < end; index++) {
-    buffer[index - begin] = _signature()->byte_at(index);
+    buffer[index - begin] = _signature->byte_at(index);
   }
-  symbolOop result = SymbolTable::probe(buffer, end - begin);
+  Symbol* result = SymbolTable::probe(buffer, end - begin);
   return result;
 }
 
-bool SignatureVerifier::is_valid_signature(symbolHandle sig) {
+bool SignatureVerifier::is_valid_signature(Symbol* sig) {
   const char* signature = (const char*)sig->bytes();
   ssize_t len = sig->utf8_length();
   if (signature == NULL || signature[0] == '\0' || len < 1) {
@@ -388,7 +390,7 @@
   }
 }
 
-bool SignatureVerifier::is_valid_method_signature(symbolHandle sig) {
+bool SignatureVerifier::is_valid_method_signature(Symbol* sig) {
   const char* method_sig = (const char*)sig->bytes();
   ssize_t len = sig->utf8_length();
   ssize_t index = 0;
@@ -411,7 +413,7 @@
   return false;
 }
 
-bool SignatureVerifier::is_valid_type_signature(symbolHandle sig) {
+bool SignatureVerifier::is_valid_type_signature(Symbol* sig) {
   const char* type_sig = (const char*)sig->bytes();
   ssize_t len = sig->utf8_length();
   return (type_sig != NULL && len >= 1 &&
--- a/src/share/vm/runtime/signature.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/signature.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -47,7 +47,7 @@
 
 class SignatureIterator: public ResourceObj {
  protected:
-  symbolHandle _signature;             // the signature to iterate over
+  Symbol*      _signature;             // the signature to iterate over
   int          _index;                 // the current character index (only valid during iteration)
   int          _parameter_index;       // the current parameter index (0 outside iteration phase)
   BasicType    _return_type;
@@ -87,9 +87,7 @@
   };
 
   // Constructors
-  SignatureIterator(symbolOop signature);
-  SignatureIterator(Thread *thread, symbolOop signature);
-  SignatureIterator(symbolHandle signature);
+  SignatureIterator(Symbol* signature);
 
   // Iteration
   void dispatch_field();               // dispatches once for field signatures
@@ -138,7 +136,7 @@
   void do_array (int begin, int end)   { type_name("jobject" ); }
 
  public:
-  SignatureTypeNames(symbolHandle signature) : SignatureIterator(signature) {}
+  SignatureTypeNames(Symbol* signature) : SignatureIterator(signature) {}
 };
 
 
@@ -166,7 +164,7 @@
   void do_array (int begin, int end)   { set(T_ARRAY_size  , T_ARRAY  ); }
 
  public:
-  SignatureInfo(symbolHandle signature) : SignatureIterator(signature) {
+  SignatureInfo(Symbol* signature) : SignatureIterator(signature) {
     _has_iterated = _has_iterated_return = false;
     _size         = 0;
     _return_type  = T_ILLEGAL;
@@ -181,7 +179,7 @@
  private:
   void set(int size, BasicType type)   { _size += size; }
  public:
-  ArgumentSizeComputer(symbolHandle signature) : SignatureInfo(signature) {}
+  ArgumentSizeComputer(Symbol* signature) : SignatureInfo(signature) {}
 
   int       size()                     { lazy_iterate_parameters(); return _size; }
 };
@@ -191,7 +189,7 @@
  private:
   void set(int size, BasicType type)   { _size ++; }
  public:
-  ArgumentCount(symbolHandle signature) : SignatureInfo(signature) {}
+  ArgumentCount(Symbol* signature) : SignatureInfo(signature) {}
 
   int       size()                     { lazy_iterate_parameters(); return _size; }
 };
@@ -205,7 +203,7 @@
  public:
   BasicType type()                     { lazy_iterate_return(); return _return_type; }
 
-  ResultTypeFinder(symbolHandle signature) : SignatureInfo(signature) {}
+  ResultTypeFinder(Symbol* signature) : SignatureInfo(signature) {}
 };
 
 
@@ -238,11 +236,6 @@
     _fingerprint = 0;
   }
 
-  Fingerprinter(Thread *thread, methodHandle method) : SignatureIterator(thread, method->signature()) {
-    mh = method;
-    _fingerprint = 0;
-  }
-
   uint64_t fingerprint() {
     // See if we fingerprinted this method already
     if (mh->constMethod()->fingerprint() != CONST64(0)) {
@@ -356,18 +349,19 @@
 
 class SignatureStream : public StackObj {
  private:
-  symbolHandle _signature;
+  Symbol*      _signature;
   int          _begin;
   int          _end;
   BasicType    _type;
   bool         _at_return_type;
+  GrowableArray<Symbol*>* _names;  // symbols created while parsing signature
 
  public:
   bool at_return_type() const                    { return _at_return_type; }
   bool is_done() const;
   void next_non_primitive(int t);
   void next() {
-    symbolOop sig = _signature();
+    Symbol* sig = _signature;
     int len = sig->utf8_length();
     if (_end >= len) {
       _end = len + 1;
@@ -392,32 +386,28 @@
     _end++;
   }
 
-  SignatureStream(symbolHandle signature,
-                  bool is_method = true) :
-                   _signature(signature), _at_return_type(false) {
-    _begin = _end = (is_method ? 1 : 0);  // skip first '(' in method signatures
-    next();
-  }
+  SignatureStream(Symbol* signature, bool is_method = true);
+  ~SignatureStream();
 
   bool is_object() const;                        // True if this argument is an object
   bool is_array() const;                         // True if this argument is an array
   BasicType type() const                         { return _type; }
-  symbolOop as_symbol(TRAPS);
+  Symbol* as_symbol(TRAPS);
   enum FailureMode { ReturnNull, CNFException, NCDFError };
   klassOop as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
   oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
 
   // return same as_symbol except allocation of new symbols is avoided.
-  symbolOop as_symbol_or_null();
+  Symbol* as_symbol_or_null();
 };
 
 class SignatureVerifier : public StackObj {
   public:
     // Returns true if the symbol is valid method or type signature
-    static bool is_valid_signature(symbolHandle sig);
+    static bool is_valid_signature(Symbol* sig);
 
-    static bool is_valid_method_signature(symbolHandle sig);
-    static bool is_valid_type_signature(symbolHandle sig);
+    static bool is_valid_method_signature(Symbol* sig);
+    static bool is_valid_type_signature(Symbol* sig);
   private:
 
     static ssize_t is_valid_type(const char*, ssize_t);
--- a/src/share/vm/runtime/statSampler.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/statSampler.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -196,8 +196,8 @@
   // public static String getProperty(String key, String def);
   JavaCalls::call_static(&result,
                          KlassHandle(THREAD, SystemDictionary::System_klass()),
-                         vmSymbolHandles::getProperty_name(),
-                         vmSymbolHandles::string_string_signature(),
+                         vmSymbols::getProperty_name(),
+                         vmSymbols::string_string_signature(),
                          key_str,
                          CHECK_NULL);
 
--- a/src/share/vm/runtime/synchronizer.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/synchronizer.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -82,7 +82,7 @@
   char* bytes = NULL;                                                      \
   int len = 0;                                                             \
   jlong jtid = SharedRuntime::get_java_tid(thread);                        \
-  symbolOop klassname = ((oop)(klassOop))->klass()->klass_part()->name();  \
+  Symbol* klassname = ((oop)(klassOop))->klass()->klass_part()->name();  \
   if (klassname != NULL) {                                                 \
     bytes = (char*)klassname->bytes();                                     \
     len = klassname->utf8_length();                                        \
--- a/src/share/vm/runtime/thread.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/thread.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,12 +31,13 @@
 #include "compiler/compileBroker.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/linkResolver.hpp"
+#include "jvmtifiles/jvmtiEnv.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "prims/jvm_misc.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/jvmtiThreadState.hpp"
@@ -890,7 +891,7 @@
   return os::create_main_thread((JavaThread*)this);
 }
 
-static void initialize_class(symbolHandle class_name, TRAPS) {
+static void initialize_class(Symbol* class_name, TRAPS) {
   klassOop klass = SystemDictionary::resolve_or_fail(class_name, true, CHECK);
   instanceKlass::cast(klass)->initialize(CHECK);
 }
@@ -898,7 +899,7 @@
 
 // Creates the initial ThreadGroup
 static Handle create_initial_thread_group(TRAPS) {
-  klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_ThreadGroup(), true, CHECK_NH);
+  klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ThreadGroup(), true, CHECK_NH);
   instanceKlassHandle klass (THREAD, k);
 
   Handle system_instance = klass->allocate_instance_handle(CHECK_NH);
@@ -907,8 +908,8 @@
     JavaCalls::call_special(&result,
                             system_instance,
                             klass,
-                            vmSymbolHandles::object_initializer_name(),
-                            vmSymbolHandles::void_method_signature(),
+                            vmSymbols::object_initializer_name(),
+                            vmSymbols::void_method_signature(),
                             CHECK_NH);
   }
   Universe::set_system_thread_group(system_instance());
@@ -920,8 +921,8 @@
     JavaCalls::call_special(&result,
                             main_instance,
                             klass,
-                            vmSymbolHandles::object_initializer_name(),
-                            vmSymbolHandles::threadgroup_string_void_signature(),
+                            vmSymbols::object_initializer_name(),
+                            vmSymbols::threadgroup_string_void_signature(),
                             system_instance,
                             string,
                             CHECK_NH);
@@ -931,7 +932,7 @@
 
 // Creates the initial Thread
 static oop create_initial_thread(Handle thread_group, JavaThread* thread, TRAPS) {
-  klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(), true, CHECK_NULL);
+  klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL);
   instanceKlassHandle klass (THREAD, k);
   instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
 
@@ -944,8 +945,8 @@
   JavaValue result(T_VOID);
   JavaCalls::call_special(&result, thread_oop,
                                    klass,
-                                   vmSymbolHandles::object_initializer_name(),
-                                   vmSymbolHandles::threadgroup_string_void_signature(),
+                                   vmSymbols::object_initializer_name(),
+                                   vmSymbols::threadgroup_string_void_signature(),
                                    thread_group,
                                    string,
                                    CHECK_NULL);
@@ -953,12 +954,12 @@
 }
 
 static void call_initializeSystemClass(TRAPS) {
-  klassOop k =  SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_System(), true, CHECK);
+  klassOop k =  SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
   instanceKlassHandle klass (THREAD, k);
 
   JavaValue result(T_VOID);
-  JavaCalls::call_static(&result, klass, vmSymbolHandles::initializeSystemClass_name(),
-                                         vmSymbolHandles::void_method_signature(), CHECK);
+  JavaCalls::call_static(&result, klass, vmSymbols::initializeSystemClass_name(),
+                                         vmSymbols::void_method_signature(), CHECK);
 }
 
 #ifdef KERNEL
@@ -972,18 +973,31 @@
   }
 
   JavaValue result(T_VOID);
-  JavaCalls::call_static(&result, klass, vmSymbolHandles::setBootClassLoaderHook_name(),
-                                         vmSymbolHandles::void_method_signature(), CHECK);
+  JavaCalls::call_static(&result, klass, vmSymbols::setBootClassLoaderHook_name(),
+                                         vmSymbols::void_method_signature(), CHECK);
 }
 #endif // KERNEL
 
+// General purpose hook into Java code, run once when the VM is initialized.
+// The Java library method itself may be changed independently from the VM.
+static void call_postVMInitHook(TRAPS) {
+  klassOop k = SystemDictionary::sun_misc_PostVMInitHook_klass();
+  instanceKlassHandle klass (THREAD, k);
+  if (klass.not_null()) {
+    JavaValue result(T_VOID);
+    JavaCalls::call_static(&result, klass, vmSymbols::run_method_name(),
+                                           vmSymbols::void_method_signature(),
+                                           CHECK);
+  }
+}
+
 static void reset_vm_info_property(TRAPS) {
   // the vm info string
   ResourceMark rm(THREAD);
   const char *vm_info = VM_Version::vm_info_string();
 
   // java.lang.System class
-  klassOop k =  SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_System(), true, CHECK);
+  klassOop k =  SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
   instanceKlassHandle klass (THREAD, k);
 
   // setProperty arguments
@@ -996,8 +1010,8 @@
   // public static String setProperty(String key, String value);
   JavaCalls::call_static(&r,
                          klass,
-                         vmSymbolHandles::setProperty_name(),
-                         vmSymbolHandles::string_string_string_signature(),
+                         vmSymbols::setProperty_name(),
+                         vmSymbols::string_string_string_signature(),
                          key_str,
                          value_str,
                          CHECK);
@@ -1008,7 +1022,7 @@
   assert(thread_group.not_null(), "thread group should be specified");
   assert(threadObj() == NULL, "should only create Java thread object once");
 
-  klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(), true, CHECK);
+  klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK);
   instanceKlassHandle klass (THREAD, k);
   instanceHandle thread_oop = klass->allocate_instance_handle(CHECK);
 
@@ -1023,8 +1037,8 @@
     JavaCalls::call_special(&result,
                             thread_oop,
                             klass,
-                            vmSymbolHandles::object_initializer_name(),
-                            vmSymbolHandles::threadgroup_string_void_signature(),
+                            vmSymbols::object_initializer_name(),
+                            vmSymbols::threadgroup_string_void_signature(),
                             thread_group, // Argument 1
                             name,         // Argument 2
                             THREAD);
@@ -1034,8 +1048,8 @@
     JavaCalls::call_special(&result,
                             thread_oop,
                             klass,
-                            vmSymbolHandles::object_initializer_name(),
-                            vmSymbolHandles::threadgroup_runnable_void_signature(),
+                            vmSymbols::object_initializer_name(),
+                            vmSymbols::threadgroup_runnable_void_signature(),
                             thread_group, // Argument 1
                             Handle(),     // Argument 2
                             THREAD);
@@ -1056,8 +1070,8 @@
   JavaCalls::call_special(&result,
                          thread_group,
                          group,
-                         vmSymbolHandles::add_method_name(),
-                         vmSymbolHandles::thread_void_signature(),
+                         vmSymbols::add_method_name(),
+                         vmSymbols::thread_void_signature(),
                          threadObj,          // Arg 1
                          THREAD);
 
@@ -1496,11 +1510,11 @@
   assert(JavaThread::current() == this, "sanity check");
   assert(this->threadObj() != NULL, "just checking");
 
-  // Execute thread entry point. If this thread is being asked to restart,
-  // or has been stopped before starting, do not reexecute entry point.
+  // Execute thread entry point unless this thread has a pending exception
+  // or has been stopped before starting.
   // Note: Due to JVM_StopThread we can have pending exceptions already!
-  if (!this->has_pending_exception() && !java_lang_Thread::is_stillborn(this->threadObj())) {
-    // enter the thread's entry point only if we have no pending exceptions
+  if (!this->has_pending_exception() &&
+      !java_lang_Thread::is_stillborn(this->threadObj())) {
     HandleMark hm(this);
     this->entry_point()(this, this);
   }
@@ -1519,13 +1533,10 @@
   ObjectLocker lock(threadObj, thread);
   // Ignore pending exception (ThreadDeath), since we are exiting anyway
   thread->clear_pending_exception();
-  // It is of profound importance that we set the stillborn bit and reset the thread object,
-  // before we do the notify. Since, changing these two variable will make JVM_IsAlive return
-  // false. So in case another thread is doing a join on this thread , it will detect that the thread
-  // is dead when it gets notified.
-  java_lang_Thread::set_stillborn(threadObj());
   // Thread is exiting. So set thread_status field in  java.lang.Thread class to TERMINATED.
   java_lang_Thread::set_thread_status(threadObj(), java_lang_Thread::TERMINATED);
+  // Clear the native thread instance - this makes isAlive return false and allows the join()
+  // to complete once we've done the notify_all below
   java_lang_Thread::set_thread(threadObj(), NULL);
   lock.notify_all(thread);
   // Ignore pending exception (ThreadDeath), since we are exiting anyway
@@ -1576,8 +1587,8 @@
         CallInfo callinfo;
         KlassHandle thread_klass(THREAD, SystemDictionary::Thread_klass());
         LinkResolver::resolve_virtual_call(callinfo, threadObj, recvrKlass, thread_klass,
-                                           vmSymbolHandles::dispatchUncaughtException_name(),
-                                           vmSymbolHandles::throwable_void_signature(),
+                                           vmSymbols::dispatchUncaughtException_name(),
+                                           vmSymbols::throwable_void_signature(),
                                            KlassHandle(), false, false, THREAD);
         CLEAR_PENDING_EXCEPTION;
         methodHandle method = callinfo.selected_method();
@@ -1585,8 +1596,8 @@
           JavaValue result(T_VOID);
           JavaCalls::call_virtual(&result,
                                   threadObj, thread_klass,
-                                  vmSymbolHandles::dispatchUncaughtException_name(),
-                                  vmSymbolHandles::throwable_void_signature(),
+                                  vmSymbols::dispatchUncaughtException_name(),
+                                  vmSymbols::throwable_void_signature(),
                                   uncaught_exception,
                                   THREAD);
         } else {
@@ -1594,8 +1605,8 @@
           JavaValue result(T_VOID);
           JavaCalls::call_virtual(&result,
                                   group, thread_group,
-                                  vmSymbolHandles::uncaughtException_name(),
-                                  vmSymbolHandles::thread_throwable_void_signature(),
+                                  vmSymbols::uncaughtException_name(),
+                                  vmSymbols::thread_throwable_void_signature(),
                                   threadObj,           // Arg 1
                                   uncaught_exception,  // Arg 2
                                   THREAD);
@@ -1614,8 +1625,8 @@
         KlassHandle thread_klass(THREAD, SystemDictionary::Thread_klass());
         JavaCalls::call_virtual(&result,
                               threadObj, thread_klass,
-                              vmSymbolHandles::exit_method_name(),
-                              vmSymbolHandles::void_method_signature(),
+                              vmSymbols::exit_method_name(),
+                              vmSymbols::void_method_signature(),
                               THREAD);
         CLEAR_PENDING_EXCEPTION;
       }
@@ -1699,7 +1710,7 @@
     tlab().make_parsable(true);  // retire TLAB
   }
 
-  if (jvmti_thread_state() != NULL) {
+  if (JvmtiEnv::environments_might_exist()) {
     JvmtiExport::cleanup_thread(this);
   }
 
@@ -1984,11 +1995,6 @@
   // (tw) May we do this?
   //if (is_Compiler_thread()) return;
 
-  // This is a change from JDK 1.1, but JDK 1.2 will also do it:
-  if (java_throwable->is_a(SystemDictionary::ThreadDeath_klass())) {
-    java_lang_Thread::set_stillborn(threadObj());
-  }
-
   {
     // Actually throw the Throwable against the target Thread - however
     // only if there is no thread death exception installed already.
@@ -3150,7 +3156,7 @@
     }
 
     if (InitializeJavaLangString) {
-      initialize_class(vmSymbolHandles::java_lang_String(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_String(), CHECK_0);
     } else {
       warning("java.lang.String not initialized");
     }
@@ -3160,10 +3166,10 @@
         // 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);
+        klassOop tmp_k = SystemDictionary::find(vmSymbols::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);
+        klassOop k_o = SystemDictionary::resolve_or_null(vmSymbols::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());
@@ -3178,7 +3184,7 @@
       if (UseStringCache) {
         // Forcibly initialize java/lang/StringValue and mutate the private
         // static final "stringCacheEnabled" field before we start creating instances
-        klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_StringValue(), Handle(), Handle(), CHECK_0);
+        klassOop k_o = SystemDictionary::resolve_or_null(vmSymbols::java_lang_StringValue(), Handle(), Handle(), CHECK_0);
         // Possible that StringValue isn't present: if so, silently don't break
         if (k_o != NULL) {
           KlassHandle k = KlassHandle(THREAD, k_o);
@@ -3195,11 +3201,11 @@
 
     // Initialize java_lang.System (needed before creating the thread)
     if (InitializeJavaLangSystem) {
-      initialize_class(vmSymbolHandles::java_lang_System(), CHECK_0);
-      initialize_class(vmSymbolHandles::java_lang_ThreadGroup(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_System(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_ThreadGroup(), CHECK_0);
       Handle thread_group = create_initial_thread_group(CHECK_0);
       Universe::set_main_thread_group(thread_group());
-      initialize_class(vmSymbolHandles::java_lang_Thread(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_Thread(), CHECK_0);
       oop thread_object = create_initial_thread(thread_group, main_thread, CHECK_0);
       main_thread->set_threadObj(thread_object);
       // Set thread status to running since main thread has
@@ -3208,10 +3214,10 @@
                                           java_lang_Thread::RUNNABLE);
 
       // The VM preresolve methods to these classes. Make sure that get initialized
-      initialize_class(vmSymbolHandles::java_lang_reflect_Method(), CHECK_0);
-      initialize_class(vmSymbolHandles::java_lang_ref_Finalizer(),  CHECK_0);
+      initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_ref_Finalizer(),  CHECK_0);
       // The VM creates & returns objects of this class. Make sure it's initialized.
-      initialize_class(vmSymbolHandles::java_lang_Class(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_Class(), CHECK_0);
       call_initializeSystemClass(CHECK_0);
     } else {
       warning("java.lang.System not initialized");
@@ -3219,13 +3225,13 @@
 
     // an instance of OutOfMemory exception has been allocated earlier
     if (InitializeJavaLangExceptionsErrors) {
-      initialize_class(vmSymbolHandles::java_lang_OutOfMemoryError(), CHECK_0);
-      initialize_class(vmSymbolHandles::java_lang_NullPointerException(), CHECK_0);
-      initialize_class(vmSymbolHandles::java_lang_ClassCastException(), CHECK_0);
-      initialize_class(vmSymbolHandles::java_lang_ArrayStoreException(), CHECK_0);
-      initialize_class(vmSymbolHandles::java_lang_ArithmeticException(), CHECK_0);
-      initialize_class(vmSymbolHandles::java_lang_StackOverflowError(), CHECK_0);
-      initialize_class(vmSymbolHandles::java_lang_IllegalMonitorStateException(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_OutOfMemoryError(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_NullPointerException(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_ClassCastException(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_ArrayStoreException(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_ArithmeticException(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_StackOverflowError(), CHECK_0);
+      initialize_class(vmSymbols::java_lang_IllegalMonitorStateException(), CHECK_0);
     } else {
       warning("java.lang.OutOfMemoryError has not been initialized");
       warning("java.lang.NullPointerException has not been initialized");
@@ -3251,7 +3257,7 @@
   // Future Fix : the best fix is to grant everyone permissions to read "java.compiler" and
   //              read and write"java.vm.info" in the default policy file. See bugid 4211383
   //              Once that is done, we should remove this hack.
-  initialize_class(vmSymbolHandles::java_lang_Compiler(), CHECK_0);
+  initialize_class(vmSymbols::java_lang_Compiler(), CHECK_0);
 
   // More hackery - the static initializer of java.lang.Compiler adds the string "nojit" to
   // the java.vm.info property if no jit gets loaded through java.lang.Compiler (the hotspot
@@ -3348,6 +3354,14 @@
 
   BiasedLocking::init();
 
+  if (JDK_Version::current().post_vm_init_hook_enabled()) {
+    call_postVMInitHook(THREAD);
+    // The Java side of PostVMInitHook.run must deal with all
+    // exceptions and provide means of diagnosis.
+    if (HAS_PENDING_EXCEPTION) {
+      CLEAR_PENDING_EXCEPTION;
+    }
+  }
 
   // Start up the WatcherThread if there are any periodic tasks
   // NOTE:  All PeriodicTasks should be registered by now. If they
@@ -3569,7 +3583,7 @@
 
   EXCEPTION_MARK;
   klassOop k =
-    SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_Shutdown(),
+    SystemDictionary::resolve_or_null(vmSymbols::java_lang_Shutdown(),
                                       THREAD);
   if (k != NULL) {
     // SystemDictionary::resolve_or_null will return null if there was
@@ -3583,8 +3597,8 @@
     JavaValue result(T_VOID);
     JavaCalls::call_static(&result,
                            shutdown_klass,
-                           vmSymbolHandles::shutdown_method_name(),
-                           vmSymbolHandles::void_method_signature(),
+                           vmSymbols::shutdown_method_name(),
+                           vmSymbols::void_method_signature(),
                            THREAD);
   }
   CLEAR_PENDING_EXCEPTION;
--- a/src/share/vm/runtime/thread.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/thread.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -809,7 +809,7 @@
   //
   // _vm_exited is a special value to cover the case of a JavaThread
   // executing native code after the VM itself is terminated.
-  TerminatedTypes       _terminated;
+  volatile TerminatedTypes _terminated;
   // suspend/resume support
   volatile bool         _suspend_equivalent;     // Suspend equivalent condition
   jint                  _in_deopt_handler;       // count of deoptimization
--- a/src/share/vm/runtime/vframe.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/vframe.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -552,7 +552,7 @@
   tty->print("%s.%s", Klass::cast(k)->internal_name(), m->name()->as_C_string());
 
   if (!m->is_native()) {
-    symbolOop  source_name = instanceKlass::cast(k)->source_file_name();
+    Symbol*  source_name = instanceKlass::cast(k)->source_file_name();
     int        line_number = m->line_number_from_bci(bci());
     if (source_name != NULL && (line_number != -1)) {
       tty->print("(%s:%d)", source_name->as_C_string(), line_number);
--- a/src/share/vm/runtime/vframeArray.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/vframeArray.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -431,7 +431,7 @@
   } else if (TraceDeoptimization) {
     tty->print("     ");
     method()->print_value();
-    Bytecodes::Code code = Bytecodes::java_code_at(bcp);
+    Bytecodes::Code code = Bytecodes::java_code_at(method(), bcp);
     int bci = method()->bci_from(bcp);
     tty->print(" - %s", Bytecodes::name(code));
     tty->print(" @ bci %d ", bci);
--- a/src/share/vm/runtime/vmStructs.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -83,8 +83,7 @@
 #include "oops/objArrayKlassKlass.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
-#include "oops/symbolKlass.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "oops/typeArrayKlassKlass.hpp"
 #include "oops/typeArrayOop.hpp"
@@ -219,8 +218,8 @@
   volatile_nonstatic_field(oopDesc,            _metadata._compressed_klass,                   narrowOop)                             \
      static_field(oopDesc,                     _bs,                                           BarrierSet*)                           \
   nonstatic_field(arrayKlass,                  _dimension,                                    int)                                   \
-  nonstatic_field(arrayKlass,                  _higher_dimension,                             klassOop)                              \
-  nonstatic_field(arrayKlass,                  _lower_dimension,                              klassOop)                              \
+  volatile_nonstatic_field(arrayKlass,         _higher_dimension,                             klassOop)                              \
+  volatile_nonstatic_field(arrayKlass,         _lower_dimension,                              klassOop)                              \
   nonstatic_field(arrayKlass,                  _vtable_len,                                   int)                                   \
   nonstatic_field(arrayKlass,                  _alloc_size,                                   juint)                                 \
   nonstatic_field(arrayKlass,                  _component_mirror,                             oop)                                   \
@@ -246,8 +245,8 @@
   nonstatic_field(instanceKlass,               _class_loader,                                 oop)                                   \
   nonstatic_field(instanceKlass,               _protection_domain,                            oop)                                   \
   nonstatic_field(instanceKlass,               _signers,                                      objArrayOop)                           \
-  nonstatic_field(instanceKlass,               _source_file_name,                             symbolOop)                             \
-  nonstatic_field(instanceKlass,               _source_debug_extension,                       symbolOop)                             \
+  nonstatic_field(instanceKlass,               _source_file_name,                             Symbol*)                               \
+  nonstatic_field(instanceKlass,               _source_debug_extension,                       Symbol*)                               \
   nonstatic_field(instanceKlass,               _inner_classes,                                typeArrayOop)                          \
   nonstatic_field(instanceKlass,               _nonstatic_field_size,                         int)                                   \
   nonstatic_field(instanceKlass,               _static_field_size,                            int)                                   \
@@ -265,7 +264,7 @@
   nonstatic_field(instanceKlass,               _jni_ids,                                      JNIid*)                                \
   nonstatic_field(instanceKlass,               _osr_nmethods_head,                            nmethod*)                              \
   nonstatic_field(instanceKlass,               _breakpoints,                                  BreakpointInfo*)                       \
-  nonstatic_field(instanceKlass,               _generic_signature,                            symbolOop)                             \
+  nonstatic_field(instanceKlass,               _generic_signature,                            Symbol*)                               \
   nonstatic_field(instanceKlass,               _methods_jmethod_ids,                          jmethodID*)                            \
   nonstatic_field(instanceKlass,               _methods_cached_itable_indices,                int*)                                  \
   volatile_nonstatic_field(instanceKlass,      _idnum_allocated_count,                        u2)                                    \
@@ -282,7 +281,7 @@
   nonstatic_field(Klass,                       _modifier_flags,                               jint)                                  \
   nonstatic_field(Klass,                       _super,                                        klassOop)                              \
   nonstatic_field(Klass,                       _layout_helper,                                jint)                                  \
-  nonstatic_field(Klass,                       _name,                                         symbolOop)                             \
+  nonstatic_field(Klass,                       _name,                                         Symbol*)                               \
   nonstatic_field(Klass,                       _access_flags,                                 AccessFlags)                           \
   nonstatic_field(Klass,                       _subklass,                                     klassOop)                              \
   nonstatic_field(Klass,                       _next_sibling,                                 klassOop)                              \
@@ -326,9 +325,10 @@
   nonstatic_field(constMethodOopDesc,          _generic_signature_index,                      u2)                                    \
   nonstatic_field(objArrayKlass,               _element_klass,                                klassOop)                              \
   nonstatic_field(objArrayKlass,               _bottom_klass,                                 klassOop)                              \
-  nonstatic_field(symbolKlass,                 _alloc_size,                                   juint)                                 \
-  nonstatic_field(symbolOopDesc,               _length,                                       unsigned short)                        \
-  unchecked_nonstatic_field(symbolOopDesc,     _body,                                         sizeof(jbyte)) /* NOTE: no type */     \
+  volatile_nonstatic_field(Symbol,             _refcount,                                     int)                                   \
+  nonstatic_field(Symbol,                      _identity_hash,                                int)                                   \
+  nonstatic_field(Symbol,                      _length,                                       unsigned short)                        \
+  unchecked_nonstatic_field(Symbol,            _body,                                         sizeof(jbyte)) /* NOTE: no type */     \
   nonstatic_field(typeArrayKlass,              _max_length,                                   int)                                   \
                                                                                                                                      \
   /***********************/                                                                                                          \
@@ -375,7 +375,6 @@
      static_field(Universe,                    _longArrayKlassObj,                            klassOop)                              \
      static_field(Universe,                    _singleArrayKlassObj,                          klassOop)                              \
      static_field(Universe,                    _doubleArrayKlassObj,                          klassOop)                              \
-     static_field(Universe,                    _symbolKlassObj,                               klassOop)                              \
      static_field(Universe,                    _methodKlassObj,                               klassOop)                              \
      static_field(Universe,                    _constMethodKlassObj,                          klassOop)                              \
      static_field(Universe,                    _methodDataKlassObj,                           klassOop)                              \
@@ -648,7 +647,7 @@
                                                                                                                                      \
   nonstatic_field(BasicHashtableEntry,         _next,                                         BasicHashtableEntry*)                  \
   nonstatic_field(BasicHashtableEntry,         _hash,                                         unsigned int)                          \
-  nonstatic_field(HashtableEntry,              _literal,                                      oop)                                   \
+  nonstatic_field(HashtableEntry<intptr_t>,    _literal,                                      intptr_t) \
                                                                                                                                      \
   /*************/                                                                                                                    \
   /* Hashtable */                                                                                                                    \
@@ -683,7 +682,7 @@
   /* LoaderConstraintEntry */                                                                                                        \
   /*************************/                                                                                                        \
                                                                                                                                      \
-  nonstatic_field(LoaderConstraintEntry,       _name,                                         symbolOop)                             \
+  nonstatic_field(LoaderConstraintEntry,       _name,                                         Symbol*)                               \
   nonstatic_field(LoaderConstraintEntry,       _num_loaders,                                  int)                                   \
   nonstatic_field(LoaderConstraintEntry,       _max_loaders,                                  int)                                   \
   nonstatic_field(LoaderConstraintEntry,       _loaders,                                      oop*)                                  \
@@ -1088,11 +1087,11 @@
            declare_type(objArrayKlassKlass, arrayKlassKlass)              \
            declare_type(objArrayOopDesc, arrayOopDesc)                    \
            declare_type(constMethodOopDesc, oopDesc)                      \
-           declare_type(symbolKlass, Klass)                               \
-           declare_type(symbolOopDesc, oopDesc)                           \
            declare_type(typeArrayKlass, arrayKlass)                       \
            declare_type(typeArrayKlassKlass, arrayKlassKlass)             \
            declare_type(typeArrayOopDesc, arrayOopDesc)                   \
+           declare_toplevel_type(Symbol)                                  \
+           declare_toplevel_type(Symbol*)                                 \
                                                                           \
   /********/                                                              \
   /* Oops */                                                              \
@@ -1109,7 +1108,6 @@
   declare_oop_type(narrowOop)                                             \
   declare_oop_type(wideKlassOop)                                          \
   declare_oop_type(constMethodOop)                                        \
-  declare_oop_type(symbolOop)                                             \
   declare_oop_type(typeArrayOop)                                          \
                                                                           \
   /*************************************/                                 \
@@ -1207,33 +1205,21 @@
   /*********************************/                                     \
                                                                           \
   declare_toplevel_type(BasicHashtable)                                   \
-    declare_type(Hashtable, BasicHashtable)                               \
-    declare_type(SymbolTable, Hashtable)                                  \
-    declare_type(StringTable, Hashtable)                                  \
-    declare_type(LoaderConstraintTable, Hashtable)                        \
-    declare_type(TwoOopHashtable, Hashtable)                              \
-    declare_type(Dictionary, TwoOopHashtable)                             \
-    declare_type(PlaceholderTable, TwoOopHashtable)                       \
-  declare_toplevel_type(Hashtable*)                                       \
-  declare_toplevel_type(SymbolTable*)                                     \
-  declare_toplevel_type(StringTable*)                                     \
-  declare_toplevel_type(LoaderConstraintTable*)                           \
-  declare_toplevel_type(TwoOopHashtable*)                                 \
-  declare_toplevel_type(Dictionary*)                                      \
-  declare_toplevel_type(PlaceholderTable*)                                \
+    declare_type(Hashtable<intptr_t>, BasicHashtable)                     \
+  declare_type(SymbolTable, Hashtable<Symbol*>)                           \
+  declare_type(StringTable, Hashtable<oop>)                               \
+    declare_type(LoaderConstraintTable, Hashtable<klassOop>)              \
+    declare_type(TwoOopHashtable<klassOop>, Hashtable<klassOop>)          \
+    declare_type(Dictionary, TwoOopHashtable<klassOop>)                   \
+    declare_type(PlaceholderTable, TwoOopHashtable<Symbol*>)              \
   declare_toplevel_type(BasicHashtableEntry)                              \
-  declare_toplevel_type(BasicHashtableEntry*)                             \
-    declare_type(HashtableEntry, BasicHashtableEntry)                     \
-    declare_type(DictionaryEntry, HashtableEntry)                         \
-    declare_type(PlaceholderEntry, HashtableEntry)                        \
-    declare_type(LoaderConstraintEntry, HashtableEntry)                   \
-  declare_toplevel_type(HashtableEntry*)                                  \
-  declare_toplevel_type(DictionaryEntry*)                                 \
+  declare_type(HashtableEntry<intptr_t>, BasicHashtableEntry)             \
+    declare_type(DictionaryEntry, HashtableEntry<klassOop>)               \
+    declare_type(PlaceholderEntry, HashtableEntry<Symbol*>)               \
+    declare_type(LoaderConstraintEntry, HashtableEntry<klassOop>)         \
   declare_toplevel_type(HashtableBucket)                                  \
-  declare_toplevel_type(HashtableBucket*)                                 \
   declare_toplevel_type(SystemDictionary)                                 \
   declare_toplevel_type(ProtectionDomainEntry)                            \
-  declare_toplevel_type(ProtectionDomainEntry*)                           \
                                                                           \
   /***********************************************************/           \
   /* Thread hierarchy (needed for run-time type information) */           \
@@ -1667,10 +1653,10 @@
   declare_constant(instanceKlass::initialization_error)                   \
                                                                           \
   /*********************************/                                     \
-  /* symbolOop - symbol max length */                                     \
+  /* Symbol* - symbol max length */                                     \
   /*********************************/                                     \
                                                                           \
-  declare_constant(symbolOopDesc::max_symbol_length)                      \
+  declare_constant(Symbol::max_symbol_length)                             \
                                                                           \
   /*************************************************/                     \
   /* constantPoolOop layout enum for InvokeDynamic */                     \
@@ -2431,17 +2417,69 @@
 }
 
 #ifdef ASSERT
+static int recursiveFindType(VMTypeEntry* origtypes, const char* typeName, bool isRecurse) {
+  {
+    VMTypeEntry* types = origtypes;
+    while (types->typeName != NULL) {
+      if (!strcmp(typeName, types->typeName)) {
+        return 1;
+      }
+      ++types;
+    }
+  }
+  size_t len = strlen(typeName);
+  if (typeName[len-1] == '*') {
+    char * s = new char[len];
+    strncpy(s, typeName, len - 1);
+    s[len-1] = '\0';
+    // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName);
+    if (recursiveFindType(origtypes, s, true) == 1) {
+      delete s;
+      return 1;
+    }
+    delete s;
+  }
+  if (strstr(typeName, "GrowableArray<") == typeName) {
+    const char * start = typeName + strlen("GrowableArray<");
+    const char * end = strrchr(typeName, '>');
+    int len = end - start + 1;
+    char * s = new char[len];
+    strncpy(s, start, len - 1);
+    s[len-1] = '\0';
+    // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName);
+    if (recursiveFindType(origtypes, s, true) == 1) {
+      delete s;
+      return 1;
+    }
+    delete s;
+  }
+  if (strstr(typeName, "const ") == typeName) {
+    const char * s = typeName + strlen("const ");
+    // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName);
+    if (recursiveFindType(origtypes, s, true) == 1) {
+      return 1;
+    }
+  }
+  if (strstr(typeName, " const") == typeName + len - 6) {
+    char * s = strdup(typeName);
+    s[len - 6] = '\0';
+    // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName);
+    if (recursiveFindType(origtypes, s, true) == 1) {
+      return 1;
+    }
+  }
+  if (!isRecurse) {
+    tty->print_cr("type \"%s\" not found", typeName);
+  }
+  return 2;
+}
+
+
 int
 VMStructs::findType(const char* typeName) {
   VMTypeEntry* types = gHotSpotVMTypes;
 
-  while (types->typeName != NULL) {
-    if (!strcmp(typeName, types->typeName)) {
-      return 1;
-    }
-    ++types;
-  }
-  return 0;
+  return recursiveFindType(types, typeName, false);
 }
 #endif
 
--- a/src/share/vm/runtime/vmStructs.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/vmStructs.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -68,7 +68,7 @@
 typedef struct {
   const char* typeName;            // The type name containing the given field (example: "Klass")
   const char* fieldName;           // The field name within the type           (example: "_name")
-  const char* typeString;          // Quoted name of the type of this field (example: "symbolOopDesc*";
+  const char* typeString;          // Quoted name of the type of this field (example: "Symbol*";
                                    // parsed in Java to ensure type correctness
   int32_t  isStatic;               // Indicates whether following field is an offset or an address
   uint64_t offset;                 // Offset of field within structure; only used for nonstatic fields
--- a/src/share/vm/runtime/vm_operations.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/vm_operations.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -23,11 +23,13 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/symbolTable.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/compilerOracle.hpp"
 #include "gc_implementation/shared/isGCActiveMark.hpp"
 #include "memory/resourceArea.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/interfaceSupport.hpp"
@@ -170,6 +172,12 @@
 
 #endif // !PRODUCT
 
+void VM_UnlinkSymbols::doit() {
+  JavaThread *thread = (JavaThread *)calling_thread();
+  assert(thread->is_Java_thread(), "must be a Java thread");
+  SymbolTable::unlink();
+}
+
 void VM_HandleFullCodeCache::doit() {
   NMethodSweeper::speculative_disconnect_nmethods(_is_full);
 }
--- a/src/share/vm/runtime/vm_operations.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/runtime/vm_operations.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -50,6 +50,7 @@
   template(DeoptimizeFrame)                       \
   template(DeoptimizeAll)                         \
   template(ZombieAll)                             \
+  template(UnlinkSymbols)                         \
   template(HandleFullCodeCache)                   \
   template(Verify)                                \
   template(PrintJNI)                              \
@@ -288,6 +289,14 @@
 };
 #endif // PRODUCT
 
+class VM_UnlinkSymbols: public VM_Operation {
+ public:
+  VM_UnlinkSymbols() {}
+  VMOp_Type type() const                         { return VMOp_UnlinkSymbols; }
+  void doit();
+  bool allow_nested_vm_operations() const        { return true; }
+};
+
 class VM_Verify: public VM_Operation {
  private:
   KlassHandle _dependee;
--- a/src/share/vm/services/attachListener.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/attachListener.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -43,7 +43,7 @@
 // Invokes sun.misc.VMSupport.serializePropertiesToByteArray to serialize
 // the system properties into a byte array.
 
-static klassOop load_and_initialize_klass(symbolHandle sh, TRAPS) {
+static klassOop load_and_initialize_klass(Symbol* sh, TRAPS) {
   klassOop k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL);
   instanceKlassHandle ik (THREAD, k);
   if (ik->should_be_initialized()) {
@@ -52,12 +52,12 @@
   return ik();
 }
 
-static jint get_properties(AttachOperation* op, outputStream* out, symbolHandle serializePropertiesMethod) {
+static jint get_properties(AttachOperation* op, outputStream* out, Symbol* serializePropertiesMethod) {
   Thread* THREAD = Thread::current();
   HandleMark hm;
 
   // load sun.misc.VMSupport
-  symbolHandle klass = vmSymbolHandles::sun_misc_VMSupport();
+  Symbol* klass = vmSymbols::sun_misc_VMSupport();
   klassOop k = load_and_initialize_klass(klass, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     java_lang_Throwable::print(PENDING_EXCEPTION, out);
@@ -71,7 +71,7 @@
   JavaCallArguments args;
 
 
-  symbolHandle signature = vmSymbolHandles::serializePropertiesToByteArray_signature();
+  Symbol* signature = vmSymbols::serializePropertiesToByteArray_signature();
   JavaCalls::call_static(&result,
                            ik,
                            serializePropertiesMethod,
@@ -99,12 +99,12 @@
 
 // Implementation of "properties" command.
 static jint get_system_properties(AttachOperation* op, outputStream* out) {
-  return get_properties(op, out, vmSymbolHandles::serializePropertiesToByteArray_name());
+  return get_properties(op, out, vmSymbols::serializePropertiesToByteArray_name());
 }
 
 // Implementation of "agent_properties" command.
 static jint get_agent_properties(AttachOperation* op, outputStream* out) {
-  return get_properties(op, out, vmSymbolHandles::serializeAgentPropertiesToByteArray_name());
+  return get_properties(op, out, vmSymbols::serializeAgentPropertiesToByteArray_name());
 }
 
 // Implementation of "datadump" command.
@@ -430,7 +430,7 @@
 // Starts the Attach Listener thread
 void AttachListener::init() {
   EXCEPTION_MARK;
-  klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(), true, CHECK);
+  klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK);
   instanceKlassHandle klass (THREAD, k);
   instanceHandle thread_oop = klass->allocate_instance_handle(CHECK);
 
@@ -442,8 +442,8 @@
   JavaValue result(T_VOID);
   JavaCalls::call_special(&result, thread_oop,
                        klass,
-                       vmSymbolHandles::object_initializer_name(),
-                       vmSymbolHandles::threadgroup_string_void_signature(),
+                       vmSymbols::object_initializer_name(),
+                       vmSymbols::threadgroup_string_void_signature(),
                        thread_group,
                        string,
                        CHECK);
@@ -452,8 +452,8 @@
   JavaCalls::call_special(&result,
                         thread_group,
                         group,
-                        vmSymbolHandles::add_method_name(),
-                        vmSymbolHandles::thread_void_signature(),
+                        vmSymbols::add_method_name(),
+                        vmSymbols::thread_void_signature(),
                         thread_oop,             // ARG 1
                         CHECK);
 
--- a/src/share/vm/services/classLoadingService.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/classLoadingService.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -43,7 +43,7 @@
   {                                                 \
     char* data = NULL;                              \
     int len = 0;                                    \
-    symbolOop name = (clss)->name();                \
+    Symbol* name = (clss)->name();                  \
     if (name != NULL) {                             \
       data = (char*)name->bytes();                  \
       len = name->utf8_length();                    \
--- a/src/share/vm/services/heapDumper.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/heapDumper.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -425,6 +425,7 @@
   void write_u4(u4 x);
   void write_u8(u8 x);
   void write_objectID(oop o);
+  void write_symbolID(Symbol* o);
   void write_classID(Klass* k);
   void write_id(u4 x);
 };
@@ -453,7 +454,7 @@
 
 DumpWriter::~DumpWriter() {
   // flush and close dump file
-  if (file_descriptor() >= 0) {
+  if (is_open()) {
     close();
   }
   if (_buffer != NULL) os::free(_buffer);
@@ -463,9 +464,10 @@
 // closes dump file (if open)
 void DumpWriter::close() {
   // flush and close dump file
-  if (file_descriptor() >= 0) {
+  if (is_open()) {
     flush();
     ::close(file_descriptor());
+    set_file_descriptor(-1);
   }
 }
 
@@ -567,6 +569,15 @@
 #endif
 }
 
+void DumpWriter::write_symbolID(Symbol* s) {
+  address a = (address)((uintptr_t)s);
+#ifdef _LP64
+  write_u8((u8)a);
+#else
+  write_u4((u4)a);
+#endif
+}
+
 void DumpWriter::write_id(u4 x) {
 #ifdef _LP64
   write_u8((u8) x);
@@ -591,7 +602,7 @@
   static void write_header(DumpWriter* writer, hprofTag tag, u4 len);
 
   // returns hprof tag for the given type signature
-  static hprofTag sig2tag(symbolOop sig);
+  static hprofTag sig2tag(Symbol* sig);
   // returns hprof tag for the given basic type
   static hprofTag type2tag(BasicType type);
 
@@ -635,7 +646,7 @@
 }
 
 // returns hprof tag for the given type signature
-hprofTag DumperSupport::sig2tag(symbolOop sig) {
+hprofTag DumperSupport::sig2tag(Symbol* sig) {
   switch (sig->byte_at(0)) {
     case JVM_SIGNATURE_CLASS    : return HPROF_NORMAL_OBJECT;
     case JVM_SIGNATURE_ARRAY    : return HPROF_NORMAL_OBJECT;
@@ -774,7 +785,7 @@
 
   for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) {
     if (!fld.access_flags().is_static()) {
-      symbolOop sig = fld.signature();
+      Symbol* sig = fld.signature();
       switch (sig->byte_at(0)) {
         case JVM_SIGNATURE_CLASS   :
         case JVM_SIGNATURE_ARRAY   : size += oopSize; break;
@@ -814,9 +825,9 @@
   // pass 2 - dump the field descriptors and raw values
   for (FieldStream fld(ikh, true, true); !fld.eos(); fld.next()) {
     if (fld.access_flags().is_static()) {
-      symbolOop sig = fld.signature();
+      Symbol* sig = fld.signature();
 
-      writer->write_objectID(fld.name());   // name
+      writer->write_symbolID(fld.name());   // name
       writer->write_u1(sig2tag(sig));       // type
 
       // value
@@ -835,7 +846,7 @@
 
   for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) {
     if (!fld.access_flags().is_static()) {
-      symbolOop sig = fld.signature();
+      Symbol* sig = fld.signature();
       address addr = (address)o + fld.offset();
 
       dump_field_value(writer, sig->byte_at(0), addr);
@@ -859,9 +870,9 @@
   // pass 2 - dump the field descriptors
   for (FieldStream fld(ikh, true, true); !fld.eos(); fld.next()) {
     if (!fld.access_flags().is_static()) {
-      symbolOop sig = fld.signature();
+      Symbol* sig = fld.signature();
 
-      writer->write_objectID(fld.name());                   // name
+      writer->write_symbolID(fld.name());                   // name
       writer->write_u1(sig2tag(sig));       // type
     }
   }
@@ -1114,42 +1125,40 @@
 
   write_header(writer, HPROF_FRAME, 4*oopSize + 2*sizeof(u4));
   writer->write_id(frame_serial_num);               // frame serial number
-  writer->write_objectID(m->name());                // method's name
-  writer->write_objectID(m->signature());           // method's signature
+  writer->write_symbolID(m->name());                // method's name
+  writer->write_symbolID(m->signature());           // method's signature
 
   assert(Klass::cast(m->method_holder())->oop_is_instance(), "not instanceKlass");
-  writer->write_objectID(instanceKlass::cast(m->method_holder())->source_file_name());  // source file name
+  writer->write_symbolID(instanceKlass::cast(m->method_holder())->source_file_name());  // source file name
   writer->write_u4(class_serial_num);               // class serial number
   writer->write_u4((u4) line_number);               // line number
 }
 
+
 // Support class used to generate HPROF_UTF8 records from the entries in the
 // SymbolTable.
 
-class SymbolTableDumper : public OopClosure {
+class SymbolTableDumper : public SymbolClosure {
  private:
   DumpWriter* _writer;
   DumpWriter* writer() const                { return _writer; }
  public:
   SymbolTableDumper(DumpWriter* writer)     { _writer = writer; }
-  void do_oop(oop* obj_p);
-  void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); }
+  void do_symbol(Symbol** p);
 };
 
-void SymbolTableDumper::do_oop(oop* obj_p) {
+void SymbolTableDumper::do_symbol(Symbol** p) {
   ResourceMark rm;
-  symbolOop sym = (symbolOop)*obj_p;
-
+  Symbol* sym = load_symbol(p);
   int len = sym->utf8_length();
   if (len > 0) {
     char* s = sym->as_utf8();
     DumperSupport::write_header(writer(), HPROF_UTF8, oopSize + len);
-    writer()->write_objectID(sym);
+    writer()->write_symbolID(sym);
     writer()->write_raw(s, len);
   }
 }
 
-
 // Support class used to generate HPROF_GC_ROOT_JNI_LOCAL records
 
 class JNILocalsDumper : public OopClosure {
@@ -1547,8 +1556,8 @@
     writer()->write_u4(STACK_TRACE_ID);
 
     // class name ID
-    symbolOop name = klass->name();
-    writer()->write_objectID(name);
+    Symbol* name = klass->name();
+    writer()->write_symbolID(name);
 
     // write a LOAD_CLASS record for the array type (if it exists)
     k = klass->array_klass_or_null();
@@ -1726,7 +1735,7 @@
 
   // HPROF_UTF8 records
   SymbolTableDumper sym_dumper(writer());
-  SymbolTable::oops_do(&sym_dumper);
+  SymbolTable::symbols_do(&sym_dumper);
 
   // write HPROF_LOAD_CLASS records
   SystemDictionary::classes_do(&do_load_class);
@@ -1935,18 +1944,32 @@
 void HeapDumper::dump_heap(bool oome) {
   static char base_path[JVM_MAXPATHLEN] = {'\0'};
   static uint dump_file_seq = 0;
-  char   my_path[JVM_MAXPATHLEN] = {'\0'};
+  char* my_path;
+  const int max_digit_chars = 20;
+
+  const char* dump_file_name = "java_pid";
+  const char* dump_file_ext  = ".hprof";
 
   // The dump file defaults to java_pid<pid>.hprof in the current working
   // directory. HeapDumpPath=<file> can be used to specify an alternative
   // dump file name or a directory where dump file is created.
   if (dump_file_seq == 0) { // first time in, we initialize base_path
+    // Calculate potentially longest base path and check if we have enough
+    // allocated statically.
+    const size_t total_length =
+                      (HeapDumpPath == NULL ? 0 : strlen(HeapDumpPath)) +
+                      strlen(os::file_separator()) + max_digit_chars +
+                      strlen(dump_file_name) + strlen(dump_file_ext) + 1;
+    if (total_length > sizeof(base_path)) {
+      warning("Cannot create heap dump file.  HeapDumpPath is too long.");
+      return;
+    }
+
     bool use_default_filename = true;
     if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') {
       // HeapDumpPath=<file> not specified
     } else {
-      assert(strlen(HeapDumpPath) < sizeof(base_path), "HeapDumpPath too long");
-      strcpy(base_path, HeapDumpPath);
+      strncpy(base_path, HeapDumpPath, sizeof(base_path));
       // check if the path is a directory (must exist)
       DIR* dir = os::opendir(base_path);
       if (dir == NULL) {
@@ -1960,8 +1983,6 @@
           char* end = base_path;
           end += (strlen(base_path) - fs_len);
           if (strcmp(end, os::file_separator()) != 0) {
-            assert(strlen(base_path) + strlen(os::file_separator()) < sizeof(base_path),
-              "HeapDumpPath too long");
             strcat(base_path, os::file_separator());
           }
         }
@@ -1969,21 +1990,26 @@
     }
     // If HeapDumpPath wasn't a file name then we append the default name
     if (use_default_filename) {
-      char fn[32];
-      sprintf(fn, "java_pid%d", os::current_process_id());
-      assert(strlen(base_path) + strlen(fn) + strlen(".hprof") < sizeof(base_path), "HeapDumpPath too long");
-      strcat(base_path, fn);
-      strcat(base_path, ".hprof");
+      const size_t dlen = strlen(base_path);  // if heap dump dir specified
+      jio_snprintf(&base_path[dlen], sizeof(base_path)-dlen, "%s%d%s",
+                   dump_file_name, os::current_process_id(), dump_file_ext);
     }
-    assert(strlen(base_path) < sizeof(my_path), "Buffer too small");
-    strcpy(my_path, base_path);
+    const size_t len = strlen(base_path) + 1;
+    my_path = (char*)os::malloc(len);
+    if (my_path == NULL) {
+      warning("Cannot create heap dump file.  Out of system memory.");
+      return;
+    }
+    strncpy(my_path, base_path, len);
   } else {
     // Append a sequence number id for dumps following the first
-    char fn[33];
-    sprintf(fn, ".%d", dump_file_seq);
-    assert(strlen(base_path) + strlen(fn) < sizeof(my_path), "HeapDumpPath too long");
-    strcpy(my_path, base_path);
-    strcat(my_path, fn);
+    const size_t len = strlen(base_path) + max_digit_chars + 2; // for '.' and \0
+    my_path = (char*)os::malloc(len);
+    if (my_path == NULL) {
+      warning("Cannot create heap dump file.  Out of system memory.");
+      return;
+    }
+    jio_snprintf(my_path, len, "%s.%d", base_path, dump_file_seq);
   }
   dump_file_seq++;   // increment seq number for next time we dump
 
@@ -1991,4 +2017,5 @@
                     true  /* send to tty */,
                     oome  /* pass along out-of-memory-error flag */);
   dumper.dump(my_path);
+  os::free(my_path);
 }
--- a/src/share/vm/services/lowMemoryDetector.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/lowMemoryDetector.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -52,8 +52,8 @@
   JavaValue result(T_VOID);
   JavaCalls::call_special(&result, thread_oop,
                           klass,
-                          vmSymbolHandles::object_initializer_name(),
-                          vmSymbolHandles::threadgroup_string_void_signature(),
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::threadgroup_string_void_signature(),
                           thread_group,
                           string,
                           CHECK);
@@ -377,8 +377,8 @@
 
     JavaCalls::call_virtual(&result,
                             sensorKlass,
-                            vmSymbolHandles::trigger_name(),
-                            vmSymbolHandles::trigger_method_signature(),
+                            vmSymbols::trigger_name(),
+                            vmSymbols::trigger_method_signature(),
                             &args,
                             CHECK);
   }
@@ -403,8 +403,8 @@
     args.push_int((int) count);
     JavaCalls::call_virtual(&result,
                             sensorKlass,
-                            vmSymbolHandles::clear_name(),
-                            vmSymbolHandles::int_void_signature(),
+                            vmSymbols::clear_name(),
+                            vmSymbols::int_void_signature(),
                             &args,
                             CHECK);
   }
--- a/src/share/vm/services/management.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/management.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -122,7 +122,7 @@
     // Load and initialize the sun.management.Agent class
     // invoke startAgent method to start the management server
     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
-    klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::sun_management_Agent(),
+    klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(),
                                                    loader,
                                                    Handle(),
                                                    true,
@@ -132,8 +132,8 @@
     JavaValue result(T_VOID);
     JavaCalls::call_static(&result,
                            ik,
-                           vmSymbolHandles::startAgent_name(),
-                           vmSymbolHandles::void_method_signature(),
+                           vmSymbols::startAgent_name(),
+                           vmSymbols::void_method_signature(),
                            CHECK);
   }
 }
@@ -142,7 +142,7 @@
   memcpy(support, &_optional_support, sizeof(jmmOptionalSupport));
 }
 
-klassOop Management::load_and_initialize_klass(symbolHandle sh, TRAPS) {
+klassOop Management::load_and_initialize_klass(Symbol* sh, TRAPS) {
   klassOop k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL);
   instanceKlassHandle ik (THREAD, k);
   if (ik->should_be_initialized()) {
@@ -182,49 +182,49 @@
 
 klassOop Management::java_lang_management_ThreadInfo_klass(TRAPS) {
   if (_threadInfo_klass == NULL) {
-    _threadInfo_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_ThreadInfo(), CHECK_NULL);
+    _threadInfo_klass = load_and_initialize_klass(vmSymbols::java_lang_management_ThreadInfo(), CHECK_NULL);
   }
   return _threadInfo_klass;
 }
 
 klassOop Management::java_lang_management_MemoryUsage_klass(TRAPS) {
   if (_memoryUsage_klass == NULL) {
-    _memoryUsage_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_MemoryUsage(), CHECK_NULL);
+    _memoryUsage_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryUsage(), CHECK_NULL);
   }
   return _memoryUsage_klass;
 }
 
 klassOop Management::java_lang_management_MemoryPoolMXBean_klass(TRAPS) {
   if (_memoryPoolMXBean_klass == NULL) {
-    _memoryPoolMXBean_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_MemoryPoolMXBean(), CHECK_NULL);
+    _memoryPoolMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryPoolMXBean(), CHECK_NULL);
   }
   return _memoryPoolMXBean_klass;
 }
 
 klassOop Management::java_lang_management_MemoryManagerMXBean_klass(TRAPS) {
   if (_memoryManagerMXBean_klass == NULL) {
-    _memoryManagerMXBean_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_MemoryManagerMXBean(), CHECK_NULL);
+    _memoryManagerMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_MemoryManagerMXBean(), CHECK_NULL);
   }
   return _memoryManagerMXBean_klass;
 }
 
 klassOop Management::java_lang_management_GarbageCollectorMXBean_klass(TRAPS) {
   if (_garbageCollectorMXBean_klass == NULL) {
-      _garbageCollectorMXBean_klass = load_and_initialize_klass(vmSymbolHandles::java_lang_management_GarbageCollectorMXBean(), CHECK_NULL);
+      _garbageCollectorMXBean_klass = load_and_initialize_klass(vmSymbols::java_lang_management_GarbageCollectorMXBean(), CHECK_NULL);
   }
   return _garbageCollectorMXBean_klass;
 }
 
 klassOop Management::sun_management_Sensor_klass(TRAPS) {
   if (_sensor_klass == NULL) {
-    _sensor_klass = load_and_initialize_klass(vmSymbolHandles::sun_management_Sensor(), CHECK_NULL);
+    _sensor_klass = load_and_initialize_klass(vmSymbols::sun_management_Sensor(), CHECK_NULL);
   }
   return _sensor_klass;
 }
 
 klassOop Management::sun_management_ManagementFactory_klass(TRAPS) {
   if (_managementFactory_klass == NULL) {
-    _managementFactory_klass = load_and_initialize_klass(vmSymbolHandles::sun_management_ManagementFactory(), CHECK_NULL);
+    _managementFactory_klass = load_and_initialize_klass(vmSymbols::sun_management_ManagementFactory(), CHECK_NULL);
   }
   return _managementFactory_klass;
 }
@@ -290,8 +290,8 @@
   // Call ThreadInfo constructor with no locked monitors and synchronizers
   JavaCalls::call_special(&result,
                           ik,
-                          vmSymbolHandles::object_initializer_name(),
-                          vmSymbolHandles::java_lang_management_ThreadInfo_constructor_signature(),
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::java_lang_management_ThreadInfo_constructor_signature(),
                           &args,
                           CHECK_NULL);
 
@@ -325,8 +325,8 @@
   // Call ThreadInfo constructor with locked monitors and synchronizers
   JavaCalls::call_special(&result,
                           ik,
-                          vmSymbolHandles::object_initializer_name(),
-                          vmSymbolHandles::java_lang_management_ThreadInfo_with_locks_constructor_signature(),
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::java_lang_management_ThreadInfo_with_locks_constructor_signature(),
                           &args,
                           CHECK_NULL);
 
--- a/src/share/vm/services/management.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/management.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -50,7 +50,7 @@
   static klassOop           _garbageCollectorMXBean_klass;
   static klassOop           _managementFactory_klass;
 
-  static klassOop load_and_initialize_klass(symbolHandle sh, TRAPS);
+  static klassOop load_and_initialize_klass(Symbol* sh, TRAPS);
 
 public:
   static void init();
--- a/src/share/vm/services/memoryManager.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/memoryManager.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -106,15 +106,15 @@
     JavaCallArguments args;
     args.push_oop(mgr_name);    // Argument 1
 
-    symbolHandle method_name;
-    symbolHandle signature;
+    Symbol* method_name = NULL;
+    Symbol* signature = NULL;
     if (is_gc_memory_manager()) {
-      method_name = vmSymbolHandles::createGarbageCollector_name();
-      signature = vmSymbolHandles::createGarbageCollector_signature();
+      method_name = vmSymbols::createGarbageCollector_name();
+      signature = vmSymbols::createGarbageCollector_signature();
       args.push_oop(Handle());      // Argument 2 (for future extension)
     } else {
-      method_name = vmSymbolHandles::createMemoryManager_name();
-      signature = vmSymbolHandles::createMemoryManager_signature();
+      method_name = vmSymbols::createMemoryManager_name();
+      signature = vmSymbols::createMemoryManager_signature();
     }
 
     JavaCalls::call_static(&result,
--- a/src/share/vm/services/memoryPool.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/memoryPool.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -89,8 +89,8 @@
     args.push_oop(pool_name);           // Argument 1
     args.push_int((int) is_heap());     // Argument 2
 
-    symbolHandle method_name = vmSymbolHandles::createMemoryPool_name();
-    symbolHandle signature = vmSymbolHandles::createMemoryPool_signature();
+    Symbol* method_name = vmSymbols::createMemoryPool_name();
+    Symbol* signature = vmSymbols::createMemoryPool_signature();
 
     args.push_long(usage_threshold_value);    // Argument 3
     args.push_long(gc_usage_threshold_value); // Argument 4
--- a/src/share/vm/services/memoryService.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/memoryService.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -619,8 +619,8 @@
 
   JavaCalls::call_special(&result,
                           ik,
-                          vmSymbolHandles::object_initializer_name(),
-                          vmSymbolHandles::long_long_long_long_void_signature(),
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::long_long_long_long_void_signature(),
                           &args,
                           CHECK_NH);
   return obj;
--- a/src/share/vm/services/threadService.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/services/threadService.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -249,7 +249,7 @@
   // Allocate the resulting StackTraceElement[][] object
 
   ResourceMark rm(THREAD);
-  klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_StackTraceElement_array(), true, CHECK_NH);
+  klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_StackTraceElement_array(), true, CHECK_NH);
   objArrayKlassHandle ik (THREAD, k);
   objArrayOop r = oopFactory::new_objArray(ik(), num_threads, CHECK_NH);
   objArrayHandle result_obj(THREAD, r);
--- a/src/share/vm/utilities/debug.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/debug.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -263,6 +263,27 @@
 #endif // PRODUCT
 }
 
+void report_out_of_shared_space(SharedSpaceType shared_space) {
+  static const char* name[] = {
+    "permanent generation",
+    "shared read only space",
+    "shared read write space",
+    "shared miscellaneous data space"
+  };
+  static const char* flag[] = {
+    "PermGen",
+    "SharedReadOnlySize",
+    "SharedReadWriteSize",
+    "SharedMiscDataSize"
+  };
+
+   warning("\nThe %s is not large enough\n"
+           "to preload requested classes. Use -XX:%s=\n"
+           "to increase the initial size of %s.\n",
+           name[shared_space], flag[shared_space], name[shared_space]);
+   exit(2);
+}
+
 void report_java_out_of_memory(const char* message) {
   static jint out_of_memory_reported = 0;
 
--- a/src/share/vm/utilities/debug.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/debug.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -34,6 +34,7 @@
 class FormatBuffer {
 public:
   inline FormatBuffer(const char * format, ...);
+  inline void append(const char* format, ...);
   operator const char *() const { return _buf; }
 
 private:
@@ -51,6 +52,19 @@
   va_end(argp);
 }
 
+template <size_t bufsz>
+void FormatBuffer<bufsz>::append(const char* format, ...) {
+  // Given that the constructor does a vsnprintf we can assume that
+  // _buf is already initialized.
+  size_t len = strlen(_buf);
+  char* buf_end = _buf + len;
+
+  va_list argp;
+  va_start(argp, format);
+  vsnprintf(buf_end, bufsz - len, format, argp);
+  va_end(argp);
+}
+
 // Used to format messages for assert(), guarantee(), fatal(), etc.
 typedef FormatBuffer<> err_msg;
 
@@ -162,6 +176,16 @@
 
 void warning(const char* format, ...);
 
+// out of shared space reporting
+enum SharedSpaceType {
+  SharedPermGen,
+  SharedReadOnly,
+  SharedReadWrite,
+  SharedMiscData
+};
+
+void report_out_of_shared_space(SharedSpaceType space_type);
+
 // out of memory reporting
 void report_java_out_of_memory(const char* message);
 
--- a/src/share/vm/utilities/exceptions.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/exceptions.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -103,10 +103,10 @@
   return false;
 }
 
-bool Exceptions::special_exception(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message) {
+bool Exceptions::special_exception(Thread* thread, const char* file, int line, Symbol* h_name, const char* message) {
   // bootstrapping check
   if (!Universe::is_fully_initialized()) {
-    if (h_name.is_null()) {
+    if (h_name == NULL) {
       // atleast an informative message.
       vm_exit_during_initialization("Exception", message);
     } else {
@@ -163,7 +163,7 @@
 }
 
 
-void Exceptions::_throw_msg(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message, Handle h_loader, Handle h_protection_domain) {
+void Exceptions::_throw_msg(Thread* thread, const char* file, int line, Symbol* h_name, const char* message, Handle h_loader, Handle h_protection_domain) {
   // Check for special boot-strapping/vm-thread handling
   if (special_exception(thread, file, line, h_name, message)) return;
   // Create and throw exception
@@ -173,7 +173,7 @@
 }
 
 // Throw an exception with a message and a cause
-void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message, Handle h_cause, Handle h_loader, Handle h_protection_domain) {
+void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, Symbol* h_name, const char* message, Handle h_cause, Handle h_loader, Handle h_protection_domain) {
   // Check for special boot-strapping/vm-thread handling
   if (special_exception(thread, file, line, h_name, message)) return;
   // Create and throw exception and init cause
@@ -181,18 +181,9 @@
   _throw(thread, file, line, h_exception, message);
 }
 
-// This version creates handles and calls the other version
-void Exceptions::_throw_msg(Thread* thread, const char* file, int line,
-                            symbolOop name, const char* message) {
-  symbolHandle h_name(thread, name);
-  Handle       h_loader(thread, NULL);
-  Handle       h_protection_domain(thread, NULL);
-  Exceptions::_throw_msg(thread, file, line, h_name, message, h_loader, h_protection_domain);
-}
-
 // This version already has a handle for name
 void Exceptions::_throw_msg(Thread* thread, const char* file, int line,
-                            symbolHandle name, const char* message) {
+                            Symbol* name, const char* message) {
   Handle       h_loader(thread, NULL);
   Handle       h_protection_domain(thread, NULL);
   Exceptions::_throw_msg(thread, file, line, name, message, h_loader, h_protection_domain);
@@ -200,13 +191,13 @@
 
 // This version already has a handle for name
 void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line,
-                            symbolHandle name, const char* message, Handle cause) {
+                            Symbol* name, const char* message, Handle cause) {
   Handle       h_loader(thread, NULL);
   Handle       h_protection_domain(thread, NULL);
   Exceptions::_throw_msg_cause(thread, file, line, name, message, cause, h_loader, h_protection_domain);
 }
 
-void Exceptions::_throw_args(Thread* thread, const char* file, int line, symbolHandle h_name, symbolHandle h_signature, JavaCallArguments *args) {
+void Exceptions::_throw_args(Thread* thread, const char* file, int line, Symbol* h_name, Symbol* h_signature, JavaCallArguments *args) {
   // Check for special boot-strapping/vm-thread handling
   if (special_exception(thread, file, line, h_name, NULL)) return;
   // Create and throw exception
@@ -235,7 +226,7 @@
   _throw_oop(THREAD, file, line, exception());
 }
 
-void Exceptions::fthrow(Thread* thread, const char* file, int line, symbolHandle h_name, const char* format, ...) {
+void Exceptions::fthrow(Thread* thread, const char* file, int line, Symbol* h_name, const char* format, ...) {
   const int max_msg_size = 1024;
   va_list ap;
   va_start(ap, format);
@@ -249,8 +240,8 @@
 // Creates an exception oop, calls the <init> method with the given signature.
 // and returns a Handle
 // Initializes the cause if cause non-null
-Handle Exceptions::new_exception(Thread *thread, symbolHandle h_name,
-                                 symbolHandle signature,
+Handle Exceptions::new_exception(Thread *thread, Symbol* h_name,
+                                 Symbol* signature,
                                  JavaCallArguments *args,
                                  Handle h_cause, Handle h_loader,
                                  Handle h_protection_domain) {
@@ -277,7 +268,7 @@
         args->set_receiver(h_exception);
         // Call constructor
         JavaCalls::call_special(&result, klass,
-                                         vmSymbolHandles::object_initializer_name(),
+                                         vmSymbols::object_initializer_name(),
                                          signature,
                                          args,
                                          thread);
@@ -294,8 +285,8 @@
       args1.set_receiver(h_exception);
       args1.push_oop(h_cause);
       JavaCalls::call_virtual(&result1, klass,
-                                     vmSymbolHandles::initCause_name(),
-                                     vmSymbolHandles::throwable_throwable_signature(),
+                                     vmSymbols::initCause_name(),
+                                     vmSymbols::throwable_throwable_signature(),
                                      &args1,
                                      thread);
     }
@@ -311,15 +302,15 @@
 
 // Convenience method. Calls either the <init>() or <init>(String) method when
 // creating a new exception
-Handle Exceptions::new_exception(Thread* thread, symbolHandle h_name,
+Handle Exceptions::new_exception(Thread* thread, Symbol* h_name,
                                  const char* message, Handle h_cause,
                                  Handle h_loader,
                                  Handle h_protection_domain,
                                  ExceptionMsgToUtf8Mode to_utf8_safe) {
   JavaCallArguments args;
-  symbolHandle signature;
+  Symbol* signature = NULL;
   if (message == NULL) {
-    signature = vmSymbolHandles::void_method_signature();
+    signature = vmSymbols::void_method_signature();
   } else {
     // We want to allocate storage, but we can't do that if there's
     // a pending exception, so we preserve any pending exception
@@ -350,7 +341,7 @@
       return incoming_exception;
     }
     args.push_oop(msg);
-    signature = vmSymbolHandles::string_void_signature();
+    signature = vmSymbols::string_void_signature();
   }
   return new_exception(thread, h_name, signature, &args, h_cause, h_loader, h_protection_domain);
 }
@@ -364,15 +355,14 @@
 // point is to push this flag down to class java_lang_String since other
 // classes may need similar functionalities.
 Handle Exceptions::new_exception(Thread* thread,
-                                 symbolOop name,
+                                 Symbol* name,
                                  const char* message,
                                  ExceptionMsgToUtf8Mode to_utf8_safe) {
 
-  symbolHandle h_name(thread, name);
   Handle       h_loader(thread, NULL);
   Handle       h_prot(thread, NULL);
   Handle       h_cause(thread, NULL);
-  return Exceptions::new_exception(thread, h_name, message, h_cause, h_loader,
+  return Exceptions::new_exception(thread, name, message, h_cause, h_loader,
                                    h_prot, to_utf8_safe);
 }
 
--- a/src/share/vm/utilities/exceptions.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/exceptions.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -50,8 +50,7 @@
 
 class Thread;
 class Handle;
-class symbolHandle;
-class symbolOopDesc;
+class Symbol;
 class JavaCallArguments;
 
 // The ThreadShadow class is a helper class to access the _pending_exception
@@ -100,7 +99,7 @@
 
 class Exceptions {
   static bool special_exception(Thread *thread, const char* file, int line, Handle exception);
-  static bool special_exception(Thread* thread, const char* file, int line, symbolHandle name, const char* message);
+  static bool special_exception(Thread* thread, const char* file, int line, Symbol* name, const char* message);
  public:
   // this enum is defined to indicate whether it is safe to
   // ignore the encoding scheme of the original message string.
@@ -112,38 +111,36 @@
   static void _throw_oop(Thread* thread, const char* file, int line, oop exception);
   static void _throw(Thread* thread, const char* file, int line, Handle exception, const char* msg = NULL);
   static void _throw_msg(Thread* thread, const char* file, int line,
-                         symbolHandle name, const char* message, Handle loader,
+                         Symbol* name, const char* message, Handle loader,
                          Handle protection_domain);
   static void _throw_msg(Thread* thread, const char* file, int line,
-                         symbolOop name, const char* message);
-  static void _throw_msg(Thread* thread, const char* file, int line,
-                         symbolHandle name, const char* message);
+                         Symbol* name, const char* message);
   static void _throw_args(Thread* thread, const char* file, int line,
-                          symbolHandle name, symbolHandle signature,
+                          Symbol* name, Symbol* signature,
                           JavaCallArguments* args);
   static void _throw_msg_cause(Thread* thread, const char* file,
-                         int line, symbolHandle h_name, const char* message,
+                         int line, Symbol* h_name, const char* message,
                          Handle h_cause, Handle h_loader, Handle h_protection_domain);
   static void _throw_msg_cause(Thread* thread, const char* file, int line,
-                            symbolHandle name, const char* message, Handle cause);
+                            Symbol* name, const char* message, Handle cause);
 
   // There is no THROW... macro for this method. Caller should remember
   // to do a return after calling it.
-  static void fthrow(Thread* thread, const char* file, int line, symbolHandle name,
+  static void fthrow(Thread* thread, const char* file, int line, Symbol* name,
                      const char* format, ...);
 
   // Create and initialize a new exception
-  static Handle new_exception(Thread* thread, symbolHandle name,
-                              symbolHandle signature, JavaCallArguments* args,
+  static Handle new_exception(Thread* thread, Symbol* name,
+                              Symbol* signature, JavaCallArguments* args,
                               Handle cause, Handle loader,
                               Handle protection_domain);
 
-  static Handle new_exception(Thread* thread, symbolHandle name,
+  static Handle new_exception(Thread* thread, Symbol* name,
                               const char* message, Handle cause, Handle loader,
                               Handle protection_domain,
                               ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8);
 
- static Handle new_exception(Thread* thread, symbolOop name,
+ static Handle new_exception(Thread* thread, Symbol* name,
                              const char* message,
                              ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8);
 
--- a/src/share/vm/utilities/globalDefinitions.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1179,6 +1179,8 @@
 // '%d' formats to indicate a 64-bit quantity; commonly "l" (in LP64) or "ll"
 // (in ILP32).
 
+#define BOOL_TO_STR(__b) (__b) ? "true" : "false"
+
 // Format 32-bit quantities.
 #define INT32_FORMAT  "%d"
 #define UINT32_FORMAT "%u"
--- a/src/share/vm/utilities/hashtable.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/hashtable.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -31,8 +31,9 @@
 #include "utilities/hashtable.hpp"
 #include "utilities/hashtable.inline.hpp"
 
+
 HS_DTRACE_PROBE_DECL4(hs_private, hashtable__new_entry,
-  void*, unsigned int, oop, void*);
+  void*, unsigned int, void*, void*);
 
 // This is a generic hashtable, designed to be used for the symbol
 // and string tables.
@@ -67,62 +68,17 @@
 }
 
 
-HashtableEntry* Hashtable::new_entry(unsigned int hashValue, oop obj) {
-  HashtableEntry* entry;
+template <class T> HashtableEntry<T>* Hashtable<T>::new_entry(unsigned int hashValue, T obj) {
+  HashtableEntry<T>* entry;
 
-  entry = (HashtableEntry*)BasicHashtable::new_entry(hashValue);
-  entry->set_literal(obj);   // clears literal string field
+  entry = (HashtableEntry<T>*)BasicHashtable::new_entry(hashValue);
+  entry->set_literal(obj);
   HS_DTRACE_PROBE4(hs_private, hashtable__new_entry,
     this, hashValue, obj, entry);
   return entry;
 }
 
 
-// GC support
-
-void Hashtable::unlink(BoolObjectClosure* is_alive) {
-  // Readers of the table are unlocked, so we should only be removing
-  // entries at a safepoint.
-  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
-  for (int i = 0; i < table_size(); ++i) {
-    for (HashtableEntry** p = bucket_addr(i); *p != NULL; ) {
-      HashtableEntry* entry = *p;
-      if (entry->is_shared()) {
-        break;
-      }
-      assert(entry->literal() != NULL, "just checking");
-      if (is_alive->do_object_b(entry->literal())) {
-        p = entry->next_addr();
-      } else {
-        *p = entry->next();
-        free_entry(entry);
-      }
-    }
-  }
-}
-
-
-void Hashtable::oops_do(OopClosure* f) {
-  for (int i = 0; i < table_size(); ++i) {
-    HashtableEntry** p = bucket_addr(i);
-    HashtableEntry* entry = bucket(i);
-    while (entry != NULL) {
-      f->do_oop(entry->literal_addr());
-
-      // Did the closure remove the literal from the table?
-      if (entry->literal() == NULL) {
-        assert(!entry->is_shared(), "immutable hashtable entry?");
-        *p = entry->next();
-        free_entry(entry);
-      } else {
-        p = entry->next_addr();
-      }
-      entry = (HashtableEntry*)HashtableEntry::make_ptr(*p);
-    }
-  }
-}
-
-
 // Reverse the order of elements in the hash buckets.
 
 void BasicHashtable::reverse() {
@@ -156,11 +112,7 @@
                               *p != NULL;
                                p = (*p)->next_addr()) {
       if (*top + entry_size() > end) {
-        warning("\nThe shared miscellaneous data space is not large "
-                "enough to \npreload requested classes.  Use "
-                "-XX:SharedMiscDataSize= to increase \nthe initial "
-                "size of the miscellaneous data space.\n");
-        exit(2);
+        report_out_of_shared_space(SharedMiscData);
       }
       *p = (BasicHashtableEntry*)memcpy(*top, *p, entry_size());
       *top += entry_size();
@@ -181,15 +133,15 @@
 
 // Reverse the order of elements in the hash buckets.
 
-void Hashtable::reverse(void* boundary) {
+template <class T> void Hashtable<T>::reverse(void* boundary) {
 
   for (int i = 0; i < table_size(); ++i) {
-    HashtableEntry* high_list = NULL;
-    HashtableEntry* low_list = NULL;
-    HashtableEntry* last_low_entry = NULL;
-    HashtableEntry* p = bucket(i);
+    HashtableEntry<T>* high_list = NULL;
+    HashtableEntry<T>* low_list = NULL;
+    HashtableEntry<T>* last_low_entry = NULL;
+    HashtableEntry<T>* p = bucket(i);
     while (p != NULL) {
-      HashtableEntry* next = p->next();
+      HashtableEntry<T>* next = p->next();
       if ((void*)p->literal() >= boundary) {
         p->set_next(high_list);
         high_list = p;
@@ -223,11 +175,7 @@
   *top += sizeof(intptr_t);
 
   if (*top + len > end) {
-    warning("\nThe shared miscellaneous data space is not large "
-            "enough to \npreload requested classes.  Use "
-            "-XX:SharedMiscDataSize= to increase \nthe initial "
-            "size of the miscellaneous data space.\n");
-    exit(2);
+    report_out_of_shared_space(SharedMiscData);
   }
   _buckets = (HashtableBucket*)memcpy(*top, _buckets, len);
   *top += len;
@@ -236,11 +184,11 @@
 
 #ifndef PRODUCT
 
-void Hashtable::print() {
+template <class T> void Hashtable<T>::print() {
   ResourceMark rm;
 
   for (int i = 0; i < table_size(); i++) {
-    HashtableEntry* entry = bucket(i);
+    HashtableEntry<T>* entry = bucket(i);
     while(entry != NULL) {
       tty->print("%d : ", i);
       entry->literal()->print();
@@ -277,3 +225,10 @@
 }
 
 #endif
+
+// Explicitly instantiate these types
+template class Hashtable<constantPoolOop>;
+template class Hashtable<Symbol*>;
+template class Hashtable<klassOop>;
+template class Hashtable<oop>;
+
--- a/src/share/vm/utilities/hashtable.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/hashtable.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -27,7 +27,7 @@
 
 #include "memory/allocation.hpp"
 #include "oops/oop.hpp"
-#include "oops/symbolOop.hpp"
+#include "oops/symbol.hpp"
 #include "runtime/handles.hpp"
 
 // This is a generic hashtable, designed to be used for the symbol
@@ -96,16 +96,16 @@
 
 
 
-class HashtableEntry : public BasicHashtableEntry {
+template <class T> class HashtableEntry : public BasicHashtableEntry {
   friend class VMStructs;
 private:
-  oop               _literal;          // ref to item in table.
+  T               _literal;          // ref to item in table.
 
 public:
   // Literal
-  oop literal() const                   { return _literal; }
-  oop* literal_addr()                   { return &_literal; }
-  void set_literal(oop s)               { _literal = s; }
+  T literal() const                   { return _literal; }
+  T* literal_addr()                   { return &_literal; }
+  void set_literal(T s)               { _literal = s; }
 
   HashtableEntry* next() const {
     return (HashtableEntry*)BasicHashtableEntry::next();
@@ -159,6 +159,8 @@
   // Reverse the order of elements in each of the buckets.
   void reverse();
 
+  static unsigned int hash_symbol(const char* s, int len);
+
 private:
   // Instance variables
   int               _table_size;
@@ -205,7 +207,7 @@
 };
 
 
-class Hashtable : public BasicHashtable {
+template <class T> class Hashtable : public BasicHashtable {
   friend class VMStructs;
 
 public:
@@ -216,16 +218,9 @@
                    HashtableBucket* buckets, int number_of_entries)
     : BasicHashtable(table_size, entry_size, buckets, number_of_entries) { }
 
-  // Invoke "f->do_oop" on the locations of all oops in the table.
-  void oops_do(OopClosure* f);
-
   // Debugging
   void print()               PRODUCT_RETURN;
 
-  // GC support
-  //   Delete pointers to otherwise-unreachable objects.
-  void unlink(BoolObjectClosure* cl);
-
   // Reverse the order of elements in each of the buckets. Hashtable
   // entries which refer to objects at a lower address than 'boundary'
   // are separated from those which refer to objects at higher
@@ -234,45 +229,43 @@
 
 protected:
 
-  static unsigned int hash_symbol(const char* s, int len);
-
-  unsigned int compute_hash(symbolHandle name) {
+  unsigned int compute_hash(Symbol* name) {
     return (unsigned int) name->identity_hash();
   }
 
-  int index_for(symbolHandle name) {
+  int index_for(Symbol* name) {
     return hash_to_index(compute_hash(name));
   }
 
   // Table entry management
-  HashtableEntry* new_entry(unsigned int hashValue, oop obj);
+  HashtableEntry<T>* new_entry(unsigned int hashValue, T obj);
 
   // The following method is MT-safe and may be used with caution.
-  HashtableEntry* bucket(int i) {
-    return (HashtableEntry*)BasicHashtable::bucket(i);
+  HashtableEntry<T>* bucket(int i) {
+    return (HashtableEntry<T>*)BasicHashtable::bucket(i);
   }
 
   // The following method is not MT-safe and must be done under lock.
-  HashtableEntry** bucket_addr(int i) {
-    return (HashtableEntry**)BasicHashtable::bucket_addr(i);
+  HashtableEntry<T>** bucket_addr(int i) {
+    return (HashtableEntry<T>**)BasicHashtable::bucket_addr(i);
   }
 };
 
 
 //  Verions of hashtable where two handles are used to compute the index.
 
-class TwoOopHashtable : public Hashtable {
+template <class T> class TwoOopHashtable : public Hashtable<T> {
   friend class VMStructs;
 protected:
   TwoOopHashtable(int table_size, int entry_size)
-    : Hashtable(table_size, entry_size) {}
+    : Hashtable<T>(table_size, entry_size) {}
 
   TwoOopHashtable(int table_size, int entry_size, HashtableBucket* t,
                   int number_of_entries)
-    : Hashtable(table_size, entry_size, t, number_of_entries) {}
+    : Hashtable<T>(table_size, entry_size, t, number_of_entries) {}
 
 public:
-  unsigned int compute_hash(symbolHandle name, Handle loader) {
+  unsigned int compute_hash(Symbol* name, Handle loader) {
     // Be careful with identity_hash(), it can safepoint and if this
     // were one expression, the compiler could choose to unhandle each
     // oop before calling identity_hash() for either of them.  If the first
@@ -282,7 +275,7 @@
     return name_hash ^ loader_hash;
   }
 
-  int index_for(symbolHandle name, Handle loader) {
+  int index_for(Symbol* name, Handle loader) {
     return hash_to_index(compute_hash(name, loader));
   }
 };
--- a/src/share/vm/utilities/hashtable.inline.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/hashtable.inline.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -41,7 +41,7 @@
 
 // hash P(31) from Kernighan & Ritchie
 
-inline unsigned int Hashtable::hash_symbol(const char* s, int len) {
+inline unsigned int BasicHashtable::hash_symbol(const char* s, int len) {
   unsigned int h = 0;
   while (len-- > 0) {
     h = 31*h + (unsigned) *s;
--- a/src/share/vm/utilities/utf8.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/utf8.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -164,7 +164,7 @@
 
 // Returns NULL if 'c' it not found. This only works as long
 // as 'c' is an ASCII character
-jbyte* UTF8::strrchr(jbyte* base, int length, jbyte c) {
+const jbyte* UTF8::strrchr(const jbyte* base, int length, jbyte c) {
   assert(length >= 0, "sanity check");
   assert(c >= 0, "does not work for non-ASCII characters");
   // Skip backwards in string until 'c' is found or end is reached
@@ -172,7 +172,7 @@
   return (length < 0) ? NULL : &base[length];
 }
 
-bool UTF8::equal(jbyte* base1, int length1, jbyte* base2, int length2) {
+bool UTF8::equal(const jbyte* base1, int length1, const jbyte* base2, int length2) {
   // Length must be the same
   if (length1 != length2) return false;
   for (int i = 0; i < length1; i++) {
--- a/src/share/vm/utilities/utf8.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/utf8.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -51,8 +51,8 @@
   static char* next_character(const char* str, jint* value);
 
   // Utility methods
-  static jbyte* strrchr(jbyte* base, int length, jbyte c);
-  static bool   equal(jbyte* base1, int length1, jbyte* base2, int length2);
+  static const jbyte* strrchr(const jbyte* base, int length, jbyte c);
+  static bool   equal(const jbyte* base1, int length1, const jbyte* base2,int length2);
   static bool   is_supplementary_character(const unsigned char* str);
   static jint   get_supplementary_character(const unsigned char* str);
 };
--- a/src/share/vm/utilities/vmError.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/vmError.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -874,11 +874,13 @@
       }
 
       if (fd == -1) {
-        // try temp directory
         const char * tmpdir = os::get_temp_directory();
-        jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log",
-                     tmpdir, os::file_separator(), os::current_process_id());
-        fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+        // try temp directory if it exists.
+        if (tmpdir != NULL && tmpdir[0] != '\0') {
+          jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log",
+                       tmpdir, os::file_separator(), os::current_process_id());
+          fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+        }
       }
 
       if (fd != -1) {
--- a/src/share/vm/utilities/xmlstream.cpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/xmlstream.cpp	Wed Feb 16 13:47:20 2011 +0100
@@ -422,17 +422,17 @@
   klass->name()->print_symbol_on(out());
 }
 
-void xmlStream::name(symbolHandle name) {
+void xmlStream::name(const Symbol* name) {
   assert_if_no_error(inside_attrs(), "printing attributes");
-  if (name.is_null())  return;
+  if (name == NULL)  return;
   print_raw(" name='");
   name_text(name);
   print_raw("'");
 }
 
-void xmlStream::name_text(symbolHandle name) {
+void xmlStream::name_text(const Symbol* name) {
   assert_if_no_error(inside_attrs(), "printing attributes");
-  if (name.is_null())  return;
+  if (name == NULL)  return;
   //name->print_short_name(text());
   name->print_symbol_on(text());
 }
@@ -455,8 +455,6 @@
     method_text(methodOop(x()));
   else if (x->is_klass())
     klass_text(klassOop(x()));
-  else if (x->is_symbol())
-    name_text(symbolOop(x()));
   else
     x->print_value_on(text());
 }
--- a/src/share/vm/utilities/xmlstream.hpp	Wed Feb 16 13:38:33 2011 +0100
+++ b/src/share/vm/utilities/xmlstream.hpp	Wed Feb 16 13:47:20 2011 +0100
@@ -139,13 +139,13 @@
   void          stamp();                 // stamp='1.234'
   void          method(methodHandle m);  // method='k n s' ...
   void          klass(KlassHandle k);    // klass='name'
-  void          name(symbolHandle s);    // name='name'
+  void          name(const Symbol* s);   // name='name'
   void          object(const char* attr, Handle val);
 
   // print the text alone (sans ''):
   void          method_text(methodHandle m);
   void          klass_text(KlassHandle k);    // klass='name'
-  void          name_text(symbolHandle s);    // name='name'
+  void          name_text(const Symbol* s);   // name='name'
   void          object_text(Handle x);
 
   /*  Example uses: