1 /*
   2  * Copyright (c) 2011, 2016, 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 org.graalvm.compiler.hotspot.meta;
  24 
  25 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
  26 import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs;
  27 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
  28 import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs;
  29 import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace;
  30 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END;
  31 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_KLASS_LOCATION;
  32 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION;
  33 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_HANDLE_LOCATION;
  34 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION;
  35 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION;
  36 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION;
  37 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION;
  38 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_LAYOUT_HELPER_LOCATION;
  39 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION;
  40 import static org.graalvm.word.LocationIdentity.any;
  41 
  42 import java.lang.ref.Reference;
  43 
  44 import org.graalvm.compiler.api.directives.GraalDirectives;
  45 import org.graalvm.compiler.core.common.GraalOptions;
  46 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
  47 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
  48 import org.graalvm.compiler.core.common.type.ObjectStamp;
  49 import org.graalvm.compiler.core.common.type.Stamp;
  50 import org.graalvm.compiler.core.common.type.StampFactory;
  51 import org.graalvm.compiler.core.common.type.StampPair;
  52 import org.graalvm.compiler.debug.GraalError;
  53 import org.graalvm.compiler.graph.Node;
  54 import org.graalvm.compiler.graph.NodeInputList;
  55 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  56 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
  57 import org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode;
  58 import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
  59 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier;
  60 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier;
  61 import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
  62 import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
  63 import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier;
  64 import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode;
  65 import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode;
  66 import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode;
  67 import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode;
  68 import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier;
  69 import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier;
  70 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
  71 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
  72 import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode;
  73 import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode;
  74 import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp;
  75 import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
  76 import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp;
  77 import org.graalvm.compiler.hotspot.replacements.AssertionSnippets;
  78 import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode;
  79 import org.graalvm.compiler.hotspot.replacements.HashCodeSnippets;
  80 import org.graalvm.compiler.hotspot.replacements.HubGetClassNode;
  81 import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode;
  82 import org.graalvm.compiler.hotspot.replacements.InstanceOfSnippets;
  83 import org.graalvm.compiler.hotspot.replacements.KlassLayoutHelperNode;
  84 import org.graalvm.compiler.hotspot.replacements.LoadExceptionObjectSnippets;
  85 import org.graalvm.compiler.hotspot.replacements.MonitorSnippets;
  86 import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets;
  87 import org.graalvm.compiler.hotspot.replacements.StringToBytesSnippets;
  88 import org.graalvm.compiler.hotspot.replacements.UnsafeLoadSnippets;
  89 import org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets;
  90 import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets;
  91 import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyNode;
  92 import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopySlowPathNode;
  93 import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopySnippets;
  94 import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyUnrollNode;
  95 import org.graalvm.compiler.hotspot.replacements.arraycopy.UnsafeArrayCopySnippets;
  96 import org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets;
  97 import org.graalvm.compiler.hotspot.word.KlassPointer;
  98 import org.graalvm.compiler.nodes.AbstractBeginNode;
  99 import org.graalvm.compiler.nodes.AbstractDeoptimizeNode;
 100 import org.graalvm.compiler.nodes.CompressionNode.CompressionOp;
 101 import org.graalvm.compiler.nodes.ConstantNode;
 102 import org.graalvm.compiler.nodes.FixedNode;
 103 import org.graalvm.compiler.nodes.Invoke;
 104 import org.graalvm.compiler.nodes.LogicNode;
 105 import org.graalvm.compiler.nodes.LoweredCallTargetNode;
 106 import org.graalvm.compiler.nodes.ParameterNode;
 107 import org.graalvm.compiler.nodes.SafepointNode;
 108 import org.graalvm.compiler.nodes.StartNode;
 109 import org.graalvm.compiler.nodes.StructuredGraph;
 110 import org.graalvm.compiler.nodes.UnwindNode;
 111 import org.graalvm.compiler.nodes.ValueNode;
 112 import org.graalvm.compiler.nodes.calc.AddNode;
 113 import org.graalvm.compiler.nodes.calc.FloatingNode;
 114 import org.graalvm.compiler.nodes.calc.IntegerDivRemNode;
 115 import org.graalvm.compiler.nodes.calc.IsNullNode;
 116 import org.graalvm.compiler.nodes.calc.RemNode;
 117 import org.graalvm.compiler.nodes.debug.StringToBytesNode;
 118 import org.graalvm.compiler.nodes.debug.VerifyHeapNode;
 119 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode;
 120 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 121 import org.graalvm.compiler.nodes.extended.GetClassNode;
 122 import org.graalvm.compiler.nodes.extended.GuardedUnsafeLoadNode;
 123 import org.graalvm.compiler.nodes.extended.LoadHubNode;
 124 import org.graalvm.compiler.nodes.extended.LoadMethodNode;
 125 import org.graalvm.compiler.nodes.extended.OSRLocalNode;
 126 import org.graalvm.compiler.nodes.extended.OSRLockNode;
 127 import org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode;
 128 import org.graalvm.compiler.nodes.extended.OSRStartNode;
 129 import org.graalvm.compiler.nodes.extended.RawLoadNode;
 130 import org.graalvm.compiler.nodes.extended.StoreHubNode;
 131 import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode;
 132 import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
 133 import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode;
 134 import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
 135 import org.graalvm.compiler.nodes.java.InstanceOfNode;
 136 import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode;
 137 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
 138 import org.graalvm.compiler.nodes.java.MonitorExitNode;
 139 import org.graalvm.compiler.nodes.java.MonitorIdNode;
 140 import org.graalvm.compiler.nodes.java.NewArrayNode;
 141 import org.graalvm.compiler.nodes.java.NewInstanceNode;
 142 import org.graalvm.compiler.nodes.java.NewMultiArrayNode;
 143 import org.graalvm.compiler.nodes.java.RawMonitorEnterNode;
 144 import org.graalvm.compiler.nodes.memory.FloatingReadNode;
 145 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
 146 import org.graalvm.compiler.nodes.memory.ReadNode;
 147 import org.graalvm.compiler.nodes.memory.WriteNode;
 148 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 149 import org.graalvm.compiler.nodes.spi.LoweringProvider;
 150 import org.graalvm.compiler.nodes.spi.LoweringTool;
 151 import org.graalvm.compiler.nodes.spi.StampProvider;
 152 import org.graalvm.compiler.nodes.type.StampTool;
 153 import org.graalvm.compiler.nodes.util.GraphUtil;
 154 import org.graalvm.compiler.options.OptionValues;
 155 import org.graalvm.compiler.replacements.DefaultJavaLoweringProvider;
 156 import org.graalvm.compiler.replacements.nodes.AssertionNode;
 157 import org.graalvm.word.LocationIdentity;
 158 
 159 import jdk.vm.ci.code.TargetDescription;
 160 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
 161 import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
 162 import jdk.vm.ci.hotspot.HotSpotResolvedJavaField;
 163 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 164 import jdk.vm.ci.meta.JavaConstant;
 165 import jdk.vm.ci.meta.JavaKind;
 166 import jdk.vm.ci.meta.JavaType;
 167 import jdk.vm.ci.meta.MetaAccessProvider;
 168 import jdk.vm.ci.meta.ResolvedJavaField;
 169 import jdk.vm.ci.meta.ResolvedJavaType;
 170 
 171 /**
 172  * HotSpot implementation of {@link LoweringProvider}.
 173  */
 174 public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider implements HotSpotLoweringProvider {
 175 
 176     protected final HotSpotGraalRuntimeProvider runtime;
 177     protected final HotSpotRegistersProvider registers;
 178     protected final HotSpotConstantReflectionProvider constantReflection;
 179 
 180     protected InstanceOfSnippets.Templates instanceofSnippets;
 181     protected NewObjectSnippets.Templates newObjectSnippets;
 182     protected MonitorSnippets.Templates monitorSnippets;
 183     protected WriteBarrierSnippets.Templates writeBarrierSnippets;
 184     protected LoadExceptionObjectSnippets.Templates exceptionObjectSnippets;
 185     protected UnsafeLoadSnippets.Templates unsafeLoadSnippets;
 186     protected AssertionSnippets.Templates assertionSnippets;
 187     protected ArrayCopySnippets.Templates arraycopySnippets;
 188     protected StringToBytesSnippets.Templates stringToBytesSnippets;
 189     protected HashCodeSnippets.Templates hashCodeSnippets;
 190     protected ResolveConstantSnippets.Templates resolveConstantSnippets;
 191     protected ProfileSnippets.Templates profileSnippets;
 192 
 193     public DefaultHotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
 194                     HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
 195         super(metaAccess, foreignCalls, target);
 196         this.runtime = runtime;
 197         this.registers = registers;
 198         this.constantReflection = constantReflection;
 199     }
 200 
 201     @Override
 202     public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) {
 203         super.initialize(options, runtime, providers, providers.getSnippetReflection());
 204 
 205         assert target == providers.getCodeCache().getTarget();
 206         instanceofSnippets = new InstanceOfSnippets.Templates(options, runtime, providers, target);
 207         newObjectSnippets = new NewObjectSnippets.Templates(options, runtime, providers, target, config);
 208         monitorSnippets = new MonitorSnippets.Templates(options, runtime, providers, target, config.useFastLocking);
 209         writeBarrierSnippets = new WriteBarrierSnippets.Templates(options, runtime, providers, target, config.useCompressedOops ? config.getOopEncoding() : null);
 210         exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, providers, target);
 211         unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(options, providers, target);
 212         assertionSnippets = new AssertionSnippets.Templates(options, providers, target);
 213         arraycopySnippets = new ArrayCopySnippets.Templates(options, runtime, providers, target);
 214         stringToBytesSnippets = new StringToBytesSnippets.Templates(options, providers, target);
 215         hashCodeSnippets = new HashCodeSnippets.Templates(options, providers, target);
 216         if (GeneratePIC.getValue(options)) {
 217             resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, providers, target);
 218             profileSnippets = new ProfileSnippets.Templates(options, providers, target);
 219         }
 220         providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(options, providers, target));
 221     }
 222 
 223     public MonitorSnippets.Templates getMonitorSnippets() {
 224         return monitorSnippets;
 225     }
 226 
 227     @Override
 228     public void lower(Node n, LoweringTool tool) {
 229         StructuredGraph graph = (StructuredGraph) n.graph();
 230         if (n instanceof Invoke) {
 231             lowerInvoke((Invoke) n, tool, graph);
 232         } else if (n instanceof LoadMethodNode) {
 233             lowerLoadMethodNode((LoadMethodNode) n);
 234         } else if (n instanceof GetClassNode) {
 235             lowerGetClassNode((GetClassNode) n, tool, graph);
 236         } else if (n instanceof StoreHubNode) {
 237             lowerStoreHubNode((StoreHubNode) n, graph);
 238         } else if (n instanceof OSRStartNode) {
 239             lowerOSRStartNode((OSRStartNode) n);
 240         } else if (n instanceof BytecodeExceptionNode) {
 241             lowerBytecodeExceptionNode((BytecodeExceptionNode) n);
 242         } else if (n instanceof InstanceOfNode) {
 243             InstanceOfNode instanceOfNode = (InstanceOfNode) n;
 244             if (graph.getGuardsStage().areDeoptsFixed()) {
 245                 instanceofSnippets.lower(instanceOfNode, tool);
 246             } else {
 247                 if (instanceOfNode.allowsNull()) {
 248                     ValueNode object = instanceOfNode.getValue();
 249                     LogicNode newTypeCheck = graph.addOrUniqueWithInputs(InstanceOfNode.create(instanceOfNode.type(), object, instanceOfNode.profile(), instanceOfNode.getAnchor()));
 250                     LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY);
 251                     instanceOfNode.replaceAndDelete(newNode);
 252                 }
 253             }
 254         } else if (n instanceof InstanceOfDynamicNode) {
 255             InstanceOfDynamicNode instanceOfDynamicNode = (InstanceOfDynamicNode) n;
 256             if (graph.getGuardsStage().areDeoptsFixed()) {
 257                 instanceofSnippets.lower(instanceOfDynamicNode, tool);
 258             } else {
 259                 ValueNode mirror = instanceOfDynamicNode.getMirrorOrHub();
 260                 if (mirror.stamp().getStackKind() == JavaKind.Object) {
 261                     ClassGetHubNode classGetHub = graph.unique(new ClassGetHubNode(mirror));
 262                     instanceOfDynamicNode.setMirror(classGetHub);
 263                 }
 264 
 265                 if (instanceOfDynamicNode.allowsNull()) {
 266                     ValueNode object = instanceOfDynamicNode.getObject();
 267                     LogicNode newTypeCheck = graph.addOrUniqueWithInputs(
 268                                     InstanceOfDynamicNode.create(graph.getAssumptions(), tool.getConstantReflection(), instanceOfDynamicNode.getMirrorOrHub(), object, false));
 269                     LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY);
 270                     instanceOfDynamicNode.replaceAndDelete(newNode);
 271                 }
 272             }
 273         } else if (n instanceof ClassIsAssignableFromNode) {
 274             if (graph.getGuardsStage().areDeoptsFixed()) {
 275                 instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool);
 276             }
 277         } else if (n instanceof NewInstanceNode) {
 278             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 279                 newObjectSnippets.lower((NewInstanceNode) n, registers, tool);
 280             }
 281         } else if (n instanceof DynamicNewInstanceNode) {
 282             DynamicNewInstanceNode newInstanceNode = (DynamicNewInstanceNode) n;
 283             if (newInstanceNode.getClassClass() == null) {
 284                 JavaConstant classClassMirror = constantReflection.forObject(Class.class);
 285                 ConstantNode classClass = ConstantNode.forConstant(classClassMirror, tool.getMetaAccess(), graph);
 286                 newInstanceNode.setClassClass(classClass);
 287             }
 288             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 289                 newObjectSnippets.lower(newInstanceNode, registers, tool);
 290             }
 291         } else if (n instanceof NewArrayNode) {
 292             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 293                 newObjectSnippets.lower((NewArrayNode) n, registers, tool);
 294             }
 295         } else if (n instanceof DynamicNewArrayNode) {
 296             DynamicNewArrayNode dynamicNewArrayNode = (DynamicNewArrayNode) n;
 297             if (dynamicNewArrayNode.getVoidClass() == null) {
 298                 JavaConstant voidClassMirror = constantReflection.forObject(void.class);
 299                 ConstantNode voidClass = ConstantNode.forConstant(voidClassMirror, tool.getMetaAccess(), graph);
 300                 dynamicNewArrayNode.setVoidClass(voidClass);
 301             }
 302             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 303                 newObjectSnippets.lower(dynamicNewArrayNode, registers, tool);
 304             }
 305         } else if (n instanceof VerifyHeapNode) {
 306             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 307                 newObjectSnippets.lower((VerifyHeapNode) n, registers, tool);
 308             }
 309         } else if (n instanceof RawMonitorEnterNode) {
 310             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 311                 monitorSnippets.lower((RawMonitorEnterNode) n, registers, tool);
 312             }
 313         } else if (n instanceof MonitorExitNode) {
 314             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 315                 monitorSnippets.lower((MonitorExitNode) n, registers, tool);
 316             }
 317         } else if (n instanceof ArrayCopyNode) {
 318             arraycopySnippets.lower((ArrayCopyNode) n, tool);
 319         } else if (n instanceof ArrayCopySlowPathNode) {
 320             arraycopySnippets.lower((ArrayCopySlowPathNode) n, tool);
 321         } else if (n instanceof ArrayCopyUnrollNode) {
 322             arraycopySnippets.lower((ArrayCopyUnrollNode) n, tool);
 323         } else if (n instanceof G1PreWriteBarrier) {
 324             writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool);
 325         } else if (n instanceof G1PostWriteBarrier) {
 326             writeBarrierSnippets.lower((G1PostWriteBarrier) n, registers, tool);
 327         } else if (n instanceof G1ReferentFieldReadBarrier) {
 328             writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, registers, tool);
 329         } else if (n instanceof SerialWriteBarrier) {
 330             writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
 331         } else if (n instanceof SerialArrayRangeWriteBarrier) {
 332             writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
 333         } else if (n instanceof G1ArrayRangePreWriteBarrier) {
 334             writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, registers, tool);
 335         } else if (n instanceof G1ArrayRangePostWriteBarrier) {
 336             writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers, tool);
 337         } else if (n instanceof NewMultiArrayNode) {
 338             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 339                 newObjectSnippets.lower((NewMultiArrayNode) n, tool);
 340             }
 341         } else if (n instanceof LoadExceptionObjectNode) {
 342             exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool);
 343         } else if (n instanceof AssertionNode) {
 344             assertionSnippets.lower((AssertionNode) n, tool);
 345         } else if (n instanceof StringToBytesNode) {
 346             if (graph.getGuardsStage().areDeoptsFixed()) {
 347                 stringToBytesSnippets.lower((StringToBytesNode) n, tool);
 348             }
 349         } else if (n instanceof IntegerDivRemNode) {
 350             // Nothing to do for division nodes. The HotSpot signal handler catches divisions by
 351             // zero and the MIN_VALUE / -1 cases.
 352         } else if (n instanceof AbstractDeoptimizeNode || n instanceof UnwindNode || n instanceof RemNode || n instanceof SafepointNode) {
 353             /* No lowering, we generate LIR directly for these nodes. */
 354         } else if (n instanceof ClassGetHubNode) {
 355             lowerClassGetHubNode((ClassGetHubNode) n, tool);
 356         } else if (n instanceof HubGetClassNode) {
 357             lowerHubGetClassNode((HubGetClassNode) n, tool);
 358         } else if (n instanceof KlassLayoutHelperNode) {
 359             lowerKlassLayoutHelperNode((KlassLayoutHelperNode) n, tool);
 360         } else if (n instanceof ComputeObjectAddressNode) {
 361             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 362                 lowerComputeObjectAddressNode((ComputeObjectAddressNode) n);
 363             }
 364         } else if (n instanceof IdentityHashCodeNode) {
 365             hashCodeSnippets.lower((IdentityHashCodeNode) n, tool);
 366         } else if (n instanceof ResolveConstantNode) {
 367             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 368                 resolveConstantSnippets.lower((ResolveConstantNode) n, tool);
 369             }
 370         } else if (n instanceof ResolveMethodAndLoadCountersNode) {
 371             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 372                 resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool);
 373             }
 374         } else if (n instanceof InitializeKlassNode) {
 375             if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
 376                 resolveConstantSnippets.lower((InitializeKlassNode) n, tool);
 377             }
 378         } else if (n instanceof ProfileNode) {
 379             profileSnippets.lower((ProfileNode) n, tool);
 380         } else {
 381             super.lower(n, tool);
 382         }
 383     }
 384 
 385     private static void lowerComputeObjectAddressNode(ComputeObjectAddressNode n) {
 386         /*
 387          * Lower the node into a ComputeObjectAddress node and an Add but ensure that it's below any
 388          * potential safepoints and above it's uses.
 389          */
 390         for (Node use : n.usages().snapshot()) {
 391             if (use instanceof FixedNode) {
 392                 FixedNode fixed = (FixedNode) use;
 393                 StructuredGraph graph = n.graph();
 394                 GetObjectAddressNode address = graph.add(new GetObjectAddressNode(n.getObject()));
 395                 graph.addBeforeFixed(fixed, address);
 396                 AddNode add = graph.addOrUnique(new AddNode(address, n.getOffset()));
 397                 use.replaceFirstInput(n, add);
 398             } else {
 399                 throw GraalError.shouldNotReachHere("Unexpected floating use of ComputeObjectAddressNode " + n);
 400             }
 401         }
 402         GraphUtil.unlinkFixedNode(n);
 403         n.safeDelete();
 404     }
 405 
 406     private void lowerKlassLayoutHelperNode(KlassLayoutHelperNode n, LoweringTool tool) {
 407         if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) {
 408             return;
 409         }
 410         StructuredGraph graph = n.graph();
 411         assert !n.getHub().isConstant();
 412         AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().klassLayoutHelperOffset);
 413         n.replaceAtUsagesAndDelete(graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), null, BarrierType.NONE)));
 414     }
 415 
 416     private void lowerHubGetClassNode(HubGetClassNode n, LoweringTool tool) {
 417         if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) {
 418             return;
 419         }
 420 
 421         ValueNode hub = n.getHub();
 422         GraalHotSpotVMConfig vmConfig = runtime.getVMConfig();
 423         StructuredGraph graph = n.graph();
 424         assert !hub.isConstant() || GraalOptions.ImmutableCode.getValue(graph.getOptions());
 425         AddressNode mirrorAddress = createOffsetAddress(graph, hub, vmConfig.classMirrorOffset);
 426         FloatingReadNode read = graph.unique(new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, vmConfig.classMirrorIsHandle ? StampFactory.forKind(target.wordJavaKind) : n.stamp(),
 427                         null, BarrierType.NONE));
 428         if (vmConfig.classMirrorIsHandle) {
 429             AddressNode address = createOffsetAddress(graph, read, 0);
 430             read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_HANDLE_LOCATION, null, n.stamp(), null, BarrierType.NONE));
 431         }
 432         n.replaceAtUsagesAndDelete(read);
 433     }
 434 
 435     private void lowerClassGetHubNode(ClassGetHubNode n, LoweringTool tool) {
 436         if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) {
 437             return;
 438         }
 439 
 440         StructuredGraph graph = n.graph();
 441         assert !n.getValue().isConstant();
 442         AddressNode address = createOffsetAddress(graph, n.getValue(), runtime.getVMConfig().klassOffset);
 443         FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), null, BarrierType.NONE));
 444         n.replaceAtUsagesAndDelete(read);
 445     }
 446 
 447     private void lowerInvoke(Invoke invoke, LoweringTool tool, StructuredGraph graph) {
 448         if (invoke.callTarget() instanceof MethodCallTargetNode) {
 449             MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
 450             NodeInputList<ValueNode> parameters = callTarget.arguments();
 451             ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0);
 452             if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) {
 453                 ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool);
 454                 parameters.set(0, nonNullReceiver);
 455                 receiver = nonNullReceiver;
 456             }
 457             JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass());
 458 
 459             LoweredCallTargetNode loweredCallTarget = null;
 460             OptionValues options = graph.getOptions();
 461             if (InlineVTableStubs.getValue(options) && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue(options) || invoke.isPolymorphic())) {
 462                 HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod();
 463                 ResolvedJavaType receiverType = invoke.getReceiverType();
 464                 if (hsMethod.isInVirtualMethodTable(receiverType)) {
 465                     JavaKind wordKind = runtime.getTarget().wordJavaKind;
 466                     ValueNode hub = createReadHub(graph, receiver, tool);
 467 
 468                     ReadNode metaspaceMethod = createReadVirtualMethod(graph, hub, hsMethod, receiverType);
 469                     // We use LocationNode.ANY_LOCATION for the reads that access the
 470                     // compiled code entry as HotSpot does not guarantee they are final
 471                     // values.
 472                     int methodCompiledEntryOffset = runtime.getVMConfig().methodCompiledEntryOffset;
 473                     AddressNode address = createOffsetAddress(graph, metaspaceMethod, methodCompiledEntryOffset);
 474                     ReadNode compiledEntry = graph.add(new ReadNode(address, any(), StampFactory.forKind(wordKind), BarrierType.NONE));
 475 
 476                     loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters.toArray(new ValueNode[parameters.size()]), callTarget.returnStamp(),
 477                                     signature, callTarget.targetMethod(),
 478                                     HotSpotCallingConventionType.JavaCall, callTarget.invokeKind()));
 479 
 480                     graph.addBeforeFixed(invoke.asNode(), metaspaceMethod);
 481                     graph.addAfterFixed(metaspaceMethod, compiledEntry);
 482                 }
 483             }
 484 
 485             if (loweredCallTarget == null) {
 486                 loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters.toArray(new ValueNode[parameters.size()]), callTarget.returnStamp(),
 487                                 signature, callTarget.targetMethod(),
 488                                 HotSpotCallingConventionType.JavaCall,
 489                                 callTarget.invokeKind()));
 490             }
 491             callTarget.replaceAndDelete(loweredCallTarget);
 492         }
 493     }
 494 
 495     @Override
 496     protected Stamp loadStamp(Stamp stamp, JavaKind kind, boolean compressible) {
 497         if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) {
 498             return HotSpotNarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getVMConfig().getOopEncoding());
 499         }
 500         return super.loadStamp(stamp, kind, compressible);
 501     }
 502 
 503     @Override
 504     protected ValueNode implicitLoadConvert(JavaKind kind, ValueNode value, boolean compressible) {
 505         if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) {
 506             return new HotSpotCompressionNode(CompressionOp.Uncompress, value, runtime.getVMConfig().getOopEncoding());
 507         }
 508         return super.implicitLoadConvert(kind, value, compressible);
 509     }
 510 
 511     @Override
 512     public ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField f) {
 513         HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f;
 514         JavaConstant base = constantReflection.asJavaClass(field.getDeclaringClass());
 515         return ConstantNode.forConstant(base, metaAccess, graph);
 516     }
 517 
 518     @Override
 519     protected ValueNode implicitStoreConvert(JavaKind kind, ValueNode value, boolean compressible) {
 520         if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) {
 521             return new HotSpotCompressionNode(CompressionOp.Compress, value, runtime.getVMConfig().getOopEncoding());
 522         }
 523         return super.implicitStoreConvert(kind, value, compressible);
 524     }
 525 
 526     @Override
 527     protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor) {
 528         /*
 529          * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass
 530          * is an object class, which might not be the case in other parts of the compiled method.
 531          */
 532         AddressNode address = createOffsetAddress(graph, arrayHub, runtime.getVMConfig().arrayClassElementOffset);
 533         return graph.unique(new FloatingReadNode(address, OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION, null, KlassPointerStamp.klassNonNull(), AbstractBeginNode.prevBegin(anchor)));
 534     }
 535 
 536     @Override
 537     protected void lowerUnsafeLoadNode(RawLoadNode load, LoweringTool tool) {
 538         StructuredGraph graph = load.graph();
 539         if (!(load instanceof GuardedUnsafeLoadNode) && !graph.getGuardsStage().allowsFloatingGuards() && addReadBarrier(load)) {
 540             unsafeLoadSnippets.lower(load, tool);
 541         } else {
 542             super.lowerUnsafeLoadNode(load, tool);
 543         }
 544     }
 545 
 546     private void lowerLoadMethodNode(LoadMethodNode loadMethodNode) {
 547         StructuredGraph graph = loadMethodNode.graph();
 548         HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) loadMethodNode.getMethod();
 549         ReadNode metaspaceMethod = createReadVirtualMethod(graph, loadMethodNode.getHub(), method, loadMethodNode.getReceiverType());
 550         graph.replaceFixed(loadMethodNode, metaspaceMethod);
 551     }
 552 
 553     private static void lowerGetClassNode(GetClassNode getClass, LoweringTool tool, StructuredGraph graph) {
 554         StampProvider stampProvider = tool.getStampProvider();
 555         LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, getClass.getObject()));
 556         HubGetClassNode hubGetClass = graph.unique(new HubGetClassNode(tool.getMetaAccess(), hub));
 557         getClass.replaceAtUsagesAndDelete(hubGetClass);
 558         hub.lower(tool);
 559         hubGetClass.lower(tool);
 560     }
 561 
 562     private void lowerStoreHubNode(StoreHubNode storeHub, StructuredGraph graph) {
 563         WriteNode hub = createWriteHub(graph, storeHub.getObject(), storeHub.getValue());
 564         graph.replaceFixed(storeHub, hub);
 565     }
 566 
 567     @Override
 568     public BarrierType fieldInitializationBarrier(JavaKind entryKind) {
 569         return (entryKind == JavaKind.Object && !runtime.getVMConfig().useDeferredInitBarriers) ? BarrierType.IMPRECISE : BarrierType.NONE;
 570     }
 571 
 572     @Override
 573     public BarrierType arrayInitializationBarrier(JavaKind entryKind) {
 574         return (entryKind == JavaKind.Object && !runtime.getVMConfig().useDeferredInitBarriers) ? BarrierType.PRECISE : BarrierType.NONE;
 575     }
 576 
 577     private void lowerOSRStartNode(OSRStartNode osrStart) {
 578         StructuredGraph graph = osrStart.graph();
 579         if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
 580             StartNode newStart = graph.add(new StartNode());
 581             ParameterNode buffer = graph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(StampFactory.forKind(runtime.getTarget().wordJavaKind))));
 582             ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer));
 583             migrationEnd.setStateAfter(osrStart.stateAfter());
 584             newStart.setNext(migrationEnd);
 585             FixedNode next = osrStart.next();
 586             osrStart.setNext(null);
 587             migrationEnd.setNext(next);
 588             graph.setStart(newStart);
 589 
 590             final int wordSize = target.wordSize;
 591 
 592             // @formatter:off
 593             // taken from c2 locals_addr = osr_buf + (max_locals-1)*wordSize)
 594             // @formatter:on
 595             int localsOffset = (graph.method().getMaxLocals() - 1) * wordSize;
 596             for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.TYPE)) {
 597                 int size = osrLocal.getStackKind().getSlotCount();
 598                 int offset = localsOffset - (osrLocal.index() + size - 1) * wordSize;
 599                 AddressNode address = createOffsetAddress(graph, buffer, offset);
 600                 ReadNode load = graph.add(new ReadNode(address, any(), osrLocal.stamp(), BarrierType.NONE));
 601                 osrLocal.replaceAndDelete(load);
 602                 graph.addBeforeFixed(migrationEnd, load);
 603             }
 604 
 605             // @formatter:off
 606             // taken from c2 monitors_addr = osr_buf + (max_locals+mcnt*2-1)*wordSize);
 607             // @formatter:on
 608             final int lockCount = osrStart.stateAfter().locksSize();
 609             final int locksOffset = (graph.method().getMaxLocals() + lockCount * 2 - 1) * wordSize;
 610 
 611             // first initialize the lock slots for all enters with the displaced marks read from the
 612             // buffer
 613             for (OSRMonitorEnterNode osrMonitorEnter : graph.getNodes(OSRMonitorEnterNode.TYPE)) {
 614                 MonitorIdNode monitorID = osrMonitorEnter.getMonitorId();
 615                 OSRLockNode lock = (OSRLockNode) osrMonitorEnter.object();
 616                 final int index = lock.index();
 617 
 618                 final int offsetDisplacedHeader = locksOffset - ((index * 2) + 1) * wordSize;
 619                 final int offsetLockObject = locksOffset - index * 2 * wordSize;
 620 
 621                 // load the displaced mark from the osr buffer
 622                 AddressNode addressDisplacedHeader = createOffsetAddress(graph, buffer, offsetDisplacedHeader);
 623                 ReadNode loadDisplacedHeader = graph.add(new ReadNode(addressDisplacedHeader, any(), lock.stamp(), BarrierType.NONE));
 624                 graph.addBeforeFixed(migrationEnd, loadDisplacedHeader);
 625 
 626                 // we need to initialize the stack slot for the lock
 627                 BeginLockScopeNode beginLockScope = graph.add(new BeginLockScopeNode(lock.getStackKind(), monitorID.getLockDepth()));
 628                 graph.addBeforeFixed(migrationEnd, beginLockScope);
 629 
 630                 // write the displaced mark to the correct stack slot
 631                 AddressNode addressDisplacedMark = createOffsetAddress(graph, beginLockScope, runtime.getVMConfig().basicLockDisplacedHeaderOffset);
 632                 WriteNode writeStackSlot = graph.add(new WriteNode(addressDisplacedMark, DISPLACED_MARK_WORD_LOCATION, loadDisplacedHeader, BarrierType.NONE));
 633                 graph.addBeforeFixed(migrationEnd, writeStackSlot);
 634 
 635                 // load the lock object from the osr buffer
 636                 AddressNode addressLockObject = createOffsetAddress(graph, buffer, offsetLockObject);
 637                 ReadNode loadObject = graph.add(new ReadNode(addressLockObject, any(), lock.stamp(), BarrierType.NONE));
 638                 lock.replaceAndDelete(loadObject);
 639                 graph.addBeforeFixed(migrationEnd, loadObject);
 640             }
 641 
 642             osrStart.replaceAtUsagesAndDelete(newStart);
 643         }
 644     }
 645 
 646     static final class Exceptions {
 647         protected static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException;
 648         protected static final NullPointerException cachedNullPointerException;
 649 
 650         static {
 651             cachedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException();
 652             cachedArrayIndexOutOfBoundsException.setStackTrace(new StackTraceElement[0]);
 653             cachedNullPointerException = new NullPointerException();
 654             cachedNullPointerException.setStackTrace(new StackTraceElement[0]);
 655         }
 656     }
 657 
 658     public static final class RuntimeCalls {
 659         public static final ForeignCallDescriptor CREATE_ARRAY_STORE_EXCEPTION = new ForeignCallDescriptor("createArrayStoreException", ArrayStoreException.class, Object.class);
 660         public static final ForeignCallDescriptor CREATE_CLASS_CAST_EXCEPTION = new ForeignCallDescriptor("createClassCastException", ClassCastException.class, Object.class, KlassPointer.class);
 661         public static final ForeignCallDescriptor CREATE_NULL_POINTER_EXCEPTION = new ForeignCallDescriptor("createNullPointerException", NullPointerException.class);
 662         public static final ForeignCallDescriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new ForeignCallDescriptor("createOutOfBoundsException", ArrayIndexOutOfBoundsException.class, int.class);
 663     }
 664 
 665     private boolean throwCachedException(BytecodeExceptionNode node) {
 666         Throwable exception;
 667         if (node.getExceptionClass() == NullPointerException.class) {
 668             exception = Exceptions.cachedNullPointerException;
 669         } else if (node.getExceptionClass() == ArrayIndexOutOfBoundsException.class) {
 670             exception = Exceptions.cachedArrayIndexOutOfBoundsException;
 671         } else {
 672             return false;
 673         }
 674 
 675         StructuredGraph graph = node.graph();
 676         FloatingNode exceptionNode = ConstantNode.forConstant(constantReflection.forObject(exception), metaAccess, graph);
 677         graph.replaceFixedWithFloating(node, exceptionNode);
 678         return true;
 679     }
 680 
 681     private void lowerBytecodeExceptionNode(BytecodeExceptionNode node) {
 682         if (OmitHotExceptionStacktrace.getValue(node.getOptions())) {
 683             if (throwCachedException(node)) {
 684                 return;
 685             }
 686         }
 687 
 688         ForeignCallDescriptor descriptor;
 689         if (node.getExceptionClass() == NullPointerException.class) {
 690             descriptor = RuntimeCalls.CREATE_NULL_POINTER_EXCEPTION;
 691         } else if (node.getExceptionClass() == ArrayIndexOutOfBoundsException.class) {
 692             descriptor = RuntimeCalls.CREATE_OUT_OF_BOUNDS_EXCEPTION;
 693         } else if (node.getExceptionClass() == ArrayStoreException.class) {
 694             descriptor = RuntimeCalls.CREATE_ARRAY_STORE_EXCEPTION;
 695         } else if (node.getExceptionClass() == ClassCastException.class) {
 696             descriptor = RuntimeCalls.CREATE_CLASS_CAST_EXCEPTION;
 697         } else {
 698             throw GraalError.shouldNotReachHere();
 699         }
 700 
 701         StructuredGraph graph = node.graph();
 702         ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, descriptor, node.stamp(), node.getArguments()));
 703         graph.replaceFixedWithFixed(node, foreignCallNode);
 704     }
 705 
 706     private boolean addReadBarrier(RawLoadNode load) {
 707         if (runtime.getVMConfig().useG1GC && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getStackKind() == JavaKind.Object &&
 708                         load.accessKind() == JavaKind.Object && !StampTool.isPointerAlwaysNull(load.object())) {
 709             ResolvedJavaType type = StampTool.typeOrNull(load.object());
 710             if (type != null && !type.isArray()) {
 711                 return true;
 712             }
 713         }
 714         return false;
 715     }
 716 
 717     private ReadNode createReadVirtualMethod(StructuredGraph graph, ValueNode hub, HotSpotResolvedJavaMethod method, ResolvedJavaType receiverType) {
 718         return createReadVirtualMethod(graph, hub, method.vtableEntryOffset(receiverType));
 719     }
 720 
 721     private ReadNode createReadVirtualMethod(StructuredGraph graph, ValueNode hub, int vtableEntryOffset) {
 722         assert vtableEntryOffset > 0;
 723         // We use LocationNode.ANY_LOCATION for the reads that access the vtable
 724         // entry as HotSpot does not guarantee that this is a final value.
 725         Stamp methodStamp = MethodPointerStamp.methodNonNull();
 726         AddressNode address = createOffsetAddress(graph, hub, vtableEntryOffset);
 727         ReadNode metaspaceMethod = graph.add(new ReadNode(address, any(), methodStamp, BarrierType.NONE));
 728         return metaspaceMethod;
 729     }
 730 
 731     @Override
 732     protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, LoweringTool tool) {
 733         if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) {
 734             return graph.unique(new LoadHubNode(tool.getStampProvider(), object));
 735         }
 736         assert !object.isConstant() || object.isNullConstant();
 737 
 738         KlassPointerStamp hubStamp = KlassPointerStamp.klassNonNull();
 739         if (runtime.getVMConfig().useCompressedClassPointers) {
 740             hubStamp = hubStamp.compressed(runtime.getVMConfig().getKlassEncoding());
 741         }
 742 
 743         AddressNode address = createOffsetAddress(graph, object, runtime.getVMConfig().hubOffset);
 744         LocationIdentity hubLocation = runtime.getVMConfig().useCompressedClassPointers ? COMPRESSED_HUB_LOCATION : HUB_LOCATION;
 745         FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(address, hubLocation, null, hubStamp, null, BarrierType.NONE));
 746         if (runtime.getVMConfig().useCompressedClassPointers) {
 747             return HotSpotCompressionNode.uncompress(memoryRead, runtime.getVMConfig().getKlassEncoding());
 748         } else {
 749             return memoryRead;
 750         }
 751     }
 752 
 753     private WriteNode createWriteHub(StructuredGraph graph, ValueNode object, ValueNode value) {
 754         assert !object.isConstant() || object.asConstant().isDefaultForKind();
 755 
 756         ValueNode writeValue = value;
 757         if (runtime.getVMConfig().useCompressedClassPointers) {
 758             writeValue = HotSpotCompressionNode.compress(value, runtime.getVMConfig().getKlassEncoding());
 759         }
 760 
 761         AddressNode address = createOffsetAddress(graph, object, runtime.getVMConfig().hubOffset);
 762         return graph.add(new WriteNode(address, HUB_WRITE_LOCATION, writeValue, BarrierType.NONE));
 763     }
 764 
 765     @Override
 766     protected BarrierType fieldLoadBarrierType(ResolvedJavaField f) {
 767         HotSpotResolvedJavaField loadField = (HotSpotResolvedJavaField) f;
 768         BarrierType barrierType = BarrierType.NONE;
 769         if (runtime.getVMConfig().useG1GC && loadField.getJavaKind() == JavaKind.Object && metaAccess.lookupJavaType(Reference.class).equals(loadField.getDeclaringClass()) &&
 770                         loadField.getName().equals("referent")) {
 771             barrierType = BarrierType.PRECISE;
 772         }
 773         return barrierType;
 774     }
 775 
 776     @Override
 777     public int fieldOffset(ResolvedJavaField f) {
 778         HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f;
 779         return field.offset();
 780     }
 781 
 782     @Override
 783     public int arrayScalingFactor(JavaKind kind) {
 784         if (runtime.getVMConfig().useCompressedOops && kind == JavaKind.Object) {
 785             return super.arrayScalingFactor(JavaKind.Int);
 786         } else {
 787             return super.arrayScalingFactor(kind);
 788         }
 789     }
 790 
 791     @Override
 792     public int arrayBaseOffset(JavaKind kind) {
 793         return getArrayBaseOffset(kind);
 794     }
 795 
 796     @Override
 797     public int arrayLengthOffset() {
 798         return runtime.getVMConfig().arrayOopDescLengthOffset();
 799     }
 800 }