OpenJDK / amber / amber
changeset 8205:3b68fb0c8dc6
Merge
author | mfang |
---|---|
date | Fri, 11 Feb 2011 23:46:24 -0800 |
parents | e04b03ed2aa3 c5df55701e91 |
children | b97d909e0642 |
files | hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/SymbolKlass.java hotspot/src/share/vm/ci/ciSymbolKlass.cpp hotspot/src/share/vm/ci/ciSymbolKlass.hpp hotspot/src/share/vm/oops/symbolKlass.cpp hotspot/src/share/vm/oops/symbolKlass.hpp hotspot/src/share/vm/oops/symbolOop.cpp hotspot/src/share/vm/oops/symbolOop.hpp |
diffstat | 276 files changed, 4595 insertions(+), 3988 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Feb 11 22:57:35 2011 -0800 +++ b/.hgtags Fri Feb 11 23:46:24 2011 -0800 @@ -102,3 +102,4 @@ f658ec2730fa29323c36d23c27e54c7219ef5e16 jdk7-b125 f1df068076986679ea1105532a65529d63a89060 jdk7-b126 f83cd8bd35c678f94e526990e03dc838d0ec2717 jdk7-b127 +7da3f5f30855dec6bf3a86529e87dee883b90c72 jdk7-b128
--- a/.hgtags-top-repo Fri Feb 11 22:57:35 2011 -0800 +++ b/.hgtags-top-repo Fri Feb 11 23:46:24 2011 -0800 @@ -102,3 +102,4 @@ 5c4df7e992775c102f08e9f1c0a124b324641b70 jdk7-b125 b566d490905691787f8931f69947a92c67c6d5e4 jdk7-b126 bd70f76b0309068f157ae759c36eac8f2c6d098e jdk7-b127 +57d702105b23fb90e40beaf00f8f8aeae5e249e7 jdk7-b128
--- a/README-builds.html Fri Feb 11 22:57:35 2011 -0800 +++ b/README-builds.html Fri Feb 11 23:46:24 2011 -0800 @@ -921,7 +921,7 @@ <!-- ------------------------------------------------------ --> <h4><a name="ant">Ant</a></h4> <blockquote> - All OpenJDK builds require access to least Ant 1.6.5. + All OpenJDK builds require access to least Ant 1.7.1. The Ant tool is available from the <a href="http://ant.apache.org" target="_blank"> Ant download site</a>.
--- a/corba/.hgtags Fri Feb 11 22:57:35 2011 -0800 +++ b/corba/.hgtags Fri Feb 11 23:46:24 2011 -0800 @@ -102,3 +102,4 @@ 1ce58c72b7892cb813eb920276c7e7f17a1b79fe jdk7-b125 d7532bcd3742f1576dd07ff9fbb535c9c9a276e9 jdk7-b126 64775e83f4df894355f45555f50c410de6727b4e jdk7-b127 +9baa8f94a11d6c5cab3f9f0e5a20106326d0932e jdk7-b128
--- a/corba/src/share/classes/com/sun/corba/se/spi/logging/data/Activation.mc Fri Feb 11 22:57:35 2011 -0800 +++ b/corba/src/share/classes/com/sun/corba/se/spi/logging/data/Activation.mc Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ ; -; Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. +; Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. ; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ; ; This code is free software; you can redistribute it and/or modify it
--- a/corba/src/share/classes/com/sun/corba/se/spi/logging/data/IOR.mc Fri Feb 11 22:57:35 2011 -0800 +++ b/corba/src/share/classes/com/sun/corba/se/spi/logging/data/IOR.mc Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ ; -; Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. +; Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. ; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ; ; This code is free software; you can redistribute it and/or modify it
--- a/corba/src/share/classes/com/sun/corba/se/spi/logging/data/Interceptors.mc Fri Feb 11 22:57:35 2011 -0800 +++ b/corba/src/share/classes/com/sun/corba/se/spi/logging/data/Interceptors.mc Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ ; -; Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. +; Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. ; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ; ; This code is free software; you can redistribute it and/or modify it
--- a/corba/src/share/classes/com/sun/corba/se/spi/logging/data/Naming.mc Fri Feb 11 22:57:35 2011 -0800 +++ b/corba/src/share/classes/com/sun/corba/se/spi/logging/data/Naming.mc Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ ; -; Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. +; Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. ; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ; ; This code is free software; you can redistribute it and/or modify it
--- a/corba/src/share/classes/com/sun/corba/se/spi/logging/data/OMG.mc Fri Feb 11 22:57:35 2011 -0800 +++ b/corba/src/share/classes/com/sun/corba/se/spi/logging/data/OMG.mc Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ ; -; Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. +; Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. ; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ; ; This code is free software; you can redistribute it and/or modify it
--- a/corba/src/share/classes/com/sun/corba/se/spi/logging/data/ORBUtil.mc Fri Feb 11 22:57:35 2011 -0800 +++ b/corba/src/share/classes/com/sun/corba/se/spi/logging/data/ORBUtil.mc Fri Feb 11 23:46:24 2011 -0800 @@ -1,6 +1,6 @@ ; -; Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. +; Copyright (c) 2003, 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
--- a/corba/src/share/classes/com/sun/corba/se/spi/logging/data/POA.mc Fri Feb 11 22:57:35 2011 -0800 +++ b/corba/src/share/classes/com/sun/corba/se/spi/logging/data/POA.mc Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ ; -; Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. +; Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. ; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ; ; This code is free software; you can redistribute it and/or modify it
--- a/corba/src/share/classes/com/sun/corba/se/spi/logging/data/Util.mc Fri Feb 11 22:57:35 2011 -0800 +++ b/corba/src/share/classes/com/sun/corba/se/spi/logging/data/Util.mc Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ ; -; Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. +; Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. ; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ; ; This code is free software; you can redistribute it and/or modify it
--- a/hotspot/.hgtags Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/.hgtags Fri Feb 11 23:46:24 2011 -0800 @@ -143,4 +143,6 @@ e24ab3fa6aafad3efabbe7dba9918c5f461a20b1 jdk7-b125 4c851c931d001a882cab809aaf3a55371b919244 jdk7-b126 e24ab3fa6aafad3efabbe7dba9918c5f461a20b1 hs20-b06 +d535bf4c12355a2897e918da9f8910c0aceec4fb hs20-b07 102466e70debc4b907afbd7624e34ddb1aafee9f jdk7-b127 +9a5762f448595794d449a8e17342abd81a3fadaf jdk7-b128
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Fri Feb 11 23:46:24 2011 -0800 @@ -428,6 +428,36 @@ } } }, + new Command("symbol", "symbol address", false) { + public void doit(Tokens t) { + if (t.countTokens() != 1) { + usage(); + } else { + Address a = VM.getVM().getDebugger().parseAddress(t.nextToken()); + Symbol.create(a).printValueOn(out); + out.println(); + } + } + }, + new Command("symboltable", "symboltable name", false) { + public void doit(Tokens t) { + if (t.countTokens() != 1) { + usage(); + } else { + out.println(SymbolTable.getTheTable().probe(t.nextToken())); + } + } + }, + new Command("symboldump", "symboldump", false) { + public void doit(Tokens t) { + SymbolTable.getTheTable().symbolsDo(new SymbolTable.SymbolVisitor() { + public void visit(Symbol sym) { + sym.printValueOn(out); + out.println(); + } + }); + } + }, new Command("flags", "flags [ flag ]", false) { public void doit(Tokens t) { int tokens = t.countTokens(); @@ -629,17 +659,6 @@ } } }, - new Command("symbol", "symbol name", false) { - public void doit(Tokens t) { - if (t.countTokens() != 1) { - usage(); - } else { - String symbol = t.nextToken(); - Address a = lookup(symbol); - out.println(symbol + " = " + a); - } - } - }, new Command("printstatics", "printstatics [ type ]", false) { public void doit(Tokens t) { if (t.countTokens() > 1) { @@ -1262,6 +1281,9 @@ this.err = err; for (int i = 0; i < commandList.length; i++) { Command c = commandList[i]; + if (commands.get(c.name) != null) { + throw new InternalError(c.name + " has multiple definitions"); + } commands.put(c.name, c); } if (debugger.isAttached()) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Fri Feb 11 23:46:24 2011 -0800 @@ -89,6 +89,37 @@ readVMLongConstants(); } + public Type lookupType(String cTypeName, boolean throwException) { + Type fieldType = super.lookupType(cTypeName, false); + if (fieldType == null && cTypeName.startsWith("const ")) { + fieldType = (BasicType)lookupType(cTypeName.substring(6), false); + } + if (fieldType == null && cTypeName.endsWith(" const")) { + fieldType = (BasicType)lookupType(cTypeName.substring(0, cTypeName.length() - 6), false); + } + if (fieldType == null) { + if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">*")) { + String ttype = cTypeName.substring("GrowableArray<".length(), + cTypeName.length() - 2); + Type templateType = lookupType(ttype, false); + if (templateType == null && typeNameIsPointerType(ttype)) { + templateType = recursiveCreateBasicPointerType(ttype); + } + if (templateType == null) { + lookupOrFail(ttype); + } + fieldType = recursiveCreateBasicPointerType(cTypeName); + } + } + if (fieldType == null && typeNameIsPointerType(cTypeName)) { + fieldType = recursiveCreateBasicPointerType(cTypeName); + } + if (fieldType == null && throwException) { + super.lookupType(cTypeName, true); + } + return fieldType; + } + private void readVMTypes() { // Get the variables we need in order to traverse the VMTypeEntry[] long typeEntryTypeNameOffset; @@ -250,7 +281,7 @@ BasicType containingType = lookupOrFail(typeName); // The field's Type must already be in the database -- no exceptions - BasicType fieldType = lookupOrFail(typeString); + BasicType fieldType = (BasicType)lookupType(typeString); // Create field by type createField(containingType, fieldName, fieldType, @@ -442,10 +473,17 @@ workarounds due to incomplete information in the VMStructs database. */ private BasicPointerType recursiveCreateBasicPointerType(String typeName) { + BasicPointerType result = (BasicPointerType)super.lookupType(typeName, false); + if (result != null) { + return result; + } String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim(); Type targetType = null; if (typeNameIsPointerType(targetTypeName)) { - targetType = recursiveCreateBasicPointerType(targetTypeName); + targetType = lookupType(targetTypeName, false); + if (targetType == null) { + targetType = recursiveCreateBasicPointerType(targetTypeName); + } } else { targetType = lookupType(targetTypeName, false); if (targetType == null) { @@ -466,6 +504,20 @@ BasicType basicTargetType = createBasicType(targetTypeName, false, true, true); basicTargetType.setSize(1); targetType = basicTargetType; + } else if (targetTypeName.startsWith("GrowableArray<")) { + BasicType basicTargetType = createBasicType(targetTypeName, false, false, false); + + // transfer fields from GenericGrowableArray to template instance + BasicType generic = lookupOrFail("GenericGrowableArray"); + basicTargetType.setSize(generic.getSize()); + Iterator fields = generic.getFields(); + while (fields.hasNext()) { + Field f = (Field)fields.next(); + basicTargetType.addField(internalCreateField(basicTargetType, f.getName(), + f.getType(), f.isStatic(), + f.getOffset(), null)); + } + targetType = basicTargetType; } else { if (DEBUG) { System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\""); @@ -474,7 +526,10 @@ } } } - return new BasicPointerType(this, typeName, targetType); + result = new BasicPointerType(this, typeName, targetType); + result.setSize(UNINITIALIZED_SIZE); + addType(result); + return result; } private boolean typeNameIsPointerType(String typeName) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Fri Feb 11 23:46:24 2011 -0800 @@ -112,7 +112,7 @@ } // return Symbol (if unresolved) or Klass (if resolved) - public Oop getKlass() { + public Object getKlass() { if (Assert.ASSERTS_ENABLED) { Assert.that(isKlassConstant(), "not a klass literal"); } @@ -121,11 +121,11 @@ // decide based on the oop type. ConstantPool cpool = method().getConstants(); int cpIndex = index(); - Oop oop = cpool.getObjAt(cpIndex); - if (oop.isKlass()) { - return (Klass) oop; - } else if (oop.isSymbol()) { - return (Symbol) oop; + ConstantPool.CPSlot oop = cpool.getSlotAt(cpIndex); + if (oop.isOop()) { + return (Klass) oop.getOop(); + } else if (oop.isMetaData()) { + return oop.getSymbol(); } else { throw new RuntimeException("should not reach here"); } @@ -165,12 +165,12 @@ // tag change from 'unresolved' to 'string' does not happen atomically. // We just look at the object at the corresponding index and // decide based on the oop type. - Oop obj = cpool.getObjAt(cpIndex); - if (obj.isSymbol()) { - Symbol sym = (Symbol) obj; - return "<String \"" + sym.asString() + "\">"; - } else if (obj.isInstance()) { - return "<String \"" + OopUtilities.stringOopToString(obj) + "\">"; + ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex); + if (obj.isMetaData()) { + Symbol sym = obj.getSymbol(); + return "<String \"" + sym.asString() + "\">"; + } else if (obj.isOop()) { + return "<String \"" + OopUtilities.stringOopToString(obj.getOop()) + "\">"; } else { throw new RuntimeException("should not reach here"); } @@ -178,13 +178,13 @@ // tag change from 'unresolved' to 'klass' does not happen atomically. // We just look at the object at the corresponding index and // decide based on the oop type. - Oop obj = cpool.getObjAt(cpIndex); - if (obj.isKlass()) { - Klass k = (Klass) obj; - return "<Class " + k.getName().asString() + "@" + k.getHandle() + ">"; - } else if (obj.isSymbol()) { - Symbol sym = (Symbol) obj; - return "<Class " + sym.asString() + ">"; + ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex); + if (obj.isOop()) { + Klass k = (Klass) obj.getOop(); + return "<Class " + k.getName().asString() + "@" + k.getHandle() + ">"; + } else if (obj.isMetaData()) { + Symbol sym = obj.getSymbol(); + return "<Class " + sym.asString() + ">"; } else { throw new RuntimeException("should not reach here"); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java Fri Feb 11 23:46:24 2011 -0800 @@ -37,11 +37,11 @@ } public Symbol getClassName() { - Oop obj = method().getConstants().getObjAt(index()); - if (obj instanceof Symbol) { - return (Symbol)obj; + ConstantPool.CPSlot obj = method().getConstants().getSlotAt(index()); + if (obj.isMetaData()) { + return obj.getSymbol(); } else { - return ((Klass)obj).getName(); + return ((Klass)obj.getOop()).getName(); } }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java Fri Feb 11 23:46:24 2011 -0800 @@ -63,7 +63,7 @@ } public Klass klass() { - return (Klass) literal(); + return (Klass)VM.getVM().getObjectHeap().newOop(literalValue().addOffsetToAsOopHandle(0)); } public DictionaryEntry(Address addr) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java Fri Feb 11 23:46:24 2011 -0800 @@ -42,14 +42,14 @@ private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("LoaderConstraintEntry"); - nameField = type.getOopField("_name"); + nameField = type.getAddressField("_name"); numLoadersField = type.getCIntegerField("_num_loaders"); maxLoadersField = type.getCIntegerField("_max_loaders"); loadersField = type.getAddressField("_loaders"); } // Fields - private static sun.jvm.hotspot.types.OopField nameField; + private static AddressField nameField; private static CIntegerField numLoadersField; private static CIntegerField maxLoadersField; private static AddressField loadersField; @@ -57,7 +57,7 @@ // Accessors public Symbol name() { - return (Symbol) VM.getVM().getObjectHeap().newOop(nameField.getValue(addr)); + return Symbol.create(nameField.getValue(addr)); } public int numLoaders() {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java Fri Feb 11 23:46:24 2011 -0800 @@ -58,7 +58,7 @@ } public Symbol klass() { - return (Symbol) literal(); + return Symbol.create(literalValue()); } /* covariant return type :-(
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/StringTable.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/StringTable.java Fri Feb 11 23:46:24 2011 -0800 @@ -70,11 +70,13 @@ } public void stringsDo(StringVisitor visitor) { + ObjectHeap oh = VM.getVM().getObjectHeap(); int numBuckets = tableSize(); for (int i = 0; i < numBuckets; i++) { for (HashtableEntry e = (HashtableEntry) bucket(i); e != null; e = (HashtableEntry) e.next()) { - visitor.visit((Instance) e.literal()); + Instance s = (Instance)oh.newOop(e.literalValue().addOffsetToAsOopHandle(0)); + visitor.visit(s); } } }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SymbolTable.java Fri Feb 11 23:46:24 2011 -0800 @@ -85,7 +85,7 @@ long hashValue = hashSymbol(name); for (HashtableEntry e = (HashtableEntry) bucket(hashToIndex(hashValue)); e != null; e = (HashtableEntry) e.next()) { if (e.hash() == hashValue) { - Symbol sym = (Symbol) e.literal(); + Symbol sym = Symbol.create(e.literalValue()); if (sym.equals(name)) { return sym; } @@ -103,7 +103,7 @@ for (int i = 0; i < numBuckets; i++) { for (HashtableEntry e = (HashtableEntry) bucket(i); e != null; e = (HashtableEntry) e.next()) { - visitor.visit((Symbol) e.literal()); + visitor.visit(Symbol.create(e.literalValue())); } } }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Fri Feb 11 23:46:24 2011 -0800 @@ -35,6 +35,38 @@ // as described in the class file public class ConstantPool extends Oop implements ClassConstants { + + public class CPSlot { + private Address ptr; + + CPSlot(Address ptr) { + this.ptr = ptr; + } + CPSlot(Symbol sym) { + this.ptr = sym.getAddress().orWithMask(1); + } + + public boolean isOop() { + return (ptr.minus(null) & 1) == 0; + } + public boolean isMetaData() { + return (ptr.minus(null) & 1) == 1; + } + + public Symbol getSymbol() { + if (isMetaData()) { + return Symbol.create(ptr.xorWithMask(1)); + } + throw new InternalError("not a symbol"); + } + public Oop getOop() { + if (isOop()) { + return VM.getVM().getObjectHeap().newOop(ptr.addOffsetToAsOopHandle(0)); + } + throw new InternalError("not an oop"); + } + } + // Used for debugging this code private static final boolean DEBUG = false; @@ -110,12 +142,17 @@ return new ConstantTag(getTags().getByteAt((int) index)); } - public Oop getObjAt(long index){ + public CPSlot getSlotAt(long index) { + return new CPSlot(getHandle().getAddressAt(indexOffset(index))); + } + + public Oop getObjAtRaw(long index){ return getHeap().newOop(getHandle().getOopHandleAt(indexOffset(index))); } public Symbol getSymbolAt(long index) { - return (Symbol) getObjAt(index); + CPSlot slot = getSlotAt(index); + return slot.getSymbol(); } public int getIntAt(long index){ @@ -187,7 +224,7 @@ // returns null, if not resolved. public Klass getKlassRefAt(int which) { if( ! getTagAt(which).isKlass()) return null; - return (Klass) getObjAt(which); + return (Klass) getObjAtRaw(which); } // returns null, if not resolved. @@ -477,7 +514,7 @@ case JVM_CONSTANT_Class: { dos.writeByte(cpConstType); // Klass already resolved. ConstantPool constains klassOop. - Klass refKls = (Klass) getObjAt(ci); + Klass refKls = (Klass) getObjAtRaw(ci); String klassName = refKls.getName().asString(); Short s = (Short) utf8ToIndex.get(klassName); dos.writeShort(s.shortValue()); @@ -498,7 +535,7 @@ case JVM_CONSTANT_String: { dos.writeByte(cpConstType); - String str = OopUtilities.stringOopToString(getObjAt(ci)); + String str = OopUtilities.stringOopToString(getObjAtRaw(ci)); Short s = (Short) utf8ToIndex.get(str); dos.writeShort(s.shortValue()); if (DEBUG) debugMessage("CP[" + ci + "] = string " + s);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Fri Feb 11 23:46:24 2011 -0800 @@ -576,7 +576,7 @@ ConstantPool cp = method().getConstants(); int nameAndTypeIdx = cp.name_and_type_ref_index_at(idx); int signatureIdx = cp.signature_ref_index_at(nameAndTypeIdx); - symbolOop signature = cp.symbol_at(signatureIdx); + Symbol* signature = cp.symbol_at(signatureIdx); tty.print("%s", signature.as_C_string()); */ } @@ -616,7 +616,7 @@ constantPoolOop cp = method().constants(); int nameAndTypeIdx = cp.name_and_type_ref_index_at(idx); int signatureIdx = cp.signature_ref_index_at(nameAndTypeIdx); - symbolOop signature = cp.symbol_at(signatureIdx); + Symbol* signature = cp.symbol_at(signatureIdx); tty.print("%s", signature.as_C_string()); */ }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Feb 11 23:46:24 2011 -0800 @@ -82,8 +82,8 @@ classLoader = new OopField(type.getOopField("_class_loader"), Oop.getHeaderSize()); protectionDomain = new OopField(type.getOopField("_protection_domain"), Oop.getHeaderSize()); signers = new OopField(type.getOopField("_signers"), Oop.getHeaderSize()); - sourceFileName = new OopField(type.getOopField("_source_file_name"), Oop.getHeaderSize()); - sourceDebugExtension = new OopField(type.getOopField("_source_debug_extension"), Oop.getHeaderSize()); + sourceFileName = type.getAddressField("_source_file_name"); + sourceDebugExtension = type.getAddressField("_source_debug_extension"); innerClasses = new OopField(type.getOopField("_inner_classes"), Oop.getHeaderSize()); nonstaticFieldSize = new CIntField(type.getCIntegerField("_nonstatic_field_size"), Oop.getHeaderSize()); staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), Oop.getHeaderSize()); @@ -94,7 +94,7 @@ vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), Oop.getHeaderSize()); itableLen = new CIntField(type.getCIntegerField("_itable_len"), Oop.getHeaderSize()); breakpoints = type.getAddressField("_breakpoints"); - genericSignature = new OopField(type.getOopField("_generic_signature"), Oop.getHeaderSize()); + genericSignature = type.getAddressField("_generic_signature"); majorVersion = new CIntField(type.getCIntegerField("_major_version"), Oop.getHeaderSize()); minorVersion = new CIntField(type.getCIntegerField("_minor_version"), Oop.getHeaderSize()); headerSize = alignObjectOffset(Oop.getHeaderSize() + type.getSize()); @@ -135,8 +135,8 @@ private static OopField classLoader; private static OopField protectionDomain; private static OopField signers; - private static OopField sourceFileName; - private static OopField sourceDebugExtension; + private static AddressField sourceFileName; + private static AddressField sourceDebugExtension; private static OopField innerClasses; private static CIntField nonstaticFieldSize; private static CIntField staticFieldSize; @@ -147,7 +147,7 @@ private static CIntField vtableLen; private static CIntField itableLen; private static AddressField breakpoints; - private static OopField genericSignature; + private static AddressField genericSignature; private static CIntField majorVersion; private static CIntField minorVersion; @@ -257,8 +257,8 @@ public Oop getClassLoader() { return classLoader.getValue(this); } public Oop getProtectionDomain() { return protectionDomain.getValue(this); } public ObjArray getSigners() { return (ObjArray) signers.getValue(this); } - public Symbol getSourceFileName() { return (Symbol) sourceFileName.getValue(this); } - public Symbol getSourceDebugExtension(){ return (Symbol) sourceDebugExtension.getValue(this); } + public Symbol getSourceFileName() { return getSymbol(sourceFileName); } + public Symbol getSourceDebugExtension(){ return getSymbol(sourceDebugExtension); } public TypeArray getInnerClasses() { return (TypeArray) innerClasses.getValue(this); } public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); } public long getStaticFieldSize() { return staticFieldSize.getValue(this); } @@ -267,7 +267,7 @@ public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; } public long getVtableLen() { return vtableLen.getValue(this); } public long getItableLen() { return itableLen.getValue(this); } - public Symbol getGenericSignature() { return (Symbol) genericSignature.getValue(this); } + public Symbol getGenericSignature() { return getSymbol(genericSignature); } public long majorVersion() { return majorVersion.getValue(this); } public long minorVersion() { return minorVersion.getValue(this); } @@ -308,12 +308,12 @@ if (ioff != 0) { // only look at classes that are already loaded // since we are looking for the flags for our self. - Oop classInfo = getConstants().getObjAt(ioff); + ConstantPool.CPSlot classInfo = getConstants().getSlotAt(ioff); Symbol name = null; - if (classInfo instanceof Klass) { - name = ((Klass) classInfo).getName(); - } else if (classInfo instanceof Symbol) { - name = (Symbol) classInfo; + if (classInfo.isOop()) { + name = ((Klass) classInfo.getOop()).getName(); + } else if (classInfo.isMetaData()) { + name = classInfo.getSymbol(); } else { throw new RuntimeException("should not reach here"); } @@ -358,12 +358,12 @@ // 'ioff' can be zero. // refer to JVM spec. section 4.7.5. if (ioff != 0) { - Oop iclassInfo = getConstants().getObjAt(ioff); + ConstantPool.CPSlot iclassInfo = getConstants().getSlotAt(ioff); Symbol innerName = null; - if (iclassInfo instanceof Klass) { - innerName = ((Klass) iclassInfo).getName(); - } else if (iclassInfo instanceof Symbol) { - innerName = (Symbol) iclassInfo; + if (iclassInfo.isOop()) { + innerName = ((Klass) iclassInfo.getOop()).getName(); + } else if (iclassInfo.isMetaData()) { + innerName = iclassInfo.getSymbol(); } else { throw new RuntimeException("should not reach here"); } @@ -387,12 +387,12 @@ } } } else { - Oop oclassInfo = getConstants().getObjAt(ooff); + ConstantPool.CPSlot oclassInfo = getConstants().getSlotAt(ooff); Symbol outerName = null; - if (oclassInfo instanceof Klass) { - outerName = ((Klass) oclassInfo).getName(); - } else if (oclassInfo instanceof Symbol) { - outerName = (Symbol) oclassInfo; + if (oclassInfo.isOop()) { + outerName = ((Klass) oclassInfo.getOop()).getName(); + } else if (oclassInfo.isMetaData()) { + outerName = oclassInfo.getSymbol(); } else { throw new RuntimeException("should not reach here"); } @@ -450,7 +450,6 @@ visitor.doOop(classLoader, true); visitor.doOop(protectionDomain, true); visitor.doOop(signers, true); - visitor.doOop(sourceFileName, true); visitor.doOop(innerClasses, true); visitor.doCInt(nonstaticFieldSize, true); visitor.doCInt(staticFieldSize, true); @@ -467,7 +466,7 @@ for (int index = 0; index < length; index += NEXT_OFFSET) { short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); - FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex)); + FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex)); AccessFlags access = new AccessFlags(accessFlags); if (access.isStatic()) { visitField(visitor, type, index); @@ -490,7 +489,7 @@ short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); - FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex)); + FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex)); AccessFlags access = new AccessFlags(accessFlags); if (!access.isStatic()) { visitField(visitor, type, index); @@ -787,7 +786,7 @@ private Field newField(int index) { TypeArray fields = getFields(); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); - FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex)); + FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex)); if (type.isOop()) { if (VM.getVM().isCompressedOopsEnabled()) { return new NarrowOopField(this, index);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java Fri Feb 11 23:46:24 2011 -0800 @@ -53,7 +53,7 @@ javaMirror = new OopField(type.getOopField("_java_mirror"), Oop.getHeaderSize()); superField = new OopField(type.getOopField("_super"), Oop.getHeaderSize()); layoutHelper = new IntField(type.getJIntField("_layout_helper"), Oop.getHeaderSize()); - name = new OopField(type.getOopField("_name"), Oop.getHeaderSize()); + name = type.getAddressField("_name"); accessFlags = new CIntField(type.getCIntegerField("_access_flags"), Oop.getHeaderSize()); subklass = new OopField(type.getOopField("_subklass"), Oop.getHeaderSize()); nextSibling = new OopField(type.getOopField("_next_sibling"), Oop.getHeaderSize()); @@ -83,18 +83,26 @@ private static OopField javaMirror; private static OopField superField; private static IntField layoutHelper; - private static OopField name; + private static AddressField name; private static CIntField accessFlags; private static OopField subklass; private static OopField nextSibling; private static CIntField allocCount; + private Address getValue(AddressField field) { + return getHandle().getAddressAt(field.getOffset() + Oop.getHeaderSize()); + } + + protected Symbol getSymbol(AddressField field) { + return Symbol.create(getHandle().getAddressAt(field.getOffset() + Oop.getHeaderSize())); + } + // Accessors for declared fields public Instance getJavaMirror() { return (Instance) javaMirror.getValue(this); } public Klass getSuper() { return (Klass) superField.getValue(this); } public Klass getJavaSuper() { return null; } public int getLayoutHelper() { return (int) layoutHelper.getValue(this); } - public Symbol getName() { return (Symbol) name.getValue(this); } + public Symbol getName() { return getSymbol(name); } public long getAccessFlags() { return accessFlags.getValue(this); } // Convenience routine public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags()); } @@ -162,7 +170,7 @@ visitor.doOop(javaMirror, true); visitor.doOop(superField, true); visitor.doInt(layoutHelper, true); - visitor.doOop(name, true); + // visitor.doOop(name, true); visitor.doCInt(accessFlags, true); visitor.doOop(subklass, true); visitor.doOop(nextSibling, true);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Fri Feb 11 23:46:24 2011 -0800 @@ -196,11 +196,11 @@ public Address getFromCompiledCodeEntryPoint() { return fromCompiledCodeEntryPointField.getValue(this); } */ // Accessors - public Symbol getName() { return (Symbol) getConstants().getObjAt(getNameIndex()); } - public Symbol getSignature() { return (Symbol) getConstants().getObjAt(getSignatureIndex()); } + public Symbol getName() { return getConstants().getSymbolAt(getNameIndex()); } + public Symbol getSignature() { return getConstants().getSymbolAt(getSignatureIndex()); } public Symbol getGenericSignature() { long index = getGenericSignatureIndex(); - return (index != 0L) ? (Symbol) getConstants().getObjAt(index) : null; + return (index != 0L) ? getConstants().getSymbolAt(index) : null; } // Method holder (the Klass holding this method)
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Fri Feb 11 23:46:24 2011 -0800 @@ -47,7 +47,6 @@ DEBUG = System.getProperty("sun.jvm.hotspot.oops.ObjectHeap.DEBUG") != null; } - private OopHandle symbolKlassHandle; private OopHandle methodKlassHandle; private OopHandle constMethodKlassHandle; private OopHandle methodDataKlassHandle; @@ -68,7 +67,6 @@ private OopHandle arrayKlassKlassHandle; private OopHandle compiledICHolderKlassHandle; - private SymbolKlass symbolKlassObj; private MethodKlass methodKlassObj; private ConstMethodKlass constMethodKlassObj; private MethodDataKlass methodDataKlassObj; @@ -93,9 +91,6 @@ // Lookup the roots in the object hierarchy. Type universeType = db.lookupType("Universe"); - symbolKlassHandle = universeType.getOopField("_symbolKlassObj").getValue(); - symbolKlassObj = new SymbolKlass(symbolKlassHandle, this); - methodKlassHandle = universeType.getOopField("_methodKlassObj").getValue(); methodKlassObj = new MethodKlass(methodKlassHandle, this); @@ -199,7 +194,6 @@ public long getDoubleSize() { return doubleSize; } // Accessors for well-known system classes (from Universe) - public SymbolKlass getSymbolKlassObj() { return symbolKlassObj; } public MethodKlass getMethodKlassObj() { return methodKlassObj; } public ConstMethodKlass getConstMethodKlassObj() { return constMethodKlassObj; } public MethodDataKlass getMethodDataKlassObj() { return methodDataKlassObj; } @@ -337,7 +331,6 @@ // First check if handle is one of the root objects if (handle.equals(methodKlassHandle)) return getMethodKlassObj(); if (handle.equals(constMethodKlassHandle)) return getConstMethodKlassObj(); - if (handle.equals(symbolKlassHandle)) return getSymbolKlassObj(); if (handle.equals(constantPoolKlassHandle)) return getConstantPoolKlassObj(); if (handle.equals(constantPoolCacheKlassHandle)) return getConstantPoolCacheKlassObj(); if (handle.equals(instanceKlassKlassHandle)) return getInstanceKlassKlassObj(); @@ -363,7 +356,6 @@ if (klass != null) { if (klass.equals(methodKlassHandle)) return new Method(handle, this); if (klass.equals(constMethodKlassHandle)) return new ConstMethod(handle, this); - if (klass.equals(symbolKlassHandle)) return new Symbol(handle, this); if (klass.equals(constantPoolKlassHandle)) return new ConstantPool(handle, this); if (klass.equals(constantPoolCacheKlassHandle)) return new ConstantPoolCache(handle, this); if (!VM.getVM().isCore()) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Symbol.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Symbol.java Fri Feb 11 23:46:24 2011 -0800 @@ -34,7 +34,7 @@ // A Symbol is a canonicalized string. // All Symbols reside in global symbolTable. -public class Symbol extends Oop { +public class Symbol extends VMObject { static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -44,9 +44,10 @@ } private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("symbolOopDesc"); - length = new CIntField(type.getCIntegerField("_length"), 0); + Type type = db.lookupType("Symbol"); + length = type.getCIntegerField("_length"); baseOffset = type.getField("_body").getOffset(); + idHash = type.getCIntegerField("_identity_hash"); } // Format: @@ -55,8 +56,15 @@ // [length] byte size of uft8 string // ..body.. - Symbol(OopHandle handle, ObjectHeap heap) { - super(handle, heap); + public static Symbol create(Address addr) { + if (addr == null) { + return null; + } + return new Symbol(addr); + } + + Symbol(Address addr) { + super(addr); } public boolean isSymbol() { return true; } @@ -64,15 +72,19 @@ private static long baseOffset; // tells where the array part starts // Fields - private static CIntField length; + private static CIntegerField length; // Accessors for declared fields - public long getLength() { return length.getValue(this); } + public long getLength() { return length.getValue(this.addr); } public byte getByteAt(long index) { - return getHandle().getJByteAt(baseOffset + index); + return addr.getJByteAt(baseOffset + index); } + private static CIntegerField idHash; + + public int identityHash() { return (int)idHash.getValue(this.addr); } + public boolean equals(byte[] modUTF8Chars) { int l = (int) getLength(); if (l != modUTF8Chars.length) return false; @@ -98,7 +110,9 @@ // Decode the byte array and return the string. try { return readModifiedUTF8(asByteArray()); - } catch(IOException e) { + } catch(Exception e) { + System.err.println(addr); + e.printStackTrace(); return null; } } @@ -111,28 +125,13 @@ tty.print("#" + asString()); } - public long getObjectSize() { - return alignObjectSize(baseOffset + getLength()); - } - - void iterateFields(OopVisitor visitor, boolean doVMFields) { - super.iterateFields(visitor, doVMFields); - if (doVMFields) { - visitor.doCInt(length, true); - int length = (int) getLength(); - for (int index = 0; index < length; index++) { - visitor.doByte(new ByteField(new IndexableFieldIdentifier(index), baseOffset + index, false), true); - } - } - } - /** Note: this comparison is used for vtable sorting only; it doesn't matter what order it defines, as long as it is a total, - time-invariant order Since symbolOops are in permSpace, their + time-invariant order Since Symbol* are in C_HEAP, their relative order in memory never changes, so use address comparison for speed. */ public int fastCompare(Symbol other) { - return (int) getHandle().minus(other.getHandle()); + return (int) addr.minus(other.addr); } private static String readModifiedUTF8(byte[] buf) throws IOException {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/SymbolKlass.java Fri Feb 11 22:57:35 2011 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.oops; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; - -// A SymbolKlass is the klass for all Symbols - -public class SymbolKlass extends Klass { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("symbolKlass"); - headerSize = type.getSize() + Oop.getHeaderSize(); - } - - SymbolKlass(OopHandle handle, ObjectHeap heap) { - super(handle, heap); - } - - private static long headerSize; - - public long getObjectSize() { return alignObjectSize(headerSize); } - - public void printValueOn(PrintStream tty) { - tty.print("SymbolKlass"); - } -}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Fri Feb 11 23:46:24 2011 -0800 @@ -229,7 +229,7 @@ case JVM_CONSTANT_Class: { dos.writeByte(cpConstType); // Klass already resolved. ConstantPool constains klassOop. - Klass refKls = (Klass) cpool.getObjAt(ci); + Klass refKls = (Klass) cpool.getObjAtRaw(ci); String klassName = refKls.getName().asString(); Short s = (Short) utf8ToIndex.get(klassName); @@ -255,7 +255,7 @@ case JVM_CONSTANT_String: { dos.writeByte(cpConstType); - String str = OopUtilities.stringOopToString(cpool.getObjAt(ci)); + String str = OopUtilities.stringOopToString(cpool.getObjAtRaw(ci)); Short s = (Short) utf8ToIndex.get(str); dos.writeShort(s.shortValue()); if (DEBUG) debugMessage("CP[" + ci + "] = string " + s);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Field.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Field.java Fri Feb 11 23:46:24 2011 -0800 @@ -56,7 +56,7 @@ </PRE> FIXME: among other things, this interface is not sufficient to - describe fields which are themselves arrays (like symbolOop's + describe fields which are themselves arrays (like Symbol's jbyte _body[1]). */ public interface Field { /** Get the name of this field */
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Fri Feb 11 23:46:24 2011 -0800 @@ -530,7 +530,7 @@ case JVM_CONSTANT_Class: buf.cell("JVM_CONSTANT_Class"); - Klass klass = (Klass) cpool.getObjAt(index); + Klass klass = (Klass) cpool.getObjAtRaw(index); if (klass instanceof InstanceKlass) { buf.cell(genKlassLink((InstanceKlass) klass)); } else { @@ -555,7 +555,7 @@ case JVM_CONSTANT_String: buf.cell("JVM_CONSTANT_String"); buf.cell("\"" + - escapeHTMLSpecialChars(OopUtilities.stringOopToString(cpool.getObjAt(index))) + "\""); + escapeHTMLSpecialChars(OopUtilities.stringOopToString(cpool.getObjAtRaw(index))) + "\""); break; case JVM_CONSTANT_Fieldref: @@ -672,11 +672,11 @@ buf.beginTag("ul"); for (int exp = 0; exp < exceptions.length; exp++) { short cpIndex = (short) exceptions[exp].getClassCPIndex(); - Oop obj = cpool.getObjAt(cpIndex); - if (obj instanceof Symbol) { - buf.li(((Symbol)obj).asString().replace('/', '.')); + ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex); + if (obj.isMetaData()) { + buf.li((obj.getSymbol()).asString().replace('/', '.')); } else { - buf.li(genKlassLink((InstanceKlass)obj)); + buf.li(genKlassLink((InstanceKlass)obj.getOop())); } } buf.endTag("ul"); @@ -756,7 +756,7 @@ } else if (instr instanceof BytecodeLoadConstant) { BytecodeLoadConstant ldc = (BytecodeLoadConstant) instr; if (ldc.isKlassConstant()) { - Oop oop = ldc.getKlass(); + Object oop = ldc.getKlass(); if (oop instanceof Klass) { buf.append("<a href='"); buf.append(genKlassHref((InstanceKlass) oop)); @@ -803,13 +803,13 @@ buf.cell(Integer.toString(exceptionTable.getIntAt(e + 1))); buf.cell(Integer.toString(exceptionTable.getIntAt(e + 2))); short cpIndex = (short) exceptionTable.getIntAt(e + 3); - Oop obj = cpIndex == 0? null : cpool.getObjAt(cpIndex); + ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex); if (obj == null) { buf.cell("Any"); - } else if (obj instanceof Symbol) { - buf.cell(((Symbol)obj).asString().replace('/', '.')); + } else if (obj.isMetaData()) { + buf.cell(obj.getSymbol().asString().replace('/', '.')); } else { - buf.cell(genKlassLink((InstanceKlass)obj)); + buf.cell(genKlassLink((InstanceKlass)obj.getOop())); } buf.endTag("tr"); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Fri Feb 11 23:46:24 2011 -0800 @@ -40,7 +40,7 @@ private static synchronized void initialize(TypeDataBase db) { // just to confirm that type exists - Type type = db.lookupType("Hashtable"); + Type type = db.lookupType("Hashtable<intptr_t>"); } // derived class may return Class<? extends HashtableEntry>
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HashtableEntry.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HashtableEntry.java Fri Feb 11 23:46:24 2011 -0800 @@ -41,16 +41,16 @@ } private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("HashtableEntry"); - literalField = type.getOopField("_literal"); + Type type = db.lookupType("HashtableEntry<intptr_t>"); + literalField = type.getAddressField("_literal"); } // Fields - private static OopField literalField; + private static AddressField literalField; // Accessors - public Oop literal() { - return VM.getVM().getObjectHeap().newOop(literalField.getValue(addr)); + public Address literalValue() { + return literalField.getValue(addr); } public HashtableEntry(Address addr) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Fri Feb 11 23:46:24 2011 -0800 @@ -740,7 +740,7 @@ for (Iterator itr = fields.iterator(); itr.hasNext();) { Field field = (Field) itr.next(); Symbol name = symTbl.probe(field.getID().getName()); - writeObjectID(name); + writeSymbolID(name); char typeCode = (char) field.getSignature().getByteAt(0); int kind = signatureToHprofKind(typeCode); out.writeByte((byte)kind); @@ -852,7 +852,7 @@ private void writeSymbol(Symbol sym) throws IOException { byte[] buf = sym.asString().getBytes("UTF-8"); writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE); - writeObjectID(sym); + writeSymbolID(sym); out.write(buf); } @@ -869,7 +869,7 @@ out.writeInt(serialNum); writeObjectID(clazz); out.writeInt(DUMMY_STACK_TRACE_ID); - writeObjectID(k.getName()); + writeSymbolID(k.getName()); serialNum++; } catch (IOException exp) { throw new RuntimeException(exp); @@ -901,6 +901,10 @@ writeObjectID(address); } + private void writeSymbolID(Symbol sym) throws IOException { + writeObjectID(getAddressValue(sym.getAddress())); + } + private void writeObjectID(long address) throws IOException { if (OBJ_ID_SIZE == 4) { out.writeInt((int) address);
--- a/hotspot/make/hotspot_version Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/make/hotspot_version Fri Feb 11 23:46:24 2011 -0800 @@ -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=07 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,27 +129,6 @@ } -// Implementation of ArrayStoreExceptionStub - -ArrayStoreExceptionStub::ArrayStoreExceptionStub(CodeEmitInfo* info): - _info(info) { -} - - -void ArrayStoreExceptionStub::emit_code(LIR_Assembler* ce) { - __ bind(_entry); - __ call(Runtime1::entry_for(Runtime1::throw_array_store_exception_id), relocInfo::runtime_call_type); - __ delayed()->nop(); - ce->add_call_info_here(_info); - ce->verify_oop_map(_info); -#ifdef ASSERT - __ should_not_reach_here(); -#endif -} - - - - // Implementation of NewInstanceStub NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id) {
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -710,7 +710,7 @@ case throw_array_store_exception_id: { __ set_info("throw_array_store_exception", dont_gc_arguments); - oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), false); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); } break;
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -2541,7 +2541,7 @@ in_sig_bt[i++] = bt; // Collect remaining bits of signature out_sig_bt[total_c_args++] = bt; if( bt == T_OBJECT) { - symbolOop s = ss.as_symbol_or_null(); + Symbol* s = ss.as_symbol_or_null(); if (s == vmSymbols::java_lang_String()) { total_strings++; out_sig_bt[total_c_args-1] = T_ADDRESS;
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -411,20 +411,6 @@ } -ArrayStoreExceptionStub::ArrayStoreExceptionStub(CodeEmitInfo* info): - _info(info) { -} - - -void ArrayStoreExceptionStub::emit_code(LIR_Assembler* ce) { - assert(__ rsp_offset() == 0, "frame size should be fixed"); - __ bind(_entry); - __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::throw_array_store_exception_id))); - ce->add_call_info_here(_info); - debug_only(__ should_not_reach_here()); -} - - void ArrayCopyStub::emit_code(LIR_Assembler* ce) { //---------------slow case: call to native----------------- __ bind(_entry);
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -733,8 +733,8 @@ // generate compare-and-swap; produces zero condition if swap occurs int value_offset = sun_misc_AtomicLongCSImpl::value_offset(); - LIR_Opr addr = obj.result(); - __ add(addr, LIR_OprFact::intConst(value_offset), addr); + LIR_Opr addr = new_pointer_register(); + __ leal(LIR_OprFact::address(new LIR_Address(obj.result(), value_offset, T_LONG)), addr); LIR_Opr t1 = LIR_OprFact::illegalOpr; // no temp needed LIR_Opr t2 = LIR_OprFact::illegalOpr; // no temp needed __ cas_long(addr, cmp_value.result(), new_value.result(), t1, t2);
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1337,7 +1337,7 @@ { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments); // tos + 0: link // + 1: return address - oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), false); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); } break;
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1974,7 +1974,7 @@ in_sig_bt[i++] = bt; // Collect remaining bits of signature out_sig_bt[total_c_args++] = bt; if( bt == T_OBJECT) { - symbolOop s = ss.as_symbol_or_null(); + Symbol* s = ss.as_symbol_or_null(); // symbol is created if (s == vmSymbols::java_lang_String()) { total_strings++; out_sig_bt[total_c_args-1] = T_ADDRESS;
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1980,7 +1980,7 @@ in_sig_bt[i++] = bt; // Collect remaining bits of signature out_sig_bt[total_c_args++] = bt; if( bt == T_OBJECT) { - symbolOop s = ss.as_symbol_or_null(); + Symbol* s = ss.as_symbol_or_null(); // symbol is created if (s == vmSymbols::java_lang_String()) { total_strings++; out_sig_bt[total_c_args-1] = T_ADDRESS;
--- a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -49,7 +49,7 @@ #include "oops/klass.hpp" #include "oops/methodOop.hpp" #include "oops/oop.hpp" -#include "oops/symbolOop.hpp" +#include "oops/symbol.hpp" #include "runtime/virtualspace.hpp" #include "runtime/vmStructs.hpp" #include "utilities/accessFlags.hpp" @@ -215,8 +215,8 @@ GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE); GEN_VALUE(constMethodOopDesc_has_linenumber_table, constMethodOopDesc::_has_linenumber_table); GEN_OFFS(AccessFlags, _flags); - GEN_OFFS(symbolOopDesc, _length); - GEN_OFFS(symbolOopDesc, _body); + GEN_OFFS(Symbol, _length); + GEN_OFFS(Symbol, _body); printf("\n"); GEN_OFFS(methodOopDesc, _constMethod);
--- a/hotspot/src/os/solaris/dtrace/jhelper.d Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/os/solaris/dtrace/jhelper.d Fri Feb 11 23:46:24 2011 -0800 @@ -114,8 +114,8 @@ copyin_offset(OFFSET_HeapBlockHeader_used); copyin_offset(OFFSET_oopDesc_metadata); - copyin_offset(OFFSET_symbolOopDesc_length); - copyin_offset(OFFSET_symbolOopDesc_body); + copyin_offset(OFFSET_Symbol_length); + copyin_offset(OFFSET_Symbol_body); copyin_offset(OFFSET_methodOopDesc_constMethod); copyin_offset(OFFSET_methodOopDesc_constants); @@ -366,13 +366,13 @@ this->nameIndex * sizeof (pointer) + SIZE_constantPoolOopDesc); this->nameSymbolLength = copyin_uint16(this->nameSymbol + - OFFSET_symbolOopDesc_length); + OFFSET_Symbol_length); this->signatureSymbol = copyin_ptr(this->constantPool + this->signatureIndex * sizeof (pointer) + SIZE_constantPoolOopDesc); this->signatureSymbolLength = copyin_uint16(this->signatureSymbol + - OFFSET_symbolOopDesc_length); + OFFSET_Symbol_length); this->klassPtr = copyin_ptr(this->constantPool + OFFSET_constantPoolOopDesc_pool_holder); @@ -381,7 +381,7 @@ OFFSET_Klass_name + SIZE_oopDesc); this->klassSymbolLength = copyin_uint16(this->klassSymbol + - OFFSET_symbolOopDesc_length); + OFFSET_Symbol_length); /* * Enough for three strings, plus the '.', plus the trailing '\0'. @@ -390,7 +390,7 @@ this->nameSymbolLength + this->signatureSymbolLength + 2 + 1); - copyinto(this->klassSymbol + OFFSET_symbolOopDesc_body, + copyinto(this->klassSymbol + OFFSET_Symbol_body, this->klassSymbolLength, this->result); /* @@ -398,11 +398,11 @@ */ this->result[this->klassSymbolLength] = '.'; - copyinto(this->nameSymbol + OFFSET_symbolOopDesc_body, + copyinto(this->nameSymbol + OFFSET_Symbol_body, this->nameSymbolLength, this->result + this->klassSymbolLength + 1); - copyinto(this->signatureSymbol + OFFSET_symbolOopDesc_body, + copyinto(this->signatureSymbol + OFFSET_Symbol_body, this->signatureSymbolLength, this->result + this->klassSymbolLength + this->nameSymbolLength + 1);
--- a/hotspot/src/os/solaris/dtrace/libjvm_db.c Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c Fri Feb 11 23:46:24 2011 -0800 @@ -524,10 +524,10 @@ CHECK_FAIL(err); err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &nameSymbol); CHECK_FAIL(err); - err = ps_pread(J->P, nameSymbol + OFFSET_symbolOopDesc_length, &nameSymbolLength, 2); + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); CHECK_FAIL(err); nameString = (char*)calloc(nameSymbolLength + 1, 1); - err = ps_pread(J->P, nameSymbol + OFFSET_symbolOopDesc_body, nameString, nameSymbolLength); + err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength); CHECK_FAIL(err); /* To get signature string */ @@ -535,10 +535,10 @@ CHECK_FAIL(err); err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &signatureSymbol); CHECK_FAIL(err); - err = ps_pread(J->P, signatureSymbol + OFFSET_symbolOopDesc_length, &signatureSymbolLength, 2); + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); CHECK_FAIL(err); signatureString = (char*)calloc(signatureSymbolLength + 1, 1); - err = ps_pread(J->P, signatureSymbol + OFFSET_symbolOopDesc_body, signatureString, signatureSymbolLength); + err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength); CHECK_FAIL(err); /* To get klass string */ @@ -546,10 +546,10 @@ CHECK_FAIL(err); err = read_pointer(J, klassPtr + OFFSET_Klass_name + SIZE_oopDesc, &klassSymbol); CHECK_FAIL(err); - err = ps_pread(J->P, klassSymbol + OFFSET_symbolOopDesc_length, &klassSymbolLength, 2); + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2); CHECK_FAIL(err); klassString = (char*)calloc(klassSymbolLength + 1, 1); - err = ps_pread(J->P, klassSymbol + OFFSET_symbolOopDesc_body, klassString, klassSymbolLength); + err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength); CHECK_FAIL(err); result[0] = '\0';
--- a/hotspot/src/os/solaris/vm/dtraceJSDT_solaris.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/os/solaris/vm/dtraceJSDT_solaris.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -142,7 +142,7 @@ ++strcount; for(int prbc = 0; prbc < provider->probe_count; ++prbc) { JVM_DTraceProbe* p = &(provider->probes[prbc]); - symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); // function + name + one per argument strcount += 2 + ArgumentCount(sig).size(); } @@ -178,7 +178,7 @@ stroffs[curstr++] = string_index; string_index += strlen(name) + 1; - symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); SignatureStream ss(sig); for ( ; !ss.at_return_type(); ss.next()) { BasicType bt = ss.type(); @@ -227,7 +227,7 @@ uint32_t argscount = 0; for(int prbc = 0; prbc < provider->probe_count; ++prbc) { JVM_DTraceProbe* p = &(provider->probes[prbc]); - symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); argscount += ArgumentCount(sig).size(); } secoffs[argoffs_sec] = align_size_up(offset, alignment_for[ARG_OFFSETS]); @@ -298,7 +298,7 @@ strcpy(str, name); str += strlen(name) + 1; - symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); SignatureStream ss(sig); for ( ; !ss.at_return_type(); ss.next()) { BasicType bt = ss.type(); @@ -433,7 +433,7 @@ uint8_t* par = (uint8_t*)(dof + sec->dofs_offset); for (int prbc = 0; prbc < provider->probe_count; ++prbc) { JVM_DTraceProbe* p = &(provider->probes[prbc]); - symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + Symbol* sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); uint8_t count = (uint8_t)ArgumentCount(sig).size(); for (uint8_t i = 0; i < count; ++i) { *par++ = i;
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -898,4 +898,4 @@ void Canonicalizer::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {} void Canonicalizer::do_ProfileCall(ProfileCall* x) {} void Canonicalizer::do_ProfileInvoke(ProfileInvoke* x) {} - +void Canonicalizer::do_RuntimeCall(RuntimeCall* x) {}
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,6 +102,7 @@ virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); virtual void do_ProfileCall (ProfileCall* x); virtual void do_ProfileInvoke (ProfileInvoke* x); + virtual void do_RuntimeCall (RuntimeCall* x); }; #endif // SHARE_VM_C1_C1_CANONICALIZER_HPP
--- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -476,18 +476,12 @@ -class ArrayStoreExceptionStub: public CodeStub { +class ArrayStoreExceptionStub: public SimpleExceptionStub { private: CodeEmitInfo* _info; public: - ArrayStoreExceptionStub(CodeEmitInfo* info); - virtual void emit_code(LIR_Assembler* emit); - virtual CodeEmitInfo* info() const { return _info; } - virtual bool is_exception_throw_stub() const { return true; } - virtual void visit(LIR_OpVisitState* visitor) { - visitor->do_slow_case(_info); - } + ArrayStoreExceptionStub(LIR_Opr obj, CodeEmitInfo* info): SimpleExceptionStub(Runtime1::throw_array_store_exception_id, obj, info) {} #ifndef PRODUCT virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); } #endif // PRODUCT
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1396,6 +1396,13 @@ if (continuation() != NULL) { assert(!method()->is_synchronized() || InlineSynchronizedMethods, "can not inline synchronized methods yet"); + if (compilation()->env()->dtrace_method_probes()) { + // Report exit from inline methods + Values* args = new Values(1); + args->push(append(new Constant(new ObjectConstant(method())))); + append(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args)); + } + // If the inlined method is synchronized, the monitor must be // released before we jump to the continuation block. if (method()->is_synchronized()) { @@ -3301,6 +3308,13 @@ Value exception = append_with_bci(new ExceptionObject(), SynchronizationEntryBCI); assert(exception->is_pinned(), "must be"); + if (compilation()->env()->dtrace_method_probes()) { + // Report exit from inline methods + Values* args = new Values(1); + args->push(append(new Constant(new ObjectConstant(method())))); + append(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args)); + } + int bci = SynchronizationEntryBCI; if (lock) { assert(state()->locks_size() > 0 && state()->lock_at(state()->locks_size() - 1) == lock, "lock is missing"); @@ -3486,6 +3500,11 @@ inline_sync_entry(lock, sync_handler); } + if (compilation()->env()->dtrace_method_probes()) { + Values* args = new Values(1); + args->push(append(new Constant(new ObjectConstant(method())))); + append(new RuntimeCall(voidType, "dtrace_method_entry", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), args)); + } BlockBegin* callee_start_block = block_at(0); if (callee_start_block != NULL) {
--- a/hotspot/src/share/vm/c1/c1_Instruction.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,6 +106,7 @@ class UnsafePrefetchWrite; class ProfileCall; class ProfileInvoke; +class RuntimeCall; // A Value is a reference to the instruction creating the value typedef Instruction* Value; @@ -202,6 +203,7 @@ virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) = 0; virtual void do_ProfileCall (ProfileCall* x) = 0; virtual void do_ProfileInvoke (ProfileInvoke* x) = 0; + virtual void do_RuntimeCall (RuntimeCall* x) = 0; }; @@ -2267,6 +2269,38 @@ virtual void input_values_do(ValueVisitor* f) { if (_recv != NULL) f->visit(&_recv); } }; + +// Call some C runtime function that doesn't safepoint, +// optionally passing the current thread as the first argument. +LEAF(RuntimeCall, Instruction) + private: + const char* _entry_name; + address _entry; + Values* _args; + bool _pass_thread; // Pass the JavaThread* as an implicit first argument + + public: + RuntimeCall(ValueType* type, const char* entry_name, address entry, Values* args, bool pass_thread = true) + : Instruction(type) + , _entry(entry) + , _args(args) + , _entry_name(entry_name) + , _pass_thread(pass_thread) { + ASSERT_VALUES + pin(); + } + + const char* entry_name() const { return _entry_name; } + address entry() const { return _entry; } + int number_of_arguments() const { return _args->length(); } + Value argument_at(int i) const { return _args->at(i); } + bool pass_thread() const { return _pass_thread; } + + virtual void input_values_do(ValueVisitor* f) { + for (int i = 0; i < _args->length(); i++) f->visit(_args->adr_at(i)); + } +}; + // Use to trip invocation counter of an inlined method LEAF(ProfileInvoke, Instruction)
--- a/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -841,4 +841,13 @@ } +void InstructionPrinter::do_RuntimeCall(RuntimeCall* x) { + output()->print("call_rt %s(", x->entry_name()); + for (int i = 0; i < x->number_of_arguments(); i++) { + if (i > 0) output()->print(", "); + print_value(x->argument_at(i)); + } + output()->put(')'); +} + #endif // PRODUCT
--- a/hotspot/src/share/vm/c1/c1_InstructionPrinter.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_InstructionPrinter.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,6 +131,7 @@ virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); virtual void do_ProfileCall (ProfileCall* x); virtual void do_ProfileInvoke (ProfileInvoke* x); + virtual void do_RuntimeCall (RuntimeCall* x); }; #endif // PRODUCT
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -396,7 +396,7 @@ , _should_profile(false) { if (code == lir_store_check) { - _stub = new ArrayStoreExceptionStub(info_for_exception); + _stub = new ArrayStoreExceptionStub(object, info_for_exception); assert(info_for_exception != NULL, "store_check throws exceptions"); } else { ShouldNotReachHere();
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -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 @@ -2741,6 +2741,31 @@ } } +void LIRGenerator::do_RuntimeCall(RuntimeCall* x) { + LIR_OprList* args = new LIR_OprList(x->number_of_arguments()); + BasicTypeList* signature = new BasicTypeList(x->number_of_arguments()); + + if (x->pass_thread()) { + signature->append(T_ADDRESS); + args->append(getThreadPointer()); + } + + for (int i = 0; i < x->number_of_arguments(); i++) { + Value a = x->argument_at(i); + LIRItem* item = new LIRItem(a, this); + item->load_item(); + args->append(item->result()); + signature->append(as_BasicType(a->type())); + } + + LIR_Opr result = call_runtime(signature, args, x->entry(), x->type(), NULL); + if (x->type() == voidType) { + set_no_result(x); + } else { + __ move(result, rlock_result(x)); + } +} + LIR_Opr LIRGenerator::call_runtime(Value arg1, address entry, ValueType* result_type, CodeEmitInfo* info) { LIRItemList args(1); LIRItem value(arg1, this);
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -522,6 +522,7 @@ virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); virtual void do_ProfileCall (ProfileCall* x); virtual void do_ProfileInvoke (ProfileInvoke* x); + virtual void do_RuntimeCall (RuntimeCall* x); };
--- a/hotspot/src/share/vm/c1/c1_Optimizer.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_Optimizer.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -496,6 +496,7 @@ void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x); void do_ProfileCall (ProfileCall* x); void do_ProfileInvoke (ProfileInvoke* x); + void do_RuntimeCall (RuntimeCall* x); }; @@ -664,6 +665,7 @@ void NullCheckVisitor::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {} void NullCheckVisitor::do_ProfileCall (ProfileCall* x) { nce()->clear_last_explicit_null_check(); } void NullCheckVisitor::do_ProfileInvoke (ProfileInvoke* x) {} +void NullCheckVisitor::do_RuntimeCall (RuntimeCall* x) {} void NullCheckEliminator::visit(Value* p) {
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -339,8 +339,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
--- a/hotspot/src/share/vm/c1/c1_Runtime1.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -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 @@ -143,9 +143,9 @@ static void throw_index_exception(JavaThread* thread, int index); static void throw_div0_exception(JavaThread* thread); static void throw_null_pointer_exception(JavaThread* thread); - static void throw_class_cast_exception(JavaThread* thread, oopDesc* obect); + static void throw_class_cast_exception(JavaThread* thread, oopDesc* object); static void throw_incompatible_class_change_error(JavaThread* thread); - static void throw_array_store_exception(JavaThread* thread); + static void throw_array_store_exception(JavaThread* thread, oopDesc* object); static void monitorenter(JavaThread* thread, oopDesc* obj, BasicObjectLock* lock); static void monitorexit (JavaThread* thread, BasicObjectLock* lock);
--- a/hotspot/src/share/vm/c1/c1_ValueMap.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/c1/c1_ValueMap.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -192,11 +192,12 @@ void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ } void do_RoundFP (RoundFP* x) { /* nothing to do */ } void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ } - void do_ProfileInvoke (ProfileInvoke* x) { /* nothing to do */ }; void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ } void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ } void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ } void do_ProfileCall (ProfileCall* x) { /* nothing to do */ } + void do_ProfileInvoke (ProfileInvoke* x) { /* nothing to do */ }; + void do_RuntimeCall (RuntimeCall* x) { /* nothing to do */ }; };
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -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++) {
--- a/hotspot/src/share/vm/ci/ciClassList.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciClassList.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -60,7 +60,6 @@ class ciKlass; class ciInstanceKlass; class ciMethodKlass; -class ciSymbolKlass; class ciArrayKlass; class ciObjArrayKlass; class ciTypeArrayKlass; @@ -112,7 +111,6 @@ friend class ciKlass; \ friend class ciInstanceKlass; \ friend class ciMethodKlass; \ -friend class ciSymbolKlass; \ friend class ciArrayKlass; \ friend class ciObjArrayKlass; \ friend class ciTypeArrayKlass; \
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -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; @@ -202,6 +201,7 @@ ciEnv::~ciEnv() { CompilerThread* current_thread = CompilerThread::current(); + _factory->remove_symbols(); current_thread->set_env(NULL); } @@ -234,7 +234,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. @@ -261,7 +261,7 @@ if (_ArrayIndexOutOfBoundsException_instance == NULL) { _ArrayIndexOutOfBoundsException_instance = get_or_create_exception(_ArrayIndexOutOfBoundsException_handle, - vmSymbolHandles::java_lang_ArrayIndexOutOfBoundsException()); + vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); } return _ArrayIndexOutOfBoundsException_instance; } @@ -269,7 +269,7 @@ if (_ArrayStoreException_instance == NULL) { _ArrayStoreException_instance = get_or_create_exception(_ArrayStoreException_handle, - vmSymbolHandles::java_lang_ArrayStoreException()); + vmSymbols::java_lang_ArrayStoreException()); } return _ArrayStoreException_instance; } @@ -277,7 +277,7 @@ if (_ClassCastException_instance == NULL) { _ClassCastException_instance = get_or_create_exception(_ClassCastException_handle, - vmSymbolHandles::java_lang_ClassCastException()); + vmSymbols::java_lang_ClassCastException()); } return _ClassCastException_instance; } @@ -377,14 +377,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 @@ -430,13 +432,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 @@ -475,7 +478,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. @@ -490,10 +493,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); } } } @@ -501,7 +504,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()) { @@ -519,7 +522,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; @@ -605,7 +608,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()) { @@ -613,8 +616,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 { @@ -674,33 +677,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(); @@ -721,8 +722,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(); @@ -738,8 +739,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)); } @@ -759,7 +760,7 @@ // compiler, but it is simpler to stop the code path here with an unlinked method. if (!is_resolved) { ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); - ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol(); + ciSymbol* sig_sym = get_symbol(cpool->signature_ref_at(index)); return get_unloaded_method(mh_klass, ciSymbol::invokeExact_name(), sig_sym); }
--- a/hotspot/src/share/vm/ci/ciEnv.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciEnv.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -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; @@ -160,8 +159,8 @@ klassOop resolved_klassOop); methodOop lookup_method(instanceKlass* accessor, instanceKlass* holder, - symbolOop name, - symbolOop sig, + Symbol* name, + Symbol* sig, Bytecodes::Code bc); // Get a ciObject from the object factory. Ensures uniqueness @@ -174,9 +173,18 @@ } } + ciSymbol* get_symbol(Symbol* o) { + if (o == NULL) { + ShouldNotReachHere(); + return NULL; + } else { + return _factory->get_symbol(o); + } + } + ciMethod* get_method_from_handle(jobject method); - ciInstance* get_or_create_exception(jobject& handle, symbolHandle name); + ciInstance* get_or_create_exception(jobject& handle, Symbol* name); // Get a ciMethod representing either an unfound method or // a method with an unloaded holder. Ensures uniqueness of
--- a/hotspot/src/share/vm/ci/ciField.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciField.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -79,15 +79,15 @@ constantPoolHandle cpool(thread, klass->get_instanceKlass()->constants()); // Get the field's name, signature, and type. - symbolHandle name (thread, cpool->name_ref_at(index)); - _name = ciEnv::current(thread)->get_object(name())->as_symbol(); + Symbol* name = cpool->name_ref_at(index); + _name = ciEnv::current(thread)->get_symbol(name); int nt_index = cpool->name_and_type_ref_index_at(index); int sig_index = cpool->signature_ref_index_at(nt_index); - symbolHandle signature (thread, cpool->symbol_at(sig_index)); - _signature = ciEnv::current(thread)->get_object(signature())->as_symbol(); + Symbol* signature = cpool->symbol_at(sig_index); + _signature = ciEnv::current(thread)->get_symbol(signature); - BasicType field_type = FieldType::basic_type(signature()); + BasicType field_type = FieldType::basic_type(signature); // If the field is a pointer type, get the klass of the // field. @@ -100,7 +100,7 @@ _type = ciType::make(field_type); } - _name = (ciSymbol*)ciEnv::current(thread)->get_object(name()); + _name = (ciSymbol*)ciEnv::current(thread)->get_symbol(name); // Get the field's declared holder. // @@ -130,7 +130,7 @@ // Perform the field lookup. fieldDescriptor field_desc; klassOop canonical_holder = - loaded_decl_holder->find_field(name(), signature(), &field_desc); + loaded_decl_holder->find_field(name, signature, &field_desc); if (canonical_holder == NULL) { // Field lookup failed. Will be detected by will_link. _holder = declared_holder; @@ -150,8 +150,8 @@ // Get the field's name, signature, and type. ciEnv* env = CURRENT_ENV; - _name = env->get_object(fd->name())->as_symbol(); - _signature = env->get_object(fd->signature())->as_symbol(); + _name = env->get_symbol(fd->name()); + _signature = env->get_symbol(fd->signature()); BasicType field_type = fd->field_type();
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -380,7 +380,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; } @@ -541,8 +541,8 @@ ciMethod* ciInstanceKlass::find_method(ciSymbol* name, ciSymbol* signature) { VM_ENTRY_MARK; instanceKlass* k = get_instanceKlass(); - symbolOop name_sym = name->get_symbolOop(); - symbolOop sig_sym= signature->get_symbolOop(); + Symbol* name_sym = name->get_symbol(); + Symbol* sig_sym= signature->get_symbol(); methodOop m = k->find_method(name_sym, sig_sym); if (m == NULL) return NULL;
--- a/hotspot/src/share/vm/ci/ciKlass.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciKlass.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -39,9 +39,9 @@ assert(get_oop()->is_klass(), "wrong type"); Klass* k = get_Klass(); _layout_helper = k->layout_helper(); - symbolOop klass_name = k->name(); + Symbol* klass_name = k->name(); assert(klass_name != NULL, "wrong ciKlass constructor"); - _name = CURRENT_ENV->get_object(klass_name)->as_symbol(); + _name = CURRENT_ENV->get_symbol(klass_name); } // ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciMethod.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -122,9 +122,9 @@ // generating _signature may allow GC and therefore move m. // These fields are always filled in. - _name = env->get_object(h_m()->name())->as_symbol(); + _name = env->get_symbol(h_m()->name()); _holder = env->get_object(h_m()->method_holder())->as_instance_klass(); - ciSymbol* sig_symbol = env->get_object(h_m()->signature())->as_symbol(); + ciSymbol* sig_symbol = env->get_symbol(h_m()->signature()); _signature = new (env->arena()) ciSignature(_holder, sig_symbol); _method_data = NULL; // Take a snapshot of these values, so they will be commensurate with the MDO. @@ -649,8 +649,8 @@ KlassHandle caller_klass (THREAD, caller->get_klassOop()); KlassHandle h_recv (THREAD, exact_receiver->get_klassOop()); KlassHandle h_resolved (THREAD, holder()->get_klassOop()); - symbolHandle h_name (THREAD, name()->get_symbolOop()); - symbolHandle h_signature (THREAD, signature()->get_symbolOop()); + Symbol* h_name = name()->get_symbol(); + Symbol* h_signature = signature()->get_symbol(); methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, @@ -702,8 +702,8 @@ KlassHandle caller_klass (THREAD, caller->get_klassOop()); KlassHandle h_recv (THREAD, receiver->get_klassOop()); - symbolHandle h_name (THREAD, name()->get_symbolOop()); - symbolHandle h_signature (THREAD, signature()->get_symbolOop()); + Symbol* h_name = name()->get_symbol(); + Symbol* h_signature = signature()->get_symbol(); vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, h_recv, h_name, h_signature, caller_klass); if (vtable_index == methodOopDesc::nonvirtual_vtable_index) {
--- a/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -110,7 +110,7 @@ EXCEPTION_CONTEXT; int element_len = element_name->utf8_length(); - symbolOop base_name_sym = element_name->get_symbolOop(); + Symbol* base_name_sym = element_name->get_symbol(); char* name; if (base_name_sym->byte_at(0) == '[' ||
--- a/hotspot/src/share/vm/ci/ciObject.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciObject.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -268,10 +268,6 @@ assert(is_type_array_klass(), "bad cast"); return (ciTypeArrayKlass*)this; } - ciSymbolKlass* as_symbol_klass() { - assert(is_symbol_klass(), "bad cast"); - return (ciSymbolKlass*)this; - } ciKlassKlass* as_klass_klass() { assert(is_klass_klass(), "bad cast"); return (ciKlassKlass*)this;
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -38,7 +38,6 @@ #include "ci/ciObjArrayKlassKlass.hpp" #include "ci/ciObjectFactory.hpp" #include "ci/ciSymbol.hpp" -#include "ci/ciSymbolKlass.hpp" #include "ci/ciTypeArray.hpp" #include "ci/ciTypeArrayKlass.hpp" #include "ci/ciTypeArrayKlassKlass.hpp" @@ -98,6 +97,8 @@ _unloaded_instances = new (arena) GrowableArray<ciInstance*>(arena, 4, 0, NULL); _return_addresses = new (arena) GrowableArray<ciReturnAddress*>(arena, 8, 0, NULL); + + _symbols = new (arena) GrowableArray<ciSymbol*>(arena, 100, 0, NULL); } // ------------------------------------------------------------------ @@ -127,19 +128,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 } @@ -157,8 +158,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 = @@ -188,7 +187,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); @@ -218,6 +217,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 // @@ -255,15 +278,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); @@ -297,11 +311,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()) { @@ -312,8 +322,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); @@ -426,22 +434,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 { @@ -573,6 +579,10 @@ obj->set_ident(_next_ident++); } +void ciObjectFactory::init_ident_of(ciSymbol* obj) { + obj->set_ident(_next_ident++); +} + // ------------------------------------------------------------------ // ciObjectFactory::find
--- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -48,6 +48,7 @@ GrowableArray<ciKlass*>* _unloaded_klasses; GrowableArray<ciInstance*>* _unloaded_instances; GrowableArray<ciReturnAddress*>* _return_addresses; + GrowableArray<ciSymbol*>* _symbols; // keep list of symbols created int _next_ident; public: @@ -76,6 +77,7 @@ void insert_non_perm(NonPermObject* &where, oop key, ciObject* obj); void init_ident_of(ciObject* obj); + void init_ident_of(ciSymbol* obj); Arena* arena() { return _arena; } @@ -88,13 +90,15 @@ static void initialize(); void init_shared_objects(); + void remove_symbols(); ciObjectFactory(Arena* arena, int expected_size); - // Get the ciObject corresponding to some oop. ciObject* get(oop key); + ciSymbol* get_symbol(Symbol* key); + // Get the ciSymbol corresponding to one of the vmSymbols. static ciSymbol* vm_symbol_at(int index);
--- a/hotspot/src/share/vm/ci/ciSignature.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciSignature.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -47,7 +47,8 @@ int size = 0; int count = 0; - symbolHandle sh (THREAD, symbol->get_symbolOop()); + ResourceMark rm(THREAD); + Symbol* sh = symbol->get_symbol(); SignatureStream ss(sh); for (; ; ss.next()) { // Process one element of the signature @@ -55,14 +56,14 @@ if (!ss.is_object()) { type = ciType::make(ss.type()); } else { - symbolOop name = ss.as_symbol(THREAD); + Symbol* name = ss.as_symbol(THREAD); if (HAS_PENDING_EXCEPTION) { type = ss.is_array() ? (ciType*)ciEnv::unloaded_ciobjarrayklass() : (ciType*)ciEnv::unloaded_ciinstance_klass(); env->record_out_of_memory_failure(); CLEAR_PENDING_EXCEPTION; } else { - ciSymbol* klass_name = env->get_object(name)->as_symbol(); + ciSymbol* klass_name = env->get_symbol(name); type = env->get_klass_by_name_impl(_accessing_klass, klass_name, false); } }
--- a/hotspot/src/share/vm/ci/ciSignature.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciSignature.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -48,7 +48,7 @@ void get_all_klasses(); - symbolOop get_symbolOop() const { return _symbol->get_symbolOop(); } + Symbol* get_symbol() const { return _symbol->get_symbol(); } public: ciSymbol* as_symbol() const { return _symbol; }
--- a/hotspot/src/share/vm/ci/ciSymbol.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciSymbol.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -30,23 +30,27 @@ // ------------------------------------------------------------------ // ciSymbol::ciSymbol // -// Preallocated handle variant. Used with handles from vmSymboHandles. -ciSymbol::ciSymbol(symbolHandle h_s, vmSymbols::SID sid) - : ciObject(h_s), _sid(sid) +// Preallocated symbol variant. Used with symbols from vmSymbols. +ciSymbol::ciSymbol(Symbol* s, vmSymbols::SID sid) + : _symbol(s), _sid(sid) { + assert(_symbol != NULL, "adding null symbol"); + _symbol->increment_refcount(); // increment ref count assert(sid_ok(), "must be in vmSymbols"); } // Normal case for non-famous symbols. -ciSymbol::ciSymbol(symbolOop s) - : ciObject(s), _sid(vmSymbols::NO_SID) +ciSymbol::ciSymbol(Symbol* s) + : _symbol(s), _sid(vmSymbols::NO_SID) { + assert(_symbol != NULL, "adding null symbol"); + _symbol->increment_refcount(); // increment ref count assert(sid_ok(), "must not be in vmSymbols"); } // ciSymbol // -// This class represents a symbolOop in the HotSpot virtual +// This class represents a Symbol* in the HotSpot virtual // machine. // ------------------------------------------------------------------ @@ -55,20 +59,20 @@ // The text of the symbol as a null-terminated C string. const char* ciSymbol::as_utf8() { VM_QUICK_ENTRY_MARK; - symbolOop s = get_symbolOop(); + Symbol* s = get_symbol(); return s->as_utf8(); } // ------------------------------------------------------------------ // ciSymbol::base -jbyte* ciSymbol::base() { - GUARDED_VM_ENTRY(return get_symbolOop()->base();) +const jbyte* ciSymbol::base() { + GUARDED_VM_ENTRY(return get_symbol()->base();) } // ------------------------------------------------------------------ // ciSymbol::byte_at int ciSymbol::byte_at(int i) { - GUARDED_VM_ENTRY(return get_symbolOop()->byte_at(i);) + GUARDED_VM_ENTRY(return get_symbol()->byte_at(i);) } // ------------------------------------------------------------------ @@ -76,7 +80,7 @@ // // Tests if the symbol starts with the given prefix. bool ciSymbol::starts_with(const char* prefix, int len) const { - GUARDED_VM_ENTRY(return get_symbolOop()->starts_with(prefix, len);) + GUARDED_VM_ENTRY(return get_symbol()->starts_with(prefix, len);) } // ------------------------------------------------------------------ @@ -84,13 +88,13 @@ // // Determines where the symbol contains the given substring. int ciSymbol::index_of_at(int i, const char* str, int len) const { - GUARDED_VM_ENTRY(return get_symbolOop()->index_of_at(i, str, len);) + GUARDED_VM_ENTRY(return get_symbol()->index_of_at(i, str, len);) } // ------------------------------------------------------------------ // ciSymbol::utf8_length int ciSymbol::utf8_length() { - GUARDED_VM_ENTRY(return get_symbolOop()->utf8_length();) + GUARDED_VM_ENTRY(return get_symbol()->utf8_length();) } // ------------------------------------------------------------------ @@ -107,7 +111,7 @@ // // Print the value of this symbol on an outputStream void ciSymbol::print_symbol_on(outputStream *st) { - GUARDED_VM_ENTRY(get_symbolOop()->print_symbol_on(st);) + GUARDED_VM_ENTRY(get_symbol()->print_symbol_on(st);) } // ------------------------------------------------------------------ @@ -116,15 +120,13 @@ // Make a ciSymbol from a C string (implementation). ciSymbol* ciSymbol::make_impl(const char* s) { EXCEPTION_CONTEXT; - // For some reason, oopFactory::new_symbol doesn't declare its - // char* argument as const. - symbolOop sym = oopFactory::new_symbol((char*)s, (int)strlen(s), THREAD); + TempNewSymbol sym = SymbolTable::new_symbol(s, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; CURRENT_THREAD_ENV->record_out_of_memory_failure(); return ciEnv::_unloaded_cisymbol; } - return CURRENT_THREAD_ENV->get_object(sym)->as_symbol(); + return CURRENT_THREAD_ENV->get_symbol(sym); } // ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciSymbol.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/ciSymbol.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -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,24 +48,28 @@ 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 - symbolOop get_symbolOop() const { return (symbolOop)get_oop(); } + Symbol* get_symbol() const { return _symbol; } const char* type_string() { return "ciSymbol"; } 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; } @@ -79,9 +86,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); @@ -96,6 +100,13 @@ static ciSymbol* name() { return ciObjectFactory::vm_symbol_at(vmSymbols::VM_SYMBOL_ENUM_NAME(name)); } VM_SYMBOLS_DO(CI_SYMBOL_DECLARE, CI_SYMBOL_DECLARE) #undef CI_SYMBOL_DECLARE + + void print() { + _symbol->print(); + } + + // Are two ciSymbols equal? + bool equals(ciSymbol* obj) { return this->_symbol == obj->get_symbol(); } }; #endif // SHARE_VM_CI_CISYMBOL_HPP
--- a/hotspot/src/share/vm/ci/ciSymbolKlass.cpp Fri Feb 11 22:57:35 2011 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "ci/ciSymbolKlass.hpp" -#include "ci/ciUtilities.hpp" - -// ciSymbolKlass -// -// This class represents a klassOop in the HotSpot virtual machine -// whose Klass part is a symbolKlass. - -// ------------------------------------------------------------------ -// ciSymbolKlass::instance -// -// Return the distinguished instance of this class -ciSymbolKlass* ciSymbolKlass::make() { - return CURRENT_ENV->_symbol_klass_instance; -}
--- a/hotspot/src/share/vm/ci/ciSymbolKlass.hpp Fri Feb 11 22:57:35 2011 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_CI_CISYMBOLKLASS_HPP -#define SHARE_VM_CI_CISYMBOLKLASS_HPP - -#include "ci/ciKlass.hpp" -#include "ci/ciSymbol.hpp" - -// ciSymbolKlass -// -// This class represents a klassOop in the HotSpot virtual machine -// whose Klass part in a symbolKlass. Although, in the VM -// Klass hierarchy, symbolKlass is a direct subclass of typeArrayKlass, -// we do not model this relationship in the ciObject hierarchy -- the -// subclassing is used to share implementation and is not of note -// to compiler writers. -class ciSymbolKlass : public ciKlass { - CI_PACKAGE_ACCESS - -protected: - ciSymbolKlass(KlassHandle h_k) - : ciKlass(h_k, ciSymbol::make("unique_symbolKlass")) { - assert(get_Klass()->oop_is_symbol(), "wrong type"); - } - - symbolKlass* get_symbolKlass() { return (symbolKlass*)get_Klass(); } - - const char* type_string() { return "ciSymbolKlass"; } - -public: - // What kind of ciObject is this? - bool is_symbol_klass() { return true; } - - // Return the distinguished ciSymbolKlass instance. - static ciSymbolKlass* make(); -}; - -#endif // SHARE_VM_CI_CISYMBOLKLASS_HPP
--- a/hotspot/src/share/vm/ci/compilerInterface.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/ci/compilerInterface.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -49,7 +49,6 @@ #include "ci/ciSignature.hpp" #include "ci/ciStreams.hpp" #include "ci/ciSymbol.hpp" -#include "ci/ciSymbolKlass.hpp" #include "ci/ciTypeArray.hpp" #include "ci/ciTypeArrayKlass.hpp" #include "ci/ciTypeArrayKlassKlass.hpp"
--- a/hotspot/src/share/vm/classfile/classFileError.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/classFileError.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -31,25 +31,25 @@ void ClassFileParser::classfile_parse_error(const char* msg, TRAPS) { ResourceMark rm(THREAD); - Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbolHandles::java_lang_ClassFormatError(), + Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), msg, _class_name->as_C_string()); } void ClassFileParser::classfile_parse_error(const char* msg, int index, TRAPS) { ResourceMark rm(THREAD); - Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbolHandles::java_lang_ClassFormatError(), + Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), msg, index, _class_name->as_C_string()); } void ClassFileParser::classfile_parse_error(const char* msg, const char *name, TRAPS) { ResourceMark rm(THREAD); - Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbolHandles::java_lang_ClassFormatError(), + Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), msg, name, _class_name->as_C_string()); } void ClassFileParser::classfile_parse_error(const char* msg, int index, const char *name, TRAPS) { ResourceMark rm(THREAD); - Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbolHandles::java_lang_ClassFormatError(), + Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), msg, index, name, _class_name->as_C_string()); } @@ -57,7 +57,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_ClassFormatError(), + vmSymbols::java_lang_ClassFormatError(), "StackMapTable format error: %s", msg ); }
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -41,7 +41,7 @@ #include "oops/klassOop.hpp" #include "oops/klassVtable.hpp" #include "oops/methodOop.hpp" -#include "oops/symbolOop.hpp" +#include "oops/symbol.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/javaCalls.hpp" #include "runtime/perfData.hpp" @@ -267,14 +267,14 @@ } unsigned int hash; - symbolOop result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash); + Symbol* result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash); if (result == NULL) { names[names_count] = (char*)utf8_buffer; lengths[names_count] = utf8_length; indices[names_count] = index; hashValues[names_count++] = hash; if (names_count == SymbolTable::symbol_alloc_batch_size) { - oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); + SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); names_count = 0; } } else { @@ -291,7 +291,7 @@ // Allocate the remaining symbols if (names_count > 0) { - oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); + SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); } // Copy _current pointer of local copy back to stream(). @@ -301,6 +301,23 @@ cfs0->set_current(cfs1.current()); } +// This class unreferences constant pool symbols if an error has occurred +// while parsing the class before it is assigned into the class. +// If it gets an error after that it is unloaded and the constant pool will +// be cleaned up then. +class ConstantPoolCleaner : public StackObj { + constantPoolHandle _cphandle; + bool _in_error; + public: + ConstantPoolCleaner(constantPoolHandle cp) : _cphandle(cp), _in_error(true) {} + ~ConstantPoolCleaner() { + if (_in_error && _cphandle.not_null()) { + _cphandle->unreference_symbols(); + } + } + void set_in_error(bool clean) { _in_error = clean; } +}; + bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { @@ -319,6 +336,7 @@ constantPoolHandle cp (THREAD, constant_pool); cp->set_partially_loaded(); // Enables heap verify to work on partial constantPoolOops + ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up. // parsing constant pool entries parse_constant_pool_entries(cp, length, CHECK_(nullHandle)); @@ -411,7 +429,7 @@ cp->tag_at(string_index).is_utf8(), "Invalid constant pool index %u in class file %s", string_index, CHECK_(nullHandle)); - symbolOop sym = cp->symbol_at(string_index); + Symbol* sym = cp->symbol_at(string_index); cp->unresolved_string_at_put(index, sym); } break; @@ -526,6 +544,7 @@ } if (!_need_verify) { + cp_in_error.set_in_error(false); return cp; } @@ -535,7 +554,7 @@ jbyte tag = cp->tag_at(index).value(); switch (tag) { case JVM_CONSTANT_UnresolvedClass: { - symbolHandle class_name(THREAD, cp->unresolved_klass_at(index)); + Symbol* class_name = cp->unresolved_klass_at(index); // check the name, even if _cp_patches will overwrite it verify_legal_class_name(class_name, CHECK_(nullHandle)); break; @@ -544,8 +563,8 @@ if (_need_verify && _major_version >= JAVA_7_VERSION) { int sig_index = cp->signature_ref_index_at(index); int name_index = cp->name_ref_index_at(index); - symbolHandle name(THREAD, cp->symbol_at(name_index)); - symbolHandle sig(THREAD, cp->symbol_at(sig_index)); + Symbol* name = cp->symbol_at(name_index); + Symbol* sig = cp->symbol_at(sig_index); if (sig->byte_at(0) == JVM_SIGNATURE_FUNC) { verify_legal_method_signature(name, sig, CHECK_(nullHandle)); } else { @@ -562,8 +581,8 @@ int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index); // already verified to be utf8 int signature_ref_index = cp->signature_ref_index_at(name_and_type_ref_index); - symbolHandle name(THREAD, cp->symbol_at(name_ref_index)); - symbolHandle signature(THREAD, cp->symbol_at(signature_ref_index)); + Symbol* name = cp->symbol_at(name_ref_index); + Symbol* signature = cp->symbol_at(signature_ref_index); if (tag == JVM_CONSTANT_Fieldref) { verify_legal_field_name(name, CHECK_(nullHandle)); if (_need_verify && _major_version >= JAVA_7_VERSION) { @@ -590,11 +609,11 @@ } if (tag == JVM_CONSTANT_Methodref) { // 4509014: If a class method name begins with '<', it must be "<init>". - assert(!name.is_null(), "method name in constant pool is null"); + assert(name != NULL, "method name in constant pool is null"); unsigned int name_len = name->utf8_length(); assert(name_len > 0, "bad method name"); // already verified as legal name if (name->byte_at(0) == '<') { - if (name() != vmSymbols::object_initializer_name()) { + if (name != vmSymbols::object_initializer_name()) { classfile_parse_error( "Bad method name at constant pool index %u in class file %s", name_ref_index, CHECK_(nullHandle)); @@ -615,15 +634,15 @@ { int name_and_type_ref_index = cp->name_and_type_ref_index_at(ref_index); int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index); - symbolHandle name(THREAD, cp->symbol_at(name_ref_index)); + Symbol* name = cp->symbol_at(name_ref_index); if (ref_kind == JVM_REF_newInvokeSpecial) { - if (name() != vmSymbols::object_initializer_name()) { + if (name != vmSymbols::object_initializer_name()) { classfile_parse_error( "Bad constructor name at constant pool index %u in class file %s", name_ref_index, CHECK_(nullHandle)); } } else { - if (name() == vmSymbols::object_initializer_name()) { + if (name == vmSymbols::object_initializer_name()) { classfile_parse_error( "Bad method name at constant pool index %u in class file %s", name_ref_index, CHECK_(nullHandle)); @@ -636,14 +655,18 @@ break; } case JVM_CONSTANT_MethodType: { - symbolHandle no_name = vmSymbolHandles::type_name(); // place holder - symbolHandle signature(THREAD, cp->method_type_signature_at(index)); + Symbol* no_name = vmSymbols::type_name(); // place holder + Symbol* signature = cp->method_type_signature_at(index); verify_legal_method_signature(no_name, signature, CHECK_(nullHandle)); break; } + case JVM_CONSTANT_Utf8: { + assert(cp->symbol_at(index)->refcount() != 0, "count corrupted"); + } } // end of switch } // end of for + cp_in_error.set_in_error(false); return cp; } @@ -665,8 +688,8 @@ guarantee_property(java_lang_String::is_instance(patch()), "Illegal class patch at %d in class file %s", index, CHECK); - symbolHandle name = java_lang_String::as_symbol(patch(), CHECK); - cp->unresolved_klass_at_put(index, name()); + Symbol* name = java_lang_String::as_symbol(patch(), CHECK); + cp->unresolved_klass_at_put(index, name); } break; @@ -717,15 +740,15 @@ class NameSigHash: public ResourceObj { public: - symbolOop _name; // name - symbolOop _sig; // signature + Symbol* _name; // name + Symbol* _sig; // signature NameSigHash* _next; // Next entry in hash table }; #define HASH_ROW_SIZE 256 -unsigned int hash(symbolOop name, symbolOop sig) { +unsigned int hash(Symbol* name, Symbol* sig) { unsigned int raw_hash = 0; raw_hash += ((unsigned int)(uintptr_t)name) >> (LogHeapWordSize + 2); raw_hash += ((unsigned int)(uintptr_t)sig) >> LogHeapWordSize; @@ -742,8 +765,8 @@ // Return true if no duplicate is found. And name/sig is added as a new entry in table. // The old format checker uses heap sort to find duplicates. // NOTE: caller should guarantee that GC doesn't happen during the life cycle -// of table since we don't expect symbolOop's to move. -bool put_after_lookup(symbolOop name, symbolOop sig, NameSigHash** table) { +// of table since we don't expect Symbol*'s to move. +bool put_after_lookup(Symbol* name, Symbol* sig, NameSigHash** table) { assert(name != NULL, "name in constant pool is NULL"); // First lookup for duplicates @@ -773,7 +796,7 @@ int length, Handle class_loader, Handle protection_domain, - symbolHandle class_name, + Symbol* class_name, TRAPS) { ClassFileStream* cfs = stream(); assert(length > 0, "only called for length>0"); @@ -793,7 +816,7 @@ if (cp->tag_at(interface_index).is_klass()) { interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index)); } else { - symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index)); + Symbol* unresolved_klass = cp->klass_name_at(interface_index); // Don't need to check legal name because it's checked when parsing constant pool. // But need to make sure it's not an array type. @@ -830,7 +853,7 @@ debug_only(No_Safepoint_Verifier nsv;) for (index = 0; index < length; index++) { klassOop k = (klassOop)interfaces->obj_at(index); - symbolOop name = instanceKlass::cast(k)->name(); + Symbol* name = instanceKlass::cast(k)->name(); // If no duplicates, add (name, NULL) in hashtable interface_names. if (!put_after_lookup(name, NULL, interface_names)) { dup = true; @@ -908,7 +931,7 @@ "Invalid field attribute index %u in class file %s", attribute_name_index, CHECK); - symbolOop attribute_name = cp->symbol_at(attribute_name_index); + Symbol* attribute_name = cp->symbol_at(attribute_name_index); if (is_static && attribute_name == vmSymbols::tag_constant_value()) { // ignore if non-static if (constantvalue_index != 0) { @@ -1031,7 +1054,7 @@ valid_cp_range(name_index, cp_size) && cp->tag_at(name_index).is_utf8(), "Invalid constant pool index %u for field name in class file %s", name_index, CHECK_(nullHandle)); - symbolHandle name(THREAD, cp->symbol_at(name_index)); + Symbol* name = cp->symbol_at(name_index); verify_legal_field_name(name, CHECK_(nullHandle)); u2 signature_index = cfs->get_u2_fast(); @@ -1040,7 +1063,7 @@ cp->tag_at(signature_index).is_utf8(), "Invalid constant pool index %u for field signature in class file %s", signature_index, CHECK_(nullHandle)); - symbolHandle sig(THREAD, cp->symbol_at(signature_index)); + Symbol* sig = cp->symbol_at(signature_index); verify_legal_field_signature(name, sig, CHECK_(nullHandle)); u2 constantvalue_index = 0; @@ -1166,9 +1189,9 @@ debug_only(No_Safepoint_Verifier nsv;) for (int i = 0; i < length*instanceKlass::next_offset; i += instanceKlass::next_offset) { int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); - symbolOop name = cp->symbol_at(name_index); + Symbol* name = cp->symbol_at(name_index); int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset); - symbolOop sig = cp->symbol_at(sig_index); + Symbol* sig = cp->symbol_at(sig_index); // If no duplicates, add name/signature in hashtable names_and_sigs. if (!put_after_lookup(name, sig, names_and_sigs)) { dup = true; @@ -1422,16 +1445,16 @@ "Signature index %u in %s has bad constant type in class file %s", descriptor_index, tbl_name, CHECK_NULL); - symbolHandle name(THREAD, cp->symbol_at(name_index)); - symbolHandle sig(THREAD, cp->symbol_at(descriptor_index)); + Symbol* name = cp->symbol_at(name_index); + Symbol* sig = cp->symbol_at(descriptor_index); verify_legal_field_name(name, CHECK_NULL); u2 extra_slot = 0; if (!isLVTT) { verify_legal_field_signature(name, sig, CHECK_NULL); // 4894874: check special cases for double and long local variables - if (sig() == vmSymbols::type_signature(T_DOUBLE) || - sig() == vmSymbols::type_signature(T_LONG)) { + if (sig == vmSymbols::type_signature(T_DOUBLE) || + sig == vmSymbols::type_signature(T_LONG)) { extra_slot = 1; } } @@ -1539,7 +1562,7 @@ } void ClassFileParser::throwIllegalSignature( - const char* type, symbolHandle name, symbolHandle sig, TRAPS) { + const char* type, Symbol* name, Symbol* sig, TRAPS) { ResourceMark rm(THREAD); Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_ClassFormatError(), @@ -1580,7 +1603,7 @@ cp->tag_at(name_index).is_utf8(), "Illegal constant pool index %u for method name in class file %s", name_index, CHECK_(nullHandle)); - symbolHandle name(THREAD, cp->symbol_at(name_index)); + Symbol* name = cp->symbol_at(name_index); verify_legal_method_name(name, CHECK_(nullHandle)); u2 signature_index = cfs->get_u2_fast(); @@ -1589,7 +1612,7 @@ cp->tag_at(signature_index).is_utf8(), "Illegal constant pool index %u for method signature in class file %s", signature_index, CHECK_(nullHandle)); - symbolHandle signature(THREAD, cp->symbol_at(signature_index)); + Symbol* signature = cp->symbol_at(signature_index); AccessFlags access_flags; if (name == vmSymbols::class_initializer_name()) { @@ -1660,7 +1683,7 @@ "Invalid method attribute name index %u in class file %s", method_attribute_name_index, CHECK_(nullHandle)); - symbolOop method_attribute_name = cp->symbol_at(method_attribute_name_index); + Symbol* method_attribute_name = cp->symbol_at(method_attribute_name_index); if (method_attribute_name == vmSymbols::tag_code()) { // Parse Code attribute if (_need_verify) { @@ -2057,16 +2080,16 @@ 0, CHECK_(nullHandle)); - if (name() == vmSymbols::finalize_method_name() && - signature() == vmSymbols::void_method_signature()) { + if (name == vmSymbols::finalize_method_name() && + signature == vmSymbols::void_method_signature()) { if (m->is_empty_method()) { _has_empty_finalizer = true; } else { _has_finalizer = true; } } - if (name() == vmSymbols::object_initializer_name() && - signature() == vmSymbols::void_method_signature() && + if (name == vmSymbols::object_initializer_name() && + signature == vmSymbols::void_method_signature() && m->is_vanilla_constructor()) { _has_vanilla_constructor = true; } @@ -2193,7 +2216,7 @@ } } // Sort method array by ascending method name (for faster lookups & vtable construction) - // Note that the ordering is not alphabetical, see symbolOopDesc::fast_compare + // Note that the ordering is not alphabetical, see Symbol::fast_compare methodOopDesc::sort_methods(methods(), methods_annotations(), methods_parameter_annotations(), @@ -2242,9 +2265,10 @@ if (JvmtiExport::can_get_source_debug_extension()) { // Optimistically assume that only 1 byte UTF format is used // (common case) - symbolOop sde_symbol = oopFactory::new_symbol((char*)sde_buffer, - length, CHECK); + TempNewSymbol sde_symbol = SymbolTable::new_symbol((const char*)sde_buffer, length, CHECK); k->set_source_debug_extension(sde_symbol); + // Note that set_source_debug_extension() increments the reference count + // for its copy of the Symbol*, so use a TempNewSymbol here. } // Got utf8 string, set stream position forward cfs->skip_u1(length, CHECK); @@ -2440,7 +2464,7 @@ cp->tag_at(attribute_name_index).is_utf8(), "Attribute name has bad constant pool index %u in class file %s", attribute_name_index, CHECK); - symbolOop tag = cp->symbol_at(attribute_name_index); + Symbol* tag = cp->symbol_at(attribute_name_index); if (tag == vmSymbols::tag_source_file()) { // Check for SourceFile tag if (_need_verify) { @@ -2607,7 +2631,7 @@ case T_OBJECT: { #ifdef ASSERT - symbolOop sym = oopFactory::new_symbol("Ljava/lang/String;", CHECK); + TempNewSymbol sym = SymbolTable::new_symbol("Ljava/lang/String;", CHECK); assert(fd->signature() == sym, "just checking"); #endif oop string = fd->string_initial_value(CHECK); @@ -2650,8 +2674,8 @@ (*fields_ptr)()->ushort_at(i + instanceKlass::name_index_offset); int sig_index = (*fields_ptr)()->ushort_at(i + instanceKlass::signature_index_offset); - symbolOop f_name = cp->symbol_at(name_index); - symbolOop f_sig = cp->symbol_at(sig_index); + Symbol* f_name = cp->symbol_at(name_index); + Symbol* f_sig = cp->symbol_at(sig_index); if (f_sig == vmSymbols::reference_signature() && reference_index == 0) { // Save the index for reference signature for later use. // The fake discovered field does not entries in the @@ -2805,9 +2829,8 @@ int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset); int acc_flags = fields->ushort_at(i + instanceKlass::access_flags_offset); - symbolOop f_name = cp->symbol_at(name_index); - symbolOop f_sig = cp->symbol_at(sig_index); - + Symbol* f_name = cp->symbol_at(name_index); + Symbol* f_sig = cp->symbol_at(sig_index); if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) { if (f_sig == vmSymbols::machine_word_signature()) { // If the signature of vmentry is already changed, we're done. @@ -2841,12 +2864,12 @@ } -instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, +instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, Handle class_loader, Handle protection_domain, KlassHandle host_klass, GrowableArray<Handle>* cp_patches, - symbolHandle& parsed_name, + TempNewSymbol& parsed_name, bool verify, TRAPS) { // So that JVMTI can cache class file in the state before retransformable agents @@ -2899,7 +2922,7 @@ cfs->set_verify(_need_verify); // Save the class file name for easier error message printing. - _class_name = name.not_null()? name : vmSymbolHandles::unknown_class_name(); + _class_name = (name != NULL) ? name : vmSymbols::unknown_class_name(); cfs->guarantee_more(8, CHECK_(nullHandle)); // magic, major, minor // Magic value @@ -2914,10 +2937,10 @@ // Check version numbers - we check this even with verifier off if (!is_supported_version(major_version, minor_version)) { - if (name.is_null()) { + if (name == NULL) { Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_UnsupportedClassVersionError(), + vmSymbols::java_lang_UnsupportedClassVersionError(), "Unsupported major.minor version %u.%u", major_version, minor_version); @@ -2925,7 +2948,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_UnsupportedClassVersionError(), + vmSymbols::java_lang_UnsupportedClassVersionError(), "%s : Unsupported major.minor version %u.%u", name->as_C_string(), major_version, @@ -2944,6 +2967,8 @@ // Constant pool constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle)); + ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up. + int cp_size = cp->length(); cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len @@ -2968,12 +2993,15 @@ "Invalid this class index %u in constant pool in class file %s", this_class_index, CHECK_(nullHandle)); - symbolHandle class_name (THREAD, cp->unresolved_klass_at(this_class_index)); - assert(class_name.not_null(), "class_name can't be null"); + Symbol* class_name = cp->unresolved_klass_at(this_class_index); + assert(class_name != NULL, "class_name can't be null"); // It's important to set parsed_name *before* resolving the super class. // (it's used for cleanup by the caller if parsing fails) parsed_name = class_name; + // parsed_name is returned and can be used if there's an error, so add to + // its reference count. Caller will decrement the refcount. + parsed_name->increment_refcount(); // Update _class_name which could be null previously to be class_name _class_name = class_name; @@ -2993,11 +3021,11 @@ { HandleMark hm(THREAD); // Checks if name in class file matches requested name - if (name.not_null() && class_name() != name()) { + if (name != NULL && class_name != name) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_NoClassDefFoundError(), + vmSymbols::java_lang_NoClassDefFoundError(), "%s (wrong name: %s)", name->as_C_string(), class_name->as_C_string() @@ -3006,14 +3034,14 @@ } if (TraceClassLoadingPreorder) { - tty->print("[Loading %s", name()->as_klass_external_name()); + tty->print("[Loading %s", name->as_klass_external_name()); if (cfs->source() != NULL) tty->print(" from %s", cfs->source()); tty->print_cr("]"); } u2 super_class_index = cfs->get_u2_fast(); if (super_class_index == 0) { - check_property(class_name() == vmSymbols::java_lang_Object(), + check_property(class_name == vmSymbols::java_lang_Object(), "Invalid superclass index %u in class file %s", super_class_index, CHECK_(nullHandle)); @@ -3075,11 +3103,11 @@ // We check super class after class file is parsed and format is checked if (super_class_index > 0 && super_klass.is_null()) { - symbolHandle sk (THREAD, cp->klass_name_at(super_class_index)); + Symbol* sk = cp->klass_name_at(super_class_index); if (access_flags.is_interface()) { // Before attempting to resolve the superclass, check for class format // errors not checked yet. - guarantee_property(sk() == vmSymbols::java_lang_Object(), + guarantee_property(sk == vmSymbols::java_lang_Object(), "Interfaces must have java.lang.Object as superclass in class file %s", CHECK_(nullHandle)); } @@ -3100,7 +3128,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_IncompatibleClassChangeError(), + vmSymbols::java_lang_IncompatibleClassChangeError(), "class %s has interface %s as super class", class_name->as_klass_external_name(), super_klass->external_name() @@ -3193,18 +3221,18 @@ next_nonstatic_field_offset = first_nonstatic_field_offset; // Add fake fields for java.lang.Class instances (also see below) - if (class_name() == vmSymbols::java_lang_Class() && class_loader.is_null()) { + if (class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) { java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle)); } // adjust the vmentry field declaration in java.dyn.MethodHandle - if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { + if (EnableMethodHandles && class_name == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { java_dyn_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); } // Add a fake "discovered" field if it is not present // for compatibility with earlier jdk's. - if (class_name() == vmSymbols::java_lang_ref_Reference() + if (class_name == vmSymbols::java_lang_ref_Reference() && class_loader.is_null()) { java_lang_ref_Reference_fix_pre(&fields, cp, &fac, CHECK_(nullHandle)); } @@ -3236,7 +3264,7 @@ // Add fake fields for java.lang.Class instances (also see above). // FieldsAllocationStyle and CompactFields values will be reset to default. - if(class_name() == vmSymbols::java_lang_Class() && class_loader.is_null()) { + if(class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) { java_lang_Class_fix_post(&next_nonstatic_field_offset); nonstatic_oop_offsets[0] = first_nonstatic_field_offset; const uint fake_oop_count = (next_nonstatic_field_offset - @@ -3279,22 +3307,22 @@ // (see in JavaClasses::compute_hard_coded_offsets()). // Use default fields allocation order for them. if( (allocation_style != 0 || compact_fields ) && class_loader.is_null() && - (class_name() == vmSymbols::java_lang_AssertionStatusDirectives() || - class_name() == vmSymbols::java_lang_Class() || - class_name() == vmSymbols::java_lang_ClassLoader() || - class_name() == vmSymbols::java_lang_ref_Reference() || - class_name() == vmSymbols::java_lang_ref_SoftReference() || - class_name() == vmSymbols::java_lang_StackTraceElement() || - class_name() == vmSymbols::java_lang_String() || - class_name() == vmSymbols::java_lang_Throwable() || - class_name() == vmSymbols::java_lang_Boolean() || - class_name() == vmSymbols::java_lang_Character() || - class_name() == vmSymbols::java_lang_Float() || - class_name() == vmSymbols::java_lang_Double() || - class_name() == vmSymbols::java_lang_Byte() || - class_name() == vmSymbols::java_lang_Short() || - class_name() == vmSymbols::java_lang_Integer() || - class_name() == vmSymbols::java_lang_Long())) { + (class_name == vmSymbols::java_lang_AssertionStatusDirectives() || + class_name == vmSymbols::java_lang_Class() || + class_name == vmSymbols::java_lang_ClassLoader() || + class_name == vmSymbols::java_lang_ref_Reference() || + class_name == vmSymbols::java_lang_ref_SoftReference() || + class_name == vmSymbols::java_lang_StackTraceElement() || + class_name == vmSymbols::java_lang_String() || + class_name == vmSymbols::java_lang_Throwable() || + class_name == vmSymbols::java_lang_Boolean() || + class_name == vmSymbols::java_lang_Character() || + class_name == vmSymbols::java_lang_Float() || + class_name == vmSymbols::java_lang_Double() || + class_name == vmSymbols::java_lang_Byte() || + class_name == vmSymbols::java_lang_Short() || + class_name == vmSymbols::java_lang_Integer() || + class_name == vmSymbols::java_lang_Long())) { allocation_style = 0; // Allocate oops first compact_fields = false; // Don't compact fields } @@ -3543,6 +3571,7 @@ this_klass->set_has_nonstatic_fields(has_nonstatic_fields); this_klass->set_static_oop_field_size(fac.static_oop_count); cp->set_pool_holder(this_klass()); + error_handler.set_in_error(false); // turn off error handler for cp this_klass->set_constants(cp()); this_klass->set_local_interfaces(local_interfaces()); this_klass->set_fields(fields()); @@ -3935,7 +3964,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_IllegalAccessError(), + vmSymbols::java_lang_IllegalAccessError(), "class %s cannot access its superclass %s", this_klass->external_name(), instanceKlass::cast(super)->external_name() @@ -3955,7 +3984,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_IllegalAccessError(), + vmSymbols::java_lang_IllegalAccessError(), "class %s cannot access its superinterface %s", this_klass->external_name(), instanceKlass::cast(k)->external_name() @@ -3979,8 +4008,8 @@ (!m->is_static()) && (m->name() != vmSymbols::object_initializer_name())) { - symbolOop name = m->name(); - symbolOop signature = m->signature(); + Symbol* name = m->name(); + Symbol* signature = m->signature(); klassOop k = this_klass->super(); methodOop super_m = NULL; while (k != NULL) { @@ -4003,7 +4032,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_VerifyError(), + vmSymbols::java_lang_VerifyError(), "class %s overrides final method %s.%s", this_klass->external_name(), name->as_C_string(), @@ -4037,7 +4066,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_VerifyError(), + vmSymbols::java_lang_VerifyError(), "Illegal static method %s in interface %s", m->name()->as_C_string(), this_klass->external_name() @@ -4067,7 +4096,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_ClassFormatError(), + vmSymbols::java_lang_ClassFormatError(), "Illegal class modifiers in class %s: 0x%X", _class_name->as_C_string(), flags ); @@ -4127,7 +4156,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_ClassFormatError(), + vmSymbols::java_lang_ClassFormatError(), "Illegal field modifiers in class %s: 0x%X", _class_name->as_C_string(), flags); return; @@ -4135,7 +4164,7 @@ } void ClassFileParser::verify_legal_method_modifiers( - jint flags, bool is_interface, symbolHandle name, TRAPS) { + jint flags, bool is_interface, Symbol* name, TRAPS) { if (!_need_verify) { return; } const bool is_public = (flags & JVM_ACC_PUBLIC) != 0; @@ -4180,7 +4209,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_ClassFormatError(), + vmSymbols::java_lang_ClassFormatError(), "Method %s in class %s has illegal modifiers: 0x%X", name->as_C_string(), _class_name->as_C_string(), flags); return; @@ -4251,7 +4280,7 @@ } // Checks if name is a legal class name. -void ClassFileParser::verify_legal_class_name(symbolHandle name, TRAPS) { +void ClassFileParser::verify_legal_class_name(Symbol* name, TRAPS) { if (!_need_verify || _relax_verify) { return; } char buf[fixed_buffer_size]; @@ -4281,7 +4310,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_ClassFormatError(), + vmSymbols::java_lang_ClassFormatError(), "Illegal class name \"%s\" in class file %s", bytes, _class_name->as_C_string() ); @@ -4290,7 +4319,7 @@ } // Checks if name is a legal field name. -void ClassFileParser::verify_legal_field_name(symbolHandle name, TRAPS) { +void ClassFileParser::verify_legal_field_name(Symbol* name, TRAPS) { if (!_need_verify || _relax_verify) { return; } char buf[fixed_buffer_size]; @@ -4314,7 +4343,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_ClassFormatError(), + vmSymbols::java_lang_ClassFormatError(), "Illegal field name \"%s\" in class %s", bytes, _class_name->as_C_string() ); @@ -4323,10 +4352,10 @@ } // Checks if name is a legal method name. -void ClassFileParser::verify_legal_method_name(symbolHandle name, TRAPS) { +void ClassFileParser::verify_legal_method_name(Symbol* name, TRAPS) { if (!_need_verify || _relax_verify) { return; } - assert(!name.is_null(), "method name is null"); + assert(name != NULL, "method name is null"); char buf[fixed_buffer_size]; char* bytes = name->as_utf8_flexible_buffer(THREAD, buf, fixed_buffer_size); unsigned int length = name->utf8_length(); @@ -4351,7 +4380,7 @@ ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, - vmSymbolHandles::java_lang_ClassFormatError(), + vmSymbols::java_lang_ClassFormatError(), "Illegal method name \"%s\" in class %s", bytes, _class_name->as_C_string() ); @@ -4361,7 +4390,7 @@ // Checks if signature is a legal field signature. -void ClassFileParser::verify_legal_field_signature(symbolHandle name, symbolHandle signature, TRAPS) { +void ClassFileParser::verify_legal_field_signature(Symbol* name, Symbol* signature, TRAPS) { if (!_need_verify) { return; } char buf[fixed_buffer_size]; @@ -4376,7 +4405,7 @@ // Checks if signature is a legal method signature. // Returns number of parameters -int ClassFileParser::verify_legal_method_signature(symbolHandle name, symbolHandle signature, TRAPS) { +int ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signature, TRAPS) { if (!_need_verify) { // make sure caller's args_size will be less than 0 even for non-static // method so it will be recomputed in compute_size_of_parameters(). @@ -4508,8 +4537,8 @@ // public static boolean isJavaIdentifierStart(char ch); JavaCalls::call_static(&result, klass, - vmSymbolHandles::isJavaIdentifierStart_name(), - vmSymbolHandles::int_bool_signature(), + vmSymbols::isJavaIdentifierStart_name(), + vmSymbols::int_bool_signature(), &args, THREAD); @@ -4525,8 +4554,8 @@ // public static boolean isJavaIdentifierPart(char ch); JavaCalls::call_static(&result, klass, - vmSymbolHandles::isJavaIdentifierPart_name(), - vmSymbolHandles::int_bool_signature(), + vmSymbols::isJavaIdentifierPart_name(), + vmSymbols::int_bool_signature(), &args, THREAD);
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -32,6 +32,7 @@ #include "runtime/handles.inline.hpp" #include "utilities/accessFlags.hpp" +class TempNewSymbol; // Parser for for .class files // // The bytes describing the class file structure is read from a Stream object @@ -42,7 +43,7 @@ bool _relax_verify; u2 _major_version; u2 _minor_version; - symbolHandle _class_name; + Symbol* _class_name; KlassHandle _host_klass; GrowableArray<Handle>* _cp_patches; // overrides for CP entries @@ -73,7 +74,7 @@ int length, Handle class_loader, Handle protection_domain, - symbolHandle class_name, + Symbol* class_name, TRAPS); // Field parsing @@ -209,21 +210,21 @@ } void throwIllegalSignature( - const char* type, symbolHandle name, symbolHandle sig, TRAPS); + const char* type, Symbol* name, Symbol* sig, TRAPS); bool is_supported_version(u2 major, u2 minor); bool has_illegal_visibility(jint flags); void verify_constantvalue(int constantvalue_index, int signature_index, constantPoolHandle cp, TRAPS); void verify_legal_utf8(const unsigned char* buffer, int length, TRAPS); - void verify_legal_class_name(symbolHandle name, TRAPS); - void verify_legal_field_name(symbolHandle name, TRAPS); - void verify_legal_method_name(symbolHandle name, TRAPS); - void verify_legal_field_signature(symbolHandle fieldname, symbolHandle signature, TRAPS); - int verify_legal_method_signature(symbolHandle methodname, symbolHandle signature, TRAPS); + void verify_legal_class_name(Symbol* name, TRAPS); + void verify_legal_field_name(Symbol* name, TRAPS); + void verify_legal_method_name(Symbol* name, TRAPS); + void verify_legal_field_signature(Symbol* fieldname, Symbol* signature, TRAPS); + int verify_legal_method_signature(Symbol* methodname, Symbol* signature, TRAPS); void verify_legal_class_modifiers(jint flags, TRAPS); void verify_legal_field_modifiers(jint flags, bool is_interface, TRAPS); - void verify_legal_method_modifiers(jint flags, bool is_interface, symbolHandle name, TRAPS); + void verify_legal_method_modifiers(jint flags, bool is_interface, Symbol* name, TRAPS); bool verify_unqualified_name(char* name, unsigned int length, int type); char* skip_over_field_name(char* name, bool slash_ok, unsigned int length); char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS); @@ -272,21 +273,21 @@ // // "parsed_name" is updated by this method, and is the name found // while parsing the stream. - instanceKlassHandle parseClassFile(symbolHandle name, + instanceKlassHandle parseClassFile(Symbol* name, Handle class_loader, Handle protection_domain, - symbolHandle& parsed_name, + TempNewSymbol& parsed_name, bool verify, TRAPS) { KlassHandle no_host_klass; return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, verify, THREAD); } - instanceKlassHandle parseClassFile(symbolHandle name, + instanceKlassHandle parseClassFile(Symbol* name, Handle class_loader, Handle protection_domain, KlassHandle host_klass, GrowableArray<Handle>* cp_patches, - symbolHandle& parsed_name, + TempNewSymbol& parsed_name, bool verify, TRAPS);
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/classLoader.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -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);
--- a/hotspot/src/share/vm/classfile/classLoader.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/classLoader.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -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.
--- a/hotspot/src/share/vm/classfile/dictionary.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/dictionary.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -36,7 +36,7 @@ Dictionary::Dictionary(int table_size) - : TwoOopHashtable(table_size, sizeof(DictionaryEntry)) { + : TwoOopHashtable<klassOop>(table_size, sizeof(DictionaryEntry)) { _current_class_index = 0; _current_class_entry = NULL; }; @@ -45,7 +45,7 @@ Dictionary::Dictionary(int table_size, HashtableBucket* t, int number_of_entries) - : TwoOopHashtable(table_size, sizeof(DictionaryEntry), t, number_of_entries) { + : TwoOopHashtable<klassOop>(table_size, sizeof(DictionaryEntry), t, number_of_entries) { _current_class_index = 0; _current_class_entry = NULL; }; @@ -54,7 +54,7 @@ DictionaryEntry* Dictionary::new_entry(unsigned int hash, klassOop klass, oop loader) { DictionaryEntry* entry; - entry = (DictionaryEntry*)Hashtable::new_entry(hash, klass); + entry = (DictionaryEntry*)Hashtable<klassOop>::new_entry(hash, klass); entry->set_loader(loader); entry->set_pd_set(NULL); return entry; @@ -62,7 +62,7 @@ DictionaryEntry* Dictionary::new_entry() { - DictionaryEntry* entry = (DictionaryEntry*)Hashtable::new_entry(0L, NULL); + DictionaryEntry* entry = (DictionaryEntry*)Hashtable<klassOop>::new_entry(0L, NULL); entry->set_loader(NULL); entry->set_pd_set(NULL); return entry; @@ -76,7 +76,7 @@ entry->set_pd_set(to_delete->next()); delete to_delete; } - Hashtable::free_entry(entry); + Hashtable<klassOop>::free_entry(entry); } @@ -298,7 +298,7 @@ for (DictionaryEntry *probe = bucket(index); probe != NULL; probe = probe->next()) { - oop e = probe->klass(); + klassOop e = probe->klass(); oop class_loader = probe->loader(); if (is_strongly_reachable(class_loader, e)) { blk->do_oop((oop*)probe->klass_addr()); @@ -421,11 +421,11 @@ // also cast to volatile; we do this to ensure store order is maintained // by the compilers. -void Dictionary::add_klass(symbolHandle class_name, Handle class_loader, +void Dictionary::add_klass(Symbol* class_name, Handle class_loader, KlassHandle obj) { assert_locked_or_safepoint(SystemDictionary_lock); assert(obj() != NULL, "adding NULL obj"); - assert(Klass::cast(obj())->name() == class_name(), "sanity check on name"); + assert(Klass::cast(obj())->name() == class_name, "sanity check on name"); unsigned int hash = compute_hash(class_name, class_loader); int index = hash_to_index(hash); @@ -444,15 +444,14 @@ // Callers should be aware that an entry could be added just after // _buckets[index] is read here, so the caller will not see the new entry. DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash, - symbolHandle class_name, + Symbol* class_name, Handle class_loader) { - symbolOop name_ = class_name(); - oop loader_ = class_loader(); + oop loader = class_loader(); debug_only(_lookup_count++); for (DictionaryEntry* entry = bucket(index); entry != NULL; entry = entry->next()) { - if (entry->hash() == hash && entry->equals(name_, loader_)) { + if (entry->hash() == hash && entry->equals(class_name, loader)) { return entry; } debug_only(_lookup_length++); @@ -461,7 +460,7 @@ } -klassOop Dictionary::find(int index, unsigned int hash, symbolHandle name, +klassOop Dictionary::find(int index, unsigned int hash, Symbol* name, Handle loader, Handle protection_domain, TRAPS) { DictionaryEntry* entry = get_entry(index, hash, name, loader); if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) { @@ -473,7 +472,7 @@ klassOop Dictionary::find_class(int index, unsigned int hash, - symbolHandle name, Handle loader) { + Symbol* name, Handle loader) { assert_locked_or_safepoint(SystemDictionary_lock); assert (index == index_for(name, loader), "incorrect index?"); @@ -486,7 +485,7 @@ // that table is static. klassOop Dictionary::find_shared_class(int index, unsigned int hash, - symbolHandle name) { + Symbol* name) { assert (index == index_for(name, Handle()), "incorrect index?"); DictionaryEntry* entry = get_entry(index, hash, name, Handle()); @@ -498,7 +497,7 @@ instanceKlassHandle klass, Handle loader, Handle protection_domain, TRAPS) { - symbolHandle klass_name(THREAD, klass->name()); + Symbol* klass_name = klass->name(); DictionaryEntry* entry = get_entry(index, hash, klass_name, loader); assert(entry != NULL,"entry must be present, we just created it"); @@ -513,7 +512,7 @@ bool Dictionary::is_valid_protection_domain(int index, unsigned int hash, - symbolHandle name, + Symbol* name, Handle loader, Handle protection_domain) { DictionaryEntry* entry = get_entry(index, hash, name, loader); @@ -545,7 +544,7 @@ DictionaryEntry* p = master_list; master_list = master_list->next(); p->set_next(NULL); - symbolHandle class_name (thread, instanceKlass::cast((klassOop)(p->klass()))->name()); + Symbol* class_name = instanceKlass::cast((klassOop)(p->klass()))->name(); unsigned int hash = compute_hash(class_name, Handle(thread, p->loader())); int index = hash_to_index(hash); p->set_hash(hash); @@ -555,22 +554,22 @@ } SymbolPropertyTable::SymbolPropertyTable(int table_size) - : Hashtable(table_size, sizeof(SymbolPropertyEntry)) + : Hashtable<Symbol*>(table_size, sizeof(SymbolPropertyEntry)) { } SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries) - : Hashtable(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries) + : Hashtable<Symbol*>(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries) { } SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash, - symbolHandle sym, + Symbol* sym, intptr_t sym_mode) { assert(index == index_for(sym, sym_mode), "incorrect index?"); for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { - if (p->hash() == hash && p->symbol() == sym() && p->symbol_mode() == sym_mode) { + if (p->hash() == hash && p->symbol() == sym && p->symbol_mode() == sym_mode) { return p; } } @@ -579,13 +578,13 @@ SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash, - symbolHandle sym, intptr_t sym_mode) { + Symbol* sym, intptr_t sym_mode) { assert_locked_or_safepoint(SystemDictionary_lock); assert(index == index_for(sym, sym_mode), "incorrect index?"); assert(find_entry(index, hash, sym, sym_mode) == NULL, "no double entry"); - SymbolPropertyEntry* p = new_entry(hash, sym(), sym_mode); - Hashtable::add_entry(index, p); + SymbolPropertyEntry* p = new_entry(hash, sym, sym_mode); + Hashtable<Symbol*>::add_entry(index, p); return p; } @@ -593,7 +592,6 @@ void SymbolPropertyTable::oops_do(OopClosure* f) { for (int index = 0; index < table_size(); index++) { for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { - f->do_oop((oop*) p->symbol_addr()); if (p->property_oop() != NULL) { f->do_oop(p->property_oop_addr()); }
--- a/hotspot/src/share/vm/classfile/dictionary.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/dictionary.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -36,7 +36,7 @@ // The data structure for the system dictionary (and the shared system // dictionary). -class Dictionary : public TwoOopHashtable { +class Dictionary : public TwoOopHashtable<klassOop> { friend class VMStructs; private: // current iteration index. @@ -45,19 +45,19 @@ static DictionaryEntry* _current_class_entry; DictionaryEntry* get_entry(int index, unsigned int hash, - symbolHandle name, Handle loader); + Symbol* name, Handle loader); DictionaryEntry* bucket(int i) { - return (DictionaryEntry*)Hashtable::bucket(i); + return (DictionaryEntry*)Hashtable<klassOop>::bucket(i); } // The following method is not MT-safe and must be done under lock. DictionaryEntry** bucket_addr(int i) { - return (DictionaryEntry**)Hashtable::bucket_addr(i); + return (DictionaryEntry**)Hashtable<klassOop>::bucket_addr(i); } void add_entry(int index, DictionaryEntry* new_entry) { - Hashtable::add_entry(index, (HashtableEntry*)new_entry); + Hashtable<klassOop>::add_entry(index, (HashtableEntry<oop>*)new_entry); } @@ -71,12 +71,12 @@ void free_entry(DictionaryEntry* entry); - void add_klass(symbolHandle class_name, Handle class_loader,KlassHandle obj); + void add_klass(Symbol* class_name, Handle class_loader,KlassHandle obj); klassOop find_class(int index, unsigned int hash, - symbolHandle name, Handle loader); + Symbol* name, Handle loader); - klassOop find_shared_class(int index, unsigned int hash, symbolHandle name); + klassOop find_shared_class(int index, unsigned int hash, Symbol* name); // Compiler support klassOop try_get_next_class(); @@ -95,7 +95,7 @@ // Classes loaded by the bootstrap loader are always strongly reachable. // If we're not doing class unloading, all classes are strongly reachable. - static bool is_strongly_reachable(oop class_loader, oop klass) { + static bool is_strongly_reachable(oop class_loader, klassOop klass) { assert (klass != NULL, "should have non-null klass"); return (class_loader == NULL || !ClassUnloading); } @@ -105,10 +105,10 @@ bool do_unloading(BoolObjectClosure* is_alive); // Protection domains - klassOop find(int index, unsigned int hash, symbolHandle name, + klassOop find(int index, unsigned int hash, Symbol* name, Handle loader, Handle protection_domain, TRAPS); bool is_valid_protection_domain(int index, unsigned int hash, - symbolHandle name, Handle class_loader, + Symbol* name, Handle class_loader, Handle protection_domain); void add_protection_domain(int index, unsigned int hash, instanceKlassHandle klass, Handle loader, @@ -147,7 +147,7 @@ // An entry in the system dictionary, this describes a class as // { klassOop, loader, protection_domain }. -class DictionaryEntry : public HashtableEntry { +class DictionaryEntry : public HashtableEntry<klassOop> { friend class VMStructs; private: // Contains the set of approved protection domains that can access @@ -166,11 +166,11 @@ klassOop* klass_addr() { return (klassOop*)literal_addr(); } DictionaryEntry* next() const { - return (DictionaryEntry*)HashtableEntry::next(); + return (DictionaryEntry*)HashtableEntry<klassOop>::next(); } DictionaryEntry** next_addr() { - return (DictionaryEntry**)HashtableEntry::next_addr(); + return (DictionaryEntry**)HashtableEntry<klassOop>::next_addr(); } oop loader() const { return _loader; } @@ -209,7 +209,7 @@ } } - bool equals(symbolOop class_name, oop class_loader) const { + bool equals(Symbol* class_name, oop class_loader) const { klassOop klass = (klassOop)literal(); return (instanceKlass::cast(klass)->name() == class_name && _loader == class_loader); @@ -226,9 +226,9 @@ } }; -// Entry in a SymbolPropertyTable, mapping a single symbolOop +// Entry in a SymbolPropertyTable, mapping a single Symbol* // to a managed and an unmanaged pointer. -class SymbolPropertyEntry : public HashtableEntry { +class SymbolPropertyEntry : public HashtableEntry<Symbol*> { friend class VMStructs; private: intptr_t _symbol_mode; // secondary key @@ -236,7 +236,7 @@ address _property_data; public: - symbolOop symbol() const { return (symbolOop) literal(); } + Symbol* symbol() const { return literal(); } intptr_t symbol_mode() const { return _symbol_mode; } void set_symbol_mode(intptr_t m) { _symbol_mode = m; } @@ -248,14 +248,13 @@ void set_property_data(address p) { _property_data = p; } SymbolPropertyEntry* next() const { - return (SymbolPropertyEntry*)HashtableEntry::next(); + return (SymbolPropertyEntry*)HashtableEntry<Symbol*>::next(); } SymbolPropertyEntry** next_addr() { - return (SymbolPropertyEntry**)HashtableEntry::next_addr(); + return (SymbolPropertyEntry**)HashtableEntry<Symbol*>::next_addr(); } - oop* symbol_addr() { return literal_addr(); } oop* property_oop_addr() { return &_property_oop; } void print_on(outputStream* st) const { @@ -279,16 +278,16 @@ // A system-internal mapping of symbols to pointers, both managed // and unmanaged. Used to record the auto-generation of each method // MethodHandle.invoke(S)T, for all signatures (S)T. -class SymbolPropertyTable : public Hashtable { +class SymbolPropertyTable : public Hashtable<Symbol*> { friend class VMStructs; private: SymbolPropertyEntry* bucket(int i) { - return (SymbolPropertyEntry*) Hashtable::bucket(i); + return (SymbolPropertyEntry*) Hashtable<Symbol*>::bucket(i); } // The following method is not MT-safe and must be done under lock. SymbolPropertyEntry** bucket_addr(int i) { - return (SymbolPropertyEntry**) Hashtable::bucket_addr(i); + return (SymbolPropertyEntry**) Hashtable<Symbol*>::bucket_addr(i); } void add_entry(int index, SymbolPropertyEntry* new_entry) { @@ -298,8 +297,10 @@ ShouldNotReachHere(); } - SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol, intptr_t symbol_mode) { - SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol); + SymbolPropertyEntry* new_entry(unsigned int hash, Symbol* symbol, intptr_t symbol_mode) { + SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable<Symbol*>::new_entry(hash, symbol); + // Hashtable with Symbol* literal must increment and decrement refcount. + symbol->increment_refcount(); entry->set_symbol_mode(symbol_mode); entry->set_property_oop(NULL); entry->set_property_data(NULL); @@ -311,23 +312,25 @@ SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries); void free_entry(SymbolPropertyEntry* entry) { - Hashtable::free_entry(entry); + // decrement Symbol refcount here because hashtable doesn't. + entry->literal()->decrement_refcount(); + Hashtable<Symbol*>::free_entry(entry); } - unsigned int compute_hash(symbolHandle sym, intptr_t symbol_mode) { + unsigned int compute_hash(Symbol* sym, intptr_t symbol_mode) { // Use the regular identity_hash. - return Hashtable::compute_hash(sym) ^ symbol_mode; + return Hashtable<Symbol*>::compute_hash(sym) ^ symbol_mode; } - int index_for(symbolHandle name, intptr_t symbol_mode) { + int index_for(Symbol* name, intptr_t symbol_mode) { return hash_to_index(compute_hash(name, symbol_mode)); } // need not be locked; no state change - SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode); + SymbolPropertyEntry* find_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode); // must be done under SystemDictionary_lock - SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode); + SymbolPropertyEntry* add_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode); // GC support void oops_do(OopClosure* f); @@ -343,6 +346,4 @@ #endif void verify(); }; - - #endif // SHARE_VM_CLASSFILE_DICTIONARY_HPP
--- a/hotspot/src/share/vm/classfile/javaAssertions.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/javaAssertions.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -93,7 +93,7 @@ } oop JavaAssertions::createAssertionStatusDirectives(TRAPS) { - symbolHandle asd_sym = vmSymbolHandles::java_lang_AssertionStatusDirectives(); + Symbol* asd_sym = vmSymbols::java_lang_AssertionStatusDirectives(); klassOop k = SystemDictionary::resolve_or_fail(asd_sym, true, CHECK_NULL); instanceKlassHandle asd_klass (THREAD, k); asd_klass->initialize(CHECK_NULL);
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -36,7 +36,7 @@ #include "oops/klass.hpp" #include "oops/klassOop.hpp" #include "oops/methodOop.hpp" -#include "oops/symbolOop.hpp" +#include "oops/symbol.hpp" #include "oops/typeArrayOop.hpp" #include "runtime/fieldDescriptor.hpp" #include "runtime/handles.inline.hpp" @@ -57,7 +57,7 @@ #endif static bool find_field(instanceKlass* ik, - symbolOop name_symbol, symbolOop signature_symbol, + Symbol* name_symbol, Symbol* signature_symbol, fieldDescriptor* fd, bool allow_super = false) { if (allow_super) @@ -69,7 +69,7 @@ // Helpful routine for computing field offsets at run time rather than hardcoding them static void compute_offset(int &dest_offset, - klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol, + klassOop klass_oop, Symbol* name_symbol, Symbol* signature_symbol, bool allow_super = false) { fieldDescriptor fd; instanceKlass* ik = instanceKlass::cast(klass_oop); @@ -84,7 +84,7 @@ // Same as above but for "optional" offsets that might not be present in certain JDK versions static void compute_optional_offset(int& dest_offset, - klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol, + klassOop klass_oop, Symbol* name_symbol, Symbol* signature_symbol, bool allow_super = false) { fieldDescriptor fd; instanceKlass* ik = instanceKlass::cast(klass_oop); @@ -164,7 +164,7 @@ return h_obj(); } -Handle java_lang_String::create_from_symbol(symbolHandle symbol, TRAPS) { +Handle java_lang_String::create_from_symbol(Symbol* symbol, TRAPS) { int length = UTF8::unicode_length((char*)symbol->bytes(), symbol->utf8_length()); Handle h_obj = basic_create(length, false, CHECK_NH); if (length > 0) { @@ -278,17 +278,17 @@ return result; } -symbolHandle java_lang_String::as_symbol(Handle java_string, TRAPS) { +Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) { oop obj = java_string(); typeArrayOop value = java_lang_String::value(obj); int offset = java_lang_String::offset(obj); int length = java_lang_String::length(obj); jchar* base = (length == 0) ? NULL : value->char_at_addr(offset); - symbolOop sym = SymbolTable::lookup_unicode(base, length, THREAD); - return symbolHandle(THREAD, sym); + Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD); + return sym; } -symbolOop java_lang_String::as_symbol_or_null(oop java_string) { +Symbol* java_lang_String::as_symbol_or_null(oop java_string) { typeArrayOop value = java_lang_String::value(java_string); int offset = java_lang_String::offset(java_string); int length = java_lang_String::length(java_string); @@ -437,7 +437,7 @@ void java_lang_Class::print_signature(oop java_class, outputStream* st) { assert(java_lang_Class::is_instance(java_class), "must be a Class object"); - symbolOop name = NULL; + Symbol* name = NULL; bool is_instance = false; if (is_primitive(java_class)) { name = vmSymbols::type_signature(primitive_type(java_class)); @@ -455,25 +455,32 @@ if (is_instance) st->print(";"); } -symbolOop java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, TRAPS) { +Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, TRAPS) { assert(java_lang_Class::is_instance(java_class), "must be a Class object"); - symbolOop name = NULL; + Symbol* name; if (is_primitive(java_class)) { - return vmSymbols::type_signature(primitive_type(java_class)); + name = vmSymbols::type_signature(primitive_type(java_class)); + // Because this can create a new symbol, the caller has to decrement + // the refcount, so make adjustment here and below for symbols returned + // that are not created or incremented due to a successful lookup. + name->increment_refcount(); } else { klassOop k = as_klassOop(java_class); if (!Klass::cast(k)->oop_is_instance()) { - return Klass::cast(k)->name(); + name = Klass::cast(k)->name(); + name->increment_refcount(); } else { ResourceMark rm; const char* sigstr = Klass::cast(k)->signature_name(); int siglen = (int) strlen(sigstr); - if (!intern_if_not_found) - return SymbolTable::probe(sigstr, siglen); - else - return oopFactory::new_symbol(sigstr, siglen, THREAD); + if (!intern_if_not_found) { + name = SymbolTable::probe(sigstr, siglen); + } else { + name = SymbolTable::new_symbol(sigstr, siglen, THREAD); + } } } + return name; } @@ -1022,8 +1029,8 @@ JavaCalls::call_virtual(&result, stream, KlassHandle(THREAD, stream->klass()), - vmSymbolHandles::println_name(), - vmSymbolHandles::char_array_void_signature(), + vmSymbols::println_name(), + vmSymbols::char_array_void_signature(), arg, THREAD); } @@ -1077,8 +1084,8 @@ JavaCalls::call_virtual(&result, h_throwable, KlassHandle(THREAD, h_throwable->klass()), - vmSymbolHandles::getCause_name(), - vmSymbolHandles::void_throwable_signature(), + vmSymbols::getCause_name(), + vmSymbols::void_throwable_signature(), THREAD); // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. if (HAS_PENDING_EXCEPTION) { @@ -1516,7 +1523,7 @@ oop methodname = StringTable::intern(method->name(), CHECK_0); java_lang_StackTraceElement::set_methodName(element(), methodname); // Fill in source file name - symbolOop source = instanceKlass::cast(method->method_holder())->source_file_name(); + Symbol* source = instanceKlass::cast(method->method_holder())->source_file_name(); oop filename = StringTable::intern(source, CHECK_0); java_lang_StackTraceElement::set_fileName(element(), filename); // File in source line number @@ -1732,7 +1739,7 @@ Handle java_lang_reflect_Constructor::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); - symbolHandle name = vmSymbolHandles::java_lang_reflect_Constructor(); + Symbol* name = vmSymbols::java_lang_reflect_Constructor(); klassOop k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); instanceKlassHandle klass (THREAD, k); // Ensure it is initialized @@ -1854,7 +1861,7 @@ Handle java_lang_reflect_Field::create(TRAPS) { assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); - symbolHandle name = vmSymbolHandles::java_lang_reflect_Field(); + Symbol* name = vmSymbols::java_lang_reflect_Field(); klassOop k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); instanceKlassHandle klass (THREAD, k); // Ensure it is initialized @@ -2422,16 +2429,19 @@ java_lang_Class::print_signature(rtype(mt), st); } -symbolOop java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) { +Symbol* java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) { ResourceMark rm; stringStream buffer(128); print_signature(mt, &buffer); const char* sigstr = buffer.base(); int siglen = (int) buffer.size(); - if (!intern_if_not_found) - return SymbolTable::probe(sigstr, siglen); - else - return oopFactory::new_symbol(sigstr, siglen, THREAD); + Symbol *name; + if (!intern_if_not_found) { + name = SymbolTable::probe(sigstr, siglen); + } else { + name = SymbolTable::new_symbol(sigstr, siglen, THREAD); + } + return name; } oop java_dyn_MethodType::rtype(oop mt) { @@ -2908,13 +2918,12 @@ bool JavaClasses::check_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) { EXCEPTION_MARK; fieldDescriptor fd; - symbolHandle klass_sym = oopFactory::new_symbol_handle(klass_name, CATCH); + TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH); klassOop k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); instanceKlassHandle h_klass (THREAD, k); - //instanceKlassHandle h_klass(klass); - symbolHandle f_name = oopFactory::new_symbol_handle(field_name, CATCH); - symbolHandle f_sig = oopFactory::new_symbol_handle(field_sig, CATCH); - if (!h_klass->find_local_field(f_name(), f_sig(), &fd)) { + TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH); + TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH); + if (!h_klass->find_local_field(f_name, f_sig, &fd)) { tty->print_cr("Nonstatic field %s.%s not found", klass_name, field_name); return false; } @@ -2935,12 +2944,12 @@ bool JavaClasses::check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) { EXCEPTION_MARK; fieldDescriptor fd; - symbolHandle klass_sym = oopFactory::new_symbol_handle(klass_name, CATCH); + TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH); klassOop k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); instanceKlassHandle h_klass (THREAD, k); - symbolHandle f_name = oopFactory::new_symbol_handle(field_name, CATCH); - symbolHandle f_sig = oopFactory::new_symbol_handle(field_sig, CATCH); - if (!h_klass->find_local_field(f_name(), f_sig(), &fd)) { + TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH); + TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH); + if (!h_klass->find_local_field(f_name, f_sig, &fd)) { tty->print_cr("Static field %s.%s not found", klass_name, field_name); return false; } @@ -2960,12 +2969,12 @@ bool JavaClasses::check_constant(const char *klass_name, int hardcoded_constant, const char *field_name, const char* field_sig) { EXCEPTION_MARK; fieldDescriptor fd; - symbolHandle klass_sym = oopFactory::new_symbol_handle(klass_name, CATCH); + TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH); klassOop k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); instanceKlassHandle h_klass (THREAD, k); - symbolHandle f_name = oopFactory::new_symbol_handle(field_name, CATCH); - symbolHandle f_sig = oopFactory::new_symbol_handle(field_sig, CATCH); - if (!h_klass->find_local_field(f_name(), f_sig(), &fd)) { + TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH); + TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH); + if (!h_klass->find_local_field(f_name, f_sig, &fd)) { tty->print_cr("Static field %s.%s not found", klass_name, field_name); return false; }
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -78,7 +78,7 @@ static oop create_oop_from_unicode(jchar* unicode, int len, TRAPS); static Handle create_from_str(const char* utf8_str, TRAPS); static oop create_oop_from_str(const char* utf8_str, TRAPS); - static Handle create_from_symbol(symbolHandle symbol, TRAPS); + static Handle create_from_symbol(Symbol* symbol, TRAPS); static Handle create_from_platform_dependent_str(const char* str, TRAPS); static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS); @@ -116,8 +116,8 @@ static Handle internalize_classname(Handle java_string, TRAPS) { return char_converter(java_string, '.', '/', THREAD); } // Conversion - static symbolHandle as_symbol(Handle java_string, TRAPS); - static symbolOop as_symbol_or_null(oop java_string); + static Symbol* as_symbol(Handle java_string, TRAPS); + static Symbol* as_symbol_or_null(oop java_string); // Testers static bool is_instance(oop obj) { @@ -167,7 +167,7 @@ (*reference_klass) = KlassHandle(refk_oop); return result; } - static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS); + static Symbol* as_signature(oop java_class, bool intern_if_not_found, TRAPS); static void print_signature(oop java_class, outputStream *st); // Testing static bool is_instance(oop obj) { @@ -1039,7 +1039,7 @@ static oop ptype(oop mt, int index); static int ptype_count(oop mt); - static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS); + static Symbol* as_signature(oop mt, bool intern_if_not_found, TRAPS); static void print_signature(oop mt, outputStream* st); static bool is_instance(oop obj) {
--- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -31,28 +31,33 @@ #include "utilities/hashtable.inline.hpp" LoaderConstraintTable::LoaderConstraintTable(int nof_buckets) - : Hashtable(nof_buckets, sizeof(LoaderConstraintEntry)) {}; + : Hashtable<klassOop>(nof_buckets, sizeof(LoaderConstraintEntry)) {}; LoaderConstraintEntry* LoaderConstraintTable::new_entry( - unsigned int hash, symbolOop name, + unsigned int hash, Symbol* name, klassOop klass, int num_loaders, int max_loaders) { LoaderConstraintEntry* entry; - entry = (LoaderConstraintEntry*)Hashtable::new_entry(hash, klass); + entry = (LoaderConstraintEntry*)Hashtable<klassOop>::new_entry(hash, klass); entry->set_name(name); entry->set_num_loaders(num_loaders); entry->set_max_loaders(max_loaders); return entry; } +void LoaderConstraintTable::free_entry(LoaderConstraintEntry *entry) { + // decrement name refcount before freeing + entry->name()->decrement_refcount(); + Hashtable<klassOop>::free_entry(entry); +} + void LoaderConstraintTable::oops_do(OopClosure* f) { for (int index = 0; index < table_size(); index++) { for (LoaderConstraintEntry* probe = bucket(index); probe != NULL; probe = probe->next()) { - f->do_oop((oop*)(probe->name_addr())); if (probe->klass() != NULL) { f->do_oop((oop*)probe->klass_addr()); } @@ -65,27 +70,13 @@ } } -// We must keep the symbolOop used in the name alive. We'll use the -// loaders to decide if a particular entry can be purged. -void LoaderConstraintTable::always_strong_classes_do(OopClosure* blk) { - // We must keep the symbolOop used in the name alive. - for (int cindex = 0; cindex < table_size(); cindex++) { - for (LoaderConstraintEntry* lc_probe = bucket(cindex); - lc_probe != NULL; - lc_probe = lc_probe->next()) { - assert (lc_probe->name() != NULL, "corrupted loader constraint table"); - blk->do_oop((oop*)lc_probe->name_addr()); - } - } -} - // The loaderConstraintTable must always be accessed with the // SystemDictionary lock held. This is true even for readers as // entries in the table could be being dynamically resized. LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint( - symbolHandle name, Handle loader) { + Symbol* name, Handle loader) { unsigned int hash = compute_hash(name); int index = hash_to_index(hash); @@ -93,7 +84,7 @@ while (*pp) { LoaderConstraintEntry* p = *pp; if (p->hash() == hash) { - if (p->name() == name()) { + if (p->name() == name) { for (int i = p->num_loaders() - 1; i >= 0; i--) { if (p->loader(i) == loader()) { return pp; @@ -177,7 +168,6 @@ free_entry(probe); } else { #ifdef ASSERT - assert(is_alive->do_object_b(probe->name()), "name should be live"); if (probe->klass() != NULL) { assert(is_alive->do_object_b(probe->klass()), "klass should be live"); } @@ -194,7 +184,7 @@ } } -bool LoaderConstraintTable::add_entry(symbolHandle class_name, +bool LoaderConstraintTable::add_entry(Symbol* class_name, klassOop klass1, Handle class_loader1, klassOop klass2, Handle class_loader2) { int failure_code = 0; // encode different reasons for failing @@ -233,7 +223,7 @@ unsigned int hash = compute_hash(class_name); int index = hash_to_index(hash); LoaderConstraintEntry* p; - p = new_entry(hash, class_name(), klass, 2, 2); + p = new_entry(hash, class_name, klass, 2, 2); p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2)); p->set_loader(0, class_loader1()); p->set_loader(1, class_loader2()); @@ -244,7 +234,7 @@ ResourceMark rm; tty->print("[Adding new constraint for name: %s, loader[0]: %s," " loader[1]: %s ]\n", - class_name()->as_C_string(), + class_name->as_C_string(), SystemDictionary::loader_name(class_loader1()), SystemDictionary::loader_name(class_loader2()) ); @@ -257,7 +247,7 @@ ResourceMark rm; tty->print("[Setting class object in existing constraint for" " name: %s and loader %s ]\n", - class_name()->as_C_string(), + class_name->as_C_string(), SystemDictionary::loader_name(class_loader1()) ); } @@ -288,7 +278,7 @@ } tty->print("[Failed to add constraint for name: %s, loader[0]: %s," " loader[1]: %s, Reason: %s ]\n", - class_name()->as_C_string(), + class_name->as_C_string(), SystemDictionary::loader_name(class_loader1()), SystemDictionary::loader_name(class_loader2()), reason @@ -303,14 +293,14 @@ // violated bool LoaderConstraintTable::check_or_update(instanceKlassHandle k, Handle loader, - symbolHandle name) { + Symbol* name) { LoaderConstraintEntry* p = *(find_loader_constraint(name, loader)); if (p && p->klass() != NULL && p->klass() != k()) { if (TraceLoaderConstraints) { ResourceMark rm; tty->print("[Constraint check failed for name %s, loader %s: " "the presented class object differs from that stored ]\n", - name()->as_C_string(), + name->as_C_string(), SystemDictionary::loader_name(loader())); } return false; @@ -321,7 +311,7 @@ ResourceMark rm; tty->print("[Updating constraint for name %s, loader %s, " "by setting class object ]\n", - name()->as_C_string(), + name->as_C_string(), SystemDictionary::loader_name(loader())); } } @@ -329,7 +319,7 @@ } } -klassOop LoaderConstraintTable::find_constrained_klass(symbolHandle name, +klassOop LoaderConstraintTable::find_constrained_klass(Symbol* name, Handle loader) { LoaderConstraintEntry *p = *(find_loader_constraint(name, loader)); if (p != NULL && p->klass() != NULL) @@ -442,11 +432,10 @@ for (LoaderConstraintEntry* probe = bucket(cindex); probe != NULL; probe = probe->next()) { - guarantee(probe->name()->is_symbol(), "should be symbol"); if (probe->klass() != NULL) { instanceKlass* ik = instanceKlass::cast(probe->klass()); guarantee(ik->name() == probe->name(), "name should match"); - symbolHandle name (thread, ik->name()); + Symbol* name = ik->name(); Handle loader(thread, ik->class_loader()); unsigned int d_hash = dictionary->compute_hash(name, loader); int d_index = dictionary->hash_to_index(d_hash);
--- a/hotspot/src/share/vm/classfile/loaderConstraints.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/loaderConstraints.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -31,7 +31,7 @@ class LoaderConstraintEntry; -class LoaderConstraintTable : public Hashtable { +class LoaderConstraintTable : public Hashtable<klassOop> { friend class VMStructs; private: @@ -40,39 +40,39 @@ _nof_buckets = 1009 // number of buckets in hash table }; - LoaderConstraintEntry** find_loader_constraint(symbolHandle name, + LoaderConstraintEntry** find_loader_constraint(Symbol* name, Handle loader); public: LoaderConstraintTable(int nof_buckets); - LoaderConstraintEntry* new_entry(unsigned int hash, symbolOop name, + LoaderConstraintEntry* new_entry(unsigned int hash, Symbol* name, klassOop klass, int num_loaders, int max_loaders); + void free_entry(LoaderConstraintEntry *entry); LoaderConstraintEntry* bucket(int i) { - return (LoaderConstraintEntry*)Hashtable::bucket(i); + return (LoaderConstraintEntry*)Hashtable<klassOop>::bucket(i); } LoaderConstraintEntry** bucket_addr(int i) { - return (LoaderConstraintEntry**)Hashtable::bucket_addr(i); + return (LoaderConstraintEntry**)Hashtable<klassOop>::bucket_addr(i); } // GC support void oops_do(OopClosure* f); - void always_strong_classes_do(OopClosure* blk); // Check class loader constraints - bool add_entry(symbolHandle name, klassOop klass1, Handle loader1, + bool add_entry(Symbol* name, klassOop klass1, Handle loader1, klassOop klass2, Handle loader2); // Note: The main entry point for this module is via SystemDictionary. - // SystemDictionary::check_signature_loaders(symbolHandle signature, + // SystemDictionary::check_signature_loaders(Symbol* signature, // Handle loader1, Handle loader2, // bool is_method, TRAPS) - klassOop find_constrained_klass(symbolHandle name, Handle loader); + klassOop find_constrained_klass(Symbol* name, Handle loader); // Class loader constraints @@ -83,7 +83,7 @@ LoaderConstraintEntry** pp2, klassOop klass); bool check_or_update(instanceKlassHandle k, Handle loader, - symbolHandle name); + Symbol* name); void purge_loader_constraints(BoolObjectClosure* is_alive); @@ -94,34 +94,36 @@ #endif }; -class LoaderConstraintEntry : public HashtableEntry { +class LoaderConstraintEntry : public HashtableEntry<klassOop> { friend class VMStructs; private: - symbolOop _name; // class name + Symbol* _name; // class name int _num_loaders; int _max_loaders; oop* _loaders; // initiating loaders public: - klassOop klass() { return (klassOop)literal(); } - klassOop* klass_addr() { return (klassOop*)literal_addr(); } + klassOop klass() { return literal(); } + klassOop* klass_addr() { return literal_addr(); } void set_klass(klassOop k) { set_literal(k); } LoaderConstraintEntry* next() { - return (LoaderConstraintEntry*)HashtableEntry::next(); + return (LoaderConstraintEntry*)HashtableEntry<klassOop>::next(); } LoaderConstraintEntry** next_addr() { - return (LoaderConstraintEntry**)HashtableEntry::next_addr(); + return (LoaderConstraintEntry**)HashtableEntry<klassOop>::next_addr(); } void set_next(LoaderConstraintEntry* next) { - HashtableEntry::set_next(next); + HashtableEntry<klassOop>::set_next(next); } - symbolOop name() { return _name; } - symbolOop* name_addr() { return &_name; } - void set_name(symbolOop name) { _name = name; } + Symbol* name() { return _name; } + void set_name(Symbol* name) { + _name = name; + if (name != NULL) name->increment_refcount(); + } int num_loaders() { return _num_loaders; } void set_num_loaders(int i) { _num_loaders = i; }
--- a/hotspot/src/share/vm/classfile/placeholders.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/placeholders.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -31,10 +31,12 @@ // Placeholder methods -PlaceholderEntry* PlaceholderTable::new_entry(int hash, symbolOop name, +PlaceholderEntry* PlaceholderTable::new_entry(int hash, Symbol* name, oop loader, bool havesupername, - symbolOop supername) { - PlaceholderEntry* entry = (PlaceholderEntry*)Hashtable::new_entry(hash, name); + Symbol* supername) { + PlaceholderEntry* entry = (PlaceholderEntry*)Hashtable<Symbol*>::new_entry(hash, name); + // Hashtable with Symbol* literal must increment and decrement refcount. + name->increment_refcount(); entry->set_loader(loader); entry->set_havesupername(havesupername); entry->set_supername(supername); @@ -46,33 +48,40 @@ return entry; } +void PlaceholderTable::free_entry(PlaceholderEntry* entry) { + // decrement Symbol refcount here because Hashtable doesn't. + entry->literal()->decrement_refcount(); + if (entry->supername() != NULL) entry->supername()->decrement_refcount(); + Hashtable<Symbol*>::free_entry(entry); +} + // Placeholder objects represent classes currently being loaded. // All threads examining the placeholder table must hold the // SystemDictionary_lock, so we don't need special precautions // on store ordering here. void PlaceholderTable::add_entry(int index, unsigned int hash, - symbolHandle class_name, Handle class_loader, - bool havesupername, symbolHandle supername){ + Symbol* class_name, Handle class_loader, + bool havesupername, Symbol* supername){ assert_locked_or_safepoint(SystemDictionary_lock); - assert(!class_name.is_null(), "adding NULL obj"); + assert(class_name != NULL, "adding NULL obj"); // Both readers and writers are locked so it's safe to just // create the placeholder and insert it in the list without a membar. - PlaceholderEntry* entry = new_entry(hash, class_name(), class_loader(), havesupername, supername()); + PlaceholderEntry* entry = new_entry(hash, class_name, class_loader(), havesupername, supername); add_entry(index, entry); } // Remove a placeholder object. void PlaceholderTable::remove_entry(int index, unsigned int hash, - symbolHandle class_name, + Symbol* class_name, Handle class_loader) { assert_locked_or_safepoint(SystemDictionary_lock); PlaceholderEntry** p = bucket_addr(index); while (*p) { PlaceholderEntry *probe = *p; - if (probe->hash() == hash && probe->equals(class_name(), class_loader())) { + if (probe->hash() == hash && probe->equals(class_name, class_loader())) { // Delete entry *p = probe->next(); free_entry(probe); @@ -83,29 +92,28 @@ } PlaceholderEntry* PlaceholderTable::get_entry(int index, unsigned int hash, - symbolHandle class_name, + Symbol* class_name, Handle class_loader) { assert_locked_or_safepoint(SystemDictionary_lock); - symbolOop class_name_ = class_name(); oop class_loader_ = class_loader(); for (PlaceholderEntry *place_probe = bucket(index); place_probe != NULL; place_probe = place_probe->next()) { if (place_probe->hash() == hash && - place_probe->equals(class_name_, class_loader_)) { + place_probe->equals(class_name, class_loader_)) { return place_probe; } } return NULL; } -symbolOop PlaceholderTable::find_entry(int index, unsigned int hash, - symbolHandle class_name, +Symbol* PlaceholderTable::find_entry(int index, unsigned int hash, + Symbol* class_name, Handle class_loader) { PlaceholderEntry* probe = get_entry(index, hash, class_name, class_loader); - return (probe? probe->klass(): symbolOop(NULL)); + return (probe? probe->klassname(): (Symbol*)NULL); } // find_and_add returns probe pointer - old or new @@ -113,7 +121,7 @@ // If entry exists, reuse entry // For both, push SeenThread for classloadAction // if havesupername: this is used for circularity for instanceklass loading -PlaceholderEntry* PlaceholderTable::find_and_add(int index, unsigned int hash, symbolHandle name, Handle loader, classloadAction action, symbolHandle supername, Thread* thread) { +PlaceholderEntry* PlaceholderTable::find_and_add(int index, unsigned int hash, Symbol* name, Handle loader, classloadAction action, Symbol* supername, Thread* thread) { PlaceholderEntry* probe = get_entry(index, hash, name, loader); if (probe == NULL) { // Nothing found, add place holder @@ -122,7 +130,7 @@ } else { if (action == LOAD_SUPER) { probe->set_havesupername(true); - probe->set_supername(supername()); + probe->set_supername(supername); } } if (probe) probe->add_seen_thread(thread, action); @@ -145,7 +153,7 @@ // Therefore - must always check SD first // Ignores the case where entry is not found void PlaceholderTable::find_and_remove(int index, unsigned int hash, - symbolHandle name, Handle loader, Thread* thread) { + Symbol* name, Handle loader, Thread* thread) { assert_locked_or_safepoint(SystemDictionary_lock); PlaceholderEntry *probe = get_entry(index, hash, name, loader); if (probe != NULL) { @@ -158,7 +166,7 @@ } PlaceholderTable::PlaceholderTable(int table_size) - : TwoOopHashtable(table_size, sizeof(PlaceholderEntry)) { + : TwoOopHashtable<Symbol*>(table_size, sizeof(PlaceholderEntry)) { } @@ -174,26 +182,22 @@ void PlaceholderEntry::oops_do(OopClosure* blk) { - assert(klass() != NULL, "should have a non-null klass"); - blk->do_oop((oop*)klass_addr()); + assert(klassname() != NULL, "should have a non-null klass"); if (_loader != NULL) { blk->do_oop(loader_addr()); } - if (_supername != NULL) { - blk->do_oop((oop*)supername_addr()); - } if (_instanceKlass != NULL) { blk->do_oop((oop*)instanceKlass_addr()); } } // do all entries in the placeholder table -void PlaceholderTable::entries_do(void f(symbolOop, oop)) { +void PlaceholderTable::entries_do(void f(Symbol*, oop)) { for (int index = 0; index < table_size(); index++) { for (PlaceholderEntry* probe = bucket(index); probe != NULL; probe = probe->next()) { - f(probe->klass(), probe->loader()); + f(probe->klassname(), probe->loader()); } } } @@ -202,7 +206,7 @@ #ifndef PRODUCT // Note, doesn't append a cr void PlaceholderEntry::print() const { - klass()->print_value(); + klassname()->print_value(); if (loader() != NULL) { tty->print(", loader "); loader()->print_value(); @@ -238,7 +242,6 @@ guarantee(instanceKlass() == NULL || Klass::cast(instanceKlass())->oop_is_instance(), "checking type of instanceKlass result"); - klass()->verify(); } void PlaceholderTable::verify() {
--- a/hotspot/src/share/vm/classfile/placeholders.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/placeholders.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -34,35 +34,36 @@ // being loaded, as well as arrays of primitives. // -class PlaceholderTable : public TwoOopHashtable { +class PlaceholderTable : public TwoOopHashtable<Symbol*> { friend class VMStructs; public: PlaceholderTable(int table_size); - PlaceholderEntry* new_entry(int hash, symbolOop name, oop loader, bool havesupername, symbolOop supername); + PlaceholderEntry* new_entry(int hash, Symbol* name, oop loader, bool havesupername, Symbol* supername); + void free_entry(PlaceholderEntry* entry); PlaceholderEntry* bucket(int i) { - return (PlaceholderEntry*)Hashtable::bucket(i); + return (PlaceholderEntry*)Hashtable<Symbol*>::bucket(i); } PlaceholderEntry** bucket_addr(int i) { - return (PlaceholderEntry**)Hashtable::bucket_addr(i); + return (PlaceholderEntry**)Hashtable<Symbol*>::bucket_addr(i); } void add_entry(int index, PlaceholderEntry* new_entry) { - Hashtable::add_entry(index, (HashtableEntry*)new_entry); + Hashtable<Symbol*>::add_entry(index, (HashtableEntry<Symbol*>*)new_entry); } - void add_entry(int index, unsigned int hash, symbolHandle name, - Handle loader, bool havesupername, symbolHandle supername); + void add_entry(int index, unsigned int hash, Symbol* name, + Handle loader, bool havesupername, Symbol* supername); -// This returns a symbolOop to match type for SystemDictionary - symbolOop find_entry(int index, unsigned int hash, - symbolHandle name, Handle loader); + // This returns a Symbol* to match type for SystemDictionary + Symbol* find_entry(int index, unsigned int hash, + Symbol* name, Handle loader); PlaceholderEntry* get_entry(int index, unsigned int hash, - symbolHandle name, Handle loader); + Symbol* name, Handle loader); // caller to create a placeholder entry must enumerate an action // caller claims ownership of that action @@ -84,22 +85,22 @@ // If no entry exists, add a placeholder entry and push SeenThread // If entry exists, reuse entry and push SeenThread for classloadAction PlaceholderEntry* find_and_add(int index, unsigned int hash, - symbolHandle name, Handle loader, - classloadAction action, symbolHandle supername, + Symbol* name, Handle loader, + classloadAction action, Symbol* supername, Thread* thread); void remove_entry(int index, unsigned int hash, - symbolHandle name, Handle loader); + Symbol* name, Handle loader); // Remove placeholder information void find_and_remove(int index, unsigned int hash, - symbolHandle name, Handle loader, Thread* thread); + Symbol* name, Handle loader, Thread* thread); // GC support. void oops_do(OopClosure* f); // JVMTI support - void entries_do(void f(symbolOop, oop)); + void entries_do(void f(Symbol*, oop)); #ifndef PRODUCT void print(); @@ -151,14 +152,14 @@ // on store ordering here. // The system dictionary is the only user of this class. -class PlaceholderEntry : public HashtableEntry { +class PlaceholderEntry : public HashtableEntry<Symbol*> { friend class VMStructs; private: oop _loader; // initiating loader bool _havesupername; // distinguish between null supername, and unknown - symbolOop _supername; + Symbol* _supername; Thread* _definer; // owner of define token klassOop _instanceKlass; // instanceKlass from successful define SeenThread* _superThreadQ; // doubly-linked queue of Threads loading a superclass for this class @@ -173,8 +174,7 @@ public: // Simple accessors, used only by SystemDictionary - symbolOop klass() const { return (symbolOop)literal(); } - symbolOop* klass_addr() { return (symbolOop*)literal_addr(); } + Symbol* klassname() const { return literal(); } oop loader() const { return _loader; } void set_loader(oop loader) { _loader = loader; } @@ -183,9 +183,11 @@ bool havesupername() const { return _havesupername; } void set_havesupername(bool havesupername) { _havesupername = havesupername; } - symbolOop supername() const { return _supername; } - void set_supername(symbolOop supername) { _supername = supername; } - symbolOop* supername_addr() { return &_supername; } + Symbol* supername() const { return _supername; } + void set_supername(Symbol* supername) { + _supername = supername; + if (_supername != NULL) _supername->increment_refcount(); + } Thread* definer() const {return _definer; } void set_definer(Thread* definer) { _definer = definer; } @@ -204,17 +206,17 @@ void set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; } PlaceholderEntry* next() const { - return (PlaceholderEntry*)HashtableEntry::next(); + return (PlaceholderEntry*)HashtableEntry<Symbol*>::next(); } PlaceholderEntry** next_addr() { - return (PlaceholderEntry**)HashtableEntry::next_addr(); + return (PlaceholderEntry**)HashtableEntry<Symbol*>::next_addr(); } // Test for equality // Entries are unique for class/classloader name pair - bool equals(symbolOop class_name, oop class_loader) const { - return (klass() == class_name && loader() == class_loader); + bool equals(Symbol* class_name, oop class_loader) const { + return (klassname() == class_name && loader() == class_loader); } SeenThread* actionToQueue(PlaceholderTable::classloadAction action) {
--- a/hotspot/src/share/vm/classfile/resolutionErrors.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/resolutionErrors.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -32,12 +32,12 @@ // add new entry to the table void ResolutionErrorTable::add_entry(int index, unsigned int hash, - constantPoolHandle pool, int cp_index, symbolHandle error) + constantPoolHandle pool, int cp_index, Symbol* error) { assert_locked_or_safepoint(SystemDictionary_lock); - assert(!pool.is_null() && !error.is_null(), "adding NULL obj"); + assert(!pool.is_null() && error != NULL, "adding NULL obj"); - ResolutionErrorEntry* entry = new_entry(hash, pool(), cp_index, error()); + ResolutionErrorEntry* entry = new_entry(hash, pool(), cp_index, error); add_entry(index, entry); } @@ -57,20 +57,35 @@ return NULL; } +void ResolutionErrorEntry::set_error(Symbol* e) { + assert(e == NULL || _error == NULL, "cannot reset error"); + _error = e; + if (_error != NULL) _error->increment_refcount(); +} + // create new error entry ResolutionErrorEntry* ResolutionErrorTable::new_entry(int hash, constantPoolOop pool, - int cp_index, symbolOop error) + int cp_index, Symbol* error) { - ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable::new_entry(hash, pool); + ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<constantPoolOop>::new_entry(hash, pool); entry->set_cp_index(cp_index); + NOT_PRODUCT(entry->set_error(NULL);) entry->set_error(error); return entry; } +void ResolutionErrorTable::free_entry(ResolutionErrorEntry *entry) { + // decrement error refcount + assert(entry->error() != NULL, "error should be set"); + entry->error()->decrement_refcount(); + Hashtable<constantPoolOop>::free_entry(entry); +} + + // create resolution error table ResolutionErrorTable::ResolutionErrorTable(int table_size) - : Hashtable(table_size, sizeof(ResolutionErrorEntry)) { + : Hashtable<constantPoolOop>(table_size, sizeof(ResolutionErrorEntry)) { } // GC support @@ -80,7 +95,7 @@ probe != NULL; probe = probe->next()) { assert(probe->pool() != (constantPoolOop)NULL, "resolution error table is corrupt"); - assert(probe->error() != (symbolOop)NULL, "resolution error table is corrupt"); + assert(probe->error() != (Symbol*)NULL, "resolution error table is corrupt"); probe->oops_do(f); } } @@ -89,20 +104,6 @@ // GC support void ResolutionErrorEntry::oops_do(OopClosure* blk) { blk->do_oop((oop*)pool_addr()); - blk->do_oop((oop*)error_addr()); -} - -// We must keep the symbolOop used in the error alive. The constantPoolOop will -// decide when the entry can be purged. -void ResolutionErrorTable::always_strong_classes_do(OopClosure* blk) { - for (int i = 0; i < table_size(); i++) { - for (ResolutionErrorEntry* probe = bucket(i); - probe != NULL; - probe = probe->next()) { - assert(probe->error() != (symbolOop)NULL, "resolution error table is corrupt"); - blk->do_oop((oop*)probe->error_addr()); - } - } } // Remove unloaded entries from the table
--- a/hotspot/src/share/vm/classfile/resolutionErrors.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/resolutionErrors.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -33,27 +33,28 @@ // ResolutionError objects are used to record errors encountered during // constant pool resolution (JVMS 5.4.3). -class ResolutionErrorTable : public Hashtable { +class ResolutionErrorTable : public Hashtable<constantPoolOop> { public: ResolutionErrorTable(int table_size); - ResolutionErrorEntry* new_entry(int hash, constantPoolOop pool, int cp_index, symbolOop error); + ResolutionErrorEntry* new_entry(int hash, constantPoolOop pool, int cp_index, Symbol* error); + void free_entry(ResolutionErrorEntry *entry); ResolutionErrorEntry* bucket(int i) { - return (ResolutionErrorEntry*)Hashtable::bucket(i); + return (ResolutionErrorEntry*)Hashtable<constantPoolOop>::bucket(i); } ResolutionErrorEntry** bucket_addr(int i) { - return (ResolutionErrorEntry**)Hashtable::bucket_addr(i); + return (ResolutionErrorEntry**)Hashtable<constantPoolOop>::bucket_addr(i); } void add_entry(int index, ResolutionErrorEntry* new_entry) { - Hashtable::add_entry(index, (HashtableEntry*)new_entry); + Hashtable<constantPoolOop>::add_entry(index, (HashtableEntry<constantPoolOop>*)new_entry); } void add_entry(int index, unsigned int hash, - constantPoolHandle pool, int which, symbolHandle error); + constantPoolHandle pool, int which, Symbol* error); // find error given the constant pool and constant pool index @@ -68,18 +69,15 @@ // purges unloaded entries from the table void purge_resolution_errors(BoolObjectClosure* is_alive); - // this table keeps symbolOops alive - void always_strong_classes_do(OopClosure* blk); - // GC support. void oops_do(OopClosure* f); }; -class ResolutionErrorEntry : public HashtableEntry { +class ResolutionErrorEntry : public HashtableEntry<constantPoolOop> { private: int _cp_index; - symbolOop _error; + Symbol* _error; public: constantPoolOop pool() const { return (constantPoolOop)literal(); } @@ -88,16 +86,15 @@ int cp_index() const { return _cp_index; } void set_cp_index(int cp_index) { _cp_index = cp_index; } - symbolOop error() const { return _error; } - void set_error(symbolOop e) { _error = e; } - symbolOop* error_addr() { return &_error; } + Symbol* error() const { return _error; } + void set_error(Symbol* e); ResolutionErrorEntry* next() const { - return (ResolutionErrorEntry*)HashtableEntry::next(); + return (ResolutionErrorEntry*)HashtableEntry<constantPoolOop>::next(); } ResolutionErrorEntry** next_addr() { - return (ResolutionErrorEntry**)HashtableEntry::next_addr(); + return (ResolutionErrorEntry**)HashtableEntry<constantPoolOop>::next_addr(); } // GC support
--- a/hotspot/src/share/vm/classfile/stackMapFrame.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/stackMapFrame.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -27,7 +27,7 @@ #include "classfile/verifier.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" -#include "oops/symbolOop.hpp" +#include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" #include "utilities/globalDefinitions.hpp" @@ -90,8 +90,7 @@ VerificationType StackMapFrame::set_locals_from_arg( const methodHandle m, VerificationType thisKlass, TRAPS) { - symbolHandle signature(THREAD, m->signature()); - SignatureStream ss(signature); + SignatureStream ss(m->signature()); int init_local_num = 0; if (!m->is_static()) { init_local_num++; @@ -118,8 +117,14 @@ case T_OBJECT: case T_ARRAY: { - symbolOop sig = ss.as_symbol(CHECK_(VerificationType::bogus_type())); - return VerificationType::reference_type(symbolHandle(THREAD, sig)); + Symbol* sig = ss.as_symbol(CHECK_(VerificationType::bogus_type())); + // Create another symbol to save as signature stream unreferences + // this symbol. + Symbol* sig_copy = + verifier()->create_temporary_symbol(sig, 0, sig->utf8_length(), + CHECK_(VerificationType::bogus_type())); + assert(sig_copy == sig, "symbols don't match"); + return VerificationType::reference_type(sig_copy); } case T_INT: return VerificationType::integer_type(); case T_BYTE: return VerificationType::byte_type(); @@ -157,7 +162,7 @@ VerificationType* from, VerificationType* to, int32_t len, TRAPS) const { for (int32_t i = 0; i < len; i++) { bool subtype = to[i].is_assignable_from( - from[i], verifier()->current_class(), THREAD); + from[i], verifier(), THREAD); if (!subtype) { return false; } @@ -187,7 +192,7 @@ } VerificationType top = _stack[--_stack_size]; bool subtype = type.is_assignable_from( - top, verifier()->current_class(), CHECK_(VerificationType::bogus_type())); + top, verifier(), CHECK_(VerificationType::bogus_type())); if (!subtype) { verifier()->verify_error(_offset, "Bad type on operand stack"); return VerificationType::bogus_type(); @@ -203,7 +208,7 @@ return VerificationType::bogus_type(); } bool subtype = type.is_assignable_from(_locals[index], - verifier()->current_class(), CHECK_(VerificationType::bogus_type())); + verifier(), CHECK_(VerificationType::bogus_type())); if (!subtype) { verifier()->verify_error(_offset, "Bad local variable type"); return VerificationType::bogus_type(); @@ -221,9 +226,9 @@ return; } bool subtype1 = type1.is_assignable_from( - _locals[index], verifier()->current_class(), CHECK); + _locals[index], verifier(), CHECK); bool subtype2 = type2.is_assignable_from( - _locals[index+1], verifier()->current_class(), CHECK); + _locals[index+1], verifier(), CHECK); if (!subtype1 || !subtype2) { verifier()->verify_error(_offset, "Bad local variable type"); return;
--- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -177,8 +177,7 @@ if (_stack_size != 0) { VerificationType top = _stack[_stack_size - 1]; bool subtype = type.is_assignable_from( - top, verifier()->current_class(), - CHECK_(VerificationType::bogus_type())); + top, verifier(), CHECK_(VerificationType::bogus_type())); if (subtype) { _stack_size --; NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); ) @@ -194,11 +193,9 @@ assert(type2.is_long() || type2.is_double(), "must be long/double_2"); if (_stack_size >= 2) { VerificationType top1 = _stack[_stack_size - 1]; - bool subtype1 = type1.is_assignable_from( - top1, verifier()->current_class(), CHECK); + bool subtype1 = type1.is_assignable_from(top1, verifier(), CHECK); VerificationType top2 = _stack[_stack_size - 2]; - bool subtype2 = type2.is_assignable_from( - top2, verifier()->current_class(), CHECK); + bool subtype2 = type2.is_assignable_from(top2, verifier(), CHECK); if (subtype1 && subtype2) { _stack_size -= 2; NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); )
--- a/hotspot/src/share/vm/classfile/stackMapTable.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/stackMapTable.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -184,8 +184,7 @@ _stream->stackmap_format_error("bad class index", THREAD); return VerificationType::bogus_type(); } - return VerificationType::reference_type( - symbolHandle(THREAD, _cp->klass_name_at(class_index))); + return VerificationType::reference_type(_cp->klass_name_at(class_index)); } if (tag == ITEM_UninitializedThis) { if (flags != NULL) {
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -31,7 +31,6 @@ #include "memory/gcLocker.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/oop.inline2.hpp" -#include "oops/symbolKlass.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/hashtable.inline.hpp" @@ -39,14 +38,97 @@ SymbolTable* SymbolTable::_the_table = NULL; +Symbol* SymbolTable::allocate_symbol(const u1* name, int len, TRAPS) { + // Don't allow symbols to be created which cannot fit in a Symbol*. + if (len > Symbol::max_length()) { + THROW_MSG_0(vmSymbols::java_lang_InternalError(), + "name is too long to represent"); + } + Symbol* sym = new (len) Symbol(name, len); + assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); + return sym; +} + +bool SymbolTable::allocate_symbols(int names_count, const u1** names, + int* lengths, Symbol** syms, TRAPS) { + for (int i = 0; i< names_count; i++) { + if (lengths[i] > Symbol::max_length()) { + THROW_MSG_0(vmSymbols::java_lang_InternalError(), + "name is too long to represent"); + } + } + + for (int i = 0; i< names_count; i++) { + int len = lengths[i]; + syms[i] = new (len) Symbol(names[i], len); + assert(syms[i] != NULL, "new should call vm_exit_out_of_memory if " + "C_HEAP is exhausted"); + } + return true; +} + +// Call function for all symbols in the symbol table. +void SymbolTable::symbols_do(SymbolClosure *cl) { + const int n = the_table()->table_size(); + for (int i = 0; i < n; i++) { + for (HashtableEntry<Symbol*>* p = the_table()->bucket(i); + p != NULL; + p = p->next()) { + cl->do_symbol(p->literal_addr()); + } + } +} + +int SymbolTable::symbols_removed = 0; +int SymbolTable::symbols_counted = 0; + +// Remove unreferenced symbols from the symbol table +// This is done late during GC. This doesn't use the hash table unlink because +// it assumes that the literals are oops. +void SymbolTable::unlink() { + int removed = 0; + int total = 0; + int memory_total = 0; + for (int i = 0; i < the_table()->table_size(); ++i) { + for (HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i); *p != NULL; ) { + HashtableEntry<Symbol*>* entry = *p; + if (entry->is_shared()) { + break; + } + Symbol* s = entry->literal(); + memory_total += s->object_size(); + total++; + assert(s != NULL, "just checking"); + // If reference count is zero, remove. + if (s->refcount() == 0) { + delete s; + removed++; + *p = entry->next(); + the_table()->free_entry(entry); + } else { + p = entry->next_addr(); + } + } + } + symbols_removed += removed; + symbols_counted += total; + if (PrintGCDetails) { + gclog_or_tty->print(" [Symbols=%d size=%dK] ", total, + (memory_total*HeapWordSize)/1024); + } +} + + // Lookup a symbol in a bucket. -symbolOop SymbolTable::lookup(int index, const char* name, +Symbol* SymbolTable::lookup(int index, const char* name, int len, unsigned int hash) { - for (HashtableEntry* e = bucket(index); e != NULL; e = e->next()) { + for (HashtableEntry<Symbol*>* e = bucket(index); e != NULL; e = e->next()) { if (e->hash() == hash) { - symbolOop sym = symbolOop(e->literal()); + Symbol* sym = e->literal(); if (sym->equals(name, len)) { + // something is referencing this symbol now. + sym->increment_refcount(); return sym; } } @@ -62,11 +144,11 @@ // entries in the symbol table during normal execution (only during // safepoints). -symbolOop SymbolTable::lookup(const char* name, int len, TRAPS) { +Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { unsigned int hashValue = hash_symbol(name, len); int index = the_table()->hash_to_index(hashValue); - symbolOop s = the_table()->lookup(index, name, len, hashValue); + Symbol* s = the_table()->lookup(index, name, len, hashValue); // Found if (s != NULL) return s; @@ -75,7 +157,7 @@ return the_table()->basic_add(index, (u1*)name, len, hashValue, CHECK_NULL); } -symbolOop SymbolTable::lookup(symbolHandle sym, int begin, int end, TRAPS) { +Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { char* buffer; int index, len; unsigned int hashValue; @@ -87,7 +169,7 @@ len = end - begin; hashValue = hash_symbol(name, len); index = the_table()->hash_to_index(hashValue); - symbolOop s = the_table()->lookup(index, name, len, hashValue); + Symbol* s = the_table()->lookup(index, name, len, hashValue); // Found if (s != NULL) return s; @@ -111,18 +193,19 @@ return the_table()->basic_add(index, (u1*)buffer, len, hashValue, CHECK_NULL); } -symbolOop SymbolTable::lookup_only(const char* name, int len, +Symbol* SymbolTable::lookup_only(const char* name, int len, unsigned int& hash) { hash = hash_symbol(name, len); int index = the_table()->hash_to_index(hash); - return the_table()->lookup(index, name, len, hash); + Symbol* s = the_table()->lookup(index, name, len, hash); + return s; } // Suggestion: Push unicode-based lookup all the way into the hashing // and probing logic, so there is no need for convert_to_utf8 until -// an actual new symbolOop is created. -symbolOop SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { +// an actual new Symbol* is created. +Symbol* SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) { int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); char stack_buf[128]; if (utf8_length < (int) sizeof(stack_buf)) { @@ -137,7 +220,7 @@ } } -symbolOop SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, +Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, unsigned int& hash) { int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length); char stack_buf[128]; @@ -163,25 +246,23 @@ // do it the hard way for (int i=0; i<names_count; i++) { int index = table->hash_to_index(hashValues[i]); - symbolOop sym = table->basic_add(index, (u1*)names[i], lengths[i], + Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], CHECK); cp->symbol_at_put(cp_indices[i], sym); } } } -symbolOop SymbolTable::basic_add(int index, u1 *name, int len, +Symbol* SymbolTable::basic_add(int index, u1 *name, int len, unsigned int hashValue, TRAPS) { assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), "proposed name of symbol must be stable"); // We assume that lookup() has been called already, that it failed, // and symbol was not found. We create the symbol here. - symbolKlass* sk = (symbolKlass*) Universe::symbolKlassObj()->klass_part(); - symbolOop s_oop = sk->allocate_symbol(name, len, CHECK_NULL); - symbolHandle sym (THREAD, s_oop); + Symbol* sym = allocate_symbol(name, len, CHECK_NULL); - // Allocation must be done before grapping the SymbolTable_lock lock + // Allocation must be done before grabbing the SymbolTable_lock lock MutexLocker ml(SymbolTable_lock, THREAD); assert(sym->equals((char*)name, len), "symbol must be properly initialized"); @@ -189,51 +270,51 @@ // Since look-up was done lock-free, we need to check if another // thread beat us in the race to insert the symbol. - symbolOop test = lookup(index, (char*)name, len, hashValue); + Symbol* test = lookup(index, (char*)name, len, hashValue); if (test != NULL) { // A race occurred and another thread introduced the symbol, this one // will be dropped and collected. + delete sym; + assert(test->refcount() != 0, "lookup should have incremented the count"); return test; } - HashtableEntry* entry = new_entry(hashValue, sym()); + HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym); + sym->increment_refcount(); add_entry(index, entry); - return sym(); + return sym; } bool SymbolTable::basic_add(constantPoolHandle cp, int names_count, const char** names, int* lengths, int* cp_indices, unsigned int* hashValues, TRAPS) { - symbolKlass* sk = (symbolKlass*) Universe::symbolKlassObj()->klass_part(); - symbolOop sym_oops[symbol_alloc_batch_size]; - bool allocated = sk->allocate_symbols(names_count, names, lengths, - sym_oops, CHECK_false); + Symbol* syms[symbol_alloc_batch_size]; + bool allocated = allocate_symbols(names_count, (const u1**)names, lengths, + syms, CHECK_false); if (!allocated) { return false; } - symbolHandle syms[symbol_alloc_batch_size]; - int i; - for (i=0; i<names_count; i++) { - syms[i] = symbolHandle(THREAD, sym_oops[i]); - } // Allocation must be done before grabbing the SymbolTable_lock lock MutexLocker ml(SymbolTable_lock, THREAD); - for (i=0; i<names_count; i++) { + for (int i=0; i<names_count; i++) { assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized"); // Since look-up was done lock-free, we need to check if another // thread beat us in the race to insert the symbol. int index = hash_to_index(hashValues[i]); - symbolOop test = lookup(index, names[i], lengths[i], hashValues[i]); + Symbol* test = lookup(index, names[i], lengths[i], hashValues[i]); if (test != NULL) { // A race occurred and another thread introduced the symbol, this one // will be dropped and collected. Use test instead. cp->symbol_at_put(cp_indices[i], test); + assert(test->refcount() != 0, "lookup should have incremented the count"); + delete syms[i]; } else { - symbolOop sym = syms[i](); - HashtableEntry* entry = new_entry(hashValues[i], sym); + Symbol* sym = syms[i]; + HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym); + sym->increment_refcount(); // increment refcount in external hashtable add_entry(index, entry); cp->symbol_at_put(cp_indices[i], sym); } @@ -245,12 +326,10 @@ void SymbolTable::verify() { for (int i = 0; i < the_table()->table_size(); ++i) { - HashtableEntry* p = the_table()->bucket(i); + HashtableEntry<Symbol*>* p = the_table()->bucket(i); for ( ; p != NULL; p = p->next()) { - symbolOop s = symbolOop(p->literal()); + Symbol* s = (Symbol*)(p->literal()); guarantee(s != NULL, "symbol is NULL"); - s->verify(); - guarantee(s->is_perm(), "symbol not in permspace"); unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length()); guarantee(p->hash() == h, "broken hash in symbol table entry"); guarantee(the_table()->hash_to_index(h) == i, @@ -279,10 +358,14 @@ int total = 0; int max_symbols = 0; int out_of_range = 0; + int memory_total = 0; + int count = 0; for (i = 0; i < the_table()->table_size(); i++) { - HashtableEntry* p = the_table()->bucket(i); + HashtableEntry<Symbol*>* p = the_table()->bucket(i); for ( ; p != NULL; p = p->next()) { - int counter = symbolOop(p->literal())->utf8_length(); + memory_total += p->literal()->object_size(); + count++; + int counter = p->literal()->utf8_length(); total += counter; if (counter < results_length) { results[counter]++; @@ -293,6 +376,17 @@ } } tty->print_cr("Symbol Table:"); + tty->print_cr("Total number of symbols %5d", count); + tty->print_cr("Total size in memory %5dK", + (memory_total*HeapWordSize)/1024); + tty->print_cr("Total counted %5d", symbols_counted); + tty->print_cr("Total removed %5d", symbols_removed); + if (symbols_counted > 0) { + tty->print_cr("Percent removed %3.2f", + ((float)symbols_removed/(float)symbols_counted)* 100); + } + tty->print_cr("Reference counts %5d", Symbol::_total_count); + tty->print_cr("Histogram of symbol length:"); tty->print_cr("%8s %5d", "Total ", total); tty->print_cr("%8s %5d", "Maximum", max_symbols); tty->print_cr("%8s %3.2f", "Average", @@ -304,22 +398,41 @@ tty->print_cr("%6d %10d", i, results[i]); } } - int line_length = 70; - tty->print_cr("%s %30s", " Length", "Number chains that length"); - for (i = 0; i < results_length; i++) { - if (results[i] > 0) { - tty->print("%4d", i); - for (j = 0; (j < results[i]) && (j < line_length); j++) { - tty->print("%1s", "*"); + if (Verbose) { + int line_length = 70; + tty->print_cr("%s %30s", " Length", "Number chains that length"); + for (i = 0; i < results_length; i++) { + if (results[i] > 0) { + tty->print("%4d", i); + for (j = 0; (j < results[i]) && (j < line_length); j++) { + tty->print("%1s", "*"); + } + if (j == line_length) { + tty->print("%1s", "+"); + } + tty->cr(); } - if (j == line_length) { - tty->print("%1s", "+"); + } + } + tty->print_cr(" %s %d: %d\n", "Number chains longer than", + results_length, out_of_range); +} + +void SymbolTable::print() { + for (int i = 0; i < the_table()->table_size(); ++i) { + HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i); + HashtableEntry<Symbol*>* entry = the_table()->bucket(i); + if (entry != NULL) { + while (entry != NULL) { + tty->print(PTR_FORMAT " ", entry->literal()); + entry->literal()->print(); + tty->print(" %d", entry->literal()->refcount()); + p = entry->next_addr(); + entry = (HashtableEntry<Symbol*>*)HashtableEntry<Symbol*>::make_ptr(*p); } tty->cr(); } } - tty->print_cr(" %s %d: %d\n", "Number chains longer than", - results_length, out_of_range); } #endif // PRODUCT @@ -396,7 +509,7 @@ oop StringTable::lookup(int index, jchar* name, int len, unsigned int hash) { - for (HashtableEntry* l = bucket(index); l != NULL; l = l->next()) { + for (HashtableEntry<oop>* l = bucket(index); l != NULL; l = l->next()) { if (l->hash() == hash) { if (java_lang_String::equals(l->literal(), name, len)) { return l->literal(); @@ -436,13 +549,13 @@ return test; } - HashtableEntry* entry = new_entry(hashValue, string()); + HashtableEntry<oop>* entry = new_entry(hashValue, string()); add_entry(index, entry); return string(); } -oop StringTable::lookup(symbolOop symbol) { +oop StringTable::lookup(Symbol* symbol) { ResourceMark rm; int length; jchar* chars = symbol->as_unicode(length); @@ -466,7 +579,7 @@ hashValue, CHECK_NULL); } -oop StringTable::intern(symbolOop symbol, TRAPS) { +oop StringTable::intern(Symbol* symbol, TRAPS) { if (symbol == NULL) return NULL; ResourceMark rm(THREAD); int length; @@ -500,9 +613,50 @@ return result; } +void StringTable::unlink(BoolObjectClosure* is_alive) { + // Readers of the table are unlocked, so we should only be removing + // entries at a safepoint. + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); + for (int i = 0; i < the_table()->table_size(); ++i) { + for (HashtableEntry<oop>** p = the_table()->bucket_addr(i); *p != NULL; ) { + HashtableEntry<oop>* entry = *p; + if (entry->is_shared()) { + break; + } + assert(entry->literal() != NULL, "just checking"); + if (is_alive->do_object_b(entry->literal())) { + p = entry->next_addr(); + } else { + *p = entry->next(); + the_table()->free_entry(entry); + } + } + } +} + +void StringTable::oops_do(OopClosure* f) { + for (int i = 0; i < the_table()->table_size(); ++i) { + HashtableEntry<oop>** p = the_table()->bucket_addr(i); + HashtableEntry<oop>* entry = the_table()->bucket(i); + while (entry != NULL) { + f->do_oop((oop*)entry->literal_addr()); + + // Did the closure remove the literal from the table? + if (entry->literal() == NULL) { + assert(!entry->is_shared(), "immutable hashtable entry?"); + *p = entry->next(); + the_table()->free_entry(entry); + } else { + p = entry->next_addr(); + } + entry = (HashtableEntry<oop>*)HashtableEntry<oop>::make_ptr(*p); + } + } +} + void StringTable::verify() { for (int i = 0; i < the_table()->table_size(); ++i) { - HashtableEntry* p = the_table()->bucket(i); + HashtableEntry<oop>* p = the_table()->bucket(i); for ( ; p != NULL; p = p->next()) { oop s = p->literal(); guarantee(s != NULL, "interned string is NULL");
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/symbolTable.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -26,11 +26,11 @@ #define SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP #include "memory/allocation.inline.hpp" -#include "oops/symbolOop.hpp" +#include "oops/symbol.hpp" #include "utilities/hashtable.hpp" -// The symbol table holds all symbolOops and corresponding interned strings. -// symbolOops and literal strings should be canonicalized. +// The symbol table holds all Symbol*s and corresponding interned strings. +// Symbol*s and literal strings should be canonicalized. // // The interned strings are created lazily. // @@ -42,32 +42,76 @@ class BoolObjectClosure; -class SymbolTable : public Hashtable { +// Class to hold a newly created or referenced Symbol* temporarily in scope. +// new_symbol() and lookup() will create a Symbol* if not already in the +// symbol table and add to the symbol's reference count. +// probe() and lookup_only() will increment the refcount if symbol is found. +class TempNewSymbol : public StackObj { + Symbol* _temp; + + public: + TempNewSymbol() : _temp(NULL) {} + // Creating or looking up a symbol increments the symbol's reference count + TempNewSymbol(Symbol *s) : _temp(s) {} + + // Operator= increments reference count. + void operator=(const TempNewSymbol &s) { + _temp = s._temp; + if (_temp !=NULL) _temp->increment_refcount(); + } + + // Decrement reference counter so it can go away if it's unique + ~TempNewSymbol() { if (_temp != NULL) _temp->decrement_refcount(); } + + // Operators so they can be used like Symbols + Symbol* operator -> () const { return _temp; } + bool operator == (Symbol* o) const { return _temp == o; } + // Sneaky conversion function + operator Symbol*() { return _temp; } +}; + +class SymbolTable : public Hashtable<Symbol*> { friend class VMStructs; + friend class ClassFileParser; private: // The symbol table static SymbolTable* _the_table; + // For statistics + static int symbols_removed; + static int symbols_counted; + + Symbol* allocate_symbol(const u1* name, int len, TRAPS); // Assumes no characters larger than 0x7F + bool allocate_symbols(int names_count, const u1** names, int* lengths, Symbol** syms, TRAPS); + // Adding elements - symbolOop basic_add(int index, u1* name, int len, + Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue, TRAPS); bool basic_add(constantPoolHandle cp, int names_count, const char** names, int* lengths, int* cp_indices, unsigned int* hashValues, TRAPS); + static void new_symbols(constantPoolHandle cp, int names_count, + const char** name, int* lengths, + int* cp_indices, unsigned int* hashValues, + TRAPS) { + add(cp, names_count, name, lengths, cp_indices, hashValues, THREAD); + } + + // Table size enum { symbol_table_size = 20011 }; - symbolOop lookup(int index, const char* name, int len, unsigned int hash); + Symbol* lookup(int index, const char* name, int len, unsigned int hash); SymbolTable() - : Hashtable(symbol_table_size, sizeof (HashtableEntry)) {} + : Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>)) {} SymbolTable(HashtableBucket* t, int number_of_entries) - : Hashtable(symbol_table_size, sizeof (HashtableEntry), t, + : Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>), t, number_of_entries) {} @@ -92,66 +136,76 @@ _the_table = new SymbolTable(t, number_of_entries); } - static symbolOop lookup(const char* name, int len, TRAPS); + static Symbol* lookup(const char* name, int len, TRAPS); // lookup only, won't add. Also calculate hash. - static symbolOop lookup_only(const char* name, int len, unsigned int& hash); + static Symbol* lookup_only(const char* name, int len, unsigned int& hash); // Only copy to C string to be added if lookup failed. - static symbolOop lookup(symbolHandle sym, int begin, int end, TRAPS); + static Symbol* lookup(const Symbol* sym, int begin, int end, TRAPS); + + static void release(Symbol* sym); // jchar (utf16) version of lookups - static symbolOop lookup_unicode(const jchar* name, int len, TRAPS); - static symbolOop lookup_only_unicode(const jchar* name, int len, unsigned int& hash); + static Symbol* lookup_unicode(const jchar* name, int len, TRAPS); + static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash); static void add(constantPoolHandle cp, int names_count, const char** names, int* lengths, int* cp_indices, unsigned int* hashValues, TRAPS); - // GC support - // Delete pointers to otherwise-unreachable objects. - static void unlink(BoolObjectClosure* cl) { - the_table()->Hashtable::unlink(cl); + // Release any dead symbols + static void unlink(); + + // iterate over symbols + static void symbols_do(SymbolClosure *cl); + + // Symbol creation + static Symbol* new_symbol(const char* utf8_buffer, int length, TRAPS) { + assert(utf8_buffer != NULL, "just checking"); + return lookup(utf8_buffer, length, THREAD); } - - // Invoke "f->do_oop" on the locations of all oops in the table. - static void oops_do(OopClosure* f) { - the_table()->Hashtable::oops_do(f); + static Symbol* new_symbol(const char* name, TRAPS) { + return new_symbol(name, (int)strlen(name), THREAD); + } + static Symbol* new_symbol(const Symbol* sym, int begin, int end, TRAPS) { + assert(begin <= end && end <= sym->utf8_length(), "just checking"); + return lookup(sym, begin, end, THREAD); } // Symbol lookup - static symbolOop lookup(int index, const char* name, int len, TRAPS); + static Symbol* lookup(int index, const char* name, int len, TRAPS); // Needed for preloading classes in signatures when compiling. // Returns the symbol is already present in symbol table, otherwise // NULL. NO ALLOCATION IS GUARANTEED! - static symbolOop probe(const char* name, int len) { + static Symbol* probe(const char* name, int len) { unsigned int ignore_hash; return lookup_only(name, len, ignore_hash); } - static symbolOop probe_unicode(const jchar* name, int len) { + static Symbol* probe_unicode(const jchar* name, int len) { unsigned int ignore_hash; return lookup_only_unicode(name, len, ignore_hash); } // Histogram static void print_histogram() PRODUCT_RETURN; + static void print() PRODUCT_RETURN; // Debugging static void verify(); // Sharing static void copy_buckets(char** top, char*end) { - the_table()->Hashtable::copy_buckets(top, end); + the_table()->Hashtable<Symbol*>::copy_buckets(top, end); } static void copy_table(char** top, char*end) { - the_table()->Hashtable::copy_table(top, end); + the_table()->Hashtable<Symbol*>::copy_table(top, end); } static void reverse(void* boundary = NULL) { - ((Hashtable*)the_table())->reverse(boundary); + the_table()->Hashtable<Symbol*>::reverse(boundary); } }; - -class StringTable : public Hashtable { +class StringTable : public Hashtable<oop> { friend class VMStructs; private: @@ -169,10 +223,10 @@ oop lookup(int index, jchar* chars, int length, unsigned int hashValue); - StringTable() : Hashtable(string_table_size, sizeof (HashtableEntry)) {} + StringTable() : Hashtable<oop>(string_table_size, sizeof (HashtableEntry<oop>)) {} StringTable(HashtableBucket* t, int number_of_entries) - : Hashtable(string_table_size, sizeof (HashtableEntry), t, + : Hashtable<oop>(string_table_size, sizeof (HashtableEntry<oop>), t, number_of_entries) {} public: @@ -192,26 +246,20 @@ _the_table = new StringTable(t, number_of_entries); } - static int hash_string(jchar* s, int len); - // GC support // Delete pointers to otherwise-unreachable objects. - static void unlink(BoolObjectClosure* cl) { - the_table()->Hashtable::unlink(cl); - } + static void unlink(BoolObjectClosure* cl); // Invoke "f->do_oop" on the locations of all oops in the table. - static void oops_do(OopClosure* f) { - the_table()->Hashtable::oops_do(f); - } + static void oops_do(OopClosure* f); // Probing - static oop lookup(symbolOop symbol); + static oop lookup(Symbol* symbol); // Interning - static oop intern(symbolOop symbol, TRAPS); + static oop intern(Symbol* symbol, TRAPS); static oop intern(oop string, TRAPS); static oop intern(const char *utf8_string, TRAPS); @@ -220,13 +268,13 @@ // Sharing static void copy_buckets(char** top, char*end) { - the_table()->Hashtable::copy_buckets(top, end); + the_table()->Hashtable<oop>::copy_buckets(top, end); } static void copy_table(char** top, char*end) { - the_table()->Hashtable::copy_table(top, end); + the_table()->Hashtable<oop>::copy_table(top, end); } static void reverse() { - ((BasicHashtable*)the_table())->reverse(); + the_table()->Hashtable<oop>::reverse(); } };
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -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,48 +189,49 @@ // 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) { assert(!THREAD->is_Compiler_thread(), "Can not load classes with the Compiler thread"); - if (FieldType::is_array(class_name())) { + 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; } @@ -271,8 +272,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, @@ -281,7 +282,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; } @@ -323,7 +324,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 { @@ -342,7 +343,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, @@ -392,8 +393,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); @@ -414,7 +415,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); @@ -489,7 +490,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 @@ -578,17 +579,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 @@ -632,7 +625,7 @@ bool havesupername = false; instanceKlassHandle k; PlaceholderEntry* placeholder; - symbolHandle superclassname; + Symbol* superclassname = NULL; { MutexLocker mu(SystemDictionary_lock, THREAD); @@ -646,7 +639,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; } } @@ -691,7 +684,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); @@ -733,7 +725,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 @@ -837,7 +829,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 @@ -880,7 +872,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) { @@ -910,37 +902,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); @@ -949,7 +938,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; @@ -957,7 +946,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] && @@ -983,14 +972,14 @@ // Note: this method is much like resolve_from_stream, but // updates no supplemental data structures. // TODO consolidate the two methods with a helper routine? -klassOop SystemDictionary::parse_stream(symbolHandle class_name, +klassOop SystemDictionary::parse_stream(Symbol* class_name, Handle class_loader, Handle protection_domain, ClassFileStream* st, KlassHandle host_klass, GrowableArray<Handle>* cp_patches, TRAPS) { - symbolHandle parsed_name; + TempNewSymbol parsed_name = NULL; // Parse the stream. Note that we do this even though this klass might // already be present in the SystemDictionary, otherwise we would not @@ -1011,13 +1000,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); @@ -1060,7 +1048,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, @@ -1079,7 +1067,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 @@ -1101,7 +1089,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 @@ -1121,9 +1109,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), @@ -1144,7 +1131,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); @@ -1160,16 +1147,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"); } } ); @@ -1189,7 +1176,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); @@ -1207,7 +1194,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); } @@ -1222,14 +1209,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)); } @@ -1243,7 +1230,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)); } @@ -1290,7 +1277,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(); @@ -1313,8 +1300,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)); @@ -1344,7 +1331,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()) { @@ -1419,16 +1406,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)); } @@ -1444,7 +1431,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; } } @@ -1477,7 +1464,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); @@ -1536,10 +1523,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); @@ -1560,8 +1547,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 @@ -1653,7 +1639,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), @@ -1665,18 +1651,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 || @@ -1684,22 +1669,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); } @@ -1757,12 +1731,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); } @@ -1808,9 +1776,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]); } @@ -1862,7 +1827,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); } @@ -1882,7 +1847,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; @@ -1924,7 +1889,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; @@ -1954,7 +1919,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) { @@ -2081,7 +2046,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); @@ -2102,10 +2067,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) { @@ -2141,7 +2104,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); @@ -2181,7 +2144,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(); @@ -2190,7 +2153,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.) @@ -2203,23 +2166,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); @@ -2231,25 +2191,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); @@ -2272,7 +2230,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); { @@ -2282,13 +2240,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; } } @@ -2344,7 +2302,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. @@ -2352,13 +2310,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(); @@ -2367,12 +2326,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); @@ -2385,7 +2344,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(); @@ -2416,7 +2375,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, @@ -2424,11 +2383,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, @@ -2500,17 +2460,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)); @@ -2542,7 +2503,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, @@ -2557,7 +2518,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()); @@ -2740,16 +2701,20 @@ void SystemDictionary::verify_obj_klass_present(Handle obj, - symbolHandle class_name, + Symbol* class_name, Handle class_loader) { GCMutexLocker mu(SystemDictionary_lock); - oop probe = find_class_or_placeholder(class_name, class_loader); + Symbol* name; + + klassOop probe = find_class(class_name, class_loader); if (probe == NULL) { probe = SystemDictionary::find_shared_class(class_name); + if (probe == NULL) { + name = find_placeholder(class_name, class_loader); + } } - guarantee(probe != NULL && - (!probe->is_klass() || probe == obj()), - "Loaded klasses should be in SystemDictionary"); + guarantee(probe != NULL || name != NULL, + "Loaded klasses should be in SystemDictionary"); } #ifndef PRODUCT
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -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. @@ -226,26 +226,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, @@ -253,7 +253,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, @@ -261,7 +261,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, @@ -270,23 +270,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 @@ -309,7 +309,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); @@ -324,7 +324,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)); @@ -383,12 +383,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 @@ -469,19 +469,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, @@ -490,13 +490,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: @@ -519,8 +519,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: @@ -580,29 +580,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); @@ -613,34 +613,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); @@ -670,7 +665,6 @@ static bool _has_checkPackageAccess; }; -// Cf. vmSymbols vs. vmSymbolHandles class SystemDictionaryHandles : AllStatic { public: #define WK_KLASS_HANDLE_DECLARE(name, ignore_symbol, option) \
--- a/hotspot/src/share/vm/classfile/verificationType.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/verificationType.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/symbolTable.hpp" #include "classfile/verificationType.hpp" +#include "classfile/verifier.hpp" VerificationType VerificationType::from_tag(u1 tag) { switch (tag) { @@ -41,7 +42,8 @@ } bool VerificationType::is_reference_assignable_from( - const VerificationType& from, instanceKlassHandle context, TRAPS) const { + const VerificationType& from, ClassVerifier* context, TRAPS) const { + instanceKlassHandle klass = context->current_class(); if (from.is_null()) { // null is assignable to any reference return true; @@ -56,8 +58,8 @@ return true; } klassOop obj = SystemDictionary::resolve_or_fail( - name_handle(), Handle(THREAD, context->class_loader()), - Handle(THREAD, context->protection_domain()), true, CHECK_false); + name(), Handle(THREAD, klass->class_loader()), + Handle(THREAD, klass->protection_domain()), true, CHECK_false); KlassHandle this_class(THREAD, obj); if (this_class->is_interface()) { @@ -66,13 +68,13 @@ return true; } else if (from.is_object()) { klassOop from_class = SystemDictionary::resolve_or_fail( - from.name_handle(), Handle(THREAD, context->class_loader()), - Handle(THREAD, context->protection_domain()), true, CHECK_false); + from.name(), Handle(THREAD, klass->class_loader()), + Handle(THREAD, klass->protection_domain()), true, CHECK_false); return instanceKlass::cast(from_class)->is_subclass_of(this_class()); } } else if (is_array() && from.is_array()) { - VerificationType comp_this = get_component(CHECK_false); - VerificationType comp_from = from.get_component(CHECK_false); + VerificationType comp_this = get_component(context, CHECK_false); + VerificationType comp_from = from.get_component(context, CHECK_false); if (!comp_this.is_bogus() && !comp_from.is_bogus()) { return comp_this.is_assignable_from(comp_from, context, CHECK_false); } @@ -80,9 +82,9 @@ return false; } -VerificationType VerificationType::get_component(TRAPS) const { +VerificationType VerificationType::get_component(ClassVerifier *context, TRAPS) const { assert(is_array() && name()->utf8_length() >= 2, "Must be a valid array"); - symbolOop component; + Symbol* component; switch (name()->byte_at(1)) { case 'Z': return VerificationType(Boolean); case 'B': return VerificationType(Byte); @@ -93,12 +95,12 @@ case 'F': return VerificationType(Float); case 'D': return VerificationType(Double); case '[': - component = SymbolTable::lookup( + component = context->create_temporary_symbol( name(), 1, name()->utf8_length(), CHECK_(VerificationType::bogus_type())); return VerificationType::reference_type(component); case 'L': - component = SymbolTable::lookup( + component = context->create_temporary_symbol( name(), 2, name()->utf8_length() - 1, CHECK_(VerificationType::bogus_type())); return VerificationType::reference_type(component);
--- a/hotspot/src/share/vm/classfile/verificationType.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/verificationType.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -29,7 +29,7 @@ #include "memory/allocation.hpp" #include "oops/instanceKlass.hpp" #include "oops/oop.inline.hpp" -#include "oops/symbolOop.hpp" +#include "oops/symbol.hpp" #include "runtime/handles.hpp" #include "runtime/signature.hpp" @@ -47,6 +47,8 @@ ITEM_Bogus = (uint)-1 }; +class ClassVerifier; + class VerificationType VALUE_OBJ_CLASS_SPEC { private: // Least significant bits of _handle are always 0, so we use these as @@ -56,7 +58,7 @@ // will catch this and we'll have to add a descriminator tag to this // structure. union { - symbolOop* _handle; + Symbol* _sym; uintptr_t _data; } _u; @@ -73,7 +75,7 @@ TypeMask = 0x00000003, // Topmost types encoding - Reference = 0x0, // _handle contains the name + Reference = 0x0, // _sym contains the name Primitive = 0x1, // see below for primitive list Uninitialized = 0x2, // 0x00ffff00 contains bci TypeQuery = 0x3, // Meta-types used for category testing @@ -85,7 +87,7 @@ Category2_2ndFlag = 0x04, // Second word of a two-word value // special reference values - Null = 0x00000000, // A reference with a 0 handle is null + Null = 0x00000000, // A reference with a 0 sym is null // Primitives categories (the second byte determines the category) Category1 = (Category1Flag << 1 * BitsPerByte) | Primitive, @@ -152,17 +154,14 @@ static VerificationType category2_2nd_check() { return VerificationType(Category2_2ndQuery); } - // For reference types, store the actual oop* handle - static VerificationType reference_type(symbolHandle sh) { - assert(((uintptr_t)sh.raw_value() & 0x3) == 0, "Oops must be aligned"); + // For reference types, store the actual Symbol + static VerificationType reference_type(Symbol* sh) { + assert(((uintptr_t)sh & 0x3) == 0, "Oops must be aligned"); // If the above assert fails in the future because oop* isn't aligned, // then this type encoding system will have to change to have a tag value // to descriminate between oops and primitives. - return VerificationType((uintptr_t)((symbolOop*)sh.raw_value())); + return VerificationType((uintptr_t)sh); } - static VerificationType reference_type(symbolOop s, TRAPS) - { return reference_type(symbolHandle(THREAD, s)); } - static VerificationType uninitialized_type(u2 bci) { return VerificationType(bci << 1 * BitsPerByte | Uninitialized); } static VerificationType uninitialized_this_type() @@ -242,13 +241,9 @@ return ((_u._data & BciMask) >> 1 * BitsPerByte); } - symbolHandle name_handle() const { + Symbol* name() const { assert(is_reference() && !is_null(), "Must be a non-null reference"); - return symbolHandle(_u._handle, true); - } - symbolOop name() const { - assert(is_reference() && !is_null(), "Must be a non-null reference"); - return *(_u._handle); + return _u._sym; } bool equals(const VerificationType& t) const { @@ -269,7 +264,7 @@ // is assignable to another. Returns true if one can assign 'from' to // this. bool is_assignable_from( - const VerificationType& from, instanceKlassHandle context, TRAPS) const { + const VerificationType& from, ClassVerifier* context, TRAPS) const { if (equals(from) || is_bogus()) { return true; } else { @@ -298,7 +293,7 @@ } } - VerificationType get_component(TRAPS) const; + VerificationType get_component(ClassVerifier* context, TRAPS) const; int dimensions() const { assert(is_array(), "Must be an array"); @@ -312,7 +307,7 @@ private: bool is_reference_assignable_from( - const VerificationType&, instanceKlassHandle, TRAPS) const; + const VerificationType&, ClassVerifier*, TRAPS) const; }; #endif // SHARE_VM_CLASSFILE_VERIFICATIONTYPE_HPP
--- a/hotspot/src/share/vm/classfile/verifier.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -98,10 +98,10 @@ } bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool should_verify_class, TRAPS) { + HandleMark hm; ResourceMark rm(THREAD); - HandleMark hm; - symbolHandle exception_name; + Symbol* exception_name = NULL; const size_t message_buffer_len = klass->name()->utf8_length() + 1024; char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len); @@ -141,7 +141,7 @@ tty->print("Verification for %s has", klassName); tty->print_cr(" exception pending %s ", instanceKlass::cast(PENDING_EXCEPTION->klass())->external_name()); - } else if (!exception_name.is_null()) { + } else if (exception_name != NULL) { tty->print_cr("Verification for %s failed", klassName); } tty->print_cr("End class verification for: %s", klassName); @@ -150,7 +150,7 @@ if (HAS_PENDING_EXCEPTION) { return false; // use the existing exception - } else if (exception_name.is_null()) { + } else if (exception_name == NULL) { return true; // verifcation succeeded } else { // VerifyError or ClassFormatError to be created and thrown ResourceMark rm(THREAD); @@ -172,7 +172,7 @@ } bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) { - symbolOop name = klass->name(); + Symbol* name = klass->name(); klassOop refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass(); return (should_verify_for(klass->class_loader(), should_verify_class) && @@ -202,7 +202,7 @@ ); } -symbolHandle Verifier::inference_verify( +Symbol* Verifier::inference_verify( instanceKlassHandle klass, char* message, size_t message_len, TRAPS) { JavaThread* thread = (JavaThread*)THREAD; JNIEnv *env = thread->jni_environment(); @@ -245,18 +245,17 @@ // These numbers are chosen so that VerifyClassCodes interface doesn't need // to be changed (still return jboolean (unsigned char)), and result is // 1 when verification is passed. - symbolHandle nh(NULL); if (result == 0) { return vmSymbols::java_lang_VerifyError(); } else if (result == 1) { - return nh; // verified. + return NULL; // verified. } else if (result == 2) { - THROW_MSG_(vmSymbols::java_lang_OutOfMemoryError(), message, nh); + THROW_MSG_(vmSymbols::java_lang_OutOfMemoryError(), message, NULL); } else if (result == 3) { return vmSymbols::java_lang_ClassFormatError(); } else { ShouldNotReachHere(); - return nh; + return NULL; } } @@ -266,12 +265,19 @@ ClassVerifier::ClassVerifier( instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS) - : _thread(THREAD), _exception_type(symbolHandle()), _message(msg), + : _thread(THREAD), _exception_type(NULL), _message(msg), _message_buffer_len(msg_len), _klass(klass) { _this_type = VerificationType::reference_type(klass->name()); + // Create list to hold symbols in reference area. + _symbols = new GrowableArray<Symbol*>(100, 0, NULL); } ClassVerifier::~ClassVerifier() { + // Decrement the reference count for any symbols created. + for (int i = 0; i < _symbols->length(); i++) { + Symbol* s = _symbols->at(i); + s->decrement_refcount(); + } } VerificationType ClassVerifier::object_type() const { @@ -308,7 +314,6 @@ } void ClassVerifier::verify_method(methodHandle m, TRAPS) { - ResourceMark rm(THREAD); _method = m; // initialize _method if (_verify_verbose) { tty->print_cr("Verifying method %s", m->name_and_sig_as_C_string()); @@ -615,7 +620,7 @@ VerificationType::null_type(), CHECK_VERIFY(this)); } else { VerificationType component = - atype.get_component(CHECK_VERIFY(this)); + atype.get_component(this, CHECK_VERIFY(this)); current_frame.push_stack(component, CHECK_VERIFY(this)); } no_control_flow = false; break; @@ -1386,7 +1391,7 @@ VerificationType throwable = VerificationType::reference_type(vmSymbols::java_lang_Throwable()); bool is_subclass = throwable.is_assignable_from( - catch_type, current_class(), CHECK_VERIFY(this)); + catch_type, this, CHECK_VERIFY(this)); if (!is_subclass) { // 4286534: should throw VerifyError according to recent spec change verify_error( @@ -1473,8 +1478,6 @@ if(bci >= start_pc && bci < end_pc) { u1 flags = current_frame->flags(); if (this_uninit) { flags |= FLAG_THIS_UNINIT; } - - ResourceMark rm(THREAD); StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags); if (catch_type_index != 0) { // We know that this index refers to a subclass of Throwable @@ -1575,7 +1578,7 @@ va_end(va); } -klassOop ClassVerifier::load_class(symbolHandle name, TRAPS) { +klassOop ClassVerifier::load_class(Symbol* name, TRAPS) { // Get current loader and protection domain first. oop loader = current_class()->class_loader(); oop protection_domain = current_class()->protection_domain(); @@ -1587,8 +1590,8 @@ bool ClassVerifier::is_protected_access(instanceKlassHandle this_class, klassOop target_class, - symbolOop field_name, - symbolOop field_sig, + Symbol* field_name, + Symbol* field_sig, bool is_method) { No_Safepoint_Verifier nosafepoint; @@ -1736,7 +1739,7 @@ } bool ClassVerifier::name_in_supers( - symbolOop ref_name, instanceKlassHandle current) { + Symbol* ref_name, instanceKlassHandle current) { klassOop super = current->super(); while (super != NULL) { if (super->klass_part()->name() == ref_name) { @@ -1755,8 +1758,8 @@ verify_cp_type(index, cp, 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this)); // Get field name and signature - symbolHandle field_name = symbolHandle(THREAD, cp->name_ref_at(index)); - symbolHandle field_sig = symbolHandle(THREAD, cp->signature_ref_at(index)); + Symbol* field_name = cp->name_ref_at(index); + Symbol* field_sig = cp->signature_ref_at(index); if (!SignatureVerifier::is_valid_type_signature(field_sig)) { class_format_error( @@ -1823,11 +1826,11 @@ fieldDescriptor fd; if (stack_object_type == VerificationType::uninitialized_this_type() && target_class_type.equals(current_type()) && - _klass->find_local_field(field_name(), field_sig(), &fd)) { + _klass->find_local_field(field_name, field_sig, &fd)) { stack_object_type = current_type(); } is_assignable = target_class_type.is_assignable_from( - stack_object_type, current_class(), CHECK_VERIFY(this)); + stack_object_type, this, CHECK_VERIFY(this)); if (!is_assignable) { verify_error(bci, "Bad type on operand stack in putfield"); return; @@ -1836,9 +1839,9 @@ check_protected: { if (_this_type == stack_object_type) break; // stack_object_type must be assignable to _current_class_type - symbolHandle ref_class_name = symbolHandle(THREAD, - cp->klass_name_at(cp->klass_ref_index_at(index))); - if (!name_in_supers(ref_class_name(), current_class())) + Symbol* ref_class_name = + cp->klass_name_at(cp->klass_ref_index_at(index)); + if (!name_in_supers(ref_class_name, current_class())) // stack_object_type must be assignable to _current_class_type since: // 1. stack_object_type must be assignable to ref_class. // 2. ref_class must be _current_class or a subclass of it. It can't @@ -1846,12 +1849,12 @@ break; klassOop ref_class_oop = load_class(ref_class_name, CHECK); - if (is_protected_access(current_class(), ref_class_oop, field_name(), - field_sig(), false)) { + if (is_protected_access(current_class(), ref_class_oop, field_name, + field_sig, false)) { // It's protected access, check if stack object is assignable to // current class. is_assignable = current_type().is_assignable_from( - stack_object_type, current_class(), CHECK_VERIFY(this)); + stack_object_type, this, CHECK_VERIFY(this)); if (!is_assignable) { verify_error(bci, "Bad access to protected data in getfield"); return; @@ -1911,7 +1914,7 @@ instanceKlassHandle mh(THREAD, m->method_holder()); if (m->is_protected() && !mh->is_same_class_package(_klass())) { bool assignable = current_type().is_assignable_from( - objectref_type, current_class(), CHECK_VERIFY(this)); + objectref_type, this, CHECK_VERIFY(this)); if (!assignable) { verify_error(bci, "Bad access to protected <init> method"); return; @@ -1941,8 +1944,8 @@ verify_cp_type(index, cp, types, CHECK_VERIFY(this)); // Get method name and signature - symbolHandle method_name(THREAD, cp->name_ref_at(index)); - symbolHandle method_sig(THREAD, cp->signature_ref_at(index)); + Symbol* method_name = cp->name_ref_at(index); + Symbol* method_sig = cp->signature_ref_at(index); if (!SignatureVerifier::is_valid_method_signature(method_sig)) { class_format_error( @@ -2035,7 +2038,7 @@ if (method_name->byte_at(0) == '<') { // Make sure <init> can only be invoked by invokespecial if (opcode != Bytecodes::_invokespecial || - method_name() != vmSymbols::object_initializer_name()) { + method_name != vmSymbols::object_initializer_name()) { verify_error(bci, "Illegal call to internal method"); return; } @@ -2044,7 +2047,7 @@ && !ref_class_type.equals(VerificationType::reference_type( current_class()->super()->klass_part()->name()))) { bool subtype = ref_class_type.is_assignable_from( - current_type(), current_class(), CHECK_VERIFY(this)); + current_type(), this, CHECK_VERIFY(this)); if (!subtype) { verify_error(bci, "Bad invokespecial instruction: " "current class isn't assignable to reference class."); @@ -2058,7 +2061,7 @@ // Check objectref on operand stack if (opcode != Bytecodes::_invokestatic && opcode != Bytecodes::_invokedynamic) { - if (method_name() == vmSymbols::object_initializer_name()) { // <init> method + if (method_name == vmSymbols::object_initializer_name()) { // <init> method verify_invoke_init(bcs, ref_class_type, current_frame, code_length, this_uninit, cp, CHECK_VERIFY(this)); } else { // other methods @@ -2070,22 +2073,22 @@ current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this)); if (current_type() != stack_object_type) { assert(cp->cache() == NULL, "not rewritten yet"); - symbolHandle ref_class_name = symbolHandle(THREAD, - cp->klass_name_at(cp->klass_ref_index_at(index))); + Symbol* ref_class_name = + cp->klass_name_at(cp->klass_ref_index_at(index)); // See the comments in verify_field_instructions() for // the rationale behind this. - if (name_in_supers(ref_class_name(), current_class())) { + if (name_in_supers(ref_class_name, current_class())) { klassOop ref_class = load_class(ref_class_name, CHECK); if (is_protected_access( - _klass, ref_class, method_name(), method_sig(), true)) { + _klass, ref_class, method_name, method_sig, true)) { // It's protected access, check if stack object is // assignable to current class. bool is_assignable = current_type().is_assignable_from( - stack_object_type, current_class(), CHECK_VERIFY(this)); + stack_object_type, this, CHECK_VERIFY(this)); if (!is_assignable) { if (ref_class_type.name() == vmSymbols::java_lang_Object() && stack_object_type.is_array() - && method_name() == vmSymbols::clone_name()) { + && method_name == vmSymbols::clone_name()) { // Special case: arrays pretend to implement public Object // clone(). } else { @@ -2105,7 +2108,7 @@ } // Push the result type. if (sig_stream.type() != T_VOID) { - if (method_name() == vmSymbols::object_initializer_name()) { + if (method_name == vmSymbols::object_initializer_name()) { // <init> method must have a void return type verify_error(bci, "Return type must be void in <init> method"); return; @@ -2130,7 +2133,7 @@ } // from_bt[index] contains the array signature which has a length of 2 - symbolHandle sig = oopFactory::new_symbol_handle( + Symbol* sig = create_temporary_symbol( from_bt[index], 2, CHECK_(VerificationType::bogus_type())); return VerificationType::reference_type(sig); } @@ -2143,7 +2146,6 @@ VerificationType component_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); - ResourceMark rm(THREAD); int length; char* arr_sig_str; if (component_type.is_array()) { // it's an array @@ -2163,7 +2165,7 @@ strncpy(&arr_sig_str[2], component_name, length - 2); arr_sig_str[length - 1] = ';'; } - symbolHandle arr_sig = oopFactory::new_symbol_handle( + Symbol* arr_sig = create_temporary_symbol( arr_sig_str, length, CHECK_VERIFY(this)); VerificationType new_array_type = VerificationType::reference_type(arr_sig); current_frame->push_stack(new_array_type, CHECK_VERIFY(this)); @@ -2256,9 +2258,25 @@ verify_error(bci, "Method expects a return value"); return; } - bool match = return_type.is_assignable_from(type, _klass, CHECK_VERIFY(this)); + bool match = return_type.is_assignable_from(type, this, CHECK_VERIFY(this)); if (!match) { verify_error(bci, "Bad return type"); return; } } + +// The verifier creates symbols which are substrings of Symbols. +// These are stored in the verifier until the end of verification so that +// they can be reference counted. +Symbol* ClassVerifier::create_temporary_symbol(const Symbol *s, int begin, + int end, TRAPS) { + Symbol* sym = SymbolTable::new_symbol(s, begin, end, CHECK_NULL); + _symbols->push(sym); + return sym; +} + +Symbol* ClassVerifier::create_temporary_symbol(const char *s, int length, TRAPS) { + Symbol* sym = SymbolTable::new_symbol(s, length, CHECK_NULL); + _symbols->push(sym); + return sym; +}
--- a/hotspot/src/share/vm/classfile/verifier.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/verifier.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -59,7 +59,7 @@ private: static bool is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class); - static symbolHandle inference_verify( + static Symbol* inference_verify( instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS); }; @@ -69,8 +69,8 @@ // Summary of verifier's memory usage: // StackMapTable is stack allocated. -// StackMapFrame are resource allocated. There is one ResourceMark -// for each method. +// StackMapFrame are resource allocated. There is only one ResourceMark +// for each class verification, which is created at the top level. // There is one mutable StackMapFrame (current_frame) which is updated // by abstract bytecode interpretation. frame_in_exception_handler() returns // a frame that has a mutable one-item stack (ready for pushing the @@ -80,8 +80,6 @@ // locals/stack arrays in StackMapFrame are resource allocated. // locals/stack arrays can be shared between StackMapFrame's, except // the mutable StackMapFrame (current_frame). -// Care needs to be taken to make sure resource objects don't outlive -// the lifetime of their ResourceMark. // These macros are used similarly to CHECK macros but also check // the status of the verifier and return if that has an error. @@ -94,9 +92,10 @@ class ClassVerifier : public StackObj { private: Thread* _thread; - symbolHandle _exception_type; + Symbol* _exception_type; char* _message; size_t _message_buffer_len; + GrowableArray<Symbol*>* _symbols; // keep a list of symbols created void verify_method(methodHandle method, TRAPS); char* generate_code_data(methodHandle m, u4 code_length, TRAPS); @@ -110,7 +109,7 @@ bool is_protected_access( instanceKlassHandle this_class, klassOop target_class, - symbolOop field_name, symbolOop field_sig, bool is_method); + Symbol* field_name, Symbol* field_sig, bool is_method); void verify_cp_index(constantPoolHandle cp, int index, TRAPS); void verify_cp_type( @@ -165,7 +164,7 @@ void verify_astore(u2 index, StackMapFrame* current_frame, TRAPS); void verify_iinc (u2 index, StackMapFrame* current_frame, TRAPS); - bool name_in_supers(symbolOop ref_name, instanceKlassHandle current); + bool name_in_supers(Symbol* ref_name, instanceKlassHandle current); VerificationType object_type() const; @@ -206,8 +205,8 @@ void verify_class(TRAPS); // Return status modes - symbolHandle result() const { return _exception_type; } - bool has_error() const { return !(result().is_null()); } + Symbol* result() const { return _exception_type; } + bool has_error() const { return result() != NULL; } // Called when verify or class format errors are encountered. // May throw an exception based upon the mode. @@ -216,16 +215,22 @@ void class_format_error(const char* fmt, ...); void format_error_message(const char* fmt, int offset, va_list args); - klassOop load_class(symbolHandle name, TRAPS); + klassOop load_class(Symbol* name, TRAPS); int change_sig_to_verificationType( SignatureStream* sig_type, VerificationType* inference_type, TRAPS); VerificationType cp_index_to_type(int index, constantPoolHandle cp, TRAPS) { - return VerificationType::reference_type( - symbolHandle(THREAD, cp->klass_name_at(index))); + return VerificationType::reference_type(cp->klass_name_at(index)); } + // Keep a list of temporary symbols created during verification because + // their reference counts need to be decrememented when the verifier object + // goes out of scope. Since these symbols escape the scope in which they're + // created, we can't use a TempNewSymbol. + Symbol* create_temporary_symbol(const Symbol* s, int begin, int end, TRAPS); + Symbol* create_temporary_symbol(const char *s, int length, TRAPS); + static bool _verify_verbose; // for debugging }; @@ -236,9 +241,14 @@ case T_OBJECT: case T_ARRAY: { - symbolOop name = sig_type->as_symbol(CHECK_0); + Symbol* name = sig_type->as_symbol(CHECK_0); + // Create another symbol to save as signature stream unreferences + // this symbol. + Symbol* name_copy = + create_temporary_symbol(name, 0, name->utf8_length(), CHECK_0); + assert(name_copy == name, "symbols don't match"); *inference_type = - VerificationType::reference_type(symbolHandle(THREAD, name)); + VerificationType::reference_type(name_copy); return 1; } case T_LONG:
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -30,11 +30,11 @@ #include "utilities/xmlstream.hpp" -symbolOop vmSymbols::_symbols[vmSymbols::SID_LIMIT]; +Symbol* vmSymbols::_symbols[vmSymbols::SID_LIMIT]; -symbolOop vmSymbols::_type_signatures[T_VOID+1] = { NULL /*, NULL...*/ }; +Symbol* vmSymbols::_type_signatures[T_VOID+1] = { NULL /*, NULL...*/ }; -inline int compare_symbol(symbolOop a, symbolOop b) { +inline int compare_symbol(Symbol* a, Symbol* b) { if (a == b) return 0; // follow the natural address order: return (address)a > (address)b ? +1 : -1; @@ -43,8 +43,8 @@ static vmSymbols::SID vm_symbol_index[vmSymbols::SID_LIMIT]; extern "C" { static int compare_vmsymbol_sid(const void* void_a, const void* void_b) { - symbolOop a = vmSymbols::symbol_at(*((vmSymbols::SID*) void_a)); - symbolOop b = vmSymbols::symbol_at(*((vmSymbols::SID*) void_b)); + Symbol* a = vmSymbols::symbol_at(*((vmSymbols::SID*) void_a)); + Symbol* b = vmSymbols::symbol_at(*((vmSymbols::SID*) void_b)); return compare_symbol(a, b); } } @@ -79,7 +79,7 @@ if (!UseSharedSpaces) { const char* string = &vm_symbol_bodies[0]; for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { - symbolOop sym = oopFactory::new_symbol(string, CHECK); + Symbol* sym = SymbolTable::new_symbol(string, CHECK); _symbols[index] = sym; string += strlen(string); // skip string body string += 1; // skip trailing null @@ -100,7 +100,7 @@ #ifdef ASSERT // Check for duplicates: for (int i1 = (int)FIRST_SID; i1 < (int)SID_LIMIT; i1++) { - symbolOop sym = symbol_at((SID)i1); + Symbol* sym = symbol_at((SID)i1); for (int i2 = (int)FIRST_SID; i2 < i1; i2++) { if (symbol_at((SID)i2) == sym) { tty->print("*** Duplicate VM symbol SIDs %s(%d) and %s(%d): \"", @@ -128,16 +128,16 @@ // Spot-check correspondence between strings, symbols, and enums: assert(_symbols[NO_SID] == NULL, "must be"); const char* str = "java/lang/Object"; - symbolOop sym = oopFactory::new_symbol(str, CHECK); - assert(strcmp(str, (char*)sym->base()) == 0, ""); - assert(sym == java_lang_Object(), ""); + TempNewSymbol jlo = SymbolTable::new_symbol(str, CHECK); + assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, ""); + assert(jlo == java_lang_Object(), ""); SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object); - assert(find_sid(sym) == sid, ""); - assert(symbol_at(sid) == sym, ""); + assert(find_sid(jlo) == sid, ""); + assert(symbol_at(sid) == jlo, ""); // Make sure find_sid produces the right answer in each case. for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { - sym = symbol_at((SID)index); + Symbol* sym = symbol_at((SID)index); sid = find_sid(sym); assert(sid == (SID)index, "symbol index works"); // Note: If there are duplicates, this assert will fail. @@ -147,8 +147,8 @@ // The string "format" happens (at the moment) not to be a vmSymbol, // though it is a method name in java.lang.String. str = "format"; - sym = oopFactory::new_symbol(str, CHECK); - sid = find_sid(sym); + TempNewSymbol fmt = SymbolTable::new_symbol(str, CHECK); + sid = find_sid(fmt); assert(sid == NO_SID, "symbol index works (negative test)"); } #endif @@ -172,22 +172,23 @@ -void vmSymbols::oops_do(OopClosure* f, bool do_all) { +void vmSymbols::symbols_do(SymbolClosure* f) { for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { - f->do_oop((oop*) &_symbols[index]); + f->do_symbol(&_symbols[index]); } for (int i = 0; i < T_VOID+1; i++) { - if (_type_signatures[i] != NULL) { - assert(i >= T_BOOLEAN, "checking"); - f->do_oop((oop*)&_type_signatures[i]); - } else if (do_all) { - f->do_oop((oop*)&_type_signatures[i]); - } + f->do_symbol(&_type_signatures[i]); } } +void vmSymbols::serialize(SerializeOopClosure* soc) { + soc->do_region((u_char*)&_symbols[FIRST_SID], + (SID_LIMIT - FIRST_SID) * sizeof(_symbols[0])); + soc->do_region((u_char*)_type_signatures, sizeof(_type_signatures)); +} -BasicType vmSymbols::signature_type(symbolOop s) { + +BasicType vmSymbols::signature_type(Symbol* s) { assert(s != NULL, "checking"); for (int i = T_BOOLEAN; i < T_VOID+1; i++) { if (s == _type_signatures[i]) { @@ -205,7 +206,7 @@ // (Typical counts are calls=7000 and probes=17000.) #endif -vmSymbols::SID vmSymbols::find_sid(symbolOop symbol) { +vmSymbols::SID vmSymbols::find_sid(Symbol* symbol) { // Handle the majority of misses by a bounds check. // Then, use a binary search over the index. // Expected trip count is less than log2_SID_LIMIT, about eight. @@ -260,7 +261,7 @@ // (We have already proven that there are no duplicates in the list.) SID sid2 = NO_SID; for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { - symbolOop sym2 = symbol_at((SID)index); + Symbol* sym2 = symbol_at((SID)index); if (sym2 == symbol) { sid2 = (SID)index; break; @@ -319,9 +320,9 @@ methodOop vmIntrinsics::method_for(vmIntrinsics::ID id) { if (id == _none) return NULL; - symbolOop cname = vmSymbols::symbol_at(class_for(id)); - symbolOop mname = vmSymbols::symbol_at(name_for(id)); - symbolOop msig = vmSymbols::symbol_at(signature_for(id)); + Symbol* cname = vmSymbols::symbol_at(class_for(id)); + Symbol* mname = vmSymbols::symbol_at(name_for(id)); + Symbol* msig = vmSymbols::symbol_at(signature_for(id)); if (cname == NULL || mname == NULL || msig == NULL) return NULL; klassOop k = SystemDictionary::find_well_known_klass(cname); if (k == NULL) return NULL; @@ -490,17 +491,17 @@ #ifndef PRODUCT // verify_method performs an extra check on a matched intrinsic method -static bool match_method(methodOop m, symbolOop n, symbolOop s) { +static bool match_method(methodOop m, Symbol* n, Symbol* s) { return (m->name() == n && m->signature() == s); } -static vmIntrinsics::ID match_method_with_klass(methodOop m, symbolOop mk) { +static vmIntrinsics::ID match_method_with_klass(methodOop m, Symbol* mk) { #define VM_INTRINSIC_MATCH(id, klassname, namepart, sigpart, flags) \ - { symbolOop k = vmSymbols::klassname(); \ + { Symbol* k = vmSymbols::klassname(); \ if (mk == k) { \ - symbolOop n = vmSymbols::namepart(); \ - symbolOop s = vmSymbols::sigpart(); \ + Symbol* n = vmSymbols::namepart(); \ + Symbol* s = vmSymbols::sigpart(); \ if (match_method(m, n, s)) \ return vmIntrinsics::id; \ } } @@ -511,7 +512,7 @@ } void vmIntrinsics::verify_method(ID actual_id, methodOop m) { - symbolOop mk = Klass::cast(m->method_holder())->name(); + Symbol* mk = Klass::cast(m->method_holder())->name(); ID declared_id = match_method_with_klass(m, mk); if (declared_id == actual_id) return; // success
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -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: @@ -459,7 +457,7 @@ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, do_alias) \ \ /* returned by the C1 compiler in case there's not enough memory to allocate a new symbol*/ \ - template(dummy_symbol_oop, "illegal symbol") \ + template(dummy_symbol, "illegal symbol") \ \ /* used by ClassFormatError when class name is not known yet */ \ template(unknown_class_name, "<Unknown>") \ @@ -938,10 +936,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, @@ -963,39 +960,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: @@ -1003,34 +1003,6 @@ #endif //PRODUCT }; - -// Class vmSymbolHandles - -class vmSymbolHandles: AllStatic { - friend class vmIntrinsics; - friend class ciObjectFactory; - - public: - // Accessing - #define VM_SYMBOL_HANDLE_DECLARE(name, ignore) \ - static symbolHandle name() { return symbol_handle_at(vmSymbols::VM_SYMBOL_ENUM_NAME(name)); } - VM_SYMBOLS_DO(VM_SYMBOL_HANDLE_DECLARE, VM_SYMBOL_HANDLE_DECLARE) - #undef VM_SYMBOL_HANDLE_DECLARE - - static symbolHandle symbol_handle_at(vmSymbols::SID id) { - return symbolHandle(&vmSymbols::_symbols[(int)id], false); - } - - static symbolHandle type_signature(BasicType t) { - assert(vmSymbols::type_signature(t) != NULL, "domain check"); - return symbolHandle(&vmSymbols::_type_signatures[t], false); - } - // inverse of type_signature; returns T_OBJECT if s is not recognized - static BasicType signature_type(symbolHandle s) { - return vmSymbols::signature_type(s()); - } -}; - // VM Intrinsic ID's uniquely identify some very special methods class vmIntrinsics: AllStatic { friend class vmSymbols;
--- a/hotspot/src/share/vm/code/compiledIC.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/code/compiledIC.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -34,7 +34,7 @@ #include "memory/oopFactory.hpp" #include "oops/methodOop.hpp" #include "oops/oop.inline.hpp" -#include "oops/symbolOop.hpp" +#include "oops/symbol.hpp" #include "runtime/icache.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp"
--- a/hotspot/src/share/vm/code/dependencies.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/code/dependencies.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -628,8 +628,8 @@ private: // optional method descriptor to check for: - symbolOop _name; - symbolOop _signature; + Symbol* _name; + Symbol* _signature; // special classes which are not allowed to be witnesses: klassOop _participants[PARTICIPANT_LIMIT+1];
--- a/hotspot/src/share/vm/code/nmethod.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/code/nmethod.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -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(), \ @@ -1865,7 +1865,7 @@ SimpleScopeDesc ssd(this, fr.pc()); Bytecode_invoke call(ssd.method(), ssd.bci()); bool has_receiver = call.has_receiver(); - symbolOop signature = call.signature(); + Symbol* signature = call.signature(); fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f); } #endif // !SHARK @@ -2636,7 +2636,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;
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -66,9 +66,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(), \ @@ -79,9 +79,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(), \ @@ -689,7 +689,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); @@ -700,8 +700,8 @@ JavaValue result(T_VOID); JavaCalls::call_special(&result, thread_oop, klass, - vmSymbolHandles::object_initializer_name(), - vmSymbolHandles::threadgroup_string_void_signature(), + vmSymbols::object_initializer_name(), + vmSymbols::threadgroup_string_void_signature(), thread_group, string, CHECK_0);
--- a/hotspot/src/share/vm/compiler/compileLog.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/compiler/compileLog.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -63,7 +63,7 @@ stringStream* context() { return &_context; } void name(ciSymbol* s); // name='s' - void name(symbolHandle s) { xmlStream::name(s); } + void name(Symbol* s) { xmlStream::name(s); } // Output an object description, return obj->ident(). int identify(ciObject* obj);
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -30,7 +30,7 @@ #include "oops/klass.hpp" #include "oops/methodOop.hpp" #include "oops/oop.inline.hpp" -#include "oops/symbolOop.hpp" +#include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" #include "runtime/jniHandles.hpp" @@ -46,33 +46,33 @@ }; protected: - jobject _class_name; + Symbol* _class_name; + Symbol* _method_name; + Symbol* _signature; Mode _class_mode; - jobject _method_name; Mode _method_mode; - jobject _signature; MethodMatcher* _next; - static bool match(symbolHandle candidate, symbolHandle match, Mode match_mode); + static bool match(Symbol* candidate, Symbol* match, Mode match_mode); - symbolHandle class_name() const { return (symbolOop)JNIHandles::resolve_non_null(_class_name); } - symbolHandle method_name() const { return (symbolOop)JNIHandles::resolve_non_null(_method_name); } - symbolHandle signature() const { return (symbolOop)JNIHandles::resolve(_signature); } + Symbol* class_name() const { return _class_name; } + Symbol* method_name() const { return _method_name; } + Symbol* signature() const { return _signature; } public: - MethodMatcher(symbolHandle class_name, Mode class_mode, - symbolHandle method_name, Mode method_mode, - symbolHandle signature, MethodMatcher* next); - MethodMatcher(symbolHandle class_name, symbolHandle method_name, MethodMatcher* next); + MethodMatcher(Symbol* class_name, Mode class_mode, + Symbol* method_name, Mode method_mode, + Symbol* signature, MethodMatcher* next); + MethodMatcher(Symbol* class_name, Symbol* method_name, MethodMatcher* next); // utility method MethodMatcher* find(methodHandle method) { - symbolHandle class_name = Klass::cast(method->method_holder())->name(); - symbolHandle method_name = method->name(); + Symbol* class_name = Klass::cast(method->method_holder())->name(); + Symbol* method_name = method->name(); for (MethodMatcher* current = this; current != NULL; current = current->_next) { if (match(class_name, current->class_name(), current->_class_mode) && match(method_name, current->method_name(), current->_method_mode) && - (current->signature().is_null() || current->signature()() == method->signature())) { + (current->signature() == NULL || current->signature() == method->signature())) { return current; } } @@ -85,14 +85,14 @@ MethodMatcher* next() const { return _next; } - static void print_symbol(symbolHandle h, Mode mode) { + static void print_symbol(Symbol* h, Mode mode) { ResourceMark rm; if (mode == Suffix || mode == Substring || mode == Any) { tty->print("*"); } if (mode != Any) { - h()->print_symbol_on(tty); + h->print_symbol_on(tty); } if (mode == Prefix || mode == Substring) { tty->print("*"); @@ -103,7 +103,7 @@ print_symbol(class_name(), _class_mode); tty->print("."); print_symbol(method_name(), _method_mode); - if (!signature().is_null()) { + if (signature() != NULL) { tty->print(" "); signature()->print_symbol_on(tty); } @@ -115,9 +115,9 @@ } }; -MethodMatcher::MethodMatcher(symbolHandle class_name, symbolHandle method_name, MethodMatcher* next) { - _class_name = JNIHandles::make_global(class_name); - _method_name = JNIHandles::make_global(method_name); +MethodMatcher::MethodMatcher(Symbol* class_name, Symbol* method_name, MethodMatcher* next) { + _class_name = class_name; + _method_name = method_name; _next = next; _class_mode = MethodMatcher::Exact; _method_mode = MethodMatcher::Exact; @@ -125,24 +125,24 @@ } -MethodMatcher::MethodMatcher(symbolHandle class_name, Mode class_mode, - symbolHandle method_name, Mode method_mode, - symbolHandle signature, MethodMatcher* next): +MethodMatcher::MethodMatcher(Symbol* class_name, Mode class_mode, + Symbol* method_name, Mode method_mode, + Symbol* signature, MethodMatcher* next): _class_mode(class_mode) , _method_mode(method_mode) , _next(next) - , _class_name(JNIHandles::make_global(class_name())) - , _method_name(JNIHandles::make_global(method_name())) - , _signature(JNIHandles::make_global(signature())) { + , _class_name(class_name) + , _method_name(method_name) + , _signature(signature) { } -bool MethodMatcher::match(symbolHandle candidate, symbolHandle match, Mode match_mode) { +bool MethodMatcher::match(Symbol* candidate, Symbol* match, Mode match_mode) { if (match_mode == Any) { return true; } if (match_mode == Exact) { - return candidate() == match(); + return candidate == match; } ResourceMark rm; @@ -171,9 +171,9 @@ class MethodOptionMatcher: public MethodMatcher { const char * option; public: - MethodOptionMatcher(symbolHandle class_name, Mode class_mode, - symbolHandle method_name, Mode method_mode, - symbolHandle signature, const char * opt, MethodMatcher* next): + MethodOptionMatcher(Symbol* class_name, Mode class_mode, + Symbol* method_name, Mode method_mode, + Symbol* signature, const char * opt, MethodMatcher* next): MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) { option = opt; } @@ -256,9 +256,9 @@ static MethodMatcher* add_predicate(OracleCommand command, - symbolHandle class_name, MethodMatcher::Mode c_mode, - symbolHandle method_name, MethodMatcher::Mode m_mode, - symbolHandle signature) { + Symbol* class_name, MethodMatcher::Mode c_mode, + Symbol* method_name, MethodMatcher::Mode m_mode, + Symbol* signature) { assert(command != OptionCommand, "must use add_option_string"); if (command == LogCommand && !LogCompilation && lists[LogCommand] == NULL) tty->print_cr("Warning: +LogCompilation must be enabled in order for individual methods to be logged."); @@ -268,9 +268,9 @@ -static MethodMatcher* add_option_string(symbolHandle class_name, MethodMatcher::Mode c_mode, - symbolHandle method_name, MethodMatcher::Mode m_mode, - symbolHandle signature, +static MethodMatcher* add_option_string(Symbol* class_name, MethodMatcher::Mode c_mode, + Symbol* method_name, MethodMatcher::Mode m_mode, + Symbol* signature, const char* option) { lists[OptionCommand] = new MethodOptionMatcher(class_name, c_mode, method_name, m_mode, signature, option, lists[OptionCommand]); @@ -497,9 +497,9 @@ if (scan_line(line, class_name, &c_match, method_name, &m_match, &bytes_read, error_msg)) { EXCEPTION_MARK; - symbolHandle c_name = oopFactory::new_symbol_handle(class_name, CHECK); - symbolHandle m_name = oopFactory::new_symbol_handle(method_name, CHECK); - symbolHandle signature; + Symbol* c_name = SymbolTable::new_symbol(class_name, CHECK); + Symbol* m_name = SymbolTable::new_symbol(method_name, CHECK); + Symbol* signature = NULL; line += bytes_read; // there might be a signature following the method. @@ -507,7 +507,7 @@ if (1 == sscanf(line, "%*[ \t](%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) { sig[0] = '('; line += bytes_read; - signature = oopFactory::new_symbol_handle(sig, CHECK); + signature = SymbolTable::new_symbol(sig, CHECK); } if (command == OptionCommand) { @@ -714,9 +714,9 @@ } EXCEPTION_MARK; - symbolHandle c_name = oopFactory::new_symbol_handle(className, CHECK); - symbolHandle m_name = oopFactory::new_symbol_handle(methodName, CHECK); - symbolHandle signature; + Symbol* c_name = SymbolTable::new_symbol(className, CHECK); + Symbol* m_name = SymbolTable::new_symbol(methodName, CHECK); + Symbol* signature = NULL; add_predicate(CompileOnlyCommand, c_name, c_match, m_name, m_match, signature); if (PrintVMOptions) {
--- a/hotspot/src/share/vm/compiler/compilerOracle.hpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp Fri Feb 11 23:46:24 2011 -0800 @@ -31,8 +31,6 @@ // CompilerOracle is an interface for turning on and off compilation // for some methods -class symbolHandle; - class CompilerOracle : AllStatic { private: static bool _quiet;
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -5921,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(); } }
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Feb 11 22:57:35 2011 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Feb 11 23:46:24 2011 -0800 @@ -1055,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; @@ -1111,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) @@ -1176,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 @@ -1500,21 +1512,19 @@ size_t _max_live_bytes; size_t _regions_claimed; size_t _freed_bytes; - FreeRegionList _local_cleanup_list; - HumongousRegionSet _humongous_proxy_set; + FreeRegionList* _local_cleanup_list; + HumongousRegionSet* _humongous_proxy_set; + HRRSCleanupTask* _hrrs_cleanup_task; double _claimed_region_time; double _max_region_time; public: G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, - 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; } - FreeRegionList* local_cleanup_list() { - return &_local_cleanup_list; - } - HumongousRegionSet* humongous_proxy_set() { - return &_humongous_proxy_set; - } bool doHeapRegion(HeapRegion *r); @@ -1541,7 +1551,12 @@ void work(int i) { double start = os::elapsedTime(); - G1NoteEndOfConcMarkClosure g1_note_end(_g1h, 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); @@ -1553,15 +1568,17 @@ // Now update the lists _g1h->update_sets_after_freeing_regions(g1_note_end.freed_bytes(), NULL /* free_list */, - g1_note_end.humongous_proxy_set(), + &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(g1_note_end.local_cleanup_list()); - assert(g1_note_end.local_cleanup_list()->is_empty(), "post-condition"); + _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) { @@ -1602,13 +1619,17 @@ G1NoteEndOfConcMarkClosure:: G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, - 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), _claimed_region_time(0.0), _max_region_time(0.0), - _local_cleanup_list("Local Cleanup List"), - _humongous_proxy_set("Local Cleanup Humongous Proxy Set") { } + _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 @@ -1619,11 +1640,12 @@ _regions_claimed++; hr->note_end_of_marking(); _max_live_bytes += hr->max_live_bytes(); - _g1->free_region_if_totally_empty(hr, - &_freed_bytes, - &_local_cleanup_list, - &_humongous_proxy_set, - true /* par */); + _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; @@ -1659,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); @@ -1853,6 +1877,8 @@ 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 && @@ -1873,11 +1899,17 @@ virtual void do_oop( oop* p) { do_oop_work(p); } template <class T> void do_oop_work(T* p) { - oop thisOop = oopDesc::load_decode_heap_oop(p); - HeapWord* addr = (HeapWord*)thisOop; - if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(thisOop)) { + oop obj = oopDesc::load_decode_heap_oop(p); + HeapWord* addr = (HeapWord*)obj; + + if (_cm->verbose_high()) + gclog_or_tty->print_cr("\t[0] we're looking at location " + "*"PTR_FORMAT" = "PTR_FORMAT, + p, (void*) obj); + + if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(obj)) { _bitMap->mark(addr); - _cm->mark_stack_push(thisOop); + _cm->mark_stack_push(obj); } } }; @@ -1899,6 +1931,199 @@ } }; +// 'Keep Alive' closure used by parallel reference processing. +// An instance of this closure is used in the parallel reference processing +// code rather than an instance of G1CMKeepAliveClosure. We could have used +// the G1CMKeepAliveClosure as it is MT-safe. Also reference objects are +// placed on to discovered ref lists once so we can mark and push with no +// need to check whether the object has already been marked. Using the +// G1CMKeepAliveClosure would mean, however, having all the worker threads +// operating on the global mark stack. This means that an individual +// worker would be doing lock-free pushes while it processes its own +// discovered ref list followed by drain call. If the discovered ref lists +// are unbalanced then this could cause interference with the other +// workers. Using a CMTask (and its embedded local data structures) +// avoids that potential interference. +class G1CMParKeepAliveAndDrainClosure: public OopClosure { + ConcurrentMark* _cm; + CMTask* _task; + CMBitMap* _bitMap; + int _ref_counter_limit; + int _ref_counter; + public: + G1CMParKeepAliveAndDrainClosure(ConcurrentMark* cm, + CMTask* task, + CMBitMap* bitMap) : + _cm(cm), _task(task), _bitMap(bitMap), + _ref_counter_limit(G1RefProcDrainInterval) + { + assert(_ref_counter_limit > 0, "sanity"); + _ref_counter = _ref_counter_limit; + } + + virtual void do_oop(narrowOop* p) { do_oop_work(p); } + virtual void do_oop( oop* p) { do_oop_work(p); } + + template <class T> void do_oop_work(T* p) { + if (!_cm->has_overflown()) { + oop obj = oopDesc::load_decode_heap_oop(p); + if (_cm->verbose_high()) + gclog_or_tty->print_cr("\t[%d] we're looking at location " + "*"PTR_FORMAT" = "PTR_FORMAT, + _task->task_id(), p, (void*) obj); + + _task->deal_with_reference(obj); + _ref_counter--; + + if (_ref_counter == 0) { + // We have dealt with _ref_counter_limit references, pushing them and objects + // reachable from them on to the local stack (and possibly the global stack). + // Call do_marking_step() to process these entries. We call the routine in a + // loop, which we'll exit if there's nothing more to do (i.e. we're done + // with the entries that we've pushed as a result of the deal_with_reference + // calls above) or we overflow. + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag + // while there may still be some work to do. (See the comment at the + // beginning of CMTask::do_marking_step() for those conditions - one of which + // is reaching the specified time target.) It is only when + // CMTask::do_marking_step() returns without setting the has_aborted() flag + // that the marking has completed. + do { + double mark_step_duration_ms = G1ConcMarkStepDurationMillis; + _task->do_marking_step(mark_step_duration_ms, + false /* do_stealing */, + false /* do_termination */); + } while (_task->has_aborted() && !_cm->has_overflown()); + _ref_counter = _ref_counter_limit; + } + } else { + if (_cm->verbose_high()) + gclog_or_tty->print_cr("\t[%d] CM Overflow", _task->task_id()); + } + } +}; + +class G1CMParDrainMarkingStackClosure: public VoidClosure { + ConcurrentMark* _cm; + CMTask* _task; + public: + G1CMParDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task) : + _cm(cm), _task(task) + {} + + void do_void() { + do { + if (_cm->verbose_high()) + gclog_or_tty->print_cr("\t[%d] Drain: Calling do marking_step", _task->task_id()); + + // We call CMTask::do_marking_step() to completely drain the local and + // global marking stacks. The routine is called in a loop, which we'll + // exit if there's nothing more to do (i.e. we'completely drained the + // entries that were pushed as a result of applying the + // G1CMParKeepAliveAndDrainClosure to the entries on the discovered ref + // lists above) or we overflow the global marking stack. + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag + // while there may still be some work to do. (See the comment at the + // beginning of CMTask::do_marking_step() for those conditions - one of which + // is reaching the specified time target.) It is only when + // CMTask::do_marking_step() returns without setting the has_aborted() flag + // that the marking has completed. + + _task->do_marking_step(1000000000.0 /* something very large */, + true /* do_stealing */, + true /* do_termination */); + } while (_task->has_aborted() && !_cm->has_overflown()); + } +}; + +// Implementation of AbstractRefProcTaskExecutor for G1 +class G1RefProcTaskExecutor: public AbstractRefProcTaskExecutor { +private: + G1CollectedHeap* _g1h; + ConcurrentMark* _cm; + CMBitMap* _bitmap; + WorkGang* _workers; + int _active_workers; + +public: + G1RefProcTaskExecutor(G1CollectedHeap* g1h, + ConcurrentMark* cm, + CMBitMap* bitmap, + WorkGang* workers, + int n_workers) : + _g1h(g1h), _cm(cm), _bitmap(bitmap), + _workers(workers), _active_workers(n_workers) + { } + + // Executes the given task using concurrent marking worker threads. + virtual void execute(ProcessTask& task); + virtual void execute(EnqueueTask& task); +}; + +class G1RefProcTaskProxy: public AbstractGangTask { + typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; + ProcessTask& _proc_task; + G1CollectedHeap* _g1h; + ConcurrentMark* _cm; + CMBitMap* _bitmap; + +public: + G1RefProcTaskProxy(ProcessTask& proc_task, + G1CollectedHeap* g1h, + ConcurrentMark* cm, + CMBitMap* bitmap) : + AbstractGangTask("Process reference objects in parallel"), + _proc_task(proc_task), _g1h(g1h), _cm(cm), _bitmap(bitmap) + {} + + virtual void work(int i) { + CMTask* marking_task = _cm->task(i); + G1CMIsAliveClosure g1_is_alive(_g1h); + G1CMParKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task, _bitmap); + G1CMParDrainMarkingStackClosure g1_par_drain(_cm, marking_task); + + _proc_task.work(i, g1_is_alive, g1_par_keep_alive, g1_par_drain); + } +}; + +void G1RefProcTaskExecutor::execute(ProcessTask& proc_task) { + assert(_workers != NULL, "Need parallel worker threads."); + + G1RefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm, _bitmap); + + // We need to reset the phase for each task execution so that + // the termination protocol of CMTask::do_marking_step works. + _cm->set_phase(_active_workers, false /* concurrent */); + _g1h->set_par_threads(_active_workers); + _workers->run_task(&proc_task_proxy); + _g1h->set_par_threads(0); +} + +class G1RefEnqueueTaskProxy: public AbstractGangTask { + typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask; + EnqueueTask& _enq_task; + +public: + G1RefEnqueueTaskProxy(EnqueueTask& enq_task) : + AbstractGangTask("Enqueue reference objects in parallel"), + _enq_task(enq_task) + { } + + virtual void work(int i) { + _enq_task.work(i); + } +}; + +void G1RefProcTaskExecutor::execute(EnqueueTask& enq_task) { + assert(_workers != NULL, "Need parallel worker threads."); + + G1RefEnqueueTaskProxy enq_task_proxy(enq_task); + + _g1h->set_par_threads(_active_workers); + _workers->run_task(&enq_task_proxy); + _g1h->set_par_threads(0); +} + void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { ResourceMark rm; HandleMark hm; @@ -1917,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() { @@ -1955,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. @@ -1978,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 @@ -1992,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 @@ -2005,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.", @@ -3124,7 +3383,7 @@ // do nothing } #else // _CHECK_BOTH_FINGERS_