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 referenceMap = type.getAddressField("_reference_map"); 88 headerSize = type.getSize(); 89 elementSize = 0; 90 // fetch constants: 91 INDY_BSM_OFFSET = db.lookupIntConstant("ConstantPool::_indy_bsm_offset").intValue(); 92 INDY_ARGC_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argc_offset").intValue(); 93 INDY_ARGV_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argv_offset").intValue(); 94 } 95 96 public ConstantPool(Address addr) { 97 super(addr); 98 } 99 100 public boolean isConstantPool() { return true; } 101 102 private static AddressField tags; 103 private static AddressField operands; 104 private static AddressField cache; 105 private static MetadataField poolHolder; 106 private static CIntField length; // number of elements in oop 107 private static AddressField referenceMap; 108 109 private static long headerSize; 110 private static long elementSize; 111 112 private static int INDY_BSM_OFFSET; 113 private static int INDY_ARGC_OFFSET; 114 private static int INDY_ARGV_OFFSET; 115 116 public U1Array getTags() { return new U1Array(tags.getValue(getAddress())); } 117 public U2Array getOperands() { return new U2Array(operands.getValue(getAddress())); } 118 public ConstantPoolCache getCache() { 119 Address addr = cache.getValue(getAddress()); 120 return (ConstantPoolCache) VMObjectFactory.newObject(ConstantPoolCache.class, addr); 121 } 122 public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); } 123 public int getLength() { return (int)length.getValue(getAddress()); } 124 125 public U2Array referenceMap() { 126 return new U2Array(referenceMap.getValue(getAddress())); 127 } 128 129 public int objectToCPIndex(int index) { 130 return referenceMap().at(index); 131 } 132 133 private long getElementSize() { 134 if (elementSize !=0 ) { 135 return elementSize; 136 } else { 137 elementSize = VM.getVM().getOopSize(); 138 } 139 return elementSize; 140 } 141 142 private long indexOffset(long index) { 143 if (Assert.ASSERTS_ENABLED) { 144 Assert.that(index >= 0 && index < getLength(), "invalid cp index " + index + " " + getLength()); 145 } 146 return (index * getElementSize()) + headerSize; 147 } 148 149 public ConstantTag getTagAt(long index) { 150 return new ConstantTag((byte)getTags().at((int) index)); 151 } 152 153 public CPSlot getSlotAt(long index) { 154 return new CPSlot(getAddressAtRaw(index)); 155 } 156 157 public Address getAddressAtRaw(long index) { 158 return getAddress().getAddressAt(indexOffset(index)); 159 } 160 161 public Symbol getSymbolAt(long index) { 162 return Symbol.create(getAddressAtRaw(index)); 163 } 164 165 public int getIntAt(long index){ 166 return getAddress().getJIntAt(indexOffset(index)); 167 } 168 169 public float getFloatAt(long index){ 170 return getAddress().getJFloatAt(indexOffset(index)); 171 } 172 173 public long getLongAt(long index) { 174 int oneHalf = getAddress().getJIntAt(indexOffset(index + 1)); 175 int otherHalf = getAddress().getJIntAt(indexOffset(index)); 176 // buildLongFromIntsPD accepts higher address value, lower address value 177 // in that order. 178 return VM.getVM().buildLongFromIntsPD(oneHalf, otherHalf); 179 } 180 181 public double getDoubleAt(long index) { 182 return Double.longBitsToDouble(getLongAt(index)); 183 } 184 185 public int getFieldOrMethodAt(int which) { 186 if (DEBUG) { 187 System.err.print("ConstantPool.getFieldOrMethodAt(" + which + "): new index = "); 188 } 189 int i = -1; 190 ConstantPoolCache cache = getCache(); 191 if (cache == null) { 192 i = which; 193 } else { 194 // change byte-ordering and go via cache 195 i = cache.getEntryAt(0xFFFF & which).getConstantPoolIndex(); 196 } 197 if (Assert.ASSERTS_ENABLED) { 198 Assert.that(getTagAt(i).isFieldOrMethod(), "Corrupted constant pool"); 199 } 200 if (DEBUG) { 201 System.err.println(i); 202 } 203 int res = getIntAt(i); 204 if (DEBUG) { 205 System.err.println("ConstantPool.getFieldOrMethodAt(" + i + "): result = " + res); 206 } 207 return res; 208 } 209 210 public int[] getNameAndTypeAt(int which) { 211 if (Assert.ASSERTS_ENABLED) { 212 Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool: " + which + " " + getTagAt(which)); 213 } 214 int i = getIntAt(which); 215 if (DEBUG) { 216 System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i); 217 } 218 return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) }; 219 } 220 221 public Symbol getNameRefAt(int which) { 222 return implGetNameRefAt(which, false); 223 } 224 225 public Symbol uncachedGetNameRefAt(int which) { 226 return implGetNameRefAt(which, true); 227 } 228 229 private Symbol implGetNameRefAt(int which, boolean uncached) { 230 int signatureIndex = getNameRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); 231 return getSymbolAt(signatureIndex); 232 } 233 234 public Symbol getSignatureRefAt(int which) { 235 return implGetSignatureRefAt(which, false); 236 } 237 238 public Symbol uncachedGetSignatureRefAt(int which) { 239 return implGetSignatureRefAt(which, true); 240 } 241 242 private Symbol implGetSignatureRefAt(int which, boolean uncached) { 243 int signatureIndex = getSignatureRefIndexAt(implNameAndTypeRefIndexAt(which, uncached)); 244 return getSymbolAt(signatureIndex); 245 } 246 247 public static boolean isInvokedynamicIndex(int i) { return (i < 0); } 248 249 public static int decodeInvokedynamicIndex(int i) { Assert.that(isInvokedynamicIndex(i), ""); return ~i; } 250 251 // The invokedynamic points at the object index. The object map points at 252 // the cpCache index and the cpCache entry points at the original constant 253 // pool index. 254 public int invokedynamicCPCacheIndex(int index) { 255 Assert.that(isInvokedynamicIndex(index), "should be a invokedynamic index"); 256 int rawIndex = decodeInvokedynamicIndex(index); 257 return referenceMap().at(rawIndex); 258 } 259 260 ConstantPoolCacheEntry invokedynamicCPCacheEntryAt(int index) { 261 // decode index that invokedynamic points to. 262 int cpCacheIndex = invokedynamicCPCacheIndex(index); 263 return getCache().getEntryAt(cpCacheIndex); 264 } 265 266 private int implNameAndTypeRefIndexAt(int which, boolean uncached) { 267 int i = which; 268 if (!uncached && getCache() != null) { 269 if (isInvokedynamicIndex(which)) { 270 // Invokedynamic index is index into resolved_references 271 int poolIndex = invokedynamicCPCacheEntryAt(which).getConstantPoolIndex(); 272 poolIndex = invokeDynamicNameAndTypeRefIndexAt(poolIndex); 273 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); 274 return poolIndex; 275 } 276 // change byte-ordering and go via cache 277 i = remapInstructionOperandFromCache(which); 278 } else { 279 if (getTagAt(which).isInvokeDynamic()) { 280 int poolIndex = invokeDynamicNameAndTypeRefIndexAt(which); 281 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); 282 return poolIndex; 283 } 284 } 285 // assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); 286 // assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above"); 287 int refIndex = getIntAt(i); 288 return extractHighShortFromInt(refIndex); 289 } 290 291 private int remapInstructionOperandFromCache(int operand) { 292 int cpc_index = operand; 293 // DEBUG_ONLY(cpc_index -= CPCACHE_INDEX_TAG); 294 // assert((int)(u2)cpc_index == cpc_index, "clean u2"); 295 int member_index = getCache().getEntryAt(cpc_index).getConstantPoolIndex(); 296 return member_index; 297 } 298 299 int invokeDynamicNameAndTypeRefIndexAt(int which) { 300 // assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); 301 return extractHighShortFromInt(getIntAt(which)); 302 } 303 304 // returns null, if not resolved. 305 public Klass getKlassAt(int which) { 306 if( ! getTagAt(which).isKlass()) return null; 307 return (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(which)); 308 } 309 310 public Symbol getKlassNameAt(int which) { 311 CPSlot entry = getSlotAt(which); 312 if (entry.isResolved()) { 313 return entry.getKlass().getName(); 314 } else { 315 return entry.getSymbol(); 316 } 317 } 318 319 public Symbol getUnresolvedStringAt(int which) { 320 return getSlotAt(which).getSymbol(); 321 } 322 323 // returns null, if not resolved. 324 public InstanceKlass getFieldOrMethodKlassRefAt(int which) { 325 int refIndex = getFieldOrMethodAt(which); 326 int klassIndex = extractLowShortFromInt(refIndex); 327 return (InstanceKlass) getKlassAt(klassIndex); 328 } 329 330 // returns null, if not resolved. 331 public Method getMethodRefAt(int which) { 332 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); 333 if (klass == null) return null; 334 Symbol name = getNameRefAt(which); 335 Symbol sig = getSignatureRefAt(which); 336 return klass.findMethod(name, sig); 337 } 338 339 // returns null, if not resolved. 340 public Field getFieldRefAt(int which) { 341 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); 342 if (klass == null) return null; 343 Symbol name = getNameRefAt(which); 344 Symbol sig = getSignatureRefAt(which); 345 return klass.findField(name, sig); 346 } 347 348 public int getNameAndTypeRefIndexAt(int index) { 349 return implNameAndTypeRefIndexAt(index, false); 350 } 351 352 /** Lookup for entries consisting of (name_index, signature_index) */ 353 public int getNameRefIndexAt(int index) { 354 int[] refIndex = getNameAndTypeAt(index); 355 if (DEBUG) { 356 System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); 357 } 358 int i = refIndex[0]; 359 if (DEBUG) { 360 System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i); 361 } 362 return i; 363 } 364 365 /** Lookup for entries consisting of (name_index, signature_index) */ 366 public int getSignatureRefIndexAt(int index) { 367 int[] refIndex = getNameAndTypeAt(index); 368 if (DEBUG) { 369 System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); 370 } 371 int i = refIndex[1]; 372 if (DEBUG) { 373 System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i); 374 } 375 return i; 376 } 377 378 /** Lookup for MethodHandle entries. */ 379 public int getMethodHandleIndexAt(int i) { 380 if (Assert.ASSERTS_ENABLED) { 381 Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); 382 } 383 int res = extractHighShortFromInt(getIntAt(i)); 384 if (DEBUG) { 385 System.err.println("ConstantPool.getMethodHandleIndexAt(" + i + "): result = " + res); 386 } 387 return res; 388 } 389 390 /** Lookup for MethodHandle entries. */ 391 public int getMethodHandleRefKindAt(int i) { 392 if (Assert.ASSERTS_ENABLED) { 393 Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); 394 } 395 int res = extractLowShortFromInt(getIntAt(i)); 396 if (DEBUG) { 397 System.err.println("ConstantPool.getMethodHandleRefKindAt(" + i + "): result = " + res); 398 } 399 return res; 400 } 401 402 /** Lookup for MethodType entries. */ 403 public int getMethodTypeIndexAt(int i) { 404 if (Assert.ASSERTS_ENABLED) { 405 Assert.that(getTagAt(i).isMethodType(), "Corrupted constant pool"); 406 } 407 int res = getIntAt(i); 408 if (DEBUG) { 409 System.err.println("ConstantPool.getMethodHandleTypeAt(" + i + "): result = " + res); 410 } 411 return res; 412 } 413 414 /** Lookup for multi-operand (InvokeDynamic) entries. */ 415 public short[] getBootstrapSpecifierAt(int i) { 416 if (Assert.ASSERTS_ENABLED) { 417 Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool"); 418 } 419 int bsmSpec = extractLowShortFromInt(this.getIntAt(i)); 420 U2Array operands = getOperands(); 421 if (operands == null) return null; // safety first 422 int basePos = VM.getVM().buildIntFromShorts(operands.at(bsmSpec * 2 + 0), 423 operands.at(bsmSpec * 2 + 1)); 424 int argv = basePos + INDY_ARGV_OFFSET; 425 int argc = operands.at(basePos + INDY_ARGC_OFFSET); 426 int endPos = argv + argc; 427 short[] values = new short[endPos - basePos]; 428 for (int j = 0; j < values.length; j++) { 429 values[j] = operands.at(basePos+j); 430 } 431 return values; 432 } 433 434 final private static String[] nameForTag = new String[] { 435 }; 436 437 private String nameForTag(int tag) { 438 switch (tag) { 439 case JVM_CONSTANT_Utf8: return "JVM_CONSTANT_Utf8"; 440 case JVM_CONSTANT_Unicode: return "JVM_CONSTANT_Unicode"; 441 case JVM_CONSTANT_Integer: return "JVM_CONSTANT_Integer"; 442 case JVM_CONSTANT_Float: return "JVM_CONSTANT_Float"; 443 case JVM_CONSTANT_Long: return "JVM_CONSTANT_Long"; 444 case JVM_CONSTANT_Double: return "JVM_CONSTANT_Double"; 445 case JVM_CONSTANT_Class: return "JVM_CONSTANT_Class"; 446 case JVM_CONSTANT_String: return "JVM_CONSTANT_String"; 447 case JVM_CONSTANT_Fieldref: return "JVM_CONSTANT_Fieldref"; 448 case JVM_CONSTANT_Methodref: return "JVM_CONSTANT_Methodref"; 449 case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref"; 450 case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType"; 451 case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle"; 452 case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType"; 453 case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic"; 454 case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid"; 455 case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass"; 456 case JVM_CONSTANT_ClassIndex: return "JVM_CONSTANT_ClassIndex"; 457 case JVM_CONSTANT_StringIndex: return "JVM_CONSTANT_StringIndex"; 458 case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; 459 case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError"; 460 case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError"; 461 } 462 throw new InternalError("Unknown tag: " + tag); 463 } 464 465 public void iterateFields(MetadataVisitor visitor) { 466 super.iterateFields(visitor); 467 visitor.doMetadata(poolHolder, true); 468 469 final int length = (int) getLength(); 470 // zero'th pool entry is always invalid. ignore it. 471 for (int index = 1; index < length; index++) { 472 int ctag = (int) getTags().at((int) index); 473 switch (ctag) { 474 case JVM_CONSTANT_ClassIndex: 475 case JVM_CONSTANT_StringIndex: 476 case JVM_CONSTANT_Integer: 477 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 478 break; 479 480 case JVM_CONSTANT_Float: 481 visitor.doFloat(new FloatField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 482 break; 483 484 case JVM_CONSTANT_Long: 485 visitor.doLong(new LongField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 486 // long entries occupy two slots 487 index++; 488 break; 489 490 case JVM_CONSTANT_Double: 491 visitor.doDouble(new DoubleField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 492 // double entries occupy two slots 493 index++; 494 break; 495 496 case JVM_CONSTANT_UnresolvedClassInError: 497 case JVM_CONSTANT_UnresolvedClass: 498 case JVM_CONSTANT_Class: 499 case JVM_CONSTANT_Utf8: 500 visitor.doOop(new OopField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 501 break; 502 503 case JVM_CONSTANT_Fieldref: 504 case JVM_CONSTANT_Methodref: 505 case JVM_CONSTANT_InterfaceMethodref: 506 case JVM_CONSTANT_NameAndType: 507 case JVM_CONSTANT_MethodHandle: 508 case JVM_CONSTANT_MethodType: 509 case JVM_CONSTANT_InvokeDynamic: 510 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 511 break; 512 } 513 } 514 } 515 516 public void writeBytes(OutputStream os) throws IOException { 517 // Map between any modified UTF-8 and it's constant pool index. 518 Map utf8ToIndex = new HashMap(); 519 DataOutputStream dos = new DataOutputStream(os); 520 U1Array tags = getTags(); 521 int len = (int)getLength(); 522 int ci = 0; // constant pool index 523 524 // collect all modified UTF-8 Strings from Constant Pool 525 526 for (ci = 1; ci < len; ci++) { 527 int cpConstType = tags.at(ci); 528 if(cpConstType == JVM_CONSTANT_Utf8) { 529 Symbol sym = getSymbolAt(ci); 530 utf8ToIndex.put(sym.asString(), new Short((short) ci)); 531 } 532 else if(cpConstType == JVM_CONSTANT_Long || 533 cpConstType == JVM_CONSTANT_Double) { 534 ci++; 535 } 536 } 537 538 539 for(ci = 1; ci < len; ci++) { 540 int cpConstType = tags.at(ci); 541 // write cp_info 542 // write constant type 543 switch(cpConstType) { 544 case JVM_CONSTANT_Utf8: { 545 dos.writeByte(cpConstType); 546 Symbol sym = getSymbolAt(ci); 547 dos.writeShort((short)sym.getLength()); 548 dos.write(sym.asByteArray()); 549 if (DEBUG) debugMessage("CP[" + ci + "] = modified UTF-8 " + sym.asString()); 550 break; 551 } 552 553 case JVM_CONSTANT_Unicode: 554 throw new IllegalArgumentException("Unicode constant!"); 555 556 case JVM_CONSTANT_Integer: 557 dos.writeByte(cpConstType); 558 dos.writeInt(getIntAt(ci)); 559 if (DEBUG) debugMessage("CP[" + ci + "] = int " + getIntAt(ci)); 560 break; 561 562 case JVM_CONSTANT_Float: 563 dos.writeByte(cpConstType); 564 dos.writeFloat(getFloatAt(ci)); 565 if (DEBUG) debugMessage("CP[" + ci + "] = float " + getFloatAt(ci)); 566 break; 567 568 case JVM_CONSTANT_Long: { 569 dos.writeByte(cpConstType); 570 long l = getLongAt(ci); 571 // long entries occupy two pool entries 572 ci++; 573 dos.writeLong(l); 574 break; 575 } 576 577 case JVM_CONSTANT_Double: 578 dos.writeByte(cpConstType); 579 dos.writeDouble(getDoubleAt(ci)); 580 // double entries occupy two pool entries 581 ci++; 582 break; 583 584 case JVM_CONSTANT_Class: { 585 dos.writeByte(cpConstType); 586 // Klass already resolved. ConstantPool constains Klass*. 587 Klass refKls = (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(ci)); 588 String klassName = refKls.getName().asString(); 589 Short s = (Short) utf8ToIndex.get(klassName); 590 dos.writeShort(s.shortValue()); 591 if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); 592 break; 593 } 594 595 // case JVM_CONSTANT_ClassIndex: 596 case JVM_CONSTANT_UnresolvedClassInError: 597 case JVM_CONSTANT_UnresolvedClass: { 598 dos.writeByte(JVM_CONSTANT_Class); 599 String klassName = getSymbolAt(ci).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_String: { 607 dos.writeByte(cpConstType); 608 String str = getUnresolvedStringAt(ci).asString(); 609 Short s = (Short) utf8ToIndex.get(str); 610 dos.writeShort(s.shortValue()); 611 if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); 612 break; 613 } 614 615 // all external, internal method/field references 616 case JVM_CONSTANT_Fieldref: 617 case JVM_CONSTANT_Methodref: 618 case JVM_CONSTANT_InterfaceMethodref: { 619 dos.writeByte(cpConstType); 620 int value = getIntAt(ci); 621 short klassIndex = (short) extractLowShortFromInt(value); 622 short nameAndTypeIndex = (short) extractHighShortFromInt(value); 623 dos.writeShort(klassIndex); 624 dos.writeShort(nameAndTypeIndex); 625 if (DEBUG) debugMessage("CP[" + ci + "] = ref klass = " + 626 klassIndex + ", N&T = " + nameAndTypeIndex); 627 break; 628 } 629 630 case JVM_CONSTANT_NameAndType: { 631 dos.writeByte(cpConstType); 632 int value = getIntAt(ci); 633 short nameIndex = (short) extractLowShortFromInt(value); 634 short signatureIndex = (short) extractHighShortFromInt(value); 635 dos.writeShort(nameIndex); 636 dos.writeShort(signatureIndex); 637 if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex 638 + ", type = " + signatureIndex); 639 break; 640 } 641 642 case JVM_CONSTANT_MethodHandle: { 643 dos.writeByte(cpConstType); 644 int value = getIntAt(ci); 645 byte refKind = (byte) extractLowShortFromInt(value); 646 short memberIndex = (short) extractHighShortFromInt(value); 647 dos.writeByte(refKind); 648 dos.writeShort(memberIndex); 649 if (DEBUG) debugMessage("CP[" + ci + "] = MH kind = " + 650 refKind + ", mem = " + memberIndex); 651 break; 652 } 653 654 case JVM_CONSTANT_MethodType: { 655 dos.writeByte(cpConstType); 656 int value = getIntAt(ci); 657 short refIndex = (short) value; 658 dos.writeShort(refIndex); 659 if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex); 660 break; 661 } 662 663 case JVM_CONSTANT_InvokeDynamic: { 664 dos.writeByte(cpConstType); 665 int value = getIntAt(ci); 666 short bsmIndex = (short) extractLowShortFromInt(value); 667 short nameAndTypeIndex = (short) extractHighShortFromInt(value); 668 dos.writeShort(bsmIndex); 669 dos.writeShort(nameAndTypeIndex); 670 if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " + 671 bsmIndex + ", N&T = " + nameAndTypeIndex); 672 break; 673 } 674 675 default: 676 throw new InternalError("Unknown tag: " + cpConstType); 677 } // switch 678 } 679 dos.flush(); 680 return; 681 } 682 683 public void printValueOn(PrintStream tty) { 684 tty.print("ConstantPool for " + getPoolHolder().getName().asString()); 685 } 686 687 public long getSize() { 688 return Oop.alignObjectSize(headerSize + getLength()); 689 } 690 691 //---------------------------------------------------------------------- 692 // Internals only below this point 693 // 694 695 private static int extractHighShortFromInt(int val) { 696 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. 697 return (val >> 16) & 0xFFFF; 698 } 699 700 private static int extractLowShortFromInt(int val) { 701 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. 702 return val & 0xFFFF; 703 } 704 }