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 a CP cache entry. This entry points back 273 // at the original CP entry (CONSTANT_InvokeDynamic) and also (via f2) at an entry 274 // in the resolved_references array (which provides the appendix argument). 275 public int invokedynamicCPCacheIndex(int index) { 276 Assert.that(isInvokedynamicIndex(index), "should be a invokedynamic index"); 277 return decodeInvokedynamicIndex(index); 278 } 279 280 ConstantPoolCacheEntry invokedynamicCPCacheEntryAt(int index) { 281 // decode index that invokedynamic points to. 282 int cpCacheIndex = invokedynamicCPCacheIndex(index); 283 return getCache().getEntryAt(cpCacheIndex); 284 } 285 286 private int implNameAndTypeRefIndexAt(int which, boolean uncached) { 287 int i = which; 288 if (!uncached && getCache() != null) { 289 if (isInvokedynamicIndex(which)) { 290 // Invokedynamic index is index into resolved_references 291 int poolIndex = invokedynamicCPCacheEntryAt(which).getConstantPoolIndex(); 292 poolIndex = invokeDynamicNameAndTypeRefIndexAt(poolIndex); 293 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); 294 return poolIndex; 295 } 296 // change byte-ordering and go via cache 297 i = remapInstructionOperandFromCache(which); 298 } else { 299 if (getTagAt(which).isInvokeDynamic()) { 300 int poolIndex = invokeDynamicNameAndTypeRefIndexAt(which); 301 Assert.that(getTagAt(poolIndex).isNameAndType(), ""); 302 return poolIndex; 303 } 304 } 305 // assert(tag_at(i).is_field_or_method(), "Corrupted constant pool"); 306 // assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above"); 307 int refIndex = getIntAt(i); 308 return extractHighShortFromInt(refIndex); 309 } 310 311 private int remapInstructionOperandFromCache(int operand) { 312 int cpc_index = operand; 313 // DEBUG_ONLY(cpc_index -= CPCACHE_INDEX_TAG); 314 // assert((int)(u2)cpc_index == cpc_index, "clean u2"); 315 int member_index = getCache().getEntryAt(cpc_index).getConstantPoolIndex(); 316 return member_index; 317 } 318 319 public int invokeDynamicNameAndTypeRefIndexAt(int which) { 320 // assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool"); 321 return extractHighShortFromInt(getIntAt(which)); 322 } 323 324 // returns null, if not resolved. 325 public Klass getKlassAt(int which) { 326 if( ! getTagAt(which).isKlass()) return null; 327 int resolved_klass_index = getKlassSlotAt(which).getResolvedKlassIndex(); 328 KlassArray resolved_klasses = getResolvedKlasses(); 329 return resolved_klasses.getAt(resolved_klass_index); 330 } 331 332 public Symbol getKlassNameAt(int which) { 333 int name_index = getKlassSlotAt(which).getNameIndex(); 334 return getSymbolAt(name_index); 335 } 336 337 public Symbol getUnresolvedStringAt(int which) { 338 return getSlotAt(which).getSymbol(); 339 } 340 341 // returns null, if not resolved. 342 public InstanceKlass getFieldOrMethodKlassRefAt(int which) { 343 int refIndex = getFieldOrMethodAt(which); 344 int klassIndex = extractLowShortFromInt(refIndex); 345 return (InstanceKlass) getKlassAt(klassIndex); 346 } 347 348 // returns null, if not resolved. 349 public Method getMethodRefAt(int which) { 350 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); 351 if (klass == null) return null; 352 Symbol name = getNameRefAt(which); 353 Symbol sig = getSignatureRefAt(which); 354 return klass.findMethod(name, sig); 355 } 356 357 // returns null, if not resolved. 358 public Field getFieldRefAt(int which) { 359 InstanceKlass klass = getFieldOrMethodKlassRefAt(which); 360 if (klass == null) return null; 361 Symbol name = getNameRefAt(which); 362 Symbol sig = getSignatureRefAt(which); 363 return klass.findField(name, sig); 364 } 365 366 public int getNameAndTypeRefIndexAt(int index) { 367 return implNameAndTypeRefIndexAt(index, false); 368 } 369 370 /** Lookup for entries consisting of (name_index, signature_index) */ 371 public int getNameRefIndexAt(int index) { 372 int[] refIndex = getNameAndTypeAt(index); 373 if (DEBUG) { 374 System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); 375 } 376 int i = refIndex[0]; 377 if (DEBUG) { 378 System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i); 379 } 380 return i; 381 } 382 383 /** Lookup for entries consisting of (name_index, signature_index) */ 384 public int getSignatureRefIndexAt(int index) { 385 int[] refIndex = getNameAndTypeAt(index); 386 if (DEBUG) { 387 System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]); 388 } 389 int i = refIndex[1]; 390 if (DEBUG) { 391 System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i); 392 } 393 return i; 394 } 395 396 /** Lookup for MethodHandle entries. */ 397 public int getMethodHandleIndexAt(int i) { 398 if (Assert.ASSERTS_ENABLED) { 399 Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); 400 } 401 int res = extractHighShortFromInt(getIntAt(i)); 402 if (DEBUG) { 403 System.err.println("ConstantPool.getMethodHandleIndexAt(" + i + "): result = " + res); 404 } 405 return res; 406 } 407 408 /** Lookup for MethodHandle entries. */ 409 public int getMethodHandleRefKindAt(int i) { 410 if (Assert.ASSERTS_ENABLED) { 411 Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool"); 412 } 413 int res = extractLowShortFromInt(getIntAt(i)); 414 if (DEBUG) { 415 System.err.println("ConstantPool.getMethodHandleRefKindAt(" + i + "): result = " + res); 416 } 417 return res; 418 } 419 420 /** Lookup for MethodType entries. */ 421 public int getMethodTypeIndexAt(int i) { 422 if (Assert.ASSERTS_ENABLED) { 423 Assert.that(getTagAt(i).isMethodType(), "Corrupted constant pool"); 424 } 425 int res = getIntAt(i); 426 if (DEBUG) { 427 System.err.println("ConstantPool.getMethodHandleTypeAt(" + i + "): result = " + res); 428 } 429 return res; 430 } 431 432 /** Lookup for multi-operand (InvokeDynamic) entries. */ 433 public short[] getBootstrapSpecifierAt(int i) { 434 if (Assert.ASSERTS_ENABLED) { 435 Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool"); 436 } 437 int bsmSpec = extractLowShortFromInt(this.getIntAt(i)); 438 U2Array operands = getOperands(); 439 if (operands == null) return null; // safety first 440 int basePos = VM.getVM().buildIntFromShorts(operands.at(bsmSpec * 2 + 0), 441 operands.at(bsmSpec * 2 + 1)); 442 int argv = basePos + INDY_ARGV_OFFSET; 443 int argc = operands.at(basePos + INDY_ARGC_OFFSET); 444 int endPos = argv + argc; 445 short[] values = new short[endPos - basePos]; 446 for (int j = 0; j < values.length; j++) { 447 values[j] = operands.at(basePos+j); 448 } 449 return values; 450 } 451 452 final private static String[] nameForTag = new String[] { 453 }; 454 455 private String nameForTag(int tag) { 456 switch (tag) { 457 case JVM_CONSTANT_Utf8: return "JVM_CONSTANT_Utf8"; 458 case JVM_CONSTANT_Unicode: return "JVM_CONSTANT_Unicode"; 459 case JVM_CONSTANT_Integer: return "JVM_CONSTANT_Integer"; 460 case JVM_CONSTANT_Float: return "JVM_CONSTANT_Float"; 461 case JVM_CONSTANT_Long: return "JVM_CONSTANT_Long"; 462 case JVM_CONSTANT_Double: return "JVM_CONSTANT_Double"; 463 case JVM_CONSTANT_Class: return "JVM_CONSTANT_Class"; 464 case JVM_CONSTANT_String: return "JVM_CONSTANT_String"; 465 case JVM_CONSTANT_Fieldref: return "JVM_CONSTANT_Fieldref"; 466 case JVM_CONSTANT_Methodref: return "JVM_CONSTANT_Methodref"; 467 case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref"; 468 case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType"; 469 case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle"; 470 case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType"; 471 case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic"; 472 case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid"; 473 case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass"; 474 case JVM_CONSTANT_ClassIndex: return "JVM_CONSTANT_ClassIndex"; 475 case JVM_CONSTANT_StringIndex: return "JVM_CONSTANT_StringIndex"; 476 case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; 477 case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError"; 478 case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError"; 479 } 480 throw new InternalError("Unknown tag: " + tag); 481 } 482 483 public void iterateFields(MetadataVisitor visitor) { 484 super.iterateFields(visitor); 485 visitor.doMetadata(poolHolder, true); 486 487 final int length = (int) getLength(); 488 // zero'th pool entry is always invalid. ignore it. 489 for (int index = 1; index < length; index++) { 490 int ctag = (int) getTags().at((int) index); 491 switch (ctag) { 492 case JVM_CONSTANT_ClassIndex: 493 case JVM_CONSTANT_StringIndex: 494 case JVM_CONSTANT_Integer: 495 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 496 break; 497 498 case JVM_CONSTANT_Float: 499 visitor.doFloat(new FloatField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 500 break; 501 502 case JVM_CONSTANT_Long: 503 visitor.doLong(new LongField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 504 // long entries occupy two slots 505 index++; 506 break; 507 508 case JVM_CONSTANT_Double: 509 visitor.doDouble(new DoubleField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 510 // double entries occupy two slots 511 index++; 512 break; 513 514 case JVM_CONSTANT_UnresolvedClassInError: 515 case JVM_CONSTANT_UnresolvedClass: 516 case JVM_CONSTANT_Class: 517 case JVM_CONSTANT_Utf8: 518 visitor.doOop(new OopField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 519 break; 520 521 case JVM_CONSTANT_Fieldref: 522 case JVM_CONSTANT_Methodref: 523 case JVM_CONSTANT_InterfaceMethodref: 524 case JVM_CONSTANT_NameAndType: 525 case JVM_CONSTANT_MethodHandle: 526 case JVM_CONSTANT_MethodType: 527 case JVM_CONSTANT_InvokeDynamic: 528 visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true); 529 break; 530 } 531 } 532 } 533 534 public void writeBytes(OutputStream os) throws IOException { 535 // Map between any modified UTF-8 and it's constant pool index. 536 Map utf8ToIndex = new HashMap(); 537 DataOutputStream dos = new DataOutputStream(os); 538 U1Array tags = getTags(); 539 int len = (int)getLength(); 540 int ci = 0; // constant pool index 541 542 // collect all modified UTF-8 Strings from Constant Pool 543 544 for (ci = 1; ci < len; ci++) { 545 int cpConstType = tags.at(ci); 546 if(cpConstType == JVM_CONSTANT_Utf8) { 547 Symbol sym = getSymbolAt(ci); 548 utf8ToIndex.put(sym.asString(), new Short((short) ci)); 549 } 550 else if(cpConstType == JVM_CONSTANT_Long || 551 cpConstType == JVM_CONSTANT_Double) { 552 ci++; 553 } 554 } 555 556 557 for(ci = 1; ci < len; ci++) { 558 int cpConstType = tags.at(ci); 559 // write cp_info 560 // write constant type 561 switch(cpConstType) { 562 case JVM_CONSTANT_Utf8: { 563 dos.writeByte(cpConstType); 564 Symbol sym = getSymbolAt(ci); 565 dos.writeShort((short)sym.getLength()); 566 dos.write(sym.asByteArray()); 567 if (DEBUG) debugMessage("CP[" + ci + "] = modified UTF-8 " + sym.asString()); 568 break; 569 } 570 571 case JVM_CONSTANT_Unicode: 572 throw new IllegalArgumentException("Unicode constant!"); 573 574 case JVM_CONSTANT_Integer: 575 dos.writeByte(cpConstType); 576 dos.writeInt(getIntAt(ci)); 577 if (DEBUG) debugMessage("CP[" + ci + "] = int " + getIntAt(ci)); 578 break; 579 580 case JVM_CONSTANT_Float: 581 dos.writeByte(cpConstType); 582 dos.writeFloat(getFloatAt(ci)); 583 if (DEBUG) debugMessage("CP[" + ci + "] = float " + getFloatAt(ci)); 584 break; 585 586 case JVM_CONSTANT_Long: { 587 dos.writeByte(cpConstType); 588 long l = getLongAt(ci); 589 // long entries occupy two pool entries 590 ci++; 591 dos.writeLong(l); 592 break; 593 } 594 595 case JVM_CONSTANT_Double: 596 dos.writeByte(cpConstType); 597 dos.writeDouble(getDoubleAt(ci)); 598 // double entries occupy two pool entries 599 ci++; 600 break; 601 602 case JVM_CONSTANT_Class: { 603 dos.writeByte(cpConstType); 604 // Klass already resolved. ConstantPool constains Klass*. 605 Klass refKls = (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(ci)); 606 String klassName = refKls.getName().asString(); 607 Short s = (Short) utf8ToIndex.get(klassName); 608 dos.writeShort(s.shortValue()); 609 if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); 610 break; 611 } 612 613 // case JVM_CONSTANT_ClassIndex: 614 case JVM_CONSTANT_UnresolvedClassInError: 615 case JVM_CONSTANT_UnresolvedClass: { 616 dos.writeByte(JVM_CONSTANT_Class); 617 String klassName = getSymbolAt(ci).asString(); 618 Short s = (Short) utf8ToIndex.get(klassName); 619 dos.writeShort(s.shortValue()); 620 if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); 621 break; 622 } 623 624 case JVM_CONSTANT_String: { 625 dos.writeByte(cpConstType); 626 String str = getUnresolvedStringAt(ci).asString(); 627 Short s = (Short) utf8ToIndex.get(str); 628 dos.writeShort(s.shortValue()); 629 if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); 630 break; 631 } 632 633 // all external, internal method/field references 634 case JVM_CONSTANT_Fieldref: 635 case JVM_CONSTANT_Methodref: 636 case JVM_CONSTANT_InterfaceMethodref: { 637 dos.writeByte(cpConstType); 638 int value = getIntAt(ci); 639 short klassIndex = (short) extractLowShortFromInt(value); 640 short nameAndTypeIndex = (short) extractHighShortFromInt(value); 641 dos.writeShort(klassIndex); 642 dos.writeShort(nameAndTypeIndex); 643 if (DEBUG) debugMessage("CP[" + ci + "] = ref klass = " + 644 klassIndex + ", N&T = " + nameAndTypeIndex); 645 break; 646 } 647 648 case JVM_CONSTANT_NameAndType: { 649 dos.writeByte(cpConstType); 650 int value = getIntAt(ci); 651 short nameIndex = (short) extractLowShortFromInt(value); 652 short signatureIndex = (short) extractHighShortFromInt(value); 653 dos.writeShort(nameIndex); 654 dos.writeShort(signatureIndex); 655 if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex 656 + ", type = " + signatureIndex); 657 break; 658 } 659 660 case JVM_CONSTANT_MethodHandle: { 661 dos.writeByte(cpConstType); 662 int value = getIntAt(ci); 663 byte refKind = (byte) extractLowShortFromInt(value); 664 short memberIndex = (short) extractHighShortFromInt(value); 665 dos.writeByte(refKind); 666 dos.writeShort(memberIndex); 667 if (DEBUG) debugMessage("CP[" + ci + "] = MH kind = " + 668 refKind + ", mem = " + memberIndex); 669 break; 670 } 671 672 case JVM_CONSTANT_MethodType: { 673 dos.writeByte(cpConstType); 674 int value = getIntAt(ci); 675 short refIndex = (short) value; 676 dos.writeShort(refIndex); 677 if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex); 678 break; 679 } 680 681 case JVM_CONSTANT_InvokeDynamic: { 682 dos.writeByte(cpConstType); 683 int value = getIntAt(ci); 684 short bsmIndex = (short) extractLowShortFromInt(value); 685 short nameAndTypeIndex = (short) extractHighShortFromInt(value); 686 dos.writeShort(bsmIndex); 687 dos.writeShort(nameAndTypeIndex); 688 if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " + 689 bsmIndex + ", N&T = " + nameAndTypeIndex); 690 break; 691 } 692 693 default: 694 throw new InternalError("Unknown tag: " + cpConstType); 695 } // switch 696 } 697 dos.flush(); 698 return; 699 } 700 701 public void printValueOn(PrintStream tty) { 702 tty.print("ConstantPool for " + getPoolHolder().getName().asString()); 703 } 704 705 public long getSize() { 706 return alignSize(headerSize + getLength()); 707 } 708 709 //---------------------------------------------------------------------- 710 // Internals only below this point 711 // 712 713 private static int extractHighShortFromInt(int val) { 714 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. 715 return (val >> 16) & 0xFFFF; 716 } 717 718 private static int extractLowShortFromInt(int val) { 719 // must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc. 720 return val & 0xFFFF; 721 } 722 }