29
29
30
30
import java .util .concurrent .atomic .AtomicInteger ;
31
31
32
- import jdk .graal .compiler .word .Word ;
33
32
import org .graalvm .nativeimage .CurrentIsolate ;
34
33
import org .graalvm .nativeimage .ImageSingletons ;
35
34
import org .graalvm .nativeimage .IsolateThread ;
53
52
import com .oracle .svm .core .log .Log ;
54
53
import com .oracle .svm .core .nodes .CFunctionEpilogueNode ;
55
54
import com .oracle .svm .core .nodes .CFunctionPrologueNode ;
56
- import com .oracle .svm .core .nodes .CodeSynchronizationNode ;
57
55
import com .oracle .svm .core .nodes .SafepointCheckNode ;
58
56
import com .oracle .svm .core .option .HostedOptionKey ;
59
57
import com .oracle .svm .core .option .RuntimeOptionKey ;
81
79
import jdk .graal .compiler .nodes .extended .ForeignCallNode ;
82
80
import jdk .graal .compiler .nodes .extended .MembarNode ;
83
81
import jdk .graal .compiler .options .Option ;
82
+ import jdk .graal .compiler .word .Word ;
84
83
85
84
/**
86
85
* Support for initiating safepoints, which are a global state in which all threads are paused so
@@ -151,14 +150,13 @@ public final class Safepoint {
151
150
public static final SubstrateForeignCallDescriptor ENTER_SLOW_PATH_SAFEPOINT_CHECK = SnippetRuntime .findForeignCall (Safepoint .class , "enterSlowPathSafepointCheck" , NO_SIDE_EFFECT );
152
151
public static final SubstrateForeignCallDescriptor ENTER_SLOW_PATH_TRANSITION_FROM_NATIVE_TO_NEW_STATUS = SnippetRuntime .findForeignCall (Safepoint .class ,
153
152
"enterSlowPathTransitionFromNativeToNewStatus" , NO_SIDE_EFFECT );
154
- private static final SubstrateForeignCallDescriptor ENTER_SLOW_PATH_TRANSITION_FROM_VM_TO_JAVA = SnippetRuntime .findForeignCall (Safepoint .class , "enterSlowPathTransitionFromVMToJava" ,
155
- NO_SIDE_EFFECT );
153
+ private static final SubstrateForeignCallDescriptor ENTER_SLOW_PATH_RUN_PENDING_ACTIONS = SnippetRuntime .findForeignCall (Safepoint .class , "enterSlowPathRunPendingActions" , NO_SIDE_EFFECT );
156
154
157
155
/** All foreign calls defined in this class. */
158
156
public static final SubstrateForeignCallDescriptor [] FOREIGN_CALLS = new SubstrateForeignCallDescriptor []{
159
157
ENTER_SLOW_PATH_SAFEPOINT_CHECK ,
160
158
ENTER_SLOW_PATH_TRANSITION_FROM_NATIVE_TO_NEW_STATUS ,
161
- ENTER_SLOW_PATH_TRANSITION_FROM_VM_TO_JAVA ,
159
+ ENTER_SLOW_PATH_RUN_PENDING_ACTIONS ,
162
160
};
163
161
164
162
/** Private constructor: No instances: only statics. */
@@ -250,32 +248,12 @@ private static void slowPathSafepointCheck0(int newStatus, boolean callerHasJava
250
248
}
251
249
252
250
if (newStatus == StatusSupport .STATUS_IN_JAVA ) {
253
- // Resetting the safepoint counter or executing the recurring callback must only be done
254
- // if the thread is in Java state.
255
- slowPathRunJavaStateActions ();
251
+ ActionOnTransitionToJavaSupport . runPendingActions ();
252
+ /* Do this last so that a thrown exception cannot skip any of the above. */
253
+ ThreadingSupportImpl . onSafepointCheckSlowpath ();
256
254
}
257
255
}
258
256
259
- /**
260
- * Slow path code run after a safepoint check or after transitioning from VM to Java state. It
261
- * resets the safepoint counter, runs recurring callbacks if necessary, and executes pending
262
- * {@link ActionOnTransitionToJavaSupport transition actions}.
263
- */
264
- @ Uninterruptible (reason = "Must not contain safepoint checks." )
265
- private static void slowPathRunJavaStateActions () {
266
- if (ActionOnTransitionToJavaSupport .isActionPending ()) {
267
- if (ActionOnTransitionToJavaSupport .isSynchronizeCode ()) {
268
- CodeSynchronizationNode .synchronizeCode ();
269
- } else {
270
- assert false : "Unexpected action pending." ;
271
- }
272
- ActionOnTransitionToJavaSupport .clearActions ();
273
- }
274
-
275
- // Do this last so an exception cannot skip the above
276
- ThreadingSupportImpl .onSafepointCheckSlowpath ();
277
- }
278
-
279
257
@ NeverInline ("Must not be inlined in a caller that has an exception handler: We only support InvokeNode and not InvokeWithExceptionNode between a CFunctionPrologueNode and CFunctionEpilogueNode" )
280
258
@ Uninterruptible (reason = "Must not contain safepoint checks." )
281
259
private static void freezeAtSafepoint (int newStatus , boolean callerHasJavaFrameAnchor ) {
@@ -457,7 +435,7 @@ public static void transitionNativeToJava(boolean popFrameAnchor) {
457
435
JavaFrameAnchors .popFrameAnchor ();
458
436
}
459
437
} else {
460
- callSlowPathNativeToNewStatus (Safepoint . ENTER_SLOW_PATH_TRANSITION_FROM_NATIVE_TO_NEW_STATUS , newStatus , popFrameAnchor );
438
+ callSlowPathNativeToNewStatus (ENTER_SLOW_PATH_TRANSITION_FROM_NATIVE_TO_NEW_STATUS , newStatus , popFrameAnchor );
461
439
}
462
440
463
441
/*
@@ -479,22 +457,23 @@ public static void slowTransitionNativeToVM() {
479
457
int newStatus = StatusSupport .STATUS_IN_VM ;
480
458
boolean needSlowPath = !StatusSupport .compareAndSetNativeToNewStatus (newStatus );
481
459
if (BranchProbabilityNode .probability (BranchProbabilityNode .VERY_SLOW_PATH_PROBABILITY , needSlowPath )) {
482
- callSlowPathNativeToNewStatus (Safepoint . ENTER_SLOW_PATH_TRANSITION_FROM_NATIVE_TO_NEW_STATUS , newStatus , false );
460
+ callSlowPathNativeToNewStatus (ENTER_SLOW_PATH_TRANSITION_FROM_NATIVE_TO_NEW_STATUS , newStatus , false );
483
461
}
484
462
}
485
463
486
464
@ Uninterruptible (reason = "Must not contain safepoint checks" )
487
465
public static void transitionVMToJava (boolean popFrameAnchor ) {
488
- // We can directly change the thread status as no other thread will touch the status field
489
- // as long as we are in VM status.
466
+ /* Change the thread status directly (other threads won't touch the status field). */
490
467
StatusSupport .assertStatusVM ();
491
468
StatusSupport .setStatusJavaUnguarded ();
492
469
if (popFrameAnchor ) {
493
470
JavaFrameAnchors .popFrameAnchor ();
494
471
}
495
- boolean needSlowPath = ThreadingSupportImpl .needsNativeToJavaSlowpath ();
472
+
473
+ /* Only execute pending actions but don't do a safepoint slowpath call. */
474
+ boolean needSlowPath = ActionOnTransitionToJavaSupport .isActionPending ();
496
475
if (BranchProbabilityNode .probability (BranchProbabilityNode .VERY_SLOW_PATH_PROBABILITY , needSlowPath )) {
497
- callSlowPathSafepointCheck ( Safepoint . ENTER_SLOW_PATH_TRANSITION_FROM_VM_TO_JAVA );
476
+ callRunPendingActions ( ENTER_SLOW_PATH_RUN_PENDING_ACTIONS );
498
477
}
499
478
}
500
479
@@ -514,16 +493,11 @@ public static void transitionVMToNative() {
514
493
StatusSupport .setStatusNative ();
515
494
}
516
495
517
- @ NodeIntrinsic (value = ForeignCallNode .class )
518
- private static native void callSlowPathSafepointCheck (@ ConstantNodeParameter ForeignCallDescriptor descriptor );
519
-
520
496
/**
521
497
* Block until I can transition from native to a new thread status. This is not inlined and need
522
498
* not be fast. In fact, it often blocks. But it can not do much except block, since it starts
523
499
* out running with "native" thread status.
524
500
*
525
- * Foreign call: {@link #ENTER_SLOW_PATH_TRANSITION_FROM_NATIVE_TO_NEW_STATUS}.
526
- *
527
501
* This method cannot use the {@link StubCallingConvention} with callee saved registers: the
528
502
* reference map of the C call and this slow-path call must be the same. This is only guaranteed
529
503
* when both the C call and the call to this slow path do not use callee saved registers.
@@ -543,27 +517,27 @@ private static void enterSlowPathTransitionFromNativeToNewStatus(int newStatus,
543
517
}
544
518
}
545
519
546
- @ NodeIntrinsic (value = ForeignCallNode .class )
547
- private static native void callSlowPathNativeToNewStatus (@ ConstantNodeParameter ForeignCallDescriptor descriptor , int newThreadStatus , boolean popFrameAnchor );
548
-
549
520
/**
550
- * Transitions from VM to Java do not need a safepoint check. We only need to make sure that any
551
- * {@link ActionOnTransitionToJavaSupport pending transition action} is executed.
552
- *
553
- * Foreign call: {@link #ENTER_SLOW_PATH_TRANSITION_FROM_VM_TO_JAVA}.
521
+ * Runs any {@link ActionOnTransitionToJavaSupport pending transition actions}.
554
522
*
555
523
* This method cannot use the {@link StubCallingConvention} with callee saved registers: the
556
524
* reference map of the C call and this slow-path call must be the same. This is only guaranteed
557
525
* when both the C call and the call to this slow path do not use callee saved registers.
558
526
*/
559
- @ SubstrateForeignCallTarget (stubCallingConvention = false )
527
+ @ SubstrateForeignCallTarget (stubCallingConvention = false , fullyUninterruptible = true )
560
528
@ Uninterruptible (reason = "Must not contain safepoint checks." )
561
- private static void enterSlowPathTransitionFromVMToJava () {
529
+ private static void enterSlowPathRunPendingActions () {
562
530
VMError .guarantee (StatusSupport .isStatusJava (), "Must be already back in Java mode" );
563
-
564
- slowPathRunJavaStateActions ();
531
+ assert ActionOnTransitionToJavaSupport . isActionPending () : "must not be called otherwise" ;
532
+ ActionOnTransitionToJavaSupport . runPendingActions ();
565
533
}
566
534
535
+ @ NodeIntrinsic (value = ForeignCallNode .class )
536
+ private static native void callRunPendingActions (@ ConstantNodeParameter ForeignCallDescriptor descriptor );
537
+
538
+ @ NodeIntrinsic (value = ForeignCallNode .class )
539
+ private static native void callSlowPathNativeToNewStatus (@ ConstantNodeParameter ForeignCallDescriptor descriptor , int newThreadStatus , boolean popFrameAnchor );
540
+
567
541
/** Methods for the thread that brings the system to a safepoint. */
568
542
@ AutomaticallyRegisteredImageSingleton
569
543
public static final class Master {
0 commit comments