1 /* 2 * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.oops; 26 27 import java.io.*; 28 import java.util.*; 29 import sun.jvm.hotspot.debugger.*; 30 import sun.jvm.hotspot.runtime.*; 31 import sun.jvm.hotspot.types.*; 32 import sun.jvm.hotspot.utilities.*; 33 34 // A ConstantPool is an oop containing class constants 35 // as described in the class file 36 37 public class ConstantPool extends Metadata implements ClassConstants { 38 public class CPSlot { 39 private Address ptr; 40 41 CPSlot(Address ptr) { 42 this.ptr = ptr; 43 } 44 CPSlot(Symbol sym) { 45 this.ptr = sym.getAddress().orWithMask(1); 46 } 47 48 public boolean isResolved() { 49 return (ptr.minus(null) & 1) == 0; 50 } 51 public boolean isUnresolved() { 52 return (ptr.minus(null) & 1) == 1; 53 } 54 55 public Symbol getSymbol() { 56 if (!isUnresolved()) throw new InternalError("not a symbol"); 57 return Symbol.create(ptr.xorWithMask(1)); 58 } 59 public Klass getKlass() { 60 if (!isResolved()) throw new InternalError("not klass"); 61 return (Klass)Metadata.instantiateWrapperFor(ptr); 62 } 63 } 64 65 // Used for debugging this code 66 private static final boolean DEBUG = false; 67 68 protected void debugMessage(String message) { 69 System.out.println(message); 70 } 71 72 static { 73 VM.registerVMInitializedObserver(new Observer() { 74 public void update(Observable o, Object data) { 75 initialize(VM.getVM().getTypeDataBase()); 76 } 77 }); 78 } 79 80 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 81 Type type = db.lookupType("ConstantPool"); 82 tags = type.getAddressField("_tags"); 83 operands = type.getAddressField("_operands"); 84 cache = type.getAddressField("_cache"); 85 poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0); 86 length = new CIntField(type.getCIntegerField("_length"), 0); 87 resolvedReferences = type.getAddressField("_resolved_references"); 88 referenceMap = type.getAddressField("_reference_map"); 89 headerSize = type.getSize(); 90 elementSize = 0; 91 // fetch constants: 92 INDY_BSM_OFFSET = db.lookupIntConstant("ConstantPool::_indy_bsm_offset").intValue(); 93 INDY_ARGC_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argc_offset").intValue(); 94 INDY_ARGV_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argv_offset").intValue(); 95 } 96 97 public ConstantPool(Address addr) { 98 super(addr); 99 } 100 101 public boolean isConstantPool() { return true; } 102 103 private static AddressField tags; 104 private static AddressField operands; 105 private static AddressField cache; 106 private static MetadataField poolHolder; 107 private static CIntField length; // number of elements in oop 108 private static AddressField resolvedReferences; 109 private static AddressField referenceMap; 110 111 private static long headerSize; 112 private static long elementSize; 113 114 private static int INDY_BSM_OFFSET; 115 private static int INDY_ARGC_OFFSET; 116 private static int INDY_ARGV_OFFSET; 117 118 public U1Array getTags() { return new U1Array(tags.getValue(getAddress())); } 119 public U2Array getOperands() { return new U2Array(operands.getValue(getAddress())); } 120 public ConstantPoolCache getCache() { 121 Address addr = cache.getValue(getAddress()); 122 return (ConstantPoolCache) VMObjectFactory.newObject(ConstantPoolCache.class, addr); 123 } 124 public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); } 125 public int getLength() { return (int)length.getValue(getAddress()); } 126 public Oop getResolvedReferences() { 127 Address handle = resolvedReferences.getValue(getAddress()); 128 if (handle != null) { 129 // Load through the handle 130 OopHandle refs = handle.getOopHandleAt(0); 131 return VM.getVM().getObjectHeap().newOop(refs); 132 } 133 return null; 134 } 135 136 public U2Array referenceMap() { 137 return new U2Array(referenceMap.getValue(getAddress())); 138 } 139 140 public int objectToCPIndex(int index) { 141 return referenceMap().at(index); 142 } 143 144 private long getElementSize() { 145 if (elementSize !=0 ) { 146 return elementSize; 147 } else { 148 elementSize = VM.getVM().getOopSize(); 149 } 150 return elementSize; 151 } 152 153 private long indexOffset(long index) { 154 if (Assert.ASSERTS_ENABLED) { 155 Assert.that(index >= 0 && index < getLength(), "invalid cp index " + index + " " + getLength()); 156 } 157 return (index * getElementSize()) + headerSize; 158 } 159 160 public ConstantTag getTagAt(long index) { 161 return new ConstantTag((byte)getTags().at((int) index)); 162 } 163 164 public CPSlot getSlotAt(long index) { 165 return new CPSlot(getAddressAtRaw(index)); 166 } 167 168 public Address getAddressAtRaw(long index) { 169 return getAddress().getAddressAt(indexOffset(index)); 170 } 171 172 public Symbol getSymbolAt(long index) { 173 return Symbol.create(getAddressAtRaw(index)); 174 } 175 176 public int getIntAt(long index){ 177 return getAddress().getJIntAt(indexOffset(index)); 178 } 179 180 public float getFloatAt(long index){ 181 return getAddress().getJFloatAt(indexOffset(index)); 182 } 183 184 public long getLongAt(long index) { 185 int oneHalf = getAddress().getJIntAt(indexOffset(index + 1)); 186 int otherHalf = getAddress().getJIntAt(indexOffset(index)); 187 // buildLongFromIntsPD accepts higher address value, lower address value 188 // in that order. 189 return VM.getVM().buildLongFromIntsPD(oneHalf, otherHalf); 190 } 191 192 public double getDoubleAt(long index) { 193 return Double.longBitsToDouble(getLongAt(index)); 194 } 195 196 public int getFieldOrMethodAt(int which) { 197 if (DEBUG) { 198 System.err.print("ConstantPool.getFieldOrMethodAt(" + which + "): new index = "); 199 } 200 int i = -1; 201 ConstantPoolCache cache = getCache(); 202 if (cache == null) { 203 i = which; 204 } else { 205 // change byte-ordering and go via cache 206 i = cache.getEntryAt(0xFFFF & which).getConstantPoolIndex(); 207 } 208 if (Assert.ASSERTS_ENABLED) { 209 Assert.that(getTagAt(i).isFieldOrMethod(), "Corrupted constant pool"); 210 } 211 if (DEBUG) { 212 System.err.println(i); 213 } 214 int res = getIntAt(i); 215 if (DEBUG) { 216 System.err.println("ConstantPool.getFieldOrMethodAt(" + i + "): result = " + res); 217 } 218 return res; 219 } 220 221 public int[] getNameAndTypeAt(int which) { 222 if (Assert.ASSERTS_ENABLED) { 223 Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool: " + which + " " + getTagAt(which)); 224 } 225 int i = getIntAt(which); 226 if (DEBUG) { 227 System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i); 228 } 229 return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) }; 230 } 231 232 public Symbol getNameRefAt(int which) { 233 return implGetNameRefAt(which, false); 234 } 235 236 public Symbol uncachedGetNameRefAt(int which) { 237 return implGetNameRefAt(which, true); 238 } 239 240 private Symbol implGetNameRefAt(int which, boolean uncached) { 241 int signatureIndex = getNameRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); 242 return getSymbolAt(signatureIndex); 243 } 244 245 public Symbol getSignatureRefAt(int which) { 246 return implGetSignatureRefAt(which, false); 247 } 248 249 public Symbol uncachedGetSignatureRefAt(int which) { 250 return implGetSignatureRefAt(which, true); 251 } 252 253 private Symbol implGetSignatureRefAt(int which, boolean uncached) { 254 int signatureIndex = getSignatureRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); 255 return getSymbolAt(signatureIndex); 256 } 257 258 public static boolean isInvokedynamicIndex(int i) { return (i < 0); } 259 260 public static int decodeInvokedynamicIndex(int i) { Assert.that(isInvokedynamicIndex(i), ""); return ~i; } 261 262 // The invokedynamic points at the object index. The object map points at 263 // the cpCache index and the cpCache entry points at the original constant 264 // pool index. 265 public int invokedynamicCPCacheIndex(int index) { 266 Assert.that(isInvokedynamicIndex(index), "should be a invokedynamic index"); 267 int rawIndex = decodeInvokedynamicIndex(index); 268 return referenceMap().at(rawIndex); 269 } 270 271 ConstantPoolCacheEntry invokedynamicCPCacheEntryAt(int index) { 272 // decode index that invokedynamic points to. 273 int cpCacheIndex = invokedynamicCPCacheIndex(index); 274 return getCache().getEntryAt(cpCacheIndex); 275 } 276 277 private int implNameAndTypeRefIndexAt(int which, boolean uncached) { 278 int i = which; 279 if (!uncached && getCache() != null) { 280 if (isInvokedynamicIndex(which)) { 281 // Invokedynamic index is index into resolved_references 282 int poolIndex = invokedynamicCPCacheEntryAt(which).getConstantPoolIndex(); 283 poolIndex = invokeDynamicNameAndTypeRefIndexAt(poolIndex); 284 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); 285 return poolIndex; 286 } 287 // change byte-ordering and go via cache 288 i = remapInstructionOperandFromCache(which); 289 } else { 290 if (getTagAt(which).isInvokeDynamic()) { 291 int poolIndex = invokeDynamicNameAndTypeRefIndexAt(which); 292 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); 293 return poolIndex; 294 } 295 } 296 // assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); 297 // assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above"); 298 int refIndex = getIntAt(i); 299 return extractHighShortFromInt(refIndex); 300 } 301 302 private int remapInstructionOperandFromCache(int operand) { 303 int cpc_index = operand; 304 // DEBUG_ONLY(cpc_index -= CPCACHE_INDEX_TAG); 305 // assert((int)(u2)cpc_index == cpc_index, "clean u2"); 306 int member_index = getCache().getEntryAt(cpc_index).getConstantPoolIndex(); 307 return member_index; 308 } 309 310 int invokeDynamicNameAndTypeRefIndexAt(int which) { 311 // assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); 312 return extractHighShortFromInt(getIntAt(which)); 313 } 314 315 // returns null, if not resolved. 316 public Klass getKlassAt(int which) { 317 if( ! getTagAt(which).isKlass()) return null; 318 return (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(which)); 319 } 320 321 public Symbol getKlassNameAt(int which) { 322 CPSlot entry = getSlotAt(which); 323 if (entry.isResolved()) { 324 return entry.getKlass().getName(); 325 } else { 326 return entry.getSymbol(); 327 } 328 } 329 330 public Symbol getUnresolvedStringAt(int which) { 331 return getSlotAt(which).getSymbol(); 332 } 333 334 // returns null, if not resolved. 335 public InstanceKlass getFieldOrMethodKlassRefAt(int which) { 336 int refIndex = getFieldOrMethodAt(which); 337 int klassIndex = extractLowShortFromInt(refIndex); 338 return (InstanceKlass) getKlassAt(klassIndex); 339 } 340 341 // returns null, if not resolved. 342 public Method getMethodRefAt(int which) { 343 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); 344 if (klass == null) return null; 345 Symbol name = getNameRefAt(which); 346 Symbol sig = getSignatureRefAt(which); 347 return klass.findMethod(name, sig); 348 } 349 350 // returns null, if not resolved. 351 public Field getFieldRefAt(int which) { 352 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); 353 if (klass == null) return null; 354 Symbol name = getNameRefAt(which); 355 Symbol sig = getSignatureRefAt(which); 356 return klass.findField(name, sig); 357 } 358 359 public int getNameAndTypeRefIndexAt(int index) { 360 return implNameAndTypeRefIndexAt(index, false); 361 } 362 363 /** Lookup for entries consisting of (name_index, signature_index) */ 364 public int getNameRefIndexAt(int index) { 365 int[] refIndex = getNameAndTypeAt(index); 366 if (DEBUG) { 367 System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); 368 } 369 int i = refIndex[0]; 370 if (DEBUG) { 371 System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i); 372 } 373 return i; 374 } 375 376 /** Lookup for entries consisting of (name_index, signature_index) */ 377 public int getSignatureRefIndexAt(int index) { 378 int[] refIndex = getNameAndTypeAt(index); 379 if (DEBUG) { 380 System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); 381 } 382 int i = refIndex[1]; 383 if (DEBUG) { 384 System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i); 385 } 386 return i; 387 } 388 389 /** Lookup for MethodHandle entries. */ 390 public int getMethodHandleIndexAt(int i) { 391 if (Assert.ASSERTS_ENABLED) { 392 Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); 393 } 394 int res = extractHighShortFromInt(getIntAt(i)); 395 if (DEBUG) { 396 System.err.println("ConstantPool.getMethodHandleIndexAt(" + i + "): result = " + res); 397 } 398 return res; 399 } 400 401 /** Lookup for MethodHandle entries. */ 402 public int getMethodHandleRefKindAt(int i) { 403 if (Assert.ASSERTS_ENABLED) { 404 Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); 405 } 406 int res = extractLowShortFromInt(getIntAt(i)); 407 if (DEBUG) { 408 System.err.println("ConstantPool.getMethodHandleRefKindAt(" + i + "): result = " + res); 409 } 410 return res; 411 } 412 413 /** Lookup for MethodType entries. */ 414 public int getMethodTypeIndexAt(int i) { 415 if (Assert.ASSERTS_ENABLED) { 416 Assert.that(getTagAt(i).isMethodType(), "Corrupted constant pool"); 417 } 418 int res = getIntAt(i); 419 if (DEBUG) { 420 System.err.println("ConstantPool.getMethodHandleTypeAt(" + i + "): result = " + res); 421 } 422 return res; 423 } 424 425 /** Lookup for multi-operand (InvokeDynamic) entries. */ 426 public short[] getBootstrapSpecifierAt(int i) { 427 if (Assert.ASSERTS_ENABLED) { 428 Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool"); 429 } 430 int bsmSpec = extractLowShortFromInt(this.getIntAt(i)); 431 U2Array operands = getOperands(); 432 if (operands == null) return null; // safety first 433 int basePos = VM.getVM().buildIntFromShorts(operands.at(bsmSpec * 2 + 0), 434 operands.at(bsmSpec * 2 + 1)); 435 int argv = basePos + INDY_ARGV_OFFSET; 436 int argc = operands.at(basePos + INDY_ARGC_OFFSET); 437 int endPos = argv + argc; 438 short[] values = new short[endPos - basePos]; 439 for (int j = 0; j < values.length; j++) { 440 values[j] = operands.at(basePos+j); 441 } 442 return values; 443 } 444 445 final private static String[] nameForTag = new String[] { 446 }; 447 448 private String nameForTag(int tag) { 449 switch (tag) { 450 case JVM_CONSTANT_Utf8: return "JVM_CONSTANT_Utf8"; 451 case JVM_CONSTANT_Unicode: return "JVM_CONSTANT_Unicode"; 452 case JVM_CONSTANT_Integer: return "JVM_CONSTANT_Integer"; 453 case JVM_CONSTANT_Float: return "JVM_CONSTANT_Float"; 454 case JVM_CONSTANT_Long: return "JVM_CONSTANT_Long"; 455 case JVM_CONSTANT_Double: return "JVM_CONSTANT_Double"; 456 case JVM_CONSTANT_Class: return "JVM_CONSTANT_Class"; 457 case JVM_CONSTANT_String: return "JVM_CONSTANT_String"; 458 case JVM_CONSTANT_Fieldref: return "JVM_CONSTANT_Fieldref"; 459 case JVM_CONSTANT_Methodref: return "JVM_CONSTANT_Methodref"; 460 case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref"; 461 case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType"; 462 case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle"; 463 case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType"; 464 case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic"; 465 case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid"; 466 case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass"; 467 case JVM_CONSTANT_ClassIndex: return "JVM_CONSTANT_ClassIndex"; 468 case JVM_CONSTANT_StringIndex: return "JVM_CONSTANT_StringIndex"; 469 case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; 470 case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError"; 471 case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError"; 472 } 473 throw new InternalError("Unknown tag: " + tag); 474 } 475 476 public void iterateFields(MetadataVisitor visitor) { 477 super.iterateFields(visitor); 478 visitor.doMetadata(poolHolder, true); 479 480 final int length = (int) getLength(); 481 // zero'th pool entry is always invalid. ignore it. 482 for (int index = 1; index < length; index++) { 483 int ctag = (int) getTags().at((int) index); 484 switch (ctag) { 485 case JVM_CONSTANT_ClassIndex: 486 case JVM_CONSTANT_StringIndex: 487 case JVM_CONSTANT_Integer: 488 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 489 break; 490 491 case JVM_CONSTANT_Float: 492 visitor.doFloat(new FloatField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 493 break; 494 495 case JVM_CONSTANT_Long: 496 visitor.doLong(new LongField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 497 // long entries occupy two slots 498 index++; 499 break; 500 501 case JVM_CONSTANT_Double: 502 visitor.doDouble(new DoubleField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 503 // double entries occupy two slots 504 index++; 505 break; 506 507 case JVM_CONSTANT_UnresolvedClassInError: 508 case JVM_CONSTANT_UnresolvedClass: 509 case JVM_CONSTANT_Class: 510 case JVM_CONSTANT_Utf8: 511 visitor.doOop(new OopField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 512 break; 513 514 case JVM_CONSTANT_Fieldref: 515 case JVM_CONSTANT_Methodref: 516 case JVM_CONSTANT_InterfaceMethodref: 517 case JVM_CONSTANT_NameAndType: 518 case JVM_CONSTANT_MethodHandle: 519 case JVM_CONSTANT_MethodType: 520 case JVM_CONSTANT_InvokeDynamic: 521 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 522 break; 523 } 524 } 525 } 526 527 public void writeBytes(OutputStream os) throws IOException { 528 // Map between any modified UTF-8 and it's constant pool index. 529 Map utf8ToIndex = new HashMap(); 530 DataOutputStream dos = new DataOutputStream(os); 531 U1Array tags = getTags(); 532 int len = (int)getLength(); 533 int ci = 0; // constant pool index 534 535 // collect all modified UTF-8 Strings from Constant Pool 536 537 for (ci = 1; ci < len; ci++) { 538 int cpConstType = tags.at(ci); 539 if(cpConstType == JVM_CONSTANT_Utf8) { 540 Symbol sym = getSymbolAt(ci); 541 utf8ToIndex.put(sym.asString(), new Short((short) ci)); 542 } 543 else if(cpConstType == JVM_CONSTANT_Long || 544 cpConstType == JVM_CONSTANT_Double) { 545 ci++; 546 } 547 } 548 549 550 for(ci = 1; ci < len; ci++) { 551 int cpConstType = tags.at(ci); 552 // write cp_info 553 // write constant type 554 switch(cpConstType) { 555 case JVM_CONSTANT_Utf8: { 556 dos.writeByte(cpConstType); 557 Symbol sym = getSymbolAt(ci); 558 dos.writeShort((short)sym.getLength()); 559 dos.write(sym.asByteArray()); 560 if (DEBUG) debugMessage("CP[" + ci + "] = modified UTF-8 " + sym.asString()); 561 break; 562 } 563 564 case JVM_CONSTANT_Unicode: 565 throw new IllegalArgumentException("Unicode constant!"); 566 567 case JVM_CONSTANT_Integer: 568 dos.writeByte(cpConstType); 569 dos.writeInt(getIntAt(ci)); 570 if (DEBUG) debugMessage("CP[" + ci + "] = int " + getIntAt(ci)); 571 break; 572 573 case JVM_CONSTANT_Float: 574 dos.writeByte(cpConstType); 575 dos.writeFloat(getFloatAt(ci)); 576 if (DEBUG) debugMessage("CP[" + ci + "] = float " + getFloatAt(ci)); 577 break; 578 579 case JVM_CONSTANT_Long: { 580 dos.writeByte(cpConstType); 581 long l = getLongAt(ci); 582 // long entries occupy two pool entries 583 ci++; 584 dos.writeLong(l); 585 break; 586 } 587 588 case JVM_CONSTANT_Double: 589 dos.writeByte(cpConstType); 590 dos.writeDouble(getDoubleAt(ci)); 591 // double entries occupy two pool entries 592 ci++; 593 break; 594 595 case JVM_CONSTANT_Class: { 596 dos.writeByte(cpConstType); 597 // Klass already resolved. ConstantPool constains Klass*. 598 Klass refKls = (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(ci)); 599 String klassName = refKls.getName().asString(); 600 Short s = (Short) utf8ToIndex.get(klassName); 601 dos.writeShort(s.shortValue()); 602 if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); 603 break; 604 } 605 606 // case JVM_CONSTANT_ClassIndex: 607 case JVM_CONSTANT_UnresolvedClassInError: 608 case JVM_CONSTANT_UnresolvedClass: { 609 dos.writeByte(JVM_CONSTANT_Class); 610 String klassName = getSymbolAt(ci).asString(); 611 Short s = (Short) utf8ToIndex.get(klassName); 612 dos.writeShort(s.shortValue()); 613 if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); 614 break; 615 } 616 617 case JVM_CONSTANT_String: { 618 dos.writeByte(cpConstType); 619 String str = getUnresolvedStringAt(ci).asString(); 620 Short s = (Short) utf8ToIndex.get(str); 621 dos.writeShort(s.shortValue()); 622 if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); 623 break; 624 } 625 626 // all external, internal method/field references 627 case JVM_CONSTANT_Fieldref: 628 case JVM_CONSTANT_Methodref: 629 case JVM_CONSTANT_InterfaceMethodref: { 630 dos.writeByte(cpConstType); 631 int value = getIntAt(ci); 632 short klassIndex = (short) extractLowShortFromInt(value); 633 short nameAndTypeIndex = (short) extractHighShortFromInt(value); 634 dos.writeShort(klassIndex); 635 dos.writeShort(nameAndTypeIndex); 636 if (DEBUG) debugMessage("CP[" + ci + "] = ref klass = " + 637 klassIndex + ", N&T = " + nameAndTypeIndex); 638 break; 639 } 640 641 case JVM_CONSTANT_NameAndType: { 642 dos.writeByte(cpConstType); 643 int value = getIntAt(ci); 644 short nameIndex = (short) extractLowShortFromInt(value); 645 short signatureIndex = (short) extractHighShortFromInt(value); 646 dos.writeShort(nameIndex); 647 dos.writeShort(signatureIndex); 648 if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex 649 + ", type = " + signatureIndex); 650 break; 651 } 652 653 case JVM_CONSTANT_MethodHandle: { 654 dos.writeByte(cpConstType); 655 int value = getIntAt(ci); 656 byte refKind = (byte) extractLowShortFromInt(value); 657 short memberIndex = (short) extractHighShortFromInt(value); 658 dos.writeByte(refKind); 659 dos.writeShort(memberIndex); 660 if (DEBUG) debugMessage("CP[" + ci + "] = MH kind = " + 661 refKind + ", mem = " + memberIndex); 662 break; 663 } 664 665 case JVM_CONSTANT_MethodType: { 666 dos.writeByte(cpConstType); 667 int value = getIntAt(ci); 668 short refIndex = (short) value; 669 dos.writeShort(refIndex); 670 if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex); 671 break; 672 } 673 674 case JVM_CONSTANT_InvokeDynamic: { 675 dos.writeByte(cpConstType); 676 int value = getIntAt(ci); 677 short bsmIndex = (short) extractLowShortFromInt(value); 678 short nameAndTypeIndex = (short) extractHighShortFromInt(value); 679 dos.writeShort(bsmIndex); 680 dos.writeShort(nameAndTypeIndex); 681 if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " + 682 bsmIndex + ", N&T = " + nameAndTypeIndex); 683 break; 684 } 685 686 default: 687 throw new InternalError("Unknown tag: " + cpConstType); 688 } // switch 689 } 690 dos.flush(); 691 return; 692 } 693 694 public void printValueOn(PrintStream tty) { 695 tty.print("ConstantPool for " + getPoolHolder().getName().asString()); 696 } 697 698 public long getSize() { 699 return Oop.alignObjectSize(headerSize + getLength()); 700 } 701 702 //---------------------------------------------------------------------- 703 // Internals only below this point 704 // 705 706 private static int extractHighShortFromInt(int val) { 707 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. 708 return (val >> 16) & 0xFFFF; 709 } 710 711 private static int extractLowShortFromInt(int val) { 712 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. 713 return val & 0xFFFF; 714 } 715 }