1 /* 2 * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.hotspot.meta; 24 25 import static 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 171 protected final HotSpotGraalRuntimeProvider runtime; 172 protected final HotSpotRegistersProvider registers; 173 protected final HotSpotConstantReflectionProvider constantReflection; 174 175 protected InstanceOfSnippets.Templates instanceofSnippets; 176 protected NewObjectSnippets.Templates newObjectSnippets; 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()) { 236 instanceofSnippets.lower(instanceOfNode, tool); 237 } else { 238 if (instanceOfNode.allowsNull()) { 239 ValueNode object = instanceOfNode.getValue(); 240 LogicNode newTypeCheck = graph.addOrUniqueWithInputs(InstanceOfNode.create(instanceOfNode.type(), object, instanceOfNode.profile(), instanceOfNode.getAnchor())); 241 LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY); 242 instanceOfNode.replaceAndDelete(newNode); 243 } 244 } 245 } else if (n instanceof InstanceOfDynamicNode) { 246 InstanceOfDynamicNode instanceOfDynamicNode = (InstanceOfDynamicNode) n; 247 if (graph.getGuardsStage().areDeoptsFixed()) { 248 instanceofSnippets.lower(instanceOfDynamicNode, tool); 249 } else { 250 ValueNode mirror = instanceOfDynamicNode.getMirrorOrHub(); 251 if (mirror.stamp().getStackKind() == JavaKind.Object) { 252 ClassGetHubNode classGetHub = graph.unique(new ClassGetHubNode(mirror)); 253 instanceOfDynamicNode.setMirror(classGetHub); 254 } 255 256 if (instanceOfDynamicNode.allowsNull()) { 257 ValueNode object = instanceOfDynamicNode.getObject(); 258 LogicNode newTypeCheck = graph.addOrUniqueWithInputs( 259 InstanceOfDynamicNode.create(graph.getAssumptions(), tool.getConstantReflection(), instanceOfDynamicNode.getMirrorOrHub(), object, false)); 260 LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY); 261 instanceOfDynamicNode.replaceAndDelete(newNode); 262 } 263 } 264 } else if (n instanceof ClassIsAssignableFromNode) { 265 if (graph.getGuardsStage().areDeoptsFixed()) { 266 instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool); 267 } 268 } else if (n instanceof NewInstanceNode) { 269 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 270 newObjectSnippets.lower((NewInstanceNode) n, registers, tool); 271 } 272 } else if (n instanceof DynamicNewInstanceNode) { 273 DynamicNewInstanceNode newInstanceNode = (DynamicNewInstanceNode) n; 274 if (newInstanceNode.getClassClass() == null) { 275 JavaConstant classClassMirror = constantReflection.forObject(Class.class); 276 ConstantNode classClass = ConstantNode.forConstant(classClassMirror, tool.getMetaAccess(), graph); 277 newInstanceNode.setClassClass(classClass); 278 } 279 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 280 newObjectSnippets.lower(newInstanceNode, registers, tool); 281 } 282 } else if (n instanceof NewArrayNode) { 283 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 284 newObjectSnippets.lower((NewArrayNode) n, registers, tool); 285 } 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) { 327 writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers, tool); 328 } else if (n instanceof NewMultiArrayNode) { 329 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 330 newObjectSnippets.lower((NewMultiArrayNode) n, tool); 331 } 332 } else if (n instanceof LoadExceptionObjectNode) { 333 exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool); 334 } else if (n instanceof AssertionNode) { 335 assertionSnippets.lower((AssertionNode) n, tool); 336 } else if (n instanceof StringToBytesNode) { 337 if (graph.getGuardsStage().areDeoptsFixed()) { 338 stringToBytesSnippets.lower((StringToBytesNode) n, tool); 339 } 340 } else if (n instanceof IntegerDivRemNode) { 341 // Nothing to do for division nodes. The HotSpot signal handler catches divisions by 342 // zero and the MIN_VALUE / -1 cases. 343 } else if (n instanceof AbstractDeoptimizeNode || n instanceof UnwindNode || n instanceof RemNode || n instanceof SafepointNode) { 344 /* No lowering, we generate LIR directly for these nodes. */ 345 } else if (n instanceof ClassGetHubNode) { 346 lowerClassGetHubNode((ClassGetHubNode) n, tool); 347 } else if (n instanceof HubGetClassNode) { 348 lowerHubGetClassNode((HubGetClassNode) n, tool); 349 } else if (n instanceof KlassLayoutHelperNode) { 350 lowerKlassLayoutHelperNode((KlassLayoutHelperNode) n, tool); 351 } else if (n instanceof ComputeObjectAddressNode) { 352 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 353 lowerComputeObjectAddressNode((ComputeObjectAddressNode) n); 354 } 355 } else if (n instanceof IdentityHashCodeNode) { 356 hashCodeSnippets.lower((IdentityHashCodeNode) n, tool); 357 } else if (n instanceof ResolveConstantNode) { 358 resolveConstantSnippets.lower((ResolveConstantNode) n, tool); 359 } else if (n instanceof ResolveMethodAndLoadCountersNode) { 360 resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool); 361 } else if (n instanceof InitializeKlassNode) { 362 resolveConstantSnippets.lower((InitializeKlassNode) n, tool); 363 } else if (n instanceof ProfileNode) { 364 profileSnippets.lower((ProfileNode) n, tool); 365 } else { 366 super.lower(n, tool); 367 } 368 } 369 370 private static void lowerComputeObjectAddressNode(ComputeObjectAddressNode n) { 371 /* 372 * Lower the node into a ComputeObjectAddress node and an Add but ensure that it's below any 373 * potential safepoints and above it's uses. 374 */ 375 for (Node use : n.usages().snapshot()) { 376 if (use instanceof FixedNode) { 377 FixedNode fixed = (FixedNode) use; 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); 460 } 461 } 462 463 if (loweredCallTarget == null) { 464 loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters.toArray(new ValueNode[parameters.size()]), callTarget.returnStamp(), 465 signature, callTarget.targetMethod(), 466 HotSpotCallingConventionType.JavaCall, 467 callTarget.invokeKind())); 468 } 469 callTarget.replaceAndDelete(loweredCallTarget); 470 } 471 } 472 473 @Override 474 protected Stamp loadStamp(Stamp stamp, JavaKind kind, boolean compressible) { 475 if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) { 476 return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getVMConfig().getOopEncoding()); 477 } 478 return super.loadStamp(stamp, kind, compressible); 479 } 480 481 @Override 482 protected ValueNode implicitLoadConvert(JavaKind kind, ValueNode value, boolean compressible) { 483 if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) { 484 return new CompressionNode(CompressionOp.Uncompress, value, runtime.getVMConfig().getOopEncoding()); 485 } 486 return super.implicitLoadConvert(kind, value, compressible); 487 } 488 489 @Override 490 public ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField f) { 491 HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f; 492 JavaConstant base = constantReflection.asJavaClass(field.getDeclaringClass()); 493 return ConstantNode.forConstant(base, metaAccess, graph); 494 } 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); 536 hub.lower(tool); 537 hubGetClass.lower(tool); 538 } 539 540 private void lowerStoreHubNode(StoreHubNode storeHub, StructuredGraph graph) { 541 WriteNode hub = createWriteHub(graph, storeHub.getObject(), storeHub.getValue()); 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)); 683 if (runtime.getVMConfig().useCompressedClassPointers) { 684 return CompressionNode.uncompress(memoryRead, runtime.getVMConfig().getKlassEncoding()); 685 } else { 686 return memoryRead; 687 } 688 } 689 690 private WriteNode createWriteHub(StructuredGraph graph, ValueNode object, ValueNode value) { 691 assert !object.isConstant() || object.asConstant().isDefaultForKind(); 692 693 ValueNode writeValue = value; 694 if (runtime.getVMConfig().useCompressedClassPointers) { 695 writeValue = CompressionNode.compress(value, runtime.getVMConfig().getKlassEncoding()); 696 } 697 698 AddressNode address = createOffsetAddress(graph, object, runtime.getVMConfig().hubOffset); 699 return graph.add(new WriteNode(address, HUB_WRITE_LOCATION, writeValue, BarrierType.NONE)); 700 } 701 702 @Override 703 protected BarrierType fieldLoadBarrierType(ResolvedJavaField f) { 704 HotSpotResolvedJavaField loadField = (HotSpotResolvedJavaField) f; 705 BarrierType barrierType = BarrierType.NONE; 706 if (runtime.getVMConfig().useG1GC && loadField.getJavaKind() == JavaKind.Object && metaAccess.lookupJavaType(Reference.class).equals(loadField.getDeclaringClass()) && 707 loadField.getName().equals("referent")) { 708 barrierType = BarrierType.PRECISE; 709 } 710 return barrierType; 711 } 712 713 @Override 714 public int fieldOffset(ResolvedJavaField f) { 715 HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f; 716 return field.offset(); 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 }