Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java
41161 views
/*1* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.oops;2526import java.io.*;27import java.util.*;28import sun.jvm.hotspot.debugger.*;29import sun.jvm.hotspot.runtime.*;30import sun.jvm.hotspot.types.*;31import sun.jvm.hotspot.utilities.*;32import sun.jvm.hotspot.utilities.Observable;33import sun.jvm.hotspot.utilities.Observer;3435// A ConstantPool is an oop containing class constants36// as described in the class file3738public class ConstantPool extends Metadata implements ClassConstants {39private class CPSlot {40private Address ptr;4142CPSlot(Address ptr) {43this.ptr = ptr;44}4546public Symbol getSymbol() {47// (Lowest bit == 1) -> this is an pseudo string.48return Symbol.create(ptr.andWithMask(~1));49}50}51private class CPKlassSlot {52private int name_index;53private int resolved_klass_index;54private static final int temp_resolved_klass_index = 0xffff;5556public CPKlassSlot(int n, int rk) {57name_index = n;58resolved_klass_index = rk;59}60public int getNameIndex() {61return name_index;62}63public int getResolvedKlassIndex() {64if (Assert.ASSERTS_ENABLED) {65Assert.that(resolved_klass_index != temp_resolved_klass_index, "constant pool merging was incomplete");66}67return resolved_klass_index;68}69}7071// Used for debugging this code72private static final boolean DEBUG = false;7374protected void debugMessage(String message) {75System.out.println(message);76}7778static {79VM.registerVMInitializedObserver(new Observer() {80public void update(Observable o, Object data) {81initialize(VM.getVM().getTypeDataBase());82}83});84}8586private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {87Type type = db.lookupType("ConstantPool");88tags = type.getAddressField("_tags");89operands = type.getAddressField("_operands");90cache = type.getAddressField("_cache");91poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0);92length = new CIntField(type.getCIntegerField("_length"), 0);93resolved_klasses = type.getAddressField("_resolved_klasses");94majorVersion = new CIntField(type.getCIntegerField("_major_version"), 0);95minorVersion = new CIntField(type.getCIntegerField("_minor_version"), 0);96sourceFileNameIndex = new CIntField(type.getCIntegerField("_source_file_name_index"), 0);97genericSignatureIndex = new CIntField(type.getCIntegerField("_generic_signature_index"), 0);98headerSize = type.getSize();99elementSize = 0;100// fetch constants:101INDY_BSM_OFFSET = db.lookupIntConstant("ConstantPool::_indy_bsm_offset").intValue();102INDY_ARGC_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argc_offset").intValue();103INDY_ARGV_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argv_offset").intValue();104}105106public ConstantPool(Address addr) {107super(addr);108}109110public boolean isConstantPool() { return true; }111112private static AddressField tags;113private static AddressField operands;114private static AddressField cache;115private static AddressField resolved_klasses;116private static MetadataField poolHolder;117private static CIntField length; // number of elements in oop118private static CIntField majorVersion;119private static CIntField minorVersion;120private static CIntField genericSignatureIndex;121private static CIntField sourceFileNameIndex;122123private static long headerSize;124private static long elementSize;125126private static int INDY_BSM_OFFSET;127private static int INDY_ARGC_OFFSET;128private static int INDY_ARGV_OFFSET;129130public U1Array getTags() { return new U1Array(tags.getValue(getAddress())); }131public U2Array getOperands() { return new U2Array(operands.getValue(getAddress())); }132public ConstantPoolCache getCache() {133Address addr = cache.getValue(getAddress());134return (ConstantPoolCache) VMObjectFactory.newObject(ConstantPoolCache.class, addr);135}136public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); }137public int getLength() { return (int)length.getValue(getAddress()); }138public Oop getResolvedReferences() {139return getCache().getResolvedReferences();140}141public long majorVersion() { return majorVersion.getValue(this); }142public long minorVersion() { return minorVersion.getValue(this); }143144public Symbol getGenericSignature() {145long index = genericSignatureIndex.getValue(this);146if (index != 0) {147return getSymbolAt(index);148} else {149return null;150}151}152153public Symbol getSourceFileName() { return getSymbolAt(sourceFileNameIndex.getValue(this)); }154155public KlassArray getResolvedKlasses() {156return new KlassArray(resolved_klasses.getValue(getAddress()));157}158159public U2Array referenceMap() {160return getCache().referenceMap();161}162163public int objectToCPIndex(int index) {164return referenceMap().at(index);165}166167private long getElementSize() {168if (elementSize !=0 ) {169return elementSize;170} else {171elementSize = VM.getVM().getOopSize();172}173return elementSize;174}175176private long indexOffset(long index) {177if (Assert.ASSERTS_ENABLED) {178Assert.that(index >= 0 && index < getLength(), "invalid cp index " + index + " " + getLength());179}180return (index * getElementSize()) + headerSize;181}182183public ConstantTag getTagAt(long index) {184return new ConstantTag((byte)getTags().at((int) index));185}186187public CPSlot getSlotAt(long index) {188return new CPSlot(getAddressAtRaw(index));189}190191public CPKlassSlot getKlassSlotAt(long index) {192if (Assert.ASSERTS_ENABLED) {193Assert.that(getTagAt(index).isUnresolvedKlass() || getTagAt(index).isKlass(), "Corrupted constant pool");194}195int value = getIntAt(index);196int name_index = extractHighShortFromInt(value);197int resolved_klass_index = extractLowShortFromInt(value);198return new CPKlassSlot(name_index, resolved_klass_index);199}200201public Address getAddressAtRaw(long index) {202return getAddress().getAddressAt(indexOffset(index));203}204205public Symbol getSymbolAt(long index) {206return Symbol.create(getAddressAtRaw(index));207}208209public int getIntAt(long index){210return getAddress().getJIntAt(indexOffset(index));211}212213public float getFloatAt(long index){214return getAddress().getJFloatAt(indexOffset(index));215}216217public long getLongAt(long index) {218int oneHalf = getAddress().getJIntAt(indexOffset(index + 1));219int otherHalf = getAddress().getJIntAt(indexOffset(index));220// buildLongFromIntsPD accepts higher address value, lower address value221// in that order.222return VM.getVM().buildLongFromIntsPD(oneHalf, otherHalf);223}224225public double getDoubleAt(long index) {226return Double.longBitsToDouble(getLongAt(index));227}228229public int getFieldOrMethodAt(int which) {230if (DEBUG) {231System.err.print("ConstantPool.getFieldOrMethodAt(" + which + "): new index = ");232}233int i = -1;234ConstantPoolCache cache = getCache();235if (cache == null) {236i = which;237} else {238// change byte-ordering and go via cache239i = cache.getEntryAt(0xFFFF & which).getConstantPoolIndex();240}241if (Assert.ASSERTS_ENABLED) {242Assert.that(getTagAt(i).isFieldOrMethod(), "Corrupted constant pool");243}244if (DEBUG) {245System.err.println(i);246}247int res = getIntAt(i);248if (DEBUG) {249System.err.println("ConstantPool.getFieldOrMethodAt(" + i + "): result = " + res);250}251return res;252}253254public int[] getNameAndTypeAt(int which) {255if (Assert.ASSERTS_ENABLED) {256Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool: " + which + " " + getTagAt(which));257}258int i = getIntAt(which);259if (DEBUG) {260System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i);261}262return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) };263}264265public Symbol getNameRefAt(int which) {266return implGetNameRefAt(which, false);267}268269public Symbol uncachedGetNameRefAt(int which) {270return implGetNameRefAt(which, true);271}272273private Symbol implGetNameRefAt(int which, boolean uncached) {274int signatureIndex = getNameRefIndexAt(implNameAndTypeRefIndexAt(which, uncached));275return getSymbolAt(signatureIndex);276}277278public Symbol getSignatureRefAt(int which) {279return implGetSignatureRefAt(which, false);280}281282public Symbol uncachedGetSignatureRefAt(int which) {283return implGetSignatureRefAt(which, true);284}285286private Symbol implGetSignatureRefAt(int which, boolean uncached) {287int signatureIndex = getSignatureRefIndexAt(implNameAndTypeRefIndexAt(which, uncached));288return getSymbolAt(signatureIndex);289}290291public static boolean isInvokedynamicIndex(int i) { return (i < 0); }292293public static int decodeInvokedynamicIndex(int i) { Assert.that(isInvokedynamicIndex(i), ""); return ~i; }294295// The invokedynamic points at a CP cache entry. This entry points back296// at the original CP entry (CONSTANT_InvokeDynamic) and also (via f2) at an entry297// in the resolved_references array (which provides the appendix argument).298public int invokedynamicCPCacheIndex(int index) {299Assert.that(isInvokedynamicIndex(index), "should be a invokedynamic index");300return decodeInvokedynamicIndex(index);301}302303ConstantPoolCacheEntry invokedynamicCPCacheEntryAt(int index) {304// decode index that invokedynamic points to.305int cpCacheIndex = invokedynamicCPCacheIndex(index);306return getCache().getEntryAt(cpCacheIndex);307}308309private int implNameAndTypeRefIndexAt(int which, boolean uncached) {310int i = which;311if (!uncached && getCache() != null) {312if (isInvokedynamicIndex(which)) {313// Invokedynamic index is index into resolved_references314int poolIndex = invokedynamicCPCacheEntryAt(which).getConstantPoolIndex();315poolIndex = invokeDynamicNameAndTypeRefIndexAt(poolIndex);316Assert.that(getTagAt(poolIndex).isNameAndType(), "");317return poolIndex;318}319// change byte-ordering and go via cache320i = remapInstructionOperandFromCache(which);321} else {322if (getTagAt(which).isInvokeDynamic() || getTagAt(which).isDynamicConstant()) {323int poolIndex = invokeDynamicNameAndTypeRefIndexAt(which);324Assert.that(getTagAt(poolIndex).isNameAndType(), "");325return poolIndex;326}327}328// assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");329// assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above");330int refIndex = getIntAt(i);331return extractHighShortFromInt(refIndex);332}333334private int remapInstructionOperandFromCache(int operand) {335int cpc_index = operand;336// DEBUG_ONLY(cpc_index -= CPCACHE_INDEX_TAG);337// assert((int)(u2)cpc_index == cpc_index, "clean u2");338int member_index = getCache().getEntryAt(cpc_index).getConstantPoolIndex();339return member_index;340}341342public int invokeDynamicNameAndTypeRefIndexAt(int which) {343// assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");344return extractHighShortFromInt(getIntAt(which));345}346347// returns null, if not resolved.348public Klass getKlassAt(int which) {349if( ! getTagAt(which).isKlass()) return null;350int resolved_klass_index = getKlassSlotAt(which).getResolvedKlassIndex();351KlassArray resolved_klasses = getResolvedKlasses();352return resolved_klasses.getAt(resolved_klass_index);353}354355public Symbol getKlassNameAt(int which) {356int name_index = getKlassSlotAt(which).getNameIndex();357return getSymbolAt(name_index);358}359360public Symbol getUnresolvedStringAt(int which) {361return getSlotAt(which).getSymbol();362}363364// returns null, if not resolved.365public Klass getFieldOrMethodKlassRefAt(int which) {366int refIndex = getFieldOrMethodAt(which);367int klassIndex = extractLowShortFromInt(refIndex);368return getKlassAt(klassIndex);369}370371// returns null, if not resolved.372public Method getMethodRefAt(int which) {373Klass klass = getFieldOrMethodKlassRefAt(which);374if (klass == null) return null;375Symbol name = getNameRefAt(which);376Symbol sig = getSignatureRefAt(which);377// Consider the super class for arrays. (java.lang.Object)378if (klass.isArrayKlass()) {379klass = klass.getJavaSuper();380}381return ((InstanceKlass)klass).findMethod(name.asString(), sig.asString());382}383384// returns null, if not resolved.385public Field getFieldRefAt(int which) {386InstanceKlass klass = (InstanceKlass)getFieldOrMethodKlassRefAt(which);387if (klass == null) return null;388Symbol name = getNameRefAt(which);389Symbol sig = getSignatureRefAt(which);390return klass.findField(name.asString(), sig.asString());391}392393public int getNameAndTypeRefIndexAt(int index) {394return implNameAndTypeRefIndexAt(index, false);395}396397/** Lookup for entries consisting of (name_index, signature_index) */398public int getNameRefIndexAt(int index) {399int[] refIndex = getNameAndTypeAt(index);400if (DEBUG) {401System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]);402}403int i = refIndex[0];404if (DEBUG) {405System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i);406}407return i;408}409410/** Lookup for entries consisting of (name_index, signature_index) */411public int getSignatureRefIndexAt(int index) {412int[] refIndex = getNameAndTypeAt(index);413if (DEBUG) {414System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]);415}416int i = refIndex[1];417if (DEBUG) {418System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i);419}420return i;421}422423/** Lookup for MethodHandle entries. */424public int getMethodHandleIndexAt(int i) {425if (Assert.ASSERTS_ENABLED) {426Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool");427}428int res = extractHighShortFromInt(getIntAt(i));429if (DEBUG) {430System.err.println("ConstantPool.getMethodHandleIndexAt(" + i + "): result = " + res);431}432return res;433}434435/** Lookup for MethodHandle entries. */436public int getMethodHandleRefKindAt(int i) {437if (Assert.ASSERTS_ENABLED) {438Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool");439}440int res = extractLowShortFromInt(getIntAt(i));441if (DEBUG) {442System.err.println("ConstantPool.getMethodHandleRefKindAt(" + i + "): result = " + res);443}444return res;445}446447/** Lookup for MethodType entries. */448public int getMethodTypeIndexAt(int i) {449if (Assert.ASSERTS_ENABLED) {450Assert.that(getTagAt(i).isMethodType(), "Corrupted constant pool");451}452int res = getIntAt(i);453if (DEBUG) {454System.err.println("ConstantPool.getMethodHandleTypeAt(" + i + "): result = " + res);455}456return res;457}458459/** Lookup for multi-operand (InvokeDynamic, Dynamic) entries. */460public short[] getBootstrapSpecifierAt(int i) {461if (Assert.ASSERTS_ENABLED) {462Assert.that(getTagAt(i).isInvokeDynamic() || getTagAt(i).isDynamicConstant(), "Corrupted constant pool");463}464int bsmSpec = extractLowShortFromInt(this.getIntAt(i));465U2Array operands = getOperands();466if (operands == null) return null; // safety first467int basePos = VM.getVM().buildIntFromShorts(operands.at(bsmSpec * 2 + 0),468operands.at(bsmSpec * 2 + 1));469int argv = basePos + INDY_ARGV_OFFSET;470int argc = operands.at(basePos + INDY_ARGC_OFFSET);471int endPos = argv + argc;472short[] values = new short[endPos - basePos];473for (int j = 0; j < values.length; j++) {474values[j] = operands.at(basePos+j);475}476return values;477}478479final private static String[] nameForTag = new String[] {480};481482private String nameForTag(int tag) {483switch (tag) {484case JVM_CONSTANT_Utf8: return "JVM_CONSTANT_Utf8";485case JVM_CONSTANT_Unicode: return "JVM_CONSTANT_Unicode";486case JVM_CONSTANT_Integer: return "JVM_CONSTANT_Integer";487case JVM_CONSTANT_Float: return "JVM_CONSTANT_Float";488case JVM_CONSTANT_Long: return "JVM_CONSTANT_Long";489case JVM_CONSTANT_Double: return "JVM_CONSTANT_Double";490case JVM_CONSTANT_Class: return "JVM_CONSTANT_Class";491case JVM_CONSTANT_String: return "JVM_CONSTANT_String";492case JVM_CONSTANT_Fieldref: return "JVM_CONSTANT_Fieldref";493case JVM_CONSTANT_Methodref: return "JVM_CONSTANT_Methodref";494case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref";495case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType";496case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle";497case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType";498case JVM_CONSTANT_Dynamic: return "JVM_CONSTANT_Dynamic";499case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic";500case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid";501case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass";502case JVM_CONSTANT_ClassIndex: return "JVM_CONSTANT_ClassIndex";503case JVM_CONSTANT_StringIndex: return "JVM_CONSTANT_StringIndex";504case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";505case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError";506case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError";507}508throw new InternalError("Unknown tag: " + tag);509}510511public void iterateFields(MetadataVisitor visitor) {512super.iterateFields(visitor);513visitor.doMetadata(poolHolder, true);514515final int length = (int) getLength();516// zero'th pool entry is always invalid. ignore it.517for (int index = 1; index < length; index++) {518int ctag = (int) getTags().at((int) index);519switch (ctag) {520case JVM_CONSTANT_ClassIndex:521case JVM_CONSTANT_StringIndex:522case JVM_CONSTANT_Integer:523visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);524break;525526case JVM_CONSTANT_Float:527visitor.doFloat(new FloatField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);528break;529530case JVM_CONSTANT_Long:531visitor.doLong(new LongField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);532// long entries occupy two slots533index++;534break;535536case JVM_CONSTANT_Double:537visitor.doDouble(new DoubleField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);538// double entries occupy two slots539index++;540break;541542case JVM_CONSTANT_UnresolvedClassInError:543case JVM_CONSTANT_UnresolvedClass:544case JVM_CONSTANT_Class:545case JVM_CONSTANT_Utf8:546visitor.doOop(new OopField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);547break;548549case JVM_CONSTANT_Fieldref:550case JVM_CONSTANT_Methodref:551case JVM_CONSTANT_InterfaceMethodref:552case JVM_CONSTANT_NameAndType:553case JVM_CONSTANT_MethodHandle:554case JVM_CONSTANT_MethodType:555case JVM_CONSTANT_Dynamic:556case JVM_CONSTANT_InvokeDynamic:557visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);558break;559}560}561}562563public void writeBytes(OutputStream os) throws IOException {564// Map between any modified UTF-8 and it's constant pool index.565Map<String, Short> utf8ToIndex = new HashMap<>();566DataOutputStream dos = new DataOutputStream(os);567U1Array tags = getTags();568int len = (int)getLength();569int ci = 0; // constant pool index570571// collect all modified UTF-8 Strings from Constant Pool572573for (ci = 1; ci < len; ci++) {574int cpConstType = tags.at(ci);575if(cpConstType == JVM_CONSTANT_Utf8) {576Symbol sym = getSymbolAt(ci);577utf8ToIndex.put(sym.asString(), (short) ci);578}579else if(cpConstType == JVM_CONSTANT_Long ||580cpConstType == JVM_CONSTANT_Double) {581ci++;582}583}584585586for(ci = 1; ci < len; ci++) {587int cpConstType = tags.at(ci);588// write cp_info589// write constant type590switch(cpConstType) {591case JVM_CONSTANT_Utf8: {592dos.writeByte(cpConstType);593Symbol sym = getSymbolAt(ci);594dos.writeShort((short)sym.getLength());595dos.write(sym.asByteArray());596if (DEBUG) debugMessage("CP[" + ci + "] = modified UTF-8 " + sym.asString());597break;598}599600case JVM_CONSTANT_Unicode:601throw new IllegalArgumentException("Unicode constant!");602603case JVM_CONSTANT_Integer:604dos.writeByte(cpConstType);605dos.writeInt(getIntAt(ci));606if (DEBUG) debugMessage("CP[" + ci + "] = int " + getIntAt(ci));607break;608609case JVM_CONSTANT_Float:610dos.writeByte(cpConstType);611dos.writeFloat(getFloatAt(ci));612if (DEBUG) debugMessage("CP[" + ci + "] = float " + getFloatAt(ci));613break;614615case JVM_CONSTANT_Long: {616dos.writeByte(cpConstType);617long l = getLongAt(ci);618// long entries occupy two pool entries619ci++;620dos.writeLong(l);621break;622}623624case JVM_CONSTANT_Double:625dos.writeByte(cpConstType);626dos.writeDouble(getDoubleAt(ci));627// double entries occupy two pool entries628ci++;629break;630631case JVM_CONSTANT_Class: {632dos.writeByte(cpConstType);633// Klass already resolved. ConstantPool constains Klass*.634Klass refKls = (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(ci));635String klassName = refKls.getName().asString();636Short s = (Short) utf8ToIndex.get(klassName);637dos.writeShort(s.shortValue());638if (DEBUG) debugMessage("CP[" + ci + "] = class " + s);639break;640}641642// case JVM_CONSTANT_ClassIndex:643case JVM_CONSTANT_UnresolvedClassInError:644case JVM_CONSTANT_UnresolvedClass: {645dos.writeByte(JVM_CONSTANT_Class);646String klassName = getSymbolAt(ci).asString();647Short s = (Short) utf8ToIndex.get(klassName);648dos.writeShort(s.shortValue());649if (DEBUG) debugMessage("CP[" + ci + "] = class " + s);650break;651}652653case JVM_CONSTANT_String: {654dos.writeByte(cpConstType);655String str = getUnresolvedStringAt(ci).asString();656Short s = (Short) utf8ToIndex.get(str);657dos.writeShort(s.shortValue());658if (DEBUG) debugMessage("CP[" + ci + "] = string " + s);659break;660}661662// all external, internal method/field references663case JVM_CONSTANT_Fieldref:664case JVM_CONSTANT_Methodref:665case JVM_CONSTANT_InterfaceMethodref: {666dos.writeByte(cpConstType);667int value = getIntAt(ci);668short klassIndex = (short) extractLowShortFromInt(value);669short nameAndTypeIndex = (short) extractHighShortFromInt(value);670dos.writeShort(klassIndex);671dos.writeShort(nameAndTypeIndex);672if (DEBUG) debugMessage("CP[" + ci + "] = ref klass = " +673klassIndex + ", N&T = " + nameAndTypeIndex);674break;675}676677case JVM_CONSTANT_NameAndType: {678dos.writeByte(cpConstType);679int value = getIntAt(ci);680short nameIndex = (short) extractLowShortFromInt(value);681short signatureIndex = (short) extractHighShortFromInt(value);682dos.writeShort(nameIndex);683dos.writeShort(signatureIndex);684if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex685+ ", type = " + signatureIndex);686break;687}688689case JVM_CONSTANT_MethodHandle: {690dos.writeByte(cpConstType);691int value = getIntAt(ci);692byte refKind = (byte) extractLowShortFromInt(value);693short memberIndex = (short) extractHighShortFromInt(value);694dos.writeByte(refKind);695dos.writeShort(memberIndex);696if (DEBUG) debugMessage("CP[" + ci + "] = MH kind = " +697refKind + ", mem = " + memberIndex);698break;699}700701case JVM_CONSTANT_MethodType: {702dos.writeByte(cpConstType);703int value = getIntAt(ci);704short refIndex = (short) value;705dos.writeShort(refIndex);706if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex);707break;708}709710case JVM_CONSTANT_InvokeDynamic: {711dos.writeByte(cpConstType);712int value = getIntAt(ci);713short bsmIndex = (short) extractLowShortFromInt(value);714short nameAndTypeIndex = (short) extractHighShortFromInt(value);715dos.writeShort(bsmIndex);716dos.writeShort(nameAndTypeIndex);717if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " +718bsmIndex + ", N&T = " + nameAndTypeIndex);719break;720}721722default:723throw new InternalError("Unknown tag: " + cpConstType);724} // switch725}726dos.flush();727return;728}729730public void printValueOn(PrintStream tty) {731tty.print("ConstantPool for " + getPoolHolder().getName().asString());732}733734public long getSize() {735return alignSize(headerSize + getLength());736}737738//----------------------------------------------------------------------739// Internals only below this point740//741742private static int extractHighShortFromInt(int val) {743// must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc.744return (val >> 16) & 0xFFFF;745}746747private static int extractLowShortFromInt(int val) {748// must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc.749return val & 0xFFFF;750}751}752753754