Mercurial > hg > truffle
diff agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | 38fd165da001 |
children | 18fb7da42534 |
line wrap: on
line diff
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Fri Aug 31 16:39:35 2012 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Sat Sep 01 13:25:18 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,7 @@ // A ConstantPool is an oop containing class constants // as described in the class file -public class ConstantPool extends Oop implements ClassConstants { - +public class ConstantPool extends Metadata implements ClassConstants { public class CPSlot { private Address ptr; @@ -46,24 +45,20 @@ this.ptr = sym.getAddress().orWithMask(1); } - public boolean isOop() { + public boolean isResolved() { return (ptr.minus(null) & 1) == 0; } - public boolean isMetaData() { + public boolean isUnresolved() { return (ptr.minus(null) & 1) == 1; } public Symbol getSymbol() { - if (isMetaData()) { + if (!isUnresolved()) throw new InternalError("not a symbol"); 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"); + public Klass getKlass() { + if (!isResolved()) throw new InternalError("not klass"); + return (Klass)Metadata.instantiateWrapperFor(ptr); } } @@ -83,31 +78,35 @@ } private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("constantPoolOopDesc"); - tags = new OopField(type.getOopField("_tags"), 0); - operands = new OopField(type.getOopField("_operands"), 0); - cache = new OopField(type.getOopField("_cache"), 0); - poolHolder = new OopField(type.getOopField("_pool_holder"), 0); + Type type = db.lookupType("ConstantPool"); + tags = type.getAddressField("_tags"); + operands = type.getAddressField("_operands"); + cache = type.getAddressField("_cache"); + poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0); length = new CIntField(type.getCIntegerField("_length"), 0); + resolvedReferences = type.getAddressField("_resolved_references"); + referenceMap = type.getAddressField("_reference_map"); headerSize = type.getSize(); elementSize = 0; // fetch constants: - INDY_BSM_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_bsm_offset").intValue(); - INDY_ARGC_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argc_offset").intValue(); - INDY_ARGV_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argv_offset").intValue(); + INDY_BSM_OFFSET = db.lookupIntConstant("ConstantPool::_indy_bsm_offset").intValue(); + INDY_ARGC_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argc_offset").intValue(); + INDY_ARGV_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argv_offset").intValue(); } - ConstantPool(OopHandle handle, ObjectHeap heap) { - super(handle, heap); + public ConstantPool(Address addr) { + super(addr); } public boolean isConstantPool() { return true; } - private static OopField tags; - private static OopField operands; - private static OopField cache; - private static OopField poolHolder; + private static AddressField tags; + private static AddressField operands; + private static AddressField cache; + private static MetadataField poolHolder; private static CIntField length; // number of elements in oop + private static AddressField resolvedReferences; + private static AddressField referenceMap; private static long headerSize; private static long elementSize; @@ -116,11 +115,31 @@ private static int INDY_ARGC_OFFSET; private static int INDY_ARGV_OFFSET; - public TypeArray getTags() { return (TypeArray) tags.getValue(this); } - public TypeArray getOperands() { return (TypeArray) operands.getValue(this); } - public ConstantPoolCache getCache() { return (ConstantPoolCache) cache.getValue(this); } + public U1Array getTags() { return new U1Array(tags.getValue(getAddress())); } + public U2Array getOperands() { return new U2Array(operands.getValue(getAddress())); } + public ConstantPoolCache getCache() { + Address addr = cache.getValue(getAddress()); + return (ConstantPoolCache) VMObjectFactory.newObject(ConstantPoolCache.class, addr); + } public Klass getPoolHolder() { return (Klass) poolHolder.getValue(this); } - public int getLength() { return (int)length.getValue(this); } + public int getLength() { return (int)length.getValue(getAddress()); } + public Oop getResolvedReferences() { + Address handle = resolvedReferences.getValue(getAddress()); + if (handle != null) { + // Load through the handle + OopHandle refs = handle.getOopHandleAt(0); + return VM.getVM().getObjectHeap().newOop(refs); + } + return null; + } + + public U2Array referenceMap() { + return new U2Array(referenceMap.getValue(getAddress())); + } + + public int objectToCPIndex(int index) { + return referenceMap().at(index); + } private long getElementSize() { if (elementSize !=0 ) { @@ -139,33 +158,32 @@ } public ConstantTag getTagAt(long index) { - return new ConstantTag(getTags().getByteAt((int) index)); + return new ConstantTag((byte)getTags().at((int) index)); } public CPSlot getSlotAt(long index) { - return new CPSlot(getHandle().getAddressAt(indexOffset(index))); + return new CPSlot(getAddressAtRaw(index)); } - public Oop getObjAtRaw(long index){ - return getHeap().newOop(getHandle().getOopHandleAt(indexOffset(index))); + public Address getAddressAtRaw(long index) { + return getAddress().getAddressAt(indexOffset(index)); } public Symbol getSymbolAt(long index) { - CPSlot slot = getSlotAt(index); - return slot.getSymbol(); + return Symbol.create(getAddressAtRaw(index)); } public int getIntAt(long index){ - return getHandle().getJIntAt(indexOffset(index)); + return getAddress().getJIntAt(indexOffset(index)); } public float getFloatAt(long index){ - return getHandle().getJFloatAt(indexOffset(index)); + return getAddress().getJFloatAt(indexOffset(index)); } public long getLongAt(long index) { - int oneHalf = getHandle().getJIntAt(indexOffset(index + 1)); - int otherHalf = getHandle().getJIntAt(indexOffset(index)); + int oneHalf = getAddress().getJIntAt(indexOffset(index + 1)); + int otherHalf = getAddress().getJIntAt(indexOffset(index)); // buildLongFromIntsPD accepts higher address value, lower address value // in that order. return VM.getVM().buildLongFromIntsPD(oneHalf, otherHalf); @@ -185,7 +203,7 @@ i = which; } else { // change byte-ordering and go via cache - i = cache.getEntryAt(0xFFFF & VM.getVM().getBytes().swapShort((short) which)).getConstantPoolIndex(); + i = cache.getEntryAt(0xFFFF & which).getConstantPoolIndex(); } if (Assert.ASSERTS_ENABLED) { Assert.that(getTagAt(i).isFieldOrMethod(), "Corrupted constant pool"); @@ -202,7 +220,7 @@ public int[] getNameAndTypeAt(int which) { if (Assert.ASSERTS_ENABLED) { - Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool"); + Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool: " + which + " " + getTagAt(which)); } int i = getIntAt(which); if (DEBUG) { @@ -215,6 +233,10 @@ return implGetNameRefAt(which, false); } + public Symbol uncachedGetNameRefAt(int which) { + return implGetNameRefAt(which, true); + } + private Symbol implGetNameRefAt(int which, boolean uncached) { int signatureIndex = getNameRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); return getSymbolAt(signatureIndex); @@ -224,35 +246,57 @@ return implGetSignatureRefAt(which, false); } + public Symbol uncachedGetSignatureRefAt(int which) { + return implGetSignatureRefAt(which, true); + } + private Symbol implGetSignatureRefAt(int which, boolean uncached) { int signatureIndex = getSignatureRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); return getSymbolAt(signatureIndex); } + public static boolean isInvokedynamicIndex(int i) { return (i < 0); } + + public static int decodeInvokedynamicIndex(int i) { Assert.that(isInvokedynamicIndex(i), ""); return ~i; } + + // The invokedynamic points at the object index. The object map points at + // the cpCache index and the cpCache entry points at the original constant + // pool index. + public int invokedynamicCPCacheIndex(int index) { + Assert.that(isInvokedynamicIndex(index), "should be a invokedynamic index"); + int rawIndex = decodeInvokedynamicIndex(index); + return referenceMap().at(rawIndex); + } + + ConstantPoolCacheEntry invokedynamicCPCacheEntryAt(int index) { + // decode index that invokedynamic points to. + int cpCacheIndex = invokedynamicCPCacheIndex(index); + return getCache().getEntryAt(cpCacheIndex); + } private int implNameAndTypeRefIndexAt(int which, boolean uncached) { int i = which; if (!uncached && getCache() != null) { - if (ConstantPoolCache.isSecondaryIndex(which)) { - // Invokedynamic index. - int pool_index = getCache().getMainEntryAt(which).getConstantPoolIndex(); - pool_index = invokeDynamicNameAndTypeRefIndexAt(pool_index); - // assert(tagAt(pool_index).isNameAndType(), ""); - return pool_index; + if (isInvokedynamicIndex(which)) { + // Invokedynamic index is index into resolved_references + int poolIndex = invokedynamicCPCacheEntryAt(which).getConstantPoolIndex(); + poolIndex = invokeDynamicNameAndTypeRefIndexAt(poolIndex); + Assert.that(getTagAt(poolIndex).isNameAndType(), ""); + return poolIndex; } // change byte-ordering and go via cache i = remapInstructionOperandFromCache(which); } else { if (getTagAt(which).isInvokeDynamic()) { - int pool_index = invokeDynamicNameAndTypeRefIndexAt(which); - // assert(tag_at(pool_index).is_name_and_type(), ""); - return pool_index; + int poolIndex = invokeDynamicNameAndTypeRefIndexAt(which); + Assert.that(getTagAt(poolIndex).isNameAndType(), ""); + return poolIndex; } } // assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); // assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above"); - int ref_index = getIntAt(i); - return extractHighShortFromInt(ref_index); + int refIndex = getIntAt(i); + return extractHighShortFromInt(refIndex); } private int remapInstructionOperandFromCache(int operand) { @@ -269,16 +313,29 @@ } // returns null, if not resolved. - public Klass getKlassRefAt(int which) { + public Klass getKlassAt(int which) { if( ! getTagAt(which).isKlass()) return null; - return (Klass) getObjAtRaw(which); + return (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(which)); + } + + public Symbol getKlassNameAt(int which) { + CPSlot entry = getSlotAt(which); + if (entry.isResolved()) { + return entry.getKlass().getName(); + } else { + return entry.getSymbol(); + } + } + + public Symbol getUnresolvedStringAt(int which) { + return getSymbolAt(which); } // returns null, if not resolved. public InstanceKlass getFieldOrMethodKlassRefAt(int which) { int refIndex = getFieldOrMethodAt(which); int klassIndex = extractLowShortFromInt(refIndex); - return (InstanceKlass) getKlassRefAt(klassIndex); + return (InstanceKlass) getKlassAt(klassIndex); } // returns null, if not resolved. @@ -371,16 +428,16 @@ Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool"); } int bsmSpec = extractLowShortFromInt(this.getIntAt(i)); - TypeArray operands = getOperands(); + U2Array operands = getOperands(); if (operands == null) return null; // safety first - int basePos = VM.getVM().buildIntFromShorts(operands.getShortAt(bsmSpec * 2 + 0), - operands.getShortAt(bsmSpec * 2 + 1)); + int basePos = VM.getVM().buildIntFromShorts(operands.at(bsmSpec * 2 + 0), + operands.at(bsmSpec * 2 + 1)); int argv = basePos + INDY_ARGV_OFFSET; - int argc = operands.getShortAt(basePos + INDY_ARGC_OFFSET); + int argc = operands.at(basePos + INDY_ARGC_OFFSET); int endPos = argv + argc; short[] values = new short[endPos - basePos]; for (int j = 0; j < values.length; j++) { - values[j] = operands.getShortAt(basePos+j); + values[j] = operands.at(basePos+j); } return values; } @@ -407,25 +464,24 @@ case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic"; case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid"; case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass"; + case JVM_CONSTANT_ClassIndex: return "JVM_CONSTANT_ClassIndex"; + case JVM_CONSTANT_StringIndex: return "JVM_CONSTANT_StringIndex"; case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; - case JVM_CONSTANT_ClassIndex: return "JVM_CONSTANT_ClassIndex"; - case JVM_CONSTANT_UnresolvedString: return "JVM_CONSTANT_UnresolvedString"; - case JVM_CONSTANT_StringIndex: return "JVM_CONSTANT_StringIndex"; + case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError"; + case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError"; + case JVM_CONSTANT_Object: return "JVM_CONSTANT_Object"; } throw new InternalError("Unknown tag: " + tag); } - public void iterateFields(OopVisitor visitor, boolean doVMFields) { - super.iterateFields(visitor, doVMFields); - if (doVMFields) { - visitor.doOop(tags, true); - visitor.doOop(cache, true); - visitor.doOop(poolHolder, true); + public void iterateFields(MetadataVisitor visitor) { + super.iterateFields(visitor); + visitor.doMetadata(poolHolder, true); final int length = (int) getLength(); // zero'th pool entry is always invalid. ignore it. for (int index = 1; index < length; index++) { - int ctag = (int) getTags().getByteAt((int) index); + int ctag = (int) getTags().at((int) index); switch (ctag) { case JVM_CONSTANT_ClassIndex: case JVM_CONSTANT_StringIndex: @@ -452,7 +508,6 @@ case JVM_CONSTANT_UnresolvedClassInError: case JVM_CONSTANT_UnresolvedClass: case JVM_CONSTANT_Class: - case JVM_CONSTANT_UnresolvedString: case JVM_CONSTANT_Utf8: visitor.doOop(new OopField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); break; @@ -469,27 +524,19 @@ } } } - /* - int length = getLength(); - for (int index = 0; index < length; index++) { - long offset = baseOffset + (index + typeDataBase.getOopSize()); - visitor.doOop(new IndexableField(index, offset, false), getObjAt(index)); - } - */ - } public void writeBytes(OutputStream os) throws IOException { // Map between any modified UTF-8 and it's constant pool index. Map utf8ToIndex = new HashMap(); DataOutputStream dos = new DataOutputStream(os); - TypeArray tags = getTags(); + U1Array tags = getTags(); int len = (int)getLength(); int ci = 0; // constant pool index // collect all modified UTF-8 Strings from Constant Pool for (ci = 1; ci < len; ci++) { - byte cpConstType = tags.getByteAt(ci); + int cpConstType = tags.at(ci); if(cpConstType == JVM_CONSTANT_Utf8) { Symbol sym = getSymbolAt(ci); utf8ToIndex.put(sym.asString(), new Short((short) ci)); @@ -502,7 +549,7 @@ for(ci = 1; ci < len; ci++) { - int cpConstType = (int)tags.getByteAt(ci); + int cpConstType = tags.at(ci); // write cp_info // write constant type switch(cpConstType) { @@ -548,8 +595,8 @@ case JVM_CONSTANT_Class: { dos.writeByte(cpConstType); - // Klass already resolved. ConstantPool constains klassOop. - Klass refKls = (Klass) getObjAtRaw(ci); + // Klass already resolved. ConstantPool constains Klass*. + Klass refKls = (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(ci)); String klassName = refKls.getName().asString(); Short s = (Short) utf8ToIndex.get(klassName); dos.writeShort(s.shortValue()); @@ -570,24 +617,13 @@ case JVM_CONSTANT_String: { dos.writeByte(cpConstType); - String str = OopUtilities.stringOopToString(getObjAtRaw(ci)); + String str = getUnresolvedStringAt(ci).asString(); Short s = (Short) utf8ToIndex.get(str); dos.writeShort(s.shortValue()); if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); break; } - // case JVM_CONSTANT_StringIndex: - case JVM_CONSTANT_UnresolvedString: { - dos.writeByte(JVM_CONSTANT_String); - String val = getSymbolAt(ci).asString(); - - Short s = (Short) utf8ToIndex.get(val); - dos.writeShort(s.shortValue()); - if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); - break; - } - // all external, internal method/field references case JVM_CONSTANT_Fieldref: case JVM_CONSTANT_Methodref: @@ -618,12 +654,21 @@ case JVM_CONSTANT_MethodHandle: { dos.writeByte(cpConstType); int value = getIntAt(ci); - short nameIndex = (short) extractLowShortFromInt(value); - short signatureIndex = (short) extractHighShortFromInt(value); - dos.writeShort(nameIndex); - dos.writeShort(signatureIndex); - if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex - + ", type = " + signatureIndex); + byte refKind = (byte) extractLowShortFromInt(value); + short memberIndex = (short) extractHighShortFromInt(value); + dos.writeByte(refKind); + dos.writeShort(memberIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = MH kind = " + + refKind + ", mem = " + memberIndex); + break; + } + + case JVM_CONSTANT_MethodType: { + dos.writeByte(cpConstType); + int value = getIntAt(ci); + short refIndex = (short) value; + dos.writeShort(refIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex); break; } @@ -634,13 +679,13 @@ short nameAndTypeIndex = (short) extractHighShortFromInt(value); dos.writeShort(bsmIndex); dos.writeShort(nameAndTypeIndex); - if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bsmIndex - + ", N&T = " + nameAndTypeIndex); + if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " + + bsmIndex + ", N&T = " + nameAndTypeIndex); break; } default: - throw new InternalError("unknown tag: " + cpConstType); + throw new InternalError("Unknown tag: " + cpConstType); } // switch } dos.flush(); @@ -648,16 +693,11 @@ } public void printValueOn(PrintStream tty) { - Oop holder = poolHolder.getValue(this); - if (holder instanceof Klass) { - tty.print("ConstantPool for " + ((Klass)holder).getName().asString()); - } else { - tty.print("ConstantPool for partially loaded class"); - } + tty.print("ConstantPool for " + getPoolHolder().getName().asString()); } - public long getObjectSize() { - return alignObjectSize(headerSize + (getLength() * getElementSize())); + public long getSize() { + return Oop.alignObjectSize(headerSize + getLength()); } //---------------------------------------------------------------------- @@ -665,12 +705,12 @@ // private static int extractHighShortFromInt(int val) { - // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc. + // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. return (val >> 16) & 0xFFFF; } private static int extractLowShortFromInt(int val) { - // must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc. + // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. return val & 0xFFFF; } }