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