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         assertBounds(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     private long getEntryAt(int index) {
 302         assertBounds(index);
 303         return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
 304     }
 305 
 306     /**
 307      * Gets the integer constant pool entry at index {@code index}.
 308      *
 309      * @param index constant pool index
 310      * @return integer constant pool entry at index
 311      */
 312     private int getIntAt(int index) {
 313         assertTag(index, JVM_CONSTANT.Integer);
 314         return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
 315     }
 316 
 317     /**
 318      * Gets the long constant pool entry at index {@code index}.
 319      *
 320      * @param index constant pool index
 321      * @return long constant pool entry
 322      */
 323     private long getLongAt(int index) {
 324         assertTag(index, JVM_CONSTANT.Long);
 325         return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
 326     }
 327 
 328     /**
 329      * Gets the float constant pool entry at index {@code index}.
 330      *
 331      * @param index constant pool index
 332      * @return float constant pool entry
 333      */
 334     private float getFloatAt(int index) {
 335         assertTag(index, JVM_CONSTANT.Float);
 336         return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
 337     }
 338 
 339     /**
 340      * Gets the double constant pool entry at index {@code index}.
 341      *
 342      * @param index constant pool index
 343      * @return float constant pool entry
 344      */
 345     private double getDoubleAt(int index) {
 346         assertTag(index, JVM_CONSTANT.Double);
 347         return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
 348     }
 349 
 350     /**
 351      * Gets the {@code JVM_CONSTANT_NameAndType} constant pool entry at index {@code index}.
 352      *
 353      * @param index constant pool index
 354      * @return {@code JVM_CONSTANT_NameAndType} constant pool entry
 355      */
 356     private int getNameAndTypeAt(int index) {
 357         assertTag(index, JVM_CONSTANT.NameAndType);
 358         return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
 359     }
 360 
 361     /**
 362      * Gets the {@code JVM_CONSTANT_NameAndType} reference index constant pool entry at index
 363      * {@code index}.
 364      *
 365      * @param index constant pool index
 366      * @return {@code JVM_CONSTANT_NameAndType} reference constant pool entry
 367      */
 368     private int getNameAndTypeRefIndexAt(int index) {
 369         return compilerToVM().lookupNameAndTypeRefIndexInPool(this, index);
 370     }
 371 
 372     /**
 373      * Gets the name of a {@code JVM_CONSTANT_NameAndType} constant pool entry referenced by another
 374      * entry denoted by {@code which}.
 375      *
 376      * @param which constant pool index or constant pool cache index
 377      * @return name as {@link String}
 378      */
 379     private String getNameOf(int which) {
 380         return compilerToVM().lookupNameInPool(this, which);
 381     }
 382 
 383     /**
 384      * Gets the name reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry at
 385      * index {@code index}.
 386      *
 387      * @param index constant pool index
 388      * @return name reference index
 389      */
 390     private int getNameRefIndexAt(int index) {
 391         final int refIndex = getNameAndTypeAt(index);
 392         // name ref index is in the low 16-bits.
 393         return refIndex & 0xFFFF;
 394     }
 395 
 396     /**
 397      * Gets the signature of a {@code JVM_CONSTANT_NameAndType} constant pool entry referenced by
 398      * another entry denoted by {@code which}.
 399      *
 400      * @param which constant pool index or constant pool cache index
 401      * @return signature as {@link String}
 402      */
 403     private String getSignatureOf(int which) {
 404         return compilerToVM().lookupSignatureInPool(this, which);
 405     }
 406 
 407     /**
 408      * Gets the signature reference index of a {@code JVM_CONSTANT_NameAndType} constant pool entry
 409      * at index {@code index}.
 410      *
 411      * @param index constant pool index
 412      * @return signature reference index
 413      */
 414     private int getSignatureRefIndexAt(int index) {
 415         final int refIndex = getNameAndTypeAt(index);
 416         // signature ref index is in the high 16-bits.
 417         return refIndex >>> 16;
 418     }
 419 
 420     /**
 421      * Gets the klass reference index constant pool entry at index {@code index}.
 422      *
 423      * @param index constant pool index
 424      * @return klass reference index
 425      */
 426     private int getKlassRefIndexAt(int index) {
 427         return compilerToVM().lookupKlassRefIndexInPool(this, index);
 428     }
 429 
 430     /**
 431      * Gets the uncached klass reference index constant pool entry at index {@code index}. See:
 432      * {@code ConstantPool::uncached_klass_ref_index_at}.
 433      *
 434      * @param index constant pool index
 435      * @return klass reference index
 436      */
 437     private int getUncachedKlassRefIndexAt(int index) {
 438         assertTagIsFieldOrMethod(index);
 439         final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
 440         // klass ref index is in the low 16-bits.
 441         return refIndex & 0xFFFF;
 442     }
 443 
 444     /**
 445      * Asserts that the constant pool index {@code index} is in the bounds of the constant pool.
 446      *
 447      * @param index constant pool index
 448      */
 449     private void assertBounds(int index) {
 450         assert 0 <= index && index < length() : "index " + index + " not between 0 and " + length();
 451     }
 452 
 453     /**
 454      * Asserts that the constant pool tag at index {@code index} is equal to {@code tag}.
 455      *
 456      * @param index constant pool index
 457      * @param tag expected tag
 458      */
 459     private void assertTag(int index, JVM_CONSTANT tag) {
 460         final JVM_CONSTANT tagAt = getTagAt(index);
 461         assert tagAt == tag : "constant pool tag at index " + index + " is " + tagAt + " but expected " + tag;
 462     }
 463 
 464     /**
 465      * Asserts that the constant pool tag at index {@code index} is a {@link JVM_CONSTANT#Fieldref},
 466      * or a {@link JVM_CONSTANT#MethodRef}, or a {@link JVM_CONSTANT#InterfaceMethodref}.
 467      *
 468      * @param index constant pool index
 469      */
 470     private void assertTagIsFieldOrMethod(int index) {
 471         final JVM_CONSTANT tagAt = getTagAt(index);
 472         assert tagAt == JVM_CONSTANT.Fieldref || tagAt == JVM_CONSTANT.MethodRef || tagAt == JVM_CONSTANT.InterfaceMethodref : tagAt;
 473     }
 474 
 475     @Override
 476     public int length() {
 477         return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolLengthOffset);
 478     }
 479 
 480     @Override
 481     public Object lookupConstant(int cpi) {
 482         assert cpi != 0;
 483         final JVM_CONSTANT tag = getTagAt(cpi);
 484         switch (tag) {
 485             case Integer:
 486                 return JavaConstant.forInt(getIntAt(cpi));
 487             case Long:
 488                 return JavaConstant.forLong(getLongAt(cpi));
 489             case Float:
 490                 return JavaConstant.forFloat(getFloatAt(cpi));
 491             case Double:
 492                 return JavaConstant.forDouble(getDoubleAt(cpi));
 493             case Class:
 494             case UnresolvedClass:
 495             case UnresolvedClassInError:
 496                 final int opcode = -1;  // opcode is not used
 497                 return lookupType(cpi, opcode);
 498             case String:
 499                 /*
 500                  * Normally, we would expect a String here, but anonymous classes can have
 501                  * "pseudo strings" (arbitrary live objects) patched into a String entry. Such
 502                  * entries do not have a symbol in the constant pool slot.
 503                  */
 504                 Object string = compilerToVM().resolvePossiblyCachedConstantInPool(this, cpi);
 505                 return HotSpotObjectConstantImpl.forObject(string);
 506             case MethodHandle:
 507             case MethodHandleInError:
 508             case MethodType:
 509             case MethodTypeInError:
 510                 Object obj = compilerToVM().resolveConstantInPool(this, cpi);
 511                 return HotSpotObjectConstantImpl.forObject(obj);
 512             default:
 513                 throw new JVMCIError("Unknown constant pool tag %s", tag);
 514         }
 515     }
 516 
 517     @Override
 518     public String lookupUtf8(int cpi) {
 519         assertTag(cpi, JVM_CONSTANT.Utf8);
 520         return compilerToVM().getSymbol(getEntryAt(cpi));
 521     }
 522 
 523     @Override
 524     public Signature lookupSignature(int cpi) {
 525         return new HotSpotSignature(runtime(), lookupUtf8(cpi));
 526     }
 527 
 528     @Override
 529     public JavaConstant lookupAppendix(int cpi, int opcode) {
 530         assert Bytecodes.isInvoke(opcode);
 531         final int index = rawIndexToConstantPoolIndex(cpi, opcode);
 532         Object appendix = compilerToVM().lookupAppendixInPool(this, index);
 533         if (appendix == null) {
 534             return null;
 535         } else {
 536             return HotSpotObjectConstantImpl.forObject(appendix);
 537         }
 538     }
 539 
 540     /**
 541      * Gets a {@link JavaType} corresponding a given resolved or unresolved type.
 542      *
 543      * @param type either a ResolvedJavaType or a String naming a unresolved type.
 544      */
 545     private static JavaType getJavaType(final Object type) {
 546         if (type instanceof String) {
 547             String name = (String) type;
 548             return HotSpotUnresolvedJavaType.create(runtime(), "L" + name + ";");
 549         } else {
 550             return (JavaType) type;
 551         }
 552     }
 553 
 554     @Override
 555     public JavaMethod lookupMethod(int cpi, int opcode) {
 556         final int index = rawIndexToConstantPoolIndex(cpi, opcode);
 557         final HotSpotResolvedJavaMethod method = compilerToVM().lookupMethodInPool(this, index, (byte) opcode);
 558         if (method != null) {
 559             return method;
 560         } else {
 561             // Get the method's name and signature.
 562             String name = getNameOf(index);
 563             HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureOf(index));
 564             if (opcode == Bytecodes.INVOKEDYNAMIC) {
 565                 HotSpotResolvedObjectType holder = HotSpotResolvedObjectTypeImpl.fromObjectClass(MethodHandle.class);
 566                 return new HotSpotMethodUnresolved(name, signature, holder);
 567             } else {
 568                 final int klassIndex = getKlassRefIndexAt(index);
 569                 final Object type = compilerToVM().lookupKlassInPool(this, klassIndex);
 570                 JavaType holder = getJavaType(type);
 571                 return new HotSpotMethodUnresolved(name, signature, holder);
 572             }
 573         }
 574     }
 575 
 576     @Override
 577     public JavaType lookupType(int cpi, int opcode) {
 578         final LookupTypeCacheElement elem = this.lastLookupType;
 579         if (elem != null && elem.lastCpi == cpi) {
 580             return elem.javaType;
 581         } else {
 582             final Object type = compilerToVM().lookupKlassInPool(this, cpi);
 583             JavaType result = getJavaType(type);
 584             if (result instanceof ResolvedJavaType) {
 585                 this.lastLookupType = new LookupTypeCacheElement(cpi, result);
 586             }
 587             return result;
 588         }
 589     }
 590 
 591     @Override
 592     public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
 593         final int index = rawIndexToConstantPoolIndex(cpi, opcode);
 594         final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
 595         final int nameIndex = getNameRefIndexAt(nameAndTypeIndex);
 596         String name = lookupUtf8(nameIndex);
 597         final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
 598         String typeName = lookupUtf8(typeIndex);
 599         JavaType type = runtime().lookupType(typeName, getHolder(), false);
 600 
 601         final int holderIndex = getKlassRefIndexAt(index);
 602         JavaType holder = lookupType(holderIndex, opcode);
 603 
 604         if (holder instanceof HotSpotResolvedObjectTypeImpl) {
 605             long[] info = new long[2];
 606             HotSpotResolvedObjectTypeImpl resolvedHolder;
 607             try {
 608                 resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
 609             } catch (Throwable t) {
 610                 /*
 611                  * If there was an exception resolving the field we give up and return an unresolved
 612                  * field.
 613                  */
 614                 return new HotSpotUnresolvedField(holder, name, type);
 615             }
 616             final int flags = (int) info[0];
 617             final long offset = info[1];
 618             HotSpotResolvedJavaField result = resolvedHolder.createField(name, type, offset, flags);
 619             return result;
 620         } else {
 621             return new HotSpotUnresolvedField(holder, name, type);
 622         }
 623     }
 624 
 625     @Override
 626     @SuppressWarnings("fallthrough")
 627     public void loadReferencedType(int cpi, int opcode) {
 628         int index;
 629         switch (opcode) {
 630             case Bytecodes.CHECKCAST:
 631             case Bytecodes.INSTANCEOF:
 632             case Bytecodes.NEW:
 633             case Bytecodes.ANEWARRAY:
 634             case Bytecodes.MULTIANEWARRAY:
 635             case Bytecodes.LDC:
 636             case Bytecodes.LDC_W:
 637             case Bytecodes.LDC2_W:
 638                 index = cpi;
 639                 break;
 640             case Bytecodes.INVOKEDYNAMIC: {
 641                 // invokedynamic instructions point to a constant pool cache entry.
 642                 index = decodeConstantPoolCacheIndex(cpi) + config().constantPoolCpCacheIndexTag;
 643                 index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
 644                 break;
 645             }
 646             case Bytecodes.GETSTATIC:
 647             case Bytecodes.PUTSTATIC:
 648             case Bytecodes.GETFIELD:
 649             case Bytecodes.PUTFIELD:
 650             case Bytecodes.INVOKEVIRTUAL:
 651             case Bytecodes.INVOKESPECIAL:
 652             case Bytecodes.INVOKESTATIC:
 653             case Bytecodes.INVOKEINTERFACE: {
 654                 // invoke and field instructions point to a constant pool cache entry.
 655                 index = rawIndexToConstantPoolIndex(cpi, opcode);
 656                 index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
 657                 break;
 658             }
 659             default:
 660                 throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
 661         }
 662 
 663         final JVM_CONSTANT tag = getTagAt(index);
 664         if (tag == null) {
 665             assert getTagAt(index - 1) == JVM_CONSTANT.Double || getTagAt(index - 1) == JVM_CONSTANT.Long;
 666             return;
 667         }
 668         switch (tag) {
 669             case MethodRef:
 670             case Fieldref:
 671             case InterfaceMethodref:
 672                 index = getUncachedKlassRefIndexAt(index);
 673                 // Read the tag only once because it could change between multiple reads.
 674                 final JVM_CONSTANT klassTag = getTagAt(index);
 675                 assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag;
 676                 // fall through
 677             case Class:
 678             case UnresolvedClass:
 679             case UnresolvedClassInError:
 680                 final HotSpotResolvedObjectTypeImpl type = compilerToVM().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                                 compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
 691                             }
 692                         }
 693                 }
 694                 break;
 695             case InvokeDynamic:
 696                 if (isInvokedynamicIndex(cpi)) {
 697                     compilerToVM().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(compilerToVM().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 }