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