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