001/* 002 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot.meta; 024 025import static com.oracle.graal.compiler.common.GraalOptions.*; 026import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; 027import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; 028import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; 029import static jdk.internal.jvmci.meta.LocationIdentity.*; 030 031import java.lang.ref.*; 032 033import jdk.internal.jvmci.code.*; 034import jdk.internal.jvmci.common.*; 035import jdk.internal.jvmci.hotspot.*; 036import jdk.internal.jvmci.meta.*; 037 038import com.oracle.graal.compiler.common.spi.*; 039import com.oracle.graal.compiler.common.type.*; 040import com.oracle.graal.graph.*; 041import com.oracle.graal.hotspot.*; 042import com.oracle.graal.hotspot.nodes.*; 043import com.oracle.graal.hotspot.nodes.type.*; 044import com.oracle.graal.hotspot.replacements.*; 045import com.oracle.graal.hotspot.replacements.arraycopy.*; 046import com.oracle.graal.nodes.*; 047import com.oracle.graal.nodes.calc.*; 048import com.oracle.graal.nodes.debug.*; 049import com.oracle.graal.nodes.extended.*; 050import com.oracle.graal.nodes.java.*; 051import com.oracle.graal.nodes.memory.*; 052import com.oracle.graal.nodes.memory.HeapAccess.BarrierType; 053import com.oracle.graal.nodes.memory.address.*; 054import com.oracle.graal.nodes.spi.*; 055import com.oracle.graal.nodes.type.*; 056import com.oracle.graal.replacements.*; 057import com.oracle.graal.replacements.nodes.*; 058 059/** 060 * HotSpot implementation of {@link LoweringProvider}. 061 */ 062public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider implements HotSpotLoweringProvider { 063 064 protected final HotSpotGraalRuntimeProvider runtime; 065 protected final ForeignCallsProvider foreignCalls; 066 protected final HotSpotRegistersProvider registers; 067 068 protected CheckCastDynamicSnippets.Templates checkcastDynamicSnippets; 069 protected InstanceOfSnippets.Templates instanceofSnippets; 070 protected NewObjectSnippets.Templates newObjectSnippets; 071 protected MonitorSnippets.Templates monitorSnippets; 072 protected WriteBarrierSnippets.Templates writeBarrierSnippets; 073 protected LoadExceptionObjectSnippets.Templates exceptionObjectSnippets; 074 protected UnsafeLoadSnippets.Templates unsafeLoadSnippets; 075 protected AssertionSnippets.Templates assertionSnippets; 076 protected ArrayCopySnippets.Templates arraycopySnippets; 077 078 public DefaultHotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, 079 TargetDescription target) { 080 super(metaAccess, target); 081 this.runtime = runtime; 082 this.foreignCalls = foreignCalls; 083 this.registers = registers; 084 } 085 086 public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { 087 super.initialize(providers, providers.getSnippetReflection()); 088 089 assert target == providers.getCodeCache().getTarget(); 090 checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(providers, target); 091 instanceofSnippets = new InstanceOfSnippets.Templates(providers, target); 092 newObjectSnippets = new NewObjectSnippets.Templates(providers, target); 093 monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking); 094 writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null); 095 exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target); 096 unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target); 097 assertionSnippets = new AssertionSnippets.Templates(providers, target); 098 arraycopySnippets = new ArrayCopySnippets.Templates(providers, target); 099 providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target)); 100 } 101 102 @Override 103 public void lower(Node n, LoweringTool tool) { 104 StructuredGraph graph = (StructuredGraph) n.graph(); 105 if (n instanceof Invoke) { 106 lowerInvoke((Invoke) n, tool, graph); 107 } else if (n instanceof LoadMethodNode) { 108 lowerLoadMethodNode((LoadMethodNode) n); 109 } else if (n instanceof GetClassNode) { 110 lowerGetClassNode((GetClassNode) n, tool, graph); 111 } else if (n instanceof StoreHubNode) { 112 lowerStoreHubNode((StoreHubNode) n, graph); 113 } else if (n instanceof OSRStartNode) { 114 lowerOSRStartNode((OSRStartNode) n); 115 } else if (n instanceof BytecodeExceptionNode) { 116 lowerBytecodeExceptionNode((BytecodeExceptionNode) n); 117 } else if (n instanceof CheckCastDynamicNode) { 118 checkcastDynamicSnippets.lower((CheckCastDynamicNode) n, tool); 119 } else if (n instanceof InstanceOfNode) { 120 if (graph.getGuardsStage().areDeoptsFixed()) { 121 instanceofSnippets.lower((InstanceOfNode) n, tool); 122 } 123 } else if (n instanceof InstanceOfDynamicNode) { 124 if (graph.getGuardsStage().areDeoptsFixed()) { 125 instanceofSnippets.lower((InstanceOfDynamicNode) n, tool); 126 } 127 } else if (n instanceof ClassIsAssignableFromNode) { 128 if (graph.getGuardsStage().areDeoptsFixed()) { 129 instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool); 130 } 131 } else if (n instanceof NewInstanceNode) { 132 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 133 newObjectSnippets.lower((NewInstanceNode) n, registers, tool); 134 } 135 } else if (n instanceof DynamicNewInstanceNode) { 136 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 137 newObjectSnippets.lower((DynamicNewInstanceNode) n, registers, tool); 138 } 139 } else if (n instanceof NewArrayNode) { 140 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 141 newObjectSnippets.lower((NewArrayNode) n, registers, runtime, tool); 142 } 143 } else if (n instanceof DynamicNewArrayNode) { 144 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 145 newObjectSnippets.lower((DynamicNewArrayNode) n, registers, tool); 146 } 147 } else if (n instanceof VerifyHeapNode) { 148 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 149 newObjectSnippets.lower((VerifyHeapNode) n, registers, runtime, tool); 150 } 151 } else if (n instanceof RawMonitorEnterNode) { 152 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 153 monitorSnippets.lower((RawMonitorEnterNode) n, registers, tool); 154 } 155 } else if (n instanceof MonitorExitNode) { 156 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 157 monitorSnippets.lower((MonitorExitNode) n, tool); 158 } 159 } else if (n instanceof ArrayCopyNode) { 160 arraycopySnippets.lower((ArrayCopyNode) n, tool); 161 } else if (n instanceof ArrayCopySlowPathNode) { 162 arraycopySnippets.lower((ArrayCopySlowPathNode) n, tool); 163 } else if (n instanceof ArrayCopyUnrollNode) { 164 arraycopySnippets.lower((ArrayCopyUnrollNode) n, tool); 165 } else if (n instanceof G1PreWriteBarrier) { 166 writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool); 167 } else if (n instanceof G1PostWriteBarrier) { 168 writeBarrierSnippets.lower((G1PostWriteBarrier) n, registers, tool); 169 } else if (n instanceof G1ReferentFieldReadBarrier) { 170 writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, registers, tool); 171 } else if (n instanceof SerialWriteBarrier) { 172 writeBarrierSnippets.lower((SerialWriteBarrier) n, tool); 173 } else if (n instanceof SerialArrayRangeWriteBarrier) { 174 writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool); 175 } else if (n instanceof G1ArrayRangePreWriteBarrier) { 176 writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, registers, tool); 177 } else if (n instanceof G1ArrayRangePostWriteBarrier) { 178 writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers, tool); 179 } else if (n instanceof NewMultiArrayNode) { 180 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 181 newObjectSnippets.lower((NewMultiArrayNode) n, tool); 182 } 183 } else if (n instanceof LoadExceptionObjectNode) { 184 exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool); 185 } else if (n instanceof AssertionNode) { 186 assertionSnippets.lower((AssertionNode) n, tool); 187 } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { 188 // Nothing to do for division nodes. The HotSpot signal handler catches divisions by 189 // zero and the MIN_VALUE / -1 cases. 190 } else if (n instanceof AbstractDeoptimizeNode || n instanceof UnwindNode || n instanceof RemNode) { 191 /* No lowering, we generate LIR directly for these nodes. */ 192 } else if (n instanceof ClassGetHubNode) { 193 lowerClassGetHubNode((ClassGetHubNode) n, tool); 194 } else if (n instanceof HubGetClassNode) { 195 lowerHubGetClassNode((HubGetClassNode) n, tool); 196 } else if (n instanceof KlassLayoutHelperNode) { 197 lowerKlassLayoutHelperNode((KlassLayoutHelperNode) n, tool); 198 } else if (n instanceof ComputeObjectAddressNode) { 199 if (graph.getGuardsStage().areFrameStatesAtDeopts()) { 200 lowerComputeObjectAddressNode((ComputeObjectAddressNode) n); 201 } 202 } else { 203 super.lower(n, tool); 204 } 205 } 206 207 private static void lowerComputeObjectAddressNode(ComputeObjectAddressNode n) { 208 /* 209 * Lower the node into a ComputeObjectAddress node and an Add but ensure that it's below any 210 * potential safepoints and above it's uses. 211 */ 212 for (Node use : n.usages().snapshot()) { 213 if (use instanceof FixedNode) { 214 FixedNode fixed = (FixedNode) use; 215 StructuredGraph graph = n.graph(); 216 GetObjectAddressNode address = graph.add(new GetObjectAddressNode(n.getObject())); 217 graph.addBeforeFixed(fixed, address); 218 AddNode add = graph.addOrUnique(new AddNode(address, n.getOffset())); 219 graph.replaceFixedWithFloating(n, add); 220 } else { 221 throw JVMCIError.shouldNotReachHere("Unexpected floating use of ComputeObjectAddressNode"); 222 } 223 } 224 } 225 226 private void lowerKlassLayoutHelperNode(KlassLayoutHelperNode n, LoweringTool tool) { 227 if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) { 228 return; 229 } 230 StructuredGraph graph = n.graph(); 231 assert !n.getHub().isConstant(); 232 AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getConfig().klassLayoutHelperOffset); 233 graph.replaceFloating(n, graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE))); 234 } 235 236 private void lowerHubGetClassNode(HubGetClassNode n, LoweringTool tool) { 237 if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) { 238 return; 239 } 240 241 StructuredGraph graph = n.graph(); 242 assert !n.getHub().isConstant(); 243 AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getConfig().classMirrorOffset); 244 FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE)); 245 graph.replaceFloating(n, read); 246 } 247 248 private void lowerClassGetHubNode(ClassGetHubNode n, LoweringTool tool) { 249 if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) { 250 return; 251 } 252 253 StructuredGraph graph = n.graph(); 254 assert !n.getValue().isConstant(); 255 AddressNode address = createOffsetAddress(graph, n.getValue(), runtime.getConfig().klassOffset); 256 FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE)); 257 graph.replaceFloating(n, read); 258 } 259 260 private void lowerInvoke(Invoke invoke, LoweringTool tool, StructuredGraph graph) { 261 if (invoke.callTarget() instanceof MethodCallTargetNode) { 262 MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); 263 NodeInputList<ValueNode> parameters = callTarget.arguments(); 264 ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); 265 GuardingNode receiverNullCheck = null; 266 if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { 267 receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool); 268 invoke.setGuard(receiverNullCheck); 269 } 270 JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); 271 272 LoweredCallTargetNode loweredCallTarget = null; 273 if (InlineVTableStubs.getValue() && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) { 274 HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); 275 ResolvedJavaType receiverType = invoke.getReceiverType(); 276 if (hsMethod.isInVirtualMethodTable(receiverType)) { 277 Kind wordKind = runtime.getTarget().wordKind; 278 ValueNode hub = createReadHub(graph, receiver, receiverNullCheck, tool); 279 280 ReadNode metaspaceMethod = createReadVirtualMethod(graph, hub, hsMethod, receiverType); 281 // We use LocationNode.ANY_LOCATION for the reads that access the 282 // compiled code entry as HotSpot does not guarantee they are final 283 // values. 284 int methodCompiledEntryOffset = runtime.getConfig().methodCompiledEntryOffset; 285 AddressNode address = createOffsetAddress(graph, metaspaceMethod, methodCompiledEntryOffset); 286 ReadNode compiledEntry = graph.add(new ReadNode(address, any(), StampFactory.forKind(wordKind), BarrierType.NONE)); 287 288 loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), 289 CallingConvention.Type.JavaCall, callTarget.invokeKind())); 290 291 graph.addBeforeFixed(invoke.asNode(), metaspaceMethod); 292 graph.addAfterFixed(metaspaceMethod, compiledEntry); 293 } 294 } 295 296 if (loweredCallTarget == null) { 297 loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, 298 callTarget.invokeKind())); 299 } 300 callTarget.replaceAndDelete(loweredCallTarget); 301 } 302 } 303 304 @Override 305 protected Stamp loadStamp(Stamp stamp, Kind kind, boolean compressible) { 306 if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) { 307 return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getConfig().getOopEncoding()); 308 } 309 return super.loadStamp(stamp, kind, compressible); 310 } 311 312 @Override 313 protected ValueNode implicitLoadConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { 314 if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) { 315 return CompressionNode.uncompress(value, runtime.getConfig().getOopEncoding()); 316 } 317 return super.implicitLoadConvert(graph, kind, value, compressible); 318 } 319 320 @Override 321 protected ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField f) { 322 HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f; 323 JavaConstant base = field.getDeclaringClass().getJavaClass(); 324 return ConstantNode.forConstant(base, metaAccess, graph); 325 } 326 327 @Override 328 protected ValueNode implicitStoreConvert(StructuredGraph graph, Kind kind, ValueNode value, boolean compressible) { 329 if (kind == Kind.Object && compressible && runtime.getConfig().useCompressedOops) { 330 return CompressionNode.compress(value, runtime.getConfig().getOopEncoding()); 331 } 332 return super.implicitStoreConvert(graph, kind, value, compressible); 333 } 334 335 @Override 336 protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor, LoweringTool tool) { 337 /* 338 * Anchor the read of the element klass to the cfg, because it is only valid when arrayClass 339 * is an object class, which might not be the case in other parts of the compiled method. 340 */ 341 AddressNode address = createOffsetAddress(graph, arrayHub, runtime.getConfig().arrayClassElementOffset); 342 return graph.unique(new FloatingReadNode(address, OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION, null, tool.getStampProvider().createHubStamp(true), AbstractBeginNode.prevBegin(anchor))); 343 } 344 345 @Override 346 protected void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { 347 StructuredGraph graph = load.graph(); 348 if (load.getGuardingCondition() == null && !graph.getGuardsStage().allowsFloatingGuards() && addReadBarrier(load)) { 349 unsafeLoadSnippets.lower(load, tool); 350 } else { 351 super.lowerUnsafeLoadNode(load, tool); 352 } 353 } 354 355 private void lowerLoadMethodNode(LoadMethodNode loadMethodNode) { 356 StructuredGraph graph = loadMethodNode.graph(); 357 HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) loadMethodNode.getMethod(); 358 ReadNode metaspaceMethod = createReadVirtualMethod(graph, loadMethodNode.getHub(), method, loadMethodNode.getReceiverType()); 359 graph.replaceFixed(loadMethodNode, metaspaceMethod); 360 } 361 362 private static void lowerGetClassNode(GetClassNode getClass, LoweringTool tool, StructuredGraph graph) { 363 StampProvider stampProvider = tool.getStampProvider(); 364 LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, getClass.getObject())); 365 HubGetClassNode hubGetClass = graph.unique(new HubGetClassNode(tool.getMetaAccess(), hub)); 366 graph.replaceFloating(getClass, hubGetClass); 367 hub.lower(tool); 368 hubGetClass.lower(tool); 369 } 370 371 private void lowerStoreHubNode(StoreHubNode storeHub, StructuredGraph graph) { 372 WriteNode hub = createWriteHub(graph, storeHub.getObject(), storeHub.getValue()); 373 graph.replaceFixed(storeHub, hub); 374 } 375 376 @Override 377 protected BarrierType fieldInitializationBarrier(Kind entryKind) { 378 return (entryKind == Kind.Object && !runtime.getConfig().useDeferredInitBarriers) ? BarrierType.IMPRECISE : BarrierType.NONE; 379 } 380 381 @Override 382 protected BarrierType arrayInitializationBarrier(Kind entryKind) { 383 return (entryKind == Kind.Object && !runtime.getConfig().useDeferredInitBarriers) ? BarrierType.PRECISE : BarrierType.NONE; 384 } 385 386 private void lowerOSRStartNode(OSRStartNode osrStart) { 387 StructuredGraph graph = osrStart.graph(); 388 if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { 389 StartNode newStart = graph.add(new StartNode()); 390 ParameterNode buffer = graph.unique(new ParameterNode(0, StampFactory.forKind(runtime.getTarget().wordKind))); 391 ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer)); 392 migrationEnd.setStateAfter(osrStart.stateAfter()); 393 394 newStart.setNext(migrationEnd); 395 FixedNode next = osrStart.next(); 396 osrStart.setNext(null); 397 migrationEnd.setNext(next); 398 graph.setStart(newStart); 399 400 // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) 401 int localsOffset = (graph.method().getMaxLocals() - 1) * 8; 402 for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.TYPE)) { 403 int size = osrLocal.getKind().getSlotCount(); 404 int offset = localsOffset - (osrLocal.index() + size - 1) * 8; 405 AddressNode address = createOffsetAddress(graph, buffer, offset); 406 ReadNode load = graph.add(new ReadNode(address, any(), osrLocal.stamp(), BarrierType.NONE)); 407 osrLocal.replaceAndDelete(load); 408 graph.addBeforeFixed(migrationEnd, load); 409 } 410 osrStart.replaceAtUsages(newStart); 411 osrStart.safeDelete(); 412 } 413 } 414 415 static final class Exceptions { 416 protected static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException; 417 protected static final NullPointerException cachedNullPointerException; 418 419 static { 420 cachedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException(); 421 cachedArrayIndexOutOfBoundsException.setStackTrace(new StackTraceElement[0]); 422 cachedNullPointerException = new NullPointerException(); 423 cachedNullPointerException.setStackTrace(new StackTraceElement[0]); 424 } 425 } 426 427 public static final class RuntimeCalls { 428 public static final ForeignCallDescriptor CREATE_NULL_POINTER_EXCEPTION = new ForeignCallDescriptor("createNullPointerException", NullPointerException.class); 429 public static final ForeignCallDescriptor CREATE_OUT_OF_BOUNDS_EXCEPTION = new ForeignCallDescriptor("createOutOfBoundsException", ArrayIndexOutOfBoundsException.class, int.class); 430 } 431 432 private void lowerBytecodeExceptionNode(BytecodeExceptionNode node) { 433 StructuredGraph graph = node.graph(); 434 if (graph.getGuardsStage().allowsFloatingGuards()) { 435 if (OmitHotExceptionStacktrace.getValue()) { 436 Throwable exception; 437 if (node.getExceptionClass() == NullPointerException.class) { 438 exception = Exceptions.cachedNullPointerException; 439 } else if (node.getExceptionClass() == ArrayIndexOutOfBoundsException.class) { 440 exception = Exceptions.cachedArrayIndexOutOfBoundsException; 441 } else { 442 throw JVMCIError.shouldNotReachHere(); 443 } 444 FloatingNode exceptionNode = ConstantNode.forConstant(HotSpotObjectConstantImpl.forObject(exception), metaAccess, graph); 445 graph.replaceFixedWithFloating(node, exceptionNode); 446 447 } else { 448 ForeignCallDescriptor descriptor; 449 if (node.getExceptionClass() == NullPointerException.class) { 450 descriptor = RuntimeCalls.CREATE_NULL_POINTER_EXCEPTION; 451 } else if (node.getExceptionClass() == ArrayIndexOutOfBoundsException.class) { 452 descriptor = RuntimeCalls.CREATE_OUT_OF_BOUNDS_EXCEPTION; 453 } else { 454 throw JVMCIError.shouldNotReachHere(); 455 } 456 457 ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, descriptor, node.stamp(), node.getArguments())); 458 graph.replaceFixedWithFixed(node, foreignCallNode); 459 } 460 } 461 } 462 463 private boolean addReadBarrier(UnsafeLoadNode load) { 464 if (runtime.getConfig().useG1GC && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getKind() == Kind.Object && load.accessKind() == Kind.Object && 465 !StampTool.isPointerAlwaysNull(load.object())) { 466 ResolvedJavaType type = StampTool.typeOrNull(load.object()); 467 if (type != null && !type.isArray()) { 468 return true; 469 } 470 } 471 return false; 472 } 473 474 private ReadNode createReadVirtualMethod(StructuredGraph graph, ValueNode hub, HotSpotResolvedJavaMethod method, ResolvedJavaType receiverType) { 475 return createReadVirtualMethod(graph, hub, method.vtableEntryOffset(receiverType)); 476 } 477 478 private ReadNode createReadVirtualMethod(StructuredGraph graph, ValueNode hub, int vtableEntryOffset) { 479 assert vtableEntryOffset > 0; 480 // We use LocationNode.ANY_LOCATION for the reads that access the vtable 481 // entry as HotSpot does not guarantee that this is a final value. 482 Stamp methodStamp = MethodPointerStamp.method(); 483 AddressNode address = createOffsetAddress(graph, hub, vtableEntryOffset); 484 ReadNode metaspaceMethod = graph.add(new ReadNode(address, any(), methodStamp, BarrierType.NONE)); 485 return metaspaceMethod; 486 } 487 488 @Override 489 protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard, LoweringTool tool) { 490 if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) { 491 return graph.unique(new LoadHubNode(tool.getStampProvider(), object, guard != null ? guard.asNode() : null)); 492 } 493 HotSpotVMConfig config = runtime.getConfig(); 494 assert !object.isConstant() || object.isNullConstant(); 495 496 KlassPointerStamp hubStamp = (KlassPointerStamp) tool.getStampProvider().createHubStamp(true); 497 if (config.useCompressedClassPointers) { 498 hubStamp = hubStamp.compressed(config.getKlassEncoding()); 499 } 500 501 AddressNode address = createOffsetAddress(graph, object, config.hubOffset); 502 FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(address, HUB_LOCATION, null, hubStamp, guard, BarrierType.NONE)); 503 if (config.useCompressedClassPointers) { 504 return CompressionNode.uncompress(memoryRead, config.getKlassEncoding()); 505 } else { 506 return memoryRead; 507 } 508 } 509 510 private WriteNode createWriteHub(StructuredGraph graph, ValueNode object, ValueNode value) { 511 HotSpotVMConfig config = runtime.getConfig(); 512 assert !object.isConstant() || object.asConstant().isDefaultForKind(); 513 514 ValueNode writeValue = value; 515 if (config.useCompressedClassPointers) { 516 writeValue = CompressionNode.compress(value, config.getKlassEncoding()); 517 } 518 519 AddressNode address = createOffsetAddress(graph, object, config.hubOffset); 520 return graph.add(new WriteNode(address, HUB_WRITE_LOCATION, writeValue, BarrierType.NONE)); 521 } 522 523 @Override 524 protected BarrierType fieldLoadBarrierType(ResolvedJavaField f) { 525 HotSpotResolvedJavaField loadField = (HotSpotResolvedJavaField) f; 526 BarrierType barrierType = BarrierType.NONE; 527 if (runtime.getConfig().useG1GC && loadField.getKind() == Kind.Object && metaAccess.lookupJavaType(Reference.class).equals(loadField.getDeclaringClass()) && 528 loadField.getName().equals("referent")) { 529 barrierType = BarrierType.PRECISE; 530 } 531 return barrierType; 532 } 533 534 @Override 535 protected int fieldOffset(ResolvedJavaField f) { 536 HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) f; 537 return field.offset(); 538 } 539 540 @Override 541 public int arrayScalingFactor(Kind kind) { 542 if (runtime.getConfig().useCompressedOops && kind == Kind.Object) { 543 return this.runtime.getTarget().getSizeInBytes(Kind.Int); 544 } 545 return super.arrayScalingFactor(kind); 546 } 547 548 @Override 549 protected int arrayBaseOffset(Kind kind) { 550 return runtime.getJVMCIRuntime().getArrayBaseOffset(kind); 551 } 552 553 @Override 554 protected int arrayLengthOffset() { 555 return runtime.getConfig().arrayLengthOffset; 556 } 557 558 @Override 559 protected LocationIdentity initLocationIdentity() { 560 return INIT_LOCATION; 561 } 562}