# HG changeset patch # User Thomas Wuerthinger # Date 1297860440 -3600 # Node ID d25d4ca69222f362ae5058df84a882ad8ddfc8bf # Parent 50b45e2d97259dd5728bab098947db9eef6b103b# Parent 14c2f31280dda0084f8ef15178a52f07bb472926 Merge. diff -r 50b45e2d9725 -r d25d4ca69222 .hgtags --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java --- 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()) { diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java --- 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 ""; - } else if (obj.isInstance()) { - return ""; + ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex); + if (obj.isMetaData()) { + Symbol sym = obj.getSymbol(); + return ""; + } else if (obj.isOop()) { + return ""; } 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 ""; - } else if (obj.isSymbol()) { - Symbol sym = (Symbol) obj; - return ""; + ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex); + if (obj.isOop()) { + Klass k = (Klass) obj.getOop(); + return ""; + } else if (obj.isMetaData()) { + Symbol sym = obj.getSymbol(); + return ""; } else { throw new RuntimeException("should not reach here"); } diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java --- 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(); } } diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java --- 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() { diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java --- 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 :-( diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/memory/StringTable.java --- 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); } } } diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java --- 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())); } } } diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java --- 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()); */ } diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/oops/Method.java --- 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) diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java --- 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()) { diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/oops/Symbol.java --- 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 { diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/oops/SymbolKlass.java --- 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"); - } -} diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/types/Field.java --- 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 @@ 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 */ diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java --- 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(""); } // derived class may return Class diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/utilities/HashtableEntry.java --- 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"); + 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) { diff -r 50b45e2d9725 -r d25d4ca69222 agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 make/hotspot_version --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/assembler_sparc.cpp --- 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())); } diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/assembler_sparc.hpp --- 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, diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/assembler_sparc.inline.hpp --- 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 ); diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- 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))) { diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp --- 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); } } diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/c1_Runtime1_sparc.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/interp_masm_sparc.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/interp_masm_sparc.hpp --- 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, diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/methodHandles_sparc.cpp --- 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. diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/sparc.ad --- 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 %{ diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/sparc/vm/templateTable_sparc.cpp --- 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()) { diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/c1_CodeStubs_x86.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/c1_LIRGenerator_x86.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/c1_Runtime1_x86.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/globals_x86.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/interp_masm_x86_32.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/interp_masm_x86_64.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/methodHandles_x86.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/templateTable_x86_32.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/cpu/x86/vm/templateTable_x86_64.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/os/linux/vm/os_linux.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/os/solaris/dtrace/generateJvmOffsets.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/os/solaris/dtrace/jhelper.d --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/os/solaris/dtrace/libjvm_db.c --- 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'; diff -r 50b45e2d9725 -r d25d4ca69222 src/os/solaris/vm/dtraceJSDT_solaris.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/os/solaris/vm/os_solaris.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/os/windows/vm/os_windows.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp --- 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( diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/linux_x86/vm/linux_x86_32.s --- 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 + diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp --- 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 } diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp --- 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/solaris_sparc/vm/solaris_sparc.il --- 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). // diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp --- 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/solaris_x86/vm/solaris_x86_32.il --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_Canonicalizer.cpp --- 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) {} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_Canonicalizer.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_CodeStubs.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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_GraphBuilder.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_Instruction.hpp --- 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) diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_InstructionPrinter.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_InstructionPrinter.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_LIR.cpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_LIRGenerator.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_LIRGenerator.hpp --- 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); }; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_Optimizer.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_Runtime1.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_Runtime1.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/c1/c1_ValueMap.hpp --- 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 */ }; }; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/bcEscapeAnalyzer.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciClassList.hpp --- 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; \ diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciEnv.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciEnv.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciField.cpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciInstanceKlass.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciKlass.cpp --- 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); } // ------------------------------------------------------------------ diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciMethod.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciMethod.hpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciMethodBlocks.cpp --- 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()); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciMethodHandle.cpp --- 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciObjArrayKlass.cpp --- 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) == '[' || diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciObject.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciObjectFactory.cpp --- 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(arena, 4, 0, NULL); _return_addresses = new (arena) GrowableArray(arena, 8, 0, NULL); + + _symbols = new (arena) GrowableArray(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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciObjectFactory.hpp --- 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* _unloaded_klasses; GrowableArray* _unloaded_instances; GrowableArray* _return_addresses; + GrowableArray* _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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciSignature.cpp --- 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); } } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciSignature.hpp --- 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; } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciStreams.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciSymbol.cpp --- 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); } // ------------------------------------------------------------------ diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciSymbol.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciSymbolKlass.cpp --- 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; -} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciSymbolKlass.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/ciTypeFlow.cpp --- 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(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(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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/ci/compilerInterface.hpp --- 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" diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/classFileError.cpp --- 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 ); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/classFileParser.cpp --- 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 "". - 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* 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/classFileParser.hpp --- 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* _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* cp_patches, - symbolHandle& parsed_name, + TempNewSymbol& parsed_name, bool verify, TRAPS); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/classLoader.cpp --- 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(); +} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/classLoader.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/dictionary.cpp --- 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(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(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::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::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::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(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(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::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()); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/dictionary.hpp --- 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 { 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::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::bucket_addr(i); } void add_entry(int index, DictionaryEntry* new_entry) { - Hashtable::add_entry(index, (HashtableEntry*)new_entry); + Hashtable::add_entry(index, (HashtableEntry*)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 { 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::next(); } DictionaryEntry** next_addr() { - return (DictionaryEntry**)HashtableEntry::next_addr(); + return (DictionaryEntry**)HashtableEntry::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 { 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::next(); } SymbolPropertyEntry** next_addr() { - return (SymbolPropertyEntry**)HashtableEntry::next_addr(); + return (SymbolPropertyEntry**)HashtableEntry::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 { friend class VMStructs; private: SymbolPropertyEntry* bucket(int i) { - return (SymbolPropertyEntry*) Hashtable::bucket(i); + return (SymbolPropertyEntry*) Hashtable::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::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::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::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::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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/javaAssertions.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/javaClasses.cpp --- 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; } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/javaClasses.hpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/loaderConstraints.cpp --- 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(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::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::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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/loaderConstraints.hpp --- 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 { 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::bucket(i); } LoaderConstraintEntry** bucket_addr(int i) { - return (LoaderConstraintEntry**)Hashtable::bucket_addr(i); + return (LoaderConstraintEntry**)Hashtable::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 { 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::next(); } LoaderConstraintEntry** next_addr() { - return (LoaderConstraintEntry**)HashtableEntry::next_addr(); + return (LoaderConstraintEntry**)HashtableEntry::next_addr(); } void set_next(LoaderConstraintEntry* next) { - HashtableEntry::set_next(next); + HashtableEntry::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; } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/placeholders.cpp --- 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::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::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(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() { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/placeholders.hpp --- 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 { 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::bucket(i); } PlaceholderEntry** bucket_addr(int i) { - return (PlaceholderEntry**)Hashtable::bucket_addr(i); + return (PlaceholderEntry**)Hashtable::bucket_addr(i); } void add_entry(int index, PlaceholderEntry* new_entry) { - Hashtable::add_entry(index, (HashtableEntry*)new_entry); + Hashtable::add_entry(index, (HashtableEntry*)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 { 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::next(); } PlaceholderEntry** next_addr() { - return (PlaceholderEntry**)HashtableEntry::next_addr(); + return (PlaceholderEntry**)HashtableEntry::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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/resolutionErrors.cpp --- 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::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::free_entry(entry); +} + + // create resolution error table ResolutionErrorTable::ResolutionErrorTable(int table_size) - : Hashtable(table_size, sizeof(ResolutionErrorEntry)) { + : Hashtable(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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/resolutionErrors.hpp --- 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 { 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::bucket(i); } ResolutionErrorEntry** bucket_addr(int i) { - return (ResolutionErrorEntry**)Hashtable::bucket_addr(i); + return (ResolutionErrorEntry**)Hashtable::bucket_addr(i); } void add_entry(int index, ResolutionErrorEntry* new_entry) { - Hashtable::add_entry(index, (HashtableEntry*)new_entry); + Hashtable::add_entry(index, (HashtableEntry*)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 { 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::next(); } ResolutionErrorEntry** next_addr() { - return (ResolutionErrorEntry**)HashtableEntry::next_addr(); + return (ResolutionErrorEntry**)HashtableEntry::next_addr(); } // GC support diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/stackMapFrame.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/stackMapFrame.hpp --- 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(); ) diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/stackMapTable.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/symbolTable.cpp --- 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* 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** p = the_table()->bucket_addr(i); *p != NULL; ) { + HashtableEntry* 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* 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; ihash_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* 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; iequals(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* 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* 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* 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** p = the_table()->bucket_addr(i); + HashtableEntry* 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*)HashtableEntry::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* 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* 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** p = the_table()->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(); + the_table()->free_entry(entry); + } + } + } +} + +void StringTable::oops_do(OopClosure* f) { + for (int i = 0; i < the_table()->table_size(); ++i) { + HashtableEntry** p = the_table()->bucket_addr(i); + HashtableEntry* 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*)HashtableEntry::make_ptr(*p); + } + } +} + void StringTable::verify() { for (int i = 0; i < the_table()->table_size(); ++i) { - HashtableEntry* p = the_table()->bucket(i); + HashtableEntry* p = the_table()->bucket(i); for ( ; p != NULL; p = p->next()) { oop s = p->literal(); guarantee(s != NULL, "interned string is NULL"); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/symbolTable.hpp --- 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 { 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_table_size, sizeof (HashtableEntry)) {} SymbolTable(HashtableBucket* t, int number_of_entries) - : Hashtable(symbol_table_size, sizeof (HashtableEntry), t, + : Hashtable(symbol_table_size, sizeof (HashtableEntry), 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::copy_buckets(top, end); } static void copy_table(char** top, char*end) { - the_table()->Hashtable::copy_table(top, end); + the_table()->Hashtable::copy_table(top, end); } static void reverse(void* boundary = NULL) { - ((Hashtable*)the_table())->reverse(boundary); + the_table()->Hashtable::reverse(boundary); } }; - -class StringTable : public Hashtable { +class StringTable : public Hashtable { 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(string_table_size, sizeof (HashtableEntry)) {} StringTable(HashtableBucket* t, int number_of_entries) - : Hashtable(string_table_size, sizeof (HashtableEntry), t, + : Hashtable(string_table_size, sizeof (HashtableEntry), 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::copy_buckets(top, end); } static void copy_table(char** top, char*end) { - the_table()->Hashtable::copy_table(top, end); + the_table()->Hashtable::copy_table(top, end); } static void reverse() { - ((BasicHashtable*)the_table())->reverse(); + the_table()->Hashtable::reverse(); } }; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/systemDictionary.cpp --- 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* 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/systemDictionary.hpp --- 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) \ diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/verificationType.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/verificationType.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/verifier.cpp --- 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(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 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 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()) { // method + if (method_name == vmSymbols::object_initializer_name()) { // 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()) { // method must have a void return type verify_error(bci, "Return type must be void in 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; +} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/verifier.hpp --- 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* _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: diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/vmSymbols.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/classfile/vmSymbols.hpp --- 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, "") \ @@ -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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/code/compiledIC.cpp --- 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" diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/code/dependencies.cpp --- 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]; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/code/nmethod.cpp --- 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(""); 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(""); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/compiler/compileBroker.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/compiler/compileLog.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/compiler/compilerOracle.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/compiler/compilerOracle.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/compiler/methodLiveness.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- 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. diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/concurrentMark.cpp --- 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 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 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 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/concurrentMark.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp --- 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"); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/concurrentZFThread.cpp --- 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)); - -} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/concurrentZFThread.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- 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; } + // // 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. + // // - // 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/g1MarkSweep.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/g1_globals.hpp --- 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") diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/heapRegion.cpp --- 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 @@ } // -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; -} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/heapRegion.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp --- 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 { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/heapRegionSeq.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/heapRegionSeq.hpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/heapRegionSet.cpp --- /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); + } + } +} diff -r 50b45e2d9725 -r d25d4ca69222 src/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.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; + +// 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/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/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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/heapRegionSets.cpp --- /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(); +} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/heapRegionSets.hpp --- /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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/ptrQueue.cpp --- 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."); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/ptrQueue.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/satbQueue.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/satbQueue.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/sparsePRT.cpp --- 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; +} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/sparsePRT.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/g1/vm_operations_g1.cpp --- 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) || diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp --- 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)); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- 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()); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp --- 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/shared/concurrentGCThread.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/shared/markSweep.cpp --- 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() { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/shared/vmGCOperations.cpp --- 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/gc_implementation/shared/vmGCOperations.hpp --- 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(); } }; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/bytecode.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/bytecode.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/bytecodeInterpreter.cpp --- 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; } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/bytecodeStream.cpp --- 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()); } } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/bytecodeStream.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/bytecodeTracer.cpp --- 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(" %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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/bytecodes.cpp --- 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<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); } } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/bytecodes.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/interpreter.cpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/interpreterRuntime.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/interpreterRuntime.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/linkResolver.cpp --- 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(*...) diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/linkResolver.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/rewriter.cpp --- 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 ); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/interpreter/templateInterpreter.cpp --- 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.. We simply need to resume execution at diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/classify.cpp --- 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()) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/compactingPermGenGen.cpp --- 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 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/compactingPermGenGen.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/dump.cpp --- 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* _klass_objects; public: - - PatchKlassVtables(void* vtbl_ptr, VirtualSpace* md_vs) { - _vtbl_ptr = vtbl_ptr; - _md_vs = md_vs; + PatchKlassVtables() { _klass_objects = new GrowableArray(); } - 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/genCollectedHeap.cpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/genMarkSweep.cpp --- 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"); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/heapInspection.cpp --- 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 = ""; else if (_klass == Universe::instanceKlassKlassObj()) name = ""; else if (_klass == Universe::typeArrayKlassKlassObj()) name = ""; else - if (_klass == Universe::symbolKlassObj()) name = ""; else if (_klass == Universe::boolArrayKlassObj()) name = ""; else if (_klass == Universe::charArrayKlassObj()) name = ""; else if (_klass == Universe::singleArrayKlassObj()) name = ""; else diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/iterator.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/oopFactory.hpp --- 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, diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/restore.cpp --- 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. diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/serialize.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/sharedHeap.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/universe.cpp --- 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()); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/memory/universe.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/arrayKlass.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/arrayKlass.hpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/arrayOop.cpp --- 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" // <> diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/constantPoolKlass.cpp --- 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"); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/constantPoolOop.cpp --- 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*)""; } @@ -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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/constantPoolOop.hpp --- 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/generateOopMap.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/generateOopMap.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/instanceKlass.cpp --- 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--) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/instanceKlass.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/instanceKlassKlass.cpp --- 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"); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/klass.cpp --- 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. diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/klass.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/klassKlass.cpp --- 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"); - } } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/klassVtable.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/klassVtable.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/markOop.hpp --- 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, diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/methodDataOop.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/methodKlass.cpp --- 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"); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/methodOop.cpp --- 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)) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/methodOop.hpp --- 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/objArrayKlass.cpp --- 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"); } } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/objArrayKlassKlass.cpp --- 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()) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/oop.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/oop.inline.hpp --- 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(); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/oopsHierarchy.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/symbol.cpp --- /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;) diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/symbol.hpp --- /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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/symbolKlass.cpp --- 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 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; iset_mark(markOopDesc::prototype()); - s->set_klass(sk); - s->set_utf8_length(lengths[i]); - const char* name = names[i]; - for (int j=0; jbyte_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}"; -} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/symbolKlass.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/symbolOop.cpp --- 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; -} diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/symbolOop.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/oops/typeArrayKlass.cpp --- 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"); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/opto/runtime.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/opto/type.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/precompiled.hpp --- 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" diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jni.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jniCheck.cpp --- 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" diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvm.cpp --- 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()); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvm.h --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvm_misc.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmti.xml --- 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 @@ - 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 @@ - 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 functions except those which diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiClassFileReconstituter.cpp --- 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"); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiClassFileReconstituter.hpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiEnv.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiEnvBase.cpp --- 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()); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiEventController.cpp --- 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, diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiExport.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiExport.hpp --- 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 { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiImpl.cpp --- 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; iat(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]); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiImpl.hpp --- 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(); }; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiRedefineClasses.cpp --- 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. diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiRedefineClasses.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiTagMap.cpp --- 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; iset_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; itable(); - for (int j=0; jsize(); 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; ientry_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; posnext(); - - 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_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); } } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/jvmtiTagMap.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/methodComparator.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/methodHandleWalk.cpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/methodHandleWalk.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/methodHandles.cpp --- 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 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/methodHandles.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/nativeLookup.cpp --- 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"); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/prims/unsafe.cpp --- 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, diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/arguments.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/deoptimization.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/fieldDescriptor.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/fieldType.cpp --- 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; } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/fieldType.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/fprofiler.cpp --- 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); } } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/frame.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/frame.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/globals.hpp --- 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. */ \ diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/handles.hpp --- 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 ) diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/interfaceSupport.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/interfaceSupport.hpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/java.cpp --- 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); } } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/java.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/javaCalls.cpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/javaCalls.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/jniHandles.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/mutexLocker.cpp --- 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 ); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/mutexLocker.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/objectMonitor.cpp --- 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(); \ diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/os.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/reflection.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/reflection.hpp --- 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. diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/reflectionUtils.hpp --- 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(); // ... // } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/relocator.hpp --- 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; } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/rframe.cpp --- 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" diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/safepoint.cpp --- 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" diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/sharedRuntime.cpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/sharedRuntime.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/signature.cpp --- 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(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 && diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/signature.hpp --- 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* _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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/statSampler.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/synchronizer.cpp --- 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(); \ diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/thread.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/thread.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/vframe.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/vframeArray.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/vmStructs.cpp --- 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, _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, 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(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, BasicHashtableEntry) \ + declare_type(DictionaryEntry, HashtableEntry) \ + declare_type(PlaceholderEntry, HashtableEntry) \ + declare_type(LoaderConstraintEntry, HashtableEntry) \ 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/vmStructs.hpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/vm_operations.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/runtime/vm_operations.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/attachListener.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/classLoadingService.cpp --- 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(); \ diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/heapDumper.cpp --- 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.hprof in the current working // directory. HeapDumpPath= 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= 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/lowMemoryDetector.cpp --- 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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/management.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/management.hpp --- 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(); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/memoryManager.cpp --- 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, diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/memoryPool.cpp --- 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 diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/memoryService.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/services/threadService.cpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/debug.cpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/debug.hpp --- 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 +void FormatBuffer::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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/exceptions.cpp --- 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 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 () or (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); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/exceptions.hpp --- 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); diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/globalDefinitions.hpp --- 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" diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/hashtable.cpp --- 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 HashtableEntry* Hashtable::new_entry(unsigned int hashValue, T obj) { + HashtableEntry* entry; - entry = (HashtableEntry*)BasicHashtable::new_entry(hashValue); - entry->set_literal(obj); // clears literal string field + entry = (HashtableEntry*)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 void Hashtable::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* high_list = NULL; + HashtableEntry* low_list = NULL; + HashtableEntry* last_low_entry = NULL; + HashtableEntry* p = bucket(i); while (p != NULL) { - HashtableEntry* next = p->next(); + HashtableEntry* 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 void Hashtable::print() { ResourceMark rm; for (int i = 0; i < table_size(); i++) { - HashtableEntry* entry = bucket(i); + HashtableEntry* 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; +template class Hashtable; +template class Hashtable; +template class Hashtable; + diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/hashtable.hpp --- 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 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 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* 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* bucket(int i) { + return (HashtableEntry*)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** bucket_addr(int i) { + return (HashtableEntry**)BasicHashtable::bucket_addr(i); } }; // Verions of hashtable where two handles are used to compute the index. -class TwoOopHashtable : public Hashtable { +template class TwoOopHashtable : public Hashtable { friend class VMStructs; protected: TwoOopHashtable(int table_size, int entry_size) - : Hashtable(table_size, entry_size) {} + : Hashtable(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(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)); } }; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/hashtable.inline.hpp --- 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; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/utf8.cpp --- 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++) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/utf8.hpp --- 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); }; diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/vmError.cpp --- 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) { diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/xmlstream.cpp --- 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()); } diff -r 50b45e2d9725 -r d25d4ca69222 src/share/vm/utilities/xmlstream.hpp --- 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: