1 /* 2 * Copyright (c) 2011, 2015, 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 package jdk.vm.ci.hotspot; 24 25 import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; 26 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; 27 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; 28 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; 29 30 import java.lang.invoke.MethodHandle; 31 32 import jdk.vm.ci.common.JVMCIError; 33 import jdk.vm.ci.meta.ConstantPool; 34 import jdk.vm.ci.meta.JavaConstant; 35 import jdk.vm.ci.meta.JavaField; 36 import jdk.vm.ci.meta.JavaMethod; 37 import jdk.vm.ci.meta.JavaType; 38 import jdk.vm.ci.meta.ResolvedJavaMethod; 39 import jdk.vm.ci.meta.ResolvedJavaType; 40 import jdk.vm.ci.meta.Signature; 41 42 /** 43 * Implementation of {@link ConstantPool} for HotSpot. 44 */ 45 final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject { 46 47 /** 48 * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}. 49 */ 50 public static class Bytecodes { 51 public static final int LDC = 18; // 0x12 52 public static final int LDC_W = 19; // 0x13 53 public static final int LDC2_W = 20; // 0x14 54 public static final int GETSTATIC = 178; // 0xB2 55 public static final int PUTSTATIC = 179; // 0xB3 56 public static final int GETFIELD = 180; // 0xB4 57 public static final int PUTFIELD = 181; // 0xB5 58 public static final int INVOKEVIRTUAL = 182; // 0xB6 59 public static final int INVOKESPECIAL = 183; // 0xB7 60 public static final int INVOKESTATIC = 184; // 0xB8 61 public static final int INVOKEINTERFACE = 185; // 0xB9 62 public static final int INVOKEDYNAMIC = 186; // 0xBA 63 public static final int NEW = 187; // 0xBB 64 public static final int NEWARRAY = 188; // 0xBC 65 public static final int ANEWARRAY = 189; // 0xBD 66 public static final int CHECKCAST = 192; // 0xC0 67 public static final int INSTANCEOF = 193; // 0xC1 68 public static final int MULTIANEWARRAY = 197; // 0xC5 69 70 static boolean isInvoke(int opcode) { 71 switch (opcode) { 72 case INVOKEVIRTUAL: 73 case INVOKESPECIAL: 74 case INVOKESTATIC: 75 case INVOKEINTERFACE: 76 case INVOKEDYNAMIC: 77 return true; 78 default: 79 return false; 80 } 81 } 82 83 /** 84 * See: {@code Rewriter::maybe_rewrite_invokehandle}. 85 */ 86 static boolean isInvokeHandleAlias(int opcode) { 87 switch (opcode) { 88 case INVOKEVIRTUAL: 89 case INVOKESPECIAL: 90 return true; 91 default: 92 return false; 93 } 94 } 95 } 96 97 /** 98 * Enum of all {@code JVM_CONSTANT} constants used in the VM. This includes the public and 99 * internal ones. 100 */ 101 private enum JVM_CONSTANT { 102 // @formatter:off 103 Utf8(config().jvmConstantUtf8), 104 Integer(config().jvmConstantInteger), 105 Long(config().jvmConstantLong), 106 Float(config().jvmConstantFloat), 107 Double(config().jvmConstantDouble), 108 Class(config().jvmConstantClass), 109 UnresolvedClass(config().jvmConstantUnresolvedClass), 110 UnresolvedClassInError(config().jvmConstantUnresolvedClassInError), 111 String(config().jvmConstantString), 112 Fieldref(config().jvmConstantFieldref), 113 MethodRef(config().jvmConstantMethodref), 114 InterfaceMethodref(config().jvmConstantInterfaceMethodref), 115 NameAndType(config().jvmConstantNameAndType), 116 MethodHandle(config().jvmConstantMethodHandle), 117 MethodHandleInError(config().jvmConstantMethodHandleInError), 118 MethodType(config().jvmConstantMethodType), 119 MethodTypeInError(config().jvmConstantMethodTypeInError), 120 InvokeDynamic(config().jvmConstantInvokeDynamic); 121 // @formatter:on 122 123 private final int tag; 124 125 private static final int ExternalMax = config().jvmConstantExternalMax; 126 private static final int InternalMin = config().jvmConstantInternalMin; 127 private static final int InternalMax = config().jvmConstantInternalMax; 128 129 JVM_CONSTANT(int tag) { 130 this.tag = tag; 131 } 132 133 /** 134 * Maps JVM_CONSTANT tags to {@link JVM_CONSTANT} values. Using a separate class for lazy 135 * initialization. 136 */ 137 static class TagValueMap { 138 private static final JVM_CONSTANT[] table = new JVM_CONSTANT[ExternalMax + 1 + (InternalMax - InternalMin) + 1]; 139 140 static { 141 assert InternalMin > ExternalMax; 142 for (JVM_CONSTANT e : values()) { 143 table[indexOf(e.tag)] = e; 144 } 145 } 146 147 private static int indexOf(int tag) { 148 if (tag >= InternalMin) { 149 return tag - InternalMin + ExternalMax + 1; 150 } else { 151 assert tag <= ExternalMax; 152 } 153 return tag; 154 } 155 156 static JVM_CONSTANT get(int tag) { 157 JVM_CONSTANT res = table[indexOf(tag)]; 158 if (res != null) { 159 return res; 160 } 161 throw new JVMCIError("Unknown JVM_CONSTANT tag %s", tag); 162 } 163 } 164 165 public static JVM_CONSTANT getEnum(int tag) { 166 return TagValueMap.get(tag); 167 } 168 } 169 170 private static class LookupTypeCacheElement { 171 int lastCpi = Integer.MIN_VALUE; 172 JavaType javaType; 173 174 LookupTypeCacheElement(int lastCpi, JavaType javaType) { 175 super(); 176 this.lastCpi = lastCpi; 177 this.javaType = javaType; 178 } 179 } 180 181 /** 182 * Reference to the C++ ConstantPool object. 183 */ 184 private final long metaspaceConstantPool; 185 private volatile LookupTypeCacheElement lastLookupType; 186 187 /** 188 * Gets the JVMCI mirror from a HotSpot constant pool.The VM is responsible for ensuring that 189 * the ConstantPool is kept alive for the duration of this call and the 190 * {@link HotSpotJVMCIMetaAccessContext} keeps it alive after that. 191 * 192 * Called from the VM. 193 * 194 * @param metaspaceConstantPool a metaspace ConstantPool object 195 * @return the {@link HotSpotConstantPool} corresponding to {@code metaspaceConstantPool} 196 */ 197 @SuppressWarnings("unused") 198 private static HotSpotConstantPool fromMetaspace(long metaspaceConstantPool) { 199 HotSpotConstantPool cp = new HotSpotConstantPool(metaspaceConstantPool); 200 runtime().metaAccessContext.add(cp); 201 return cp; 202 } 203 204 private HotSpotConstantPool(long metaspaceConstantPool) { 205 this.metaspaceConstantPool = metaspaceConstantPool; 206 } 207 208 /** 209 * Gets the holder for this constant pool as {@link HotSpotResolvedObjectTypeImpl}. 210 * 211 * @return holder for this constant pool 212 */ 213 private HotSpotResolvedObjectType getHolder() { 214 return compilerToVM().getResolvedJavaType(this, config().constantPoolHolderOffset, false); 215 } 216 217 /** 218 * Converts a raw index from the bytecodes to a constant pool index by adding a 219 * {@link HotSpotVMConfig#constantPoolCpCacheIndexTag constant}. 220 * 221 * @param rawIndex index from the bytecode 222 * @param opcode bytecode to convert the index for 223 * @return constant pool index 224 */ 225 private static int rawIndexToConstantPoolIndex(int rawIndex, int opcode) { 226 int index; 227 if (opcode == Bytecodes.INVOKEDYNAMIC) { 228 index = rawIndex; 229 // See: ConstantPool::is_invokedynamic_index 230 assert index < 0 : "not an invokedynamic constant pool index " + index; 231 } else { 232 assert opcode == Bytecodes.GETFIELD || opcode == Bytecodes.PUTFIELD || opcode == Bytecodes.GETSTATIC || opcode == Bytecodes.PUTSTATIC || opcode == Bytecodes.INVOKEINTERFACE || 233 opcode == Bytecodes.INVOKEVIRTUAL || opcode == Bytecodes.INVOKESPECIAL || opcode == Bytecodes.INVOKESTATIC : "unexpected invoke opcode " + opcode; 234 index = rawIndex + config().constantPoolCpCacheIndexTag; 235 } 236 return index; 237 } 238 239 /** 240 * Decode a constant pool cache index to a constant pool index. 241 * 242 * See {@code ConstantPool::decode_cpcache_index}. 243 * 244 * @param index constant pool cache index 245 * @return decoded index 246 */ 247 private static int decodeConstantPoolCacheIndex(int index) { 248 if (isInvokedynamicIndex(index)) { 249 return decodeInvokedynamicIndex(index); 250 } else { 251 return index - config().constantPoolCpCacheIndexTag; 252 } 253 } 254 255 /** 256 * See {@code ConstantPool::is_invokedynamic_index}. 257 */ 258 private static boolean isInvokedynamicIndex(int index) { 259 return index < 0; 260 } 261 262 /** 263 * See {@code ConstantPool::decode_invokedynamic_index}. 264 */ 265 private static int decodeInvokedynamicIndex(int i) { 266 assert isInvokedynamicIndex(i) : i; 267 return ~i; 268 } 269 270 long getMetaspaceConstantPool() { 271 return metaspaceConstantPool; 272 } 273 274 public long getMetaspacePointer() { 275 return getMetaspaceConstantPool(); 276 } 277 278 /** 279 * Gets the constant pool tag at index {@code index}. 280 * 281 * @param index constant pool index 282 * @return constant pool tag 283 */ 284 private JVM_CONSTANT getTagAt(int index) { 285 assert checkBounds(index); 286 HotSpotVMConfig config = config(); 287 final long metaspaceConstantPoolTags = UNSAFE.getAddress(getMetaspaceConstantPool() + config.constantPoolTagsOffset); 288 final int tag = UNSAFE.getByteVolatile(null, metaspaceConstantPoolTags + config.arrayU1DataOffset + index); 289 if (tag == 0) { 290 return null; 291 } 292 return JVM_CONSTANT.getEnum(tag); 293 } 294 295 /** 296 * Gets the constant pool entry at index {@code index}. 297 * 298 * @param index constant pool index 299 * @return constant pool entry 300 */ 301 long getEntryAt(int index) { 302 assert checkBounds(index); 303 int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; 304 return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + offset); 305 } 306 307 /** 308 * Gets the integer constant pool entry at index {@code index}. 309 * 310 * @param index constant pool index 311 * @return integer constant pool entry at index 312 */ 313 private int getIntAt(int index) { 314 assert checkTag(index, JVM_CONSTANT.Integer); 315 int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; 316 return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset); 317 } 318 319 /** 320 * Gets the long constant pool entry at index {@code index}. 321 * 322 * @param index constant pool index 323 * @return long constant pool entry 324 */ 325 private long getLongAt(int index) { 326 assert checkTag(index, JVM_CONSTANT.Long); 327 int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; 328 return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + offset); 329 } 330 331 /** 332 * Gets the float constant pool entry at index {@code index}. 333 * 334 * @param index constant pool index 335 * @return float constant pool entry 336 */ 337 private float getFloatAt(int index) { 338 assert checkTag(index, JVM_CONSTANT.Float); 339 int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; 340 return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + offset); 341 } 342 343 /** 344 * Gets the double constant pool entry at index {@code index}. 345 * 346 * @param index constant pool index 347 * @return float constant pool entry 348 */ 349 private double getDoubleAt(int index) { 350 assert checkTag(index, JVM_CONSTANT.Double); 351 int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; 352 return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + offset); 353 } 354 355 /** 356 * Gets the {@code JVM_CONSTANT_NameAndType} constant pool entry at index {@code index}. 357 * 358 * @param index constant pool index 359 * @return {@code JVM_CONSTANT_NameAndType} constant pool entry 360 */ 361 private int getNameAndTypeAt(int index) { 362 assert checkTag(index, JVM_CONSTANT.NameAndType); 363 int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; 364 return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset); 365 } 366 367 /** 368 * Gets the {@code JVM_CONSTANT_NameAndType} reference index constant pool entry at index 369 * {@code index}. 370 * 371 * @param index constant pool index 372 * @return {@code JVM_CONSTANT_NameAndType} reference constant pool entry 373 */ 374 private int getNameAndTypeRefIndexAt(int index) { 375 return compilerToVM().lookupNameAndTypeRefIndexInPool(this, index); 376 } 377 378 /** 379 * Gets the name of a {@code JVM_CONSTANT_NameAndType} constant pool entry referenced by another 380 * entry denoted by {@code which}. 381 * 382 * @param which constant pool index or constant pool cache index 383 * @return name as {@link String} 384 */ 385 private String getNameOf(int which) { 386 return compilerToVM().lookupNameInPool(this, which); 387 } 388 389 /** 390 * Gets the name reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry at 391 * index {@code index}. 392 * 393 * @param index constant pool index 394 * @return name reference index 395 */ 396 private int getNameRefIndexAt(int index) { 397 final int refIndex = getNameAndTypeAt(index); 398 // name ref index is in the low 16-bits. 399 return refIndex & 0xFFFF; 400 } 401 402 /** 403 * Gets the signature of a {@code JVM_CONSTANT_NameAndType} constant pool entry referenced by 404 * another entry denoted by {@code which}. 405 * 406 * @param which constant pool index or constant pool cache index 407 * @return signature as {@link String} 408 */ 409 private String getSignatureOf(int which) { 410 return compilerToVM().lookupSignatureInPool(this, which); 411 } 412 413 /** 414 * Gets the signature reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry 415 * at index {@code index}. 416 * 417 * @param index constant pool index 418 * @return signature reference index 419 */ 420 private int getSignatureRefIndexAt(int index) { 421 final int refIndex = getNameAndTypeAt(index); 422 // signature ref index is in the high 16-bits. 423 return refIndex >>> 16; 424 } 425 426 /** 427 * Gets the klass reference index constant pool entry at index {@code index}. 428 * 429 * @param index constant pool index 430 * @return klass reference index 431 */ 432 private int getKlassRefIndexAt(int index) { 433 return compilerToVM().lookupKlassRefIndexInPool(this, index); 434 } 435 436 /** 437 * Gets the uncached klass reference index constant pool entry at index {@code index}. See: 438 * {@code ConstantPool::uncached_klass_ref_index_at}. 439 * 440 * @param index constant pool index 441 * @return klass reference index 442 */ 443 private int getUncachedKlassRefIndexAt(int index) { 444 assert checkTagIsFieldOrMethod(index); 445 int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize; 446 final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset); 447 // klass ref index is in the low 16-bits. 448 return refIndex & 0xFFFF; 449 } 450 451 /** 452 * Checks that the constant pool index {@code index} is in the bounds of the constant pool. 453 * 454 * @param index constant pool index 455 * @throws AssertionError if the check fails 456 */ 457 private boolean checkBounds(int index) { 458 assert 0 <= index && index < length() : "index " + index + " not between 0 and " + length(); 459 return true; 460 } 461 462 /** 463 * Checks that the constant pool tag at index {@code index} is equal to {@code tag}. 464 * 465 * @param index constant pool index 466 * @param tag expected tag 467 * @throws AssertionError if the check fails 468 */ 469 private boolean checkTag(int index, JVM_CONSTANT tag) { 470 final JVM_CONSTANT tagAt = getTagAt(index); 471 assert tagAt == tag : "constant pool tag at index " + index + " is " + tagAt + " but expected " + tag; 472 return true; 473 } 474 475 /** 476 * Asserts that the constant pool tag at index {@code index} is a {@link JVM_CONSTANT#Fieldref}, 477 * or a {@link JVM_CONSTANT#MethodRef}, or a {@link JVM_CONSTANT#InterfaceMethodref}. 478 * 479 * @param index constant pool index 480 * @throws AssertionError if the check fails 481 */ 482 private boolean checkTagIsFieldOrMethod(int index) { 483 final JVM_CONSTANT tagAt = getTagAt(index); 484 assert tagAt == JVM_CONSTANT.Fieldref || tagAt == JVM_CONSTANT.MethodRef || tagAt == JVM_CONSTANT.InterfaceMethodref : tagAt; 485 return true; 486 } 487 488 @Override 489 public int length() { 490 return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolLengthOffset); 491 } 492 493 @Override 494 public Object lookupConstant(int cpi) { 495 assert cpi != 0; 496 final JVM_CONSTANT tag = getTagAt(cpi); 497 switch (tag) { 498 case Integer: 499 return JavaConstant.forInt(getIntAt(cpi)); 500 case Long: 501 return JavaConstant.forLong(getLongAt(cpi)); 502 case Float: 503 return JavaConstant.forFloat(getFloatAt(cpi)); 504 case Double: 505 return JavaConstant.forDouble(getDoubleAt(cpi)); 506 case Class: 507 case UnresolvedClass: 508 case UnresolvedClassInError: 509 final int opcode = -1; // opcode is not used 510 return lookupType(cpi, opcode); 511 case String: 512 /* 513 * Normally, we would expect a String here, but anonymous classes can have 514 * "pseudo strings" (arbitrary live objects) patched into a String entry. Such 515 * entries do not have a symbol in the constant pool slot. 516 */ 517 Object string = compilerToVM().resolvePossiblyCachedConstantInPool(this, cpi); 518 return HotSpotObjectConstantImpl.forObject(string); 519 case MethodHandle: 520 case MethodHandleInError: 521 case MethodType: 522 case MethodTypeInError: 523 Object obj = compilerToVM().resolveConstantInPool(this, cpi); 524 return HotSpotObjectConstantImpl.forObject(obj); 525 default: 526 throw new JVMCIError("Unknown constant pool tag %s", tag); 527 } 528 } 529 530 @Override 531 public String lookupUtf8(int cpi) { 532 assert checkTag(cpi, JVM_CONSTANT.Utf8); 533 return compilerToVM().getSymbol(getEntryAt(cpi)); 534 } 535 536 @Override 537 public Signature lookupSignature(int cpi) { 538 return new HotSpotSignature(runtime(), lookupUtf8(cpi)); 539 } 540 541 @Override 542 public JavaConstant lookupAppendix(int cpi, int opcode) { 543 assert Bytecodes.isInvoke(opcode); 544 final int index = rawIndexToConstantPoolIndex(cpi, opcode); 545 Object appendix = compilerToVM().lookupAppendixInPool(this, index); 546 if (appendix == null) { 547 return null; 548 } else { 549 return HotSpotObjectConstantImpl.forObject(appendix); 550 } 551 } 552 553 /** 554 * Gets a {@link JavaType} corresponding a given resolved or unresolved type. 555 * 556 * @param type either a ResolvedJavaType or a String naming a unresolved type. 557 */ 558 private static JavaType getJavaType(final Object type) { 559 if (type instanceof String) { 560 String name = (String) type; 561 return HotSpotUnresolvedJavaType.create(runtime(), "L" + name + ";"); 562 } else { 563 return (JavaType) type; 564 } 565 } 566 567 @Override 568 public JavaMethod lookupMethod(int cpi, int opcode) { 569 final int index = rawIndexToConstantPoolIndex(cpi, opcode); 570 final HotSpotResolvedJavaMethod method = compilerToVM().lookupMethodInPool(this, index, (byte) opcode); 571 if (method != null) { 572 return method; 573 } else { 574 // Get the method's name and signature. 575 String name = getNameOf(index); 576 HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureOf(index)); 577 if (opcode == Bytecodes.INVOKEDYNAMIC) { 578 HotSpotResolvedObjectType holder = HotSpotResolvedObjectTypeImpl.fromObjectClass(MethodHandle.class); 579 return new HotSpotMethodUnresolved(name, signature, holder); 580 } else { 581 final int klassIndex = getKlassRefIndexAt(index); 582 final Object type = compilerToVM().lookupKlassInPool(this, klassIndex); 583 JavaType holder = getJavaType(type); 584 return new HotSpotMethodUnresolved(name, signature, holder); 585 } 586 } 587 } 588 589 @Override 590 public JavaType lookupType(int cpi, int opcode) { 591 final LookupTypeCacheElement elem = this.lastLookupType; 592 if (elem != null && elem.lastCpi == cpi) { 593 return elem.javaType; 594 } else { 595 final Object type = compilerToVM().lookupKlassInPool(this, cpi); 596 JavaType result = getJavaType(type); 597 if (result instanceof ResolvedJavaType) { 598 this.lastLookupType = new LookupTypeCacheElement(cpi, result); 599 } 600 return result; 601 } 602 } 603 604 @Override 605 public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) { 606 final int index = rawIndexToConstantPoolIndex(cpi, opcode); 607 final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index); 608 final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex); 609 String typeName = lookupUtf8(typeIndex); 610 JavaType type = runtime().lookupType(typeName, getHolder(), false); 611 612 final int holderIndex = getKlassRefIndexAt(index); 613 JavaType holder = lookupType(holderIndex, opcode); 614 615 if (holder instanceof HotSpotResolvedObjectTypeImpl) { 616 int[] info = new int[3]; 617 HotSpotResolvedObjectTypeImpl resolvedHolder; 618 try { 619 resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info); 620 } catch (Throwable t) { 621 /* 622 * If there was an exception resolving the field we give up and return an unresolved 623 * field. 624 */ 625 return new HotSpotUnresolvedField(holder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type); 626 } 627 final int flags = info[0]; 628 final int offset = info[1]; 629 final int fieldIndex = info[2]; 630 HotSpotResolvedJavaField result = resolvedHolder.createField(type, offset, flags, fieldIndex); 631 return result; 632 } else { 633 return new HotSpotUnresolvedField(holder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type); 634 } 635 } 636 637 @Override 638 @SuppressWarnings("fallthrough") 639 public void loadReferencedType(int cpi, int opcode) { 640 int index; 641 switch (opcode) { 642 case Bytecodes.CHECKCAST: 643 case Bytecodes.INSTANCEOF: 644 case Bytecodes.NEW: 645 case Bytecodes.ANEWARRAY: 646 case Bytecodes.MULTIANEWARRAY: 647 case Bytecodes.LDC: 648 case Bytecodes.LDC_W: 649 case Bytecodes.LDC2_W: 650 index = cpi; 651 break; 652 case Bytecodes.INVOKEDYNAMIC: { 653 // invokedynamic instructions point to a constant pool cache entry. 654 index = decodeConstantPoolCacheIndex(cpi) + config().constantPoolCpCacheIndexTag; 655 index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index); 656 break; 657 } 658 case Bytecodes.GETSTATIC: 659 case Bytecodes.PUTSTATIC: 660 case Bytecodes.GETFIELD: 661 case Bytecodes.PUTFIELD: 662 case Bytecodes.INVOKEVIRTUAL: 663 case Bytecodes.INVOKESPECIAL: 664 case Bytecodes.INVOKESTATIC: 665 case Bytecodes.INVOKEINTERFACE: { 666 // invoke and field instructions point to a constant pool cache entry. 667 index = rawIndexToConstantPoolIndex(cpi, opcode); 668 index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index); 669 break; 670 } 671 default: 672 throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode); 673 } 674 675 final JVM_CONSTANT tag = getTagAt(index); 676 if (tag == null) { 677 assert getTagAt(index - 1) == JVM_CONSTANT.Double || getTagAt(index - 1) == JVM_CONSTANT.Long; 678 return; 679 } 680 switch (tag) { 681 case MethodRef: 682 case Fieldref: 683 case InterfaceMethodref: 684 index = getUncachedKlassRefIndexAt(index); 685 // Read the tag only once because it could change between multiple reads. 686 final JVM_CONSTANT klassTag = getTagAt(index); 687 assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag; 688 // fall through 689 case Class: 690 case UnresolvedClass: 691 case UnresolvedClassInError: 692 final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, index); 693 Class<?> klass = type.mirror(); 694 if (!klass.isPrimitive() && !klass.isArray()) { 695 UNSAFE.ensureClassInitialized(klass); 696 } 697 if (tag == JVM_CONSTANT.MethodRef) { 698 if (Bytecodes.isInvokeHandleAlias(opcode) && isSignaturePolymorphicHolder(type)) { 699 final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode); 700 assert checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef); 701 compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex); 702 } 703 } 704 705 break; 706 case InvokeDynamic: 707 if (isInvokedynamicIndex(cpi)) { 708 compilerToVM().resolveInvokeDynamicInPool(this, cpi); 709 } 710 break; 711 default: 712 // nothing 713 break; 714 } 715 716 } 717 718 // Lazily initialized. 719 private static String[] signaturePolymorphicHolders; 720 721 /** 722 * Determines if {@code type} contains signature polymorphic methods. 723 */ 724 static boolean isSignaturePolymorphicHolder(final ResolvedJavaType type) { 725 String name = type.getName(); 726 if (signaturePolymorphicHolders == null) { 727 signaturePolymorphicHolders = compilerToVM().getSignaturePolymorphicHolders(); 728 } 729 for (String holder : signaturePolymorphicHolders) { 730 if (name.equals(holder)) { 731 return true; 732 } 733 } 734 return false; 735 } 736 737 @Override 738 public String toString() { 739 HotSpotResolvedObjectType holder = getHolder(); 740 return "HotSpotConstantPool<" + holder.toJavaName() + ">"; 741 } 742 }