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