1 /*
   2  * Copyright (c) 2012, 2019, 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 org.graalvm.compiler.hotspot.replacements;
  26 
  27 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
  28 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
  29 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.VERIFY_OOP;
  30 
  31 import java.lang.ref.Reference;
  32 
  33 import org.graalvm.compiler.api.replacements.Fold;
  34 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
  35 import org.graalvm.compiler.core.common.SuppressFBWarnings;
  36 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
  37 import org.graalvm.compiler.core.common.type.ObjectStamp;
  38 import org.graalvm.compiler.core.common.type.TypeReference;
  39 import org.graalvm.compiler.debug.GraalError;
  40 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
  41 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
  42 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
  43 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  44 import org.graalvm.compiler.hotspot.word.KlassPointer;
  45 import org.graalvm.compiler.nodes.CanonicalizableLocation;
  46 import org.graalvm.compiler.nodes.CompressionNode;
  47 import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
  48 import org.graalvm.compiler.nodes.ConstantNode;
  49 import org.graalvm.compiler.nodes.NamedLocationIdentity;
  50 import org.graalvm.compiler.nodes.NodeView;
  51 import org.graalvm.compiler.nodes.ValueNode;
  52 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
  53 import org.graalvm.compiler.nodes.extended.LoadHubNode;
  54 import org.graalvm.compiler.nodes.extended.LoadHubOrNullNode;
  55 import org.graalvm.compiler.nodes.extended.RawLoadNode;
  56 import org.graalvm.compiler.nodes.extended.StoreHubNode;
  57 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
  58 import org.graalvm.compiler.nodes.memory.Access;
  59 import org.graalvm.compiler.nodes.memory.address.AddressNode;
  60 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
  61 import org.graalvm.compiler.nodes.type.StampTool;
  62 import org.graalvm.compiler.replacements.ReplacementsUtil;
  63 import org.graalvm.compiler.replacements.nodes.ReadRegisterNode;
  64 import org.graalvm.compiler.replacements.nodes.WriteRegisterNode;
  65 import org.graalvm.compiler.word.Word;
  66 import jdk.internal.vm.compiler.word.LocationIdentity;
  67 import jdk.internal.vm.compiler.word.WordFactory;
  68 
  69 import jdk.vm.ci.code.Register;
  70 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
  71 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
  72 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
  73 import jdk.vm.ci.meta.Assumptions;
  74 import jdk.vm.ci.meta.Assumptions.AssumptionResult;
  75 import jdk.vm.ci.meta.JavaKind;
  76 import jdk.vm.ci.meta.MetaAccessProvider;
  77 import jdk.vm.ci.meta.ResolvedJavaField;
  78 import jdk.vm.ci.meta.ResolvedJavaType;
  79 import jdk.vm.ci.meta.UnresolvedJavaType;
  80 
  81 //JaCoCo Exclude
  82 
  83 /**
  84  * A collection of methods used in HotSpot snippets, substitutions and stubs.
  85  */
  86 public class HotSpotReplacementsUtil {
  87 
  88     abstract static class HotSpotOptimizingLocationIdentity extends NamedLocationIdentity implements CanonicalizableLocation {
  89 
  90         HotSpotOptimizingLocationIdentity(String name) {
  91             super(name, true);
  92         }
  93 
  94         @Override
  95         public abstract ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool);
  96 
  97         protected ValueNode findReadHub(ValueNode object) {
  98             ValueNode base = object;
  99             if (base instanceof CompressionNode) {
 100                 base = ((CompressionNode) base).getValue();
 101             }
 102             if (base instanceof Access) {
 103                 Access access = (Access) base;
 104                 if (access.getLocationIdentity().equals(HUB_LOCATION) || access.getLocationIdentity().equals(COMPRESSED_HUB_LOCATION)) {
 105                     AddressNode address = access.getAddress();
 106                     if (address instanceof OffsetAddressNode) {
 107                         OffsetAddressNode offset = (OffsetAddressNode) address;
 108                         return offset.getBase();
 109                     }
 110                 }
 111             } else if (base instanceof LoadHubNode) {
 112                 LoadHubNode loadhub = (LoadHubNode) base;
 113                 return loadhub.getValue();
 114             }
 115             return null;
 116         }
 117 
 118         /**
 119          * Fold reads that convert from Class -> Hub -> Class or vice versa.
 120          *
 121          * @param read
 122          * @param object
 123          * @param otherLocation
 124          * @return an earlier read or the original {@code read}
 125          */
 126         protected static ValueNode foldIndirection(ValueNode read, ValueNode object, LocationIdentity otherLocation) {
 127             if (object instanceof Access) {
 128                 Access access = (Access) object;
 129                 if (access.getLocationIdentity().equals(otherLocation)) {
 130                     AddressNode address = access.getAddress();
 131                     if (address instanceof OffsetAddressNode) {
 132                         OffsetAddressNode offset = (OffsetAddressNode) address;
 133                         assert offset.getBase().stamp(NodeView.DEFAULT).isCompatible(read.stamp(NodeView.DEFAULT));
 134                         return offset.getBase();
 135                     }
 136                 }
 137             }
 138             return read;
 139         }
 140     }
 141 
 142     @Fold
 143     public static ResolvedJavaType methodHolderClass(@InjectedParameter IntrinsicContext context) {
 144         return context.getOriginalMethod().getDeclaringClass();
 145     }
 146 
 147     @Fold
 148     static ResolvedJavaType getType(@Fold.InjectedParameter IntrinsicContext context, String typeName) {
 149         try {
 150             UnresolvedJavaType unresolved = UnresolvedJavaType.create(typeName);
 151             return unresolved.resolve(methodHolderClass(context));
 152         } catch (LinkageError e) {
 153             throw new GraalError(e);
 154         }
 155     }
 156 
 157     @Fold
 158     static int getFieldOffset(ResolvedJavaType type, String fieldName) {
 159         for (ResolvedJavaField field : type.getInstanceFields(true)) {
 160             if (field.getName().equals(fieldName)) {
 161                 return field.getOffset();
 162             }
 163         }
 164         throw new GraalError("missing field " + fieldName + " in type " + type);
 165     }
 166 
 167     public static HotSpotJVMCIRuntime runtime() {
 168         return HotSpotJVMCIRuntime.runtime();
 169     }
 170 
 171     @Fold
 172     public static int getHeapWordSize(@InjectedParameter GraalHotSpotVMConfig injectedVMConfig) {
 173         return injectedVMConfig.heapWordSize;
 174     }
 175 
 176     @Fold
 177     public static int klassLayoutHelperNeutralValue(@InjectedParameter GraalHotSpotVMConfig config) {
 178         return config.klassLayoutHelperNeutralValue;
 179     }
 180 
 181     @Fold
 182     public static boolean useTLAB(@InjectedParameter GraalHotSpotVMConfig config) {
 183         return config.useTLAB;
 184     }
 185 
 186     @Fold
 187     public static boolean verifyOops(@InjectedParameter GraalHotSpotVMConfig config) {
 188         return config.verifyOops;
 189     }
 190 
 191     /**
 192      * @see GraalHotSpotVMConfig#doingUnsafeAccessOffset
 193      */
 194     @Fold
 195     public static int doingUnsafeAccessOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 196         return config.doingUnsafeAccessOffset;
 197     }
 198 
 199     public static final LocationIdentity EXCEPTION_OOP_LOCATION = NamedLocationIdentity.mutable("ExceptionOop");
 200 
 201     /**
 202      * @see GraalHotSpotVMConfig#threadExceptionOopOffset
 203      */
 204     @Fold
 205     public static int threadExceptionOopOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 206         return config.threadExceptionOopOffset;
 207     }
 208 
 209     public static final LocationIdentity EXCEPTION_PC_LOCATION = NamedLocationIdentity.mutable("ExceptionPc");
 210 
 211     @Fold
 212     public static int threadExceptionPcOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 213         return config.threadExceptionPcOffset;
 214     }
 215 
 216     public static final LocationIdentity TLAB_TOP_LOCATION = NamedLocationIdentity.mutable("TlabTop");
 217 
 218     @Fold
 219     public static int threadTlabTopOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 220         return config.threadTlabTopOffset();
 221     }
 222 
 223     public static final LocationIdentity TLAB_END_LOCATION = NamedLocationIdentity.mutable("TlabEnd");
 224 
 225     @Fold
 226     static int threadTlabEndOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 227         return config.threadTlabEndOffset();
 228     }
 229 
 230     public static final LocationIdentity PENDING_EXCEPTION_LOCATION = NamedLocationIdentity.mutable("PendingException");
 231 
 232     /**
 233      * @see GraalHotSpotVMConfig#pendingExceptionOffset
 234      */
 235     @Fold
 236     static int threadPendingExceptionOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 237         return config.pendingExceptionOffset;
 238     }
 239 
 240     /**
 241      * @see GraalHotSpotVMConfig#threadExceptionOopOffset
 242      */
 243     public static Object readExceptionOop(Word thread) {
 244         return thread.readObject(threadExceptionOopOffset(INJECTED_VMCONFIG), EXCEPTION_OOP_LOCATION);
 245     }
 246 
 247     public static Word readExceptionPc(Word thread) {
 248         return thread.readWord(threadExceptionPcOffset(INJECTED_VMCONFIG), EXCEPTION_PC_LOCATION);
 249     }
 250 
 251     /**
 252      * @see GraalHotSpotVMConfig#threadExceptionOopOffset
 253      */
 254     public static void writeExceptionOop(Word thread, Object value) {
 255         thread.writeObject(threadExceptionOopOffset(INJECTED_VMCONFIG), value, EXCEPTION_OOP_LOCATION);
 256     }
 257 
 258     public static void writeExceptionPc(Word thread, Word value) {
 259         thread.writeWord(threadExceptionPcOffset(INJECTED_VMCONFIG), value, EXCEPTION_PC_LOCATION);
 260     }
 261 
 262     public static Word readTlabTop(Word thread) {
 263         return thread.readWord(threadTlabTopOffset(INJECTED_VMCONFIG), TLAB_TOP_LOCATION);
 264     }
 265 
 266     public static Word readTlabEnd(Word thread) {
 267         return thread.readWord(threadTlabEndOffset(INJECTED_VMCONFIG), TLAB_END_LOCATION);
 268     }
 269 
 270     public static void writeTlabTop(Word thread, Word top) {
 271         thread.writeWord(threadTlabTopOffset(INJECTED_VMCONFIG), top, TLAB_TOP_LOCATION);
 272     }
 273 
 274     /**
 275      * Clears the pending exception for the given thread.
 276      *
 277      * @return the pending exception, or null if there was none
 278      */
 279     @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected")
 280     public static Object clearPendingException(Word thread) {
 281         Object result = thread.readObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), PENDING_EXCEPTION_LOCATION);
 282         thread.writeObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), null, PENDING_EXCEPTION_LOCATION);
 283         return result;
 284     }
 285 
 286     /**
 287      * Gets the pending exception for the given thread.
 288      *
 289      * @return the pending exception, or null if there was none
 290      */
 291     @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected")
 292     public static Object getPendingException(Word thread) {
 293         return thread.readObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), PENDING_EXCEPTION_LOCATION);
 294     }
 295 
 296     /*
 297      * As far as Java code is concerned this can be considered immutable: it is set just after the
 298      * JavaThread is created, before it is published. After that, it is never changed.
 299      */
 300     public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.immutable("JavaThread::_threadObj");
 301 
 302     @Fold
 303     public static int threadObjectOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 304         return config.threadObjectOffset;
 305     }
 306 
 307     @Fold
 308     public static JavaKind getWordKind() {
 309         return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind;
 310     }
 311 
 312     @Fold
 313     public static int wordSize() {
 314         return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordSize;
 315     }
 316 
 317     @Fold
 318     public static int pageSize(@InjectedParameter GraalHotSpotVMConfig config) {
 319         return config.vmPageSize;
 320     }
 321 
 322     public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("PrototypeMarkWord");
 323 
 324     @Fold
 325     public static int prototypeMarkWordOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 326         return config.prototypeMarkWordOffset;
 327     }
 328 
 329     public static final LocationIdentity KLASS_ACCESS_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_access_flags");
 330 
 331     @Fold
 332     public static int klassAccessFlagsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 333         return config.klassAccessFlagsOffset;
 334     }
 335 
 336     @Fold
 337     public static int jvmAccWrittenFlags(@InjectedParameter GraalHotSpotVMConfig config) {
 338         return config.jvmAccWrittenFlags;
 339     }
 340 
 341     public static final LocationIdentity KLASS_LAYOUT_HELPER_LOCATION = new HotSpotOptimizingLocationIdentity("Klass::_layout_helper") {
 342         @Override
 343         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 344             ValueNode javaObject = findReadHub(object);
 345             if (javaObject != null) {
 346                 if (javaObject.stamp(NodeView.DEFAULT) instanceof ObjectStamp) {
 347                     ObjectStamp stamp = (ObjectStamp) javaObject.stamp(NodeView.DEFAULT);
 348                     HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) stamp.javaType(tool.getMetaAccess());
 349                     if (type.isArray() && !type.getComponentType().isPrimitive()) {
 350                         int layout = type.layoutHelper();
 351                         return ConstantNode.forInt(layout);
 352                     }
 353                 }
 354             }
 355             return read;
 356         }
 357     };
 358 
 359     @Fold
 360     public static int allocatePrefetchStyle(@InjectedParameter GraalHotSpotVMConfig config) {
 361         return config.allocatePrefetchStyle;
 362     }
 363 
 364     @Fold
 365     public static int allocatePrefetchLines(@InjectedParameter GraalHotSpotVMConfig config) {
 366         return config.allocatePrefetchLines;
 367     }
 368 
 369     @Fold
 370     public static int allocatePrefetchDistance(@InjectedParameter GraalHotSpotVMConfig config) {
 371         return config.allocatePrefetchDistance;
 372     }
 373 
 374     @Fold
 375     public static int allocateInstancePrefetchLines(@InjectedParameter GraalHotSpotVMConfig config) {
 376         return config.allocateInstancePrefetchLines;
 377     }
 378 
 379     @Fold
 380     public static int allocatePrefetchStepSize(@InjectedParameter GraalHotSpotVMConfig config) {
 381         return config.allocatePrefetchStepSize;
 382     }
 383 
 384     @Fold
 385     public static int invocationCounterIncrement(@InjectedParameter GraalHotSpotVMConfig config) {
 386         return config.invocationCounterIncrement;
 387     }
 388 
 389     @Fold
 390     public static int invocationCounterOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 391         return config.invocationCounterOffset;
 392     }
 393 
 394     @Fold
 395     public static int backedgeCounterOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 396         return config.backedgeCounterOffset;
 397     }
 398 
 399     @Fold
 400     public static int invocationCounterShift(@InjectedParameter GraalHotSpotVMConfig config) {
 401         return config.invocationCounterShift;
 402     }
 403 
 404     @Fold
 405     public static int stackBias(@InjectedParameter GraalHotSpotVMConfig config) {
 406         return config.stackBias;
 407     }
 408 
 409     @NodeIntrinsic(value = KlassLayoutHelperNode.class)
 410     public static native int readLayoutHelper(KlassPointer object);
 411 
 412     /**
 413      * Checks if class {@code klass} is an array.
 414      *
 415      * See: Klass::layout_helper_is_array
 416      *
 417      * @param klassNonNull the class to be checked
 418      * @return true if klassNonNull is an array, false otherwise
 419      */
 420     public static boolean klassIsArray(KlassPointer klassNonNull) {
 421         /*
 422          * The less-than check only works if both values are ints. We use local variables to make
 423          * sure these are still ints and haven't changed.
 424          */
 425         final int layoutHelper = readLayoutHelper(klassNonNull);
 426         final int layoutHelperNeutralValue = klassLayoutHelperNeutralValue(INJECTED_VMCONFIG);
 427         return (layoutHelper < layoutHelperNeutralValue);
 428     }
 429 
 430     public static final LocationIdentity ARRAY_KLASS_COMPONENT_MIRROR = NamedLocationIdentity.immutable("ArrayKlass::_component_mirror");
 431 
 432     @Fold
 433     public static int arrayKlassComponentMirrorOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 434         return config.getFieldOffset("ArrayKlass::_component_mirror", Integer.class, "oop");
 435     }
 436 
 437     public static final LocationIdentity KLASS_SUPER_KLASS_LOCATION = NamedLocationIdentity.immutable("Klass::_super");
 438 
 439     @Fold
 440     public static int klassSuperKlassOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 441         return config.klassSuperKlassOffset;
 442     }
 443 
 444     public static final LocationIdentity MARK_WORD_LOCATION = NamedLocationIdentity.mutable("MarkWord");
 445 
 446     @Fold
 447     public static int markOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 448         return config.markOffset;
 449     }
 450 
 451     public static final LocationIdentity HUB_WRITE_LOCATION = NamedLocationIdentity.mutable("Hub:write");
 452 
 453     public static final LocationIdentity HUB_LOCATION = new HotSpotOptimizingLocationIdentity("Hub") {
 454         @Override
 455         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 456             TypeReference constantType = StampTool.typeReferenceOrNull(object);
 457             if (constantType != null && constantType.isExact()) {
 458                 return ConstantNode.forConstant(read.stamp(NodeView.DEFAULT), tool.getConstantReflection().asObjectHub(constantType.getType()), tool.getMetaAccess());
 459             }
 460             return read;
 461         }
 462     };
 463 
 464     public static final LocationIdentity COMPRESSED_HUB_LOCATION = new HotSpotOptimizingLocationIdentity("CompressedHub") {
 465         @Override
 466         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 467             TypeReference constantType = StampTool.typeReferenceOrNull(object);
 468             if (constantType != null && constantType.isExact()) {
 469                 return ConstantNode.forConstant(read.stamp(NodeView.DEFAULT), ((HotSpotMetaspaceConstant) tool.getConstantReflection().asObjectHub(constantType.getType())).compress(),
 470                                 tool.getMetaAccess());
 471             }
 472             return read;
 473         }
 474     };
 475 
 476     @Fold
 477     static int hubOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 478         return config.hubOffset;
 479     }
 480 
 481     public static void initializeObjectHeader(Word memory, Word markWord, KlassPointer hub) {
 482         memory.writeWord(markOffset(INJECTED_VMCONFIG), markWord, MARK_WORD_LOCATION);
 483         StoreHubNode.write(memory, hub);
 484     }
 485 
 486     @Fold
 487     public static int unlockedMask(@InjectedParameter GraalHotSpotVMConfig config) {
 488         return config.unlockedMask;
 489     }
 490 
 491     @Fold
 492     public static int monitorMask(@InjectedParameter GraalHotSpotVMConfig config) {
 493         return config.monitorMask;
 494     }
 495 
 496     @Fold
 497     public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 498         return config.objectMonitorOwner;
 499     }
 500 
 501     @Fold
 502     public static int objectMonitorRecursionsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 503         return config.objectMonitorRecursions;
 504     }
 505 
 506     @Fold
 507     public static int objectMonitorCxqOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 508         return config.objectMonitorCxq;
 509     }
 510 
 511     @Fold
 512     public static int objectMonitorEntryListOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 513         return config.objectMonitorEntryList;
 514     }
 515 
 516     @Fold
 517     public static int objectMonitorSuccOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 518         return config.objectMonitorSucc;
 519     }
 520 
 521     /**
 522      * Mask for a biasable, locked or unlocked mark word.
 523      *
 524      * <pre>
 525      * +----------------------------------+-+-+
 526      * |                                 1|1|1|
 527      * +----------------------------------+-+-+
 528      * </pre>
 529      *
 530      */
 531     @Fold
 532     public static int biasedLockMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
 533         return config.biasedLockMaskInPlace;
 534     }
 535 
 536     @Fold
 537     public static int epochMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
 538         return config.epochMaskInPlace;
 539     }
 540 
 541     /**
 542      * Pattern for a biasable, unlocked mark word.
 543      *
 544      * <pre>
 545      * +----------------------------------+-+-+
 546      * |                                 1|0|1|
 547      * +----------------------------------+-+-+
 548      * </pre>
 549      *
 550      */
 551     @Fold
 552     public static int biasedLockPattern(@InjectedParameter GraalHotSpotVMConfig config) {
 553         return config.biasedLockPattern;
 554     }
 555 
 556     @Fold
 557     public static int ageMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) {
 558         return config.ageMaskInPlace;
 559     }
 560 
 561     @Fold
 562     public static int metaspaceArrayLengthOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 563         return config.metaspaceArrayLengthOffset;
 564     }
 565 
 566     @Fold
 567     public static int metaspaceArrayBaseOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 568         return config.metaspaceArrayBaseOffset;
 569     }
 570 
 571     @Fold
 572     public static int arrayLengthOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 573         return config.arrayOopDescLengthOffset();
 574     }
 575 
 576     public static Word arrayStart(int[] a) {
 577         return WordFactory.unsigned(ComputeObjectAddressNode.get(a, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int)));
 578     }
 579 
 580     /**
 581      * Idiom for making {@link GraalHotSpotVMConfig} a constant.
 582      */
 583     @Fold
 584     public static int objectAlignment(@InjectedParameter GraalHotSpotVMConfig config) {
 585         return config.objectAlignment;
 586     }
 587 
 588     /**
 589      * Calls {@link #arrayAllocationSize(int, int, int, int)} using an injected VM configuration
 590      * object.
 591      */
 592     public static long arrayAllocationSize(int length, int headerSize, int log2ElementSize) {
 593         return arrayAllocationSize(length, headerSize, log2ElementSize, objectAlignment(INJECTED_VMCONFIG));
 594     }
 595 
 596     /**
 597      * Computes the size of the memory chunk allocated for an array. This size accounts for the
 598      * array header size, body size and any padding after the last element to satisfy object
 599      * alignment requirements.
 600      *
 601      * @param length the number of elements in the array
 602      * @param headerSize the size of the array header
 603      * @param log2ElementSize log2 of the size of an element in the array
 604      * @param alignment the {@linkplain GraalHotSpotVMConfig#objectAlignment object alignment
 605      *            requirement}
 606      * @return the size of the memory chunk
 607      */
 608     public static long arrayAllocationSize(int length, int headerSize, int log2ElementSize, int alignment) {
 609         long size = ((long) length << log2ElementSize) + headerSize + (alignment - 1);
 610         long mask = ~(alignment - 1);
 611         return size & mask;
 612     }
 613 
 614     @Fold
 615     public static int instanceHeaderSize(@InjectedParameter GraalHotSpotVMConfig config) {
 616         return config.useCompressedClassPointers ? (2 * wordSize()) - 4 : 2 * wordSize();
 617     }
 618 
 619     @Fold
 620     public static byte dirtyCardValue(@InjectedParameter GraalHotSpotVMConfig config) {
 621         return config.dirtyCardValue;
 622     }
 623 
 624     @Fold
 625     public static byte g1YoungCardValue(@InjectedParameter GraalHotSpotVMConfig config) {
 626         return config.g1YoungCardValue;
 627     }
 628 
 629     @Fold
 630     public static int cardTableShift(@InjectedParameter GraalHotSpotVMConfig config) {
 631         return config.cardtableShift;
 632     }
 633 
 634     @Fold
 635     public static int g1CardQueueIndexOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 636         return config.g1CardQueueIndexOffset;
 637     }
 638 
 639     @Fold
 640     public static int g1CardQueueBufferOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 641         return config.g1CardQueueBufferOffset;
 642     }
 643 
 644     @Fold
 645     public static int g1SATBQueueMarkingOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 646         return config.g1SATBQueueMarkingOffset;
 647     }
 648 
 649     @Fold
 650     public static int g1SATBQueueIndexOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 651         return config.g1SATBQueueIndexOffset;
 652     }
 653 
 654     @Fold
 655     public static int g1SATBQueueBufferOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 656         return config.g1SATBQueueBufferOffset;
 657     }
 658 
 659     public static final LocationIdentity KLASS_SUPER_CHECK_OFFSET_LOCATION = NamedLocationIdentity.immutable("Klass::_super_check_offset");
 660 
 661     @Fold
 662     public static int superCheckOffsetOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 663         return config.superCheckOffsetOffset;
 664     }
 665 
 666     public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = NamedLocationIdentity.mutable("SecondarySuperCache");
 667 
 668     @Fold
 669     public static int secondarySuperCacheOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 670         return config.secondarySuperCacheOffset;
 671     }
 672 
 673     public static final LocationIdentity SECONDARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("SecondarySupers");
 674 
 675     @Fold
 676     public static int secondarySupersOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 677         return config.secondarySupersOffset;
 678     }
 679 
 680     public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("DisplacedMarkWord");
 681 
 682     public static final LocationIdentity OBJECT_MONITOR_OWNER_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_owner");
 683 
 684     public static final LocationIdentity OBJECT_MONITOR_RECURSION_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_recursions");
 685 
 686     public static final LocationIdentity OBJECT_MONITOR_CXQ_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_cxq");
 687 
 688     public static final LocationIdentity OBJECT_MONITOR_ENTRY_LIST_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_EntryList");
 689 
 690     public static final LocationIdentity OBJECT_MONITOR_SUCC_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_succ");
 691 
 692     @Fold
 693     public static int lockDisplacedMarkOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 694         return config.basicLockDisplacedHeaderOffset;
 695     }
 696 
 697     @Fold
 698     public static boolean useBiasedLocking(@InjectedParameter GraalHotSpotVMConfig config) {
 699         return config.useBiasedLocking;
 700     }
 701 
 702     @Fold
 703     static int uninitializedIdentityHashCodeValue(@InjectedParameter GraalHotSpotVMConfig config) {
 704         return config.uninitializedIdentityHashCodeValue;
 705     }
 706 
 707     @Fold
 708     static int identityHashCodeShift(@InjectedParameter GraalHotSpotVMConfig config) {
 709         return config.identityHashCodeShift;
 710     }
 711 
 712     /**
 713      * Loads the hub of an object (without null checking it first).
 714      */
 715     public static KlassPointer loadHub(Object object) {
 716         return loadHubIntrinsic(object);
 717     }
 718 
 719     public static Object verifyOop(Object object) {
 720         if (verifyOops(INJECTED_VMCONFIG)) {
 721             verifyOopStub(VERIFY_OOP, object);
 722         }
 723         return object;
 724     }
 725 
 726     @NodeIntrinsic(ForeignCallNode.class)
 727     private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
 728 
 729     public static Word loadWordFromObject(Object object, int offset) {
 730         ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
 731         return loadWordFromObjectIntrinsic(object, offset, LocationIdentity.any(), getWordKind());
 732     }
 733 
 734     public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) {
 735         ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject");
 736         return loadWordFromObjectIntrinsic(object, offset, identity, getWordKind());
 737     }
 738 
 739     public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) {
 740         ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadKlassFromObject");
 741         return loadKlassFromObjectIntrinsic(object, offset, identity, getWordKind());
 742     }
 743 
 744     /**
 745      * Reads the value of a given register.
 746      *
 747      * @param register a register which must not be available to the register allocator
 748      * @return the value of {@code register} as a word
 749      */
 750     public static Word registerAsWord(@ConstantNodeParameter Register register) {
 751         return registerAsWord(register, true, false);
 752     }
 753 
 754     @NodeIntrinsic(value = ReadRegisterNode.class)
 755     public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming);
 756 
 757     @NodeIntrinsic(value = WriteRegisterNode.class)
 758     public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value);
 759 
 760     @NodeIntrinsic(value = RawLoadNode.class)
 761     private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind);
 762 
 763     @NodeIntrinsic(value = RawLoadNode.class)
 764     private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind);
 765 
 766     @NodeIntrinsic(value = LoadHubNode.class)
 767     public static native KlassPointer loadHubIntrinsic(Object object);
 768 
 769     @NodeIntrinsic(value = LoadHubOrNullNode.class)
 770     public static native KlassPointer loadHubOrNullIntrinsic(Object object);
 771 
 772     static final LocationIdentity CLASS_INIT_STATE_LOCATION = NamedLocationIdentity.mutable("ClassInitState");
 773 
 774     static final LocationIdentity CLASS_INIT_THREAD_LOCATION = NamedLocationIdentity.mutable("ClassInitThread");
 775 
 776     @Fold
 777     static int instanceKlassInitStateOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 778         return config.instanceKlassInitStateOffset;
 779     }
 780 
 781     @Fold
 782     static int instanceKlassInitThreadOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 783         assert config.instanceKlassInitThreadOffset != -1;
 784         return config.instanceKlassInitThreadOffset;
 785     }
 786 
 787     @Fold
 788     public static int instanceKlassStateFullyInitialized(@InjectedParameter GraalHotSpotVMConfig config) {
 789         return config.instanceKlassStateFullyInitialized;
 790     }
 791 
 792     @Fold
 793     public static int instanceKlassStateBeingInitialized(@InjectedParameter GraalHotSpotVMConfig config) {
 794         assert config.instanceKlassStateBeingInitialized != -1;
 795         return config.instanceKlassStateBeingInitialized;
 796     }
 797 
 798     /**
 799      *
 800      * @param hub the hub of an InstanceKlass
 801      * @return true is the InstanceKlass represented by hub is fully initialized
 802      */
 803     public static boolean isInstanceKlassFullyInitialized(KlassPointer hub) {
 804         return readInstanceKlassInitState(hub) == instanceKlassStateFullyInitialized(INJECTED_VMCONFIG);
 805     }
 806 
 807     static byte readInstanceKlassInitState(KlassPointer hub) {
 808         return hub.readByte(instanceKlassInitStateOffset(INJECTED_VMCONFIG), CLASS_INIT_STATE_LOCATION);
 809     }
 810 
 811     static Word readInstanceKlassInitThread(KlassPointer hub) {
 812         return hub.readWord(instanceKlassInitThreadOffset(INJECTED_VMCONFIG), CLASS_INIT_THREAD_LOCATION);
 813     }
 814 
 815     public static final LocationIdentity KLASS_MODIFIER_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_modifier_flags");
 816 
 817     @Fold
 818     public static int klassModifierFlagsOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 819         return config.klassModifierFlagsOffset;
 820     }
 821 
 822     public static final LocationIdentity CLASS_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._klass") {
 823         @Override
 824         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 825             return foldIndirection(read, object, CLASS_MIRROR_LOCATION);
 826         }
 827     };
 828 
 829     public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._array_klass") {
 830         @Override
 831         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 832             return foldIndirection(read, object, ARRAY_KLASS_COMPONENT_MIRROR);
 833         }
 834     };
 835 
 836     @Fold
 837     public static int arrayKlassOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 838         return config.arrayKlassOffset;
 839     }
 840 
 841     public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror");
 842 
 843     public static final LocationIdentity CLASS_MIRROR_HANDLE_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror handle");
 844 
 845     @Fold
 846     public static int layoutHelperHeaderSizeShift(@InjectedParameter GraalHotSpotVMConfig config) {
 847         return config.layoutHelperHeaderSizeShift;
 848     }
 849 
 850     @Fold
 851     public static int layoutHelperHeaderSizeMask(@InjectedParameter GraalHotSpotVMConfig config) {
 852         return config.layoutHelperHeaderSizeMask;
 853     }
 854 
 855     @Fold
 856     public static int layoutHelperLog2ElementSizeShift(@InjectedParameter GraalHotSpotVMConfig config) {
 857         return config.layoutHelperLog2ElementSizeShift;
 858     }
 859 
 860     @Fold
 861     public static int layoutHelperLog2ElementSizeMask(@InjectedParameter GraalHotSpotVMConfig config) {
 862         return config.layoutHelperLog2ElementSizeMask;
 863     }
 864 
 865     @NodeIntrinsic(ForeignCallNode.class)
 866     public static native int identityHashCode(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
 867 
 868     @Fold
 869     public static long gcTotalCollectionsAddress(@InjectedParameter GraalHotSpotVMConfig config) {
 870         return config.gcTotalCollectionsAddress();
 871     }
 872 
 873     @Fold
 874     public static long referentOffset(@InjectedParameter MetaAccessProvider metaAccessProvider) {
 875         return getFieldOffset(metaAccessProvider.lookupJavaType(Reference.class), "referent");
 876     }
 877 
 878     public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") {
 879         @Override
 880         public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
 881             ValueNode javaObject = findReadHub(object);
 882             if (javaObject != null) {
 883                 ResolvedJavaType type = StampTool.typeOrNull(javaObject);
 884                 if (type != null && type.isArray()) {
 885                     ResolvedJavaType element = type.getComponentType();
 886                     if (element != null && !element.isPrimitive() && !element.getElementalType().isInterface()) {
 887                         Assumptions assumptions = object.graph().getAssumptions();
 888                         AssumptionResult<ResolvedJavaType> leafType = element.findLeafConcreteSubtype();
 889                         if (leafType != null && leafType.canRecordTo(assumptions)) {
 890                             leafType.recordTo(assumptions);
 891                             return ConstantNode.forConstant(read.stamp(NodeView.DEFAULT), tool.getConstantReflection().asObjectHub(leafType.getResult()), tool.getMetaAccess());
 892                         }
 893                     }
 894                 }
 895             }
 896             return read;
 897         }
 898     };
 899 
 900     @Fold
 901     public static int arrayClassElementOffset(@InjectedParameter GraalHotSpotVMConfig config) {
 902         return config.arrayClassElementOffset;
 903     }
 904 
 905     public static final LocationIdentity PRIMARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("PrimarySupers");
 906 
 907     public static final LocationIdentity METASPACE_ARRAY_LENGTH_LOCATION = NamedLocationIdentity.immutable("MetaspaceArrayLength");
 908 
 909     public static final LocationIdentity SECONDARY_SUPERS_ELEMENT_LOCATION = NamedLocationIdentity.immutable("SecondarySupersElement");
 910 }