Mercurial > hg > graal-compiler
changeset 2181:d25d4ca69222
Merge.
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(®ion_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(®ion_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(®_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: