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