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