|
25 | 25 | package com.oracle.svm.hosted; |
26 | 26 |
|
27 | 27 | import java.lang.reflect.Field; |
| 28 | +import java.lang.reflect.Method; |
28 | 29 | import java.util.List; |
29 | 30 | import java.util.function.Function; |
30 | 31 |
|
|
34 | 35 | import com.oracle.svm.core.graal.code.PendingExceptionStateSupport; |
35 | 36 | import com.oracle.svm.core.graal.nodes.ReadReservedRegisterFloatingNode; |
36 | 37 | import com.oracle.svm.core.graal.thread.LoadVMThreadLocalNode; |
| 38 | +import com.oracle.svm.core.nodes.SubstrateMethodCallTargetNode; |
37 | 39 | import com.oracle.svm.core.threadlocal.VMThreadLocalInfo; |
38 | 40 | import com.oracle.svm.shared.util.ReflectionUtil; |
39 | 41 |
|
40 | 42 | import jdk.graal.compiler.core.common.memory.BarrierType; |
41 | 43 | import jdk.graal.compiler.core.common.memory.MemoryOrderMode; |
42 | 44 | import jdk.graal.compiler.core.common.type.ObjectStamp; |
| 45 | +import jdk.graal.compiler.core.common.type.StampFactory; |
| 46 | +import jdk.graal.compiler.core.common.type.StampPair; |
43 | 47 | import jdk.graal.compiler.debug.GraalError; |
44 | 48 | import jdk.graal.compiler.graph.Node; |
45 | 49 | import jdk.graal.compiler.nodeinfo.InputType; |
46 | 50 | import jdk.graal.compiler.nodes.AbstractMergeNode; |
| 51 | +import jdk.graal.compiler.nodes.CallTargetNode.InvokeKind; |
47 | 52 | import jdk.graal.compiler.nodes.ConstantNode; |
48 | 53 | import jdk.graal.compiler.nodes.EndNode; |
49 | 54 | import jdk.graal.compiler.nodes.FixedNode; |
50 | 55 | import jdk.graal.compiler.nodes.FixedWithNextNode; |
51 | 56 | import jdk.graal.compiler.nodes.FrameState; |
52 | 57 | import jdk.graal.compiler.nodes.InvokeWithExceptionNode; |
| 58 | +import jdk.graal.compiler.nodes.InvokeNode; |
53 | 59 | import jdk.graal.compiler.nodes.NamedLocationIdentity; |
54 | 60 | import jdk.graal.compiler.nodes.NodeView; |
55 | 61 | import jdk.graal.compiler.nodes.StructuredGraph; |
@@ -130,6 +136,7 @@ final class SubstrateBytecodeHandlerUnwindPath { |
130 | 136 |
|
131 | 137 | private static final Field OBJECT_SLOTS_FIELD = ReflectionUtil.lookupField(PendingExceptionStateHolder.class, "objectSlots"); |
132 | 138 | private static final Field PRIMITIVE_SLOTS_FIELD = ReflectionUtil.lookupField(PendingExceptionStateHolder.class, "primitiveSlots"); |
| 139 | + private static final Method POISON_OBJECT_SLOT_METHOD = ReflectionUtil.lookupMethod(PendingExceptionStateSupport.class, "poisonObjectSlot", Object[].class, int.class); |
133 | 140 |
|
134 | 141 | private record PendingStateRead(ValueNode value, FixedWithNextNode last) { |
135 | 142 | } |
@@ -547,14 +554,11 @@ private static PendingStateRead readObjectPendingStateSlot(MetaAccessProvider me |
547 | 554 | true)); |
548 | 555 | graph.addAfterFixed(insertAfter, read); |
549 | 556 | /* |
550 | | - * Object pending-state slots are thread-local roots. Clear consumed references so they do not |
551 | | - * keep object graphs live until a later exception overwrites this slot. |
| 557 | + * Object pending-state slots are thread-local roots. Replace consumed references with the |
| 558 | + * debug sentinel or null so they do not keep object graphs live until a later exception |
| 559 | + * overwrites this slot. |
552 | 560 | */ |
553 | | - JavaWriteNode clear = graph.add(createClearObjectSlotWrite(graph, slotAddress)); |
554 | | - graph.addAfterFixed(read, clear); |
555 | | - if (stateAfter != null) { |
556 | | - clear.setStateAfter(stateAfter); |
557 | | - } |
| 561 | + FixedWithNextNode clear = appendClearObjectSlotWrite(metaAccess, graph, read, objectSlots, slotIndex, slotAddress, stateAfter); |
558 | 562 | return new PendingStateRead(read, clear); |
559 | 563 | } |
560 | 564 |
|
@@ -608,19 +612,40 @@ private static void clearObjectPendingStateSlot(MetaAccessProvider metaAccess, F |
608 | 612 | long objectArrayBaseOffset = metaAccess.getArrayBaseOffset(JavaKind.Object); |
609 | 613 | int objectArrayIndexScale = metaAccess.getArrayIndexScale(JavaKind.Object); |
610 | 614 | AddressNode slotAddress = elementAddress(graph, objectSlots, objectArrayBaseOffset + (long) slotIndex * objectArrayIndexScale); |
611 | | - JavaWriteNode clear = graph.add(createClearObjectSlotWrite(graph, slotAddress)); |
612 | | - graph.addAfterFixed(last, clear); |
| 615 | + appendClearObjectSlotWrite(metaAccess, graph, last, objectSlots, slotIndex, slotAddress, null); |
613 | 616 | } |
614 | 617 |
|
615 | | - private static JavaWriteNode createClearObjectSlotWrite(StructuredGraph graph, AddressNode slotAddress) { |
616 | | - return new JavaWriteNode(JavaKind.Object, |
| 618 | + private static FixedWithNextNode appendClearObjectSlotWrite(MetaAccessProvider metaAccess, StructuredGraph graph, FixedWithNextNode insertAfter, |
| 619 | + ValueNode objectSlots, int slotIndex, AddressNode slotAddress, FrameState stateAfter) { |
| 620 | + if (useSlotDebugSentinel()) { |
| 621 | + ResolvedJavaMethod poisonMethod = metaAccess.lookupJavaMethod(POISON_OBJECT_SLOT_METHOD); |
| 622 | + SubstrateMethodCallTargetNode callTarget = graph.add(new SubstrateMethodCallTargetNode(InvokeKind.Static, poisonMethod, |
| 623 | + new ValueNode[]{objectSlots, ConstantNode.forInt(slotIndex, graph)}, StampPair.createSingle(StampFactory.forVoid()))); |
| 624 | + FrameState callState = stateAfter; |
| 625 | + if (callState == null) { |
| 626 | + FrameState lastFrameState = GraphUtil.findLastFrameState(insertAfter); |
| 627 | + callState = lastFrameState == null ? null : lastFrameState.duplicateWithVirtualState(); |
| 628 | + } |
| 629 | + GraalError.guarantee(callState != null, "Missing frame state for object-slot sentinel write"); |
| 630 | + InvokeNode poison = graph.add(new InvokeNode(callTarget, callState.bci)); |
| 631 | + graph.addAfterFixed(insertAfter, poison); |
| 632 | + poison.setStateAfter(callState); |
| 633 | + poison.setStateDuring(callState.duplicateWithVirtualState()); |
| 634 | + return poison; |
| 635 | + } |
| 636 | + JavaWriteNode clear = graph.add(new JavaWriteNode(JavaKind.Object, |
617 | 637 | slotAddress, |
618 | 638 | NamedLocationIdentity.getArrayLocation(JavaKind.Object), |
619 | 639 | ConstantNode.defaultForKind(JavaKind.Object, graph), |
620 | 640 | BarrierType.ARRAY, |
621 | 641 | true, |
622 | 642 | true, |
623 | | - MemoryOrderMode.PLAIN); |
| 643 | + MemoryOrderMode.PLAIN)); |
| 644 | + graph.addAfterFixed(insertAfter, clear); |
| 645 | + if (stateAfter != null) { |
| 646 | + clear.setStateAfter(stateAfter); |
| 647 | + } |
| 648 | + return clear; |
624 | 649 | } |
625 | 650 |
|
626 | 651 | private static FixedWithNextNode appendPrimitiveSlotDebugWrite(StructuredGraph graph, FixedWithNextNode insertAfter, |
|
0 commit comments