@@ -60,6 +60,7 @@ protected boolean onAdvance(int phase, int registeredParties) {
60
60
* per context. */
61
61
private volatile boolean active = false ;
62
62
63
+ private volatile SafepointPredicate filter ;
63
64
private volatile SafepointAction action ;
64
65
65
66
public SafepointManager (RubyContext context , RubyLanguage language ) {
@@ -155,12 +156,16 @@ private SafepointAction step(Node currentNode, boolean isDrivingThread, String r
155
156
// Wait for the assumption to be renewed
156
157
phaser .arriveAndAwaitAdvance ();
157
158
158
- // Read these while in the safepoint
159
- final SafepointAction deferredAction = SafepointAction . isDeferred ( action ) ? action : null ;
159
+ // Run the filter and read the action field while in the safepoint
160
+ SafepointAction deferredAction = null ;
160
161
161
162
try {
162
- if (action instanceof SafepointAction .Pure ) { // same as !deferred
163
- action .accept (thread , currentNode );
163
+ if (filter .test (thread )) {
164
+ if (SafepointAction .isDeferred (action )) {
165
+ deferredAction = action ;
166
+ } else {
167
+ action .accept (thread , currentNode );
168
+ }
164
169
}
165
170
} finally {
166
171
// Wait for other threads to finish their action
@@ -256,7 +261,8 @@ private void restoreDefaultInterruptHandler() {
256
261
}
257
262
258
263
@ TruffleBoundary
259
- public void pauseAllThreadsAndExecute (String reason , Node currentNode , SafepointAction action ) {
264
+ public void pauseAllThreadsAndExecute (String reason , Node currentNode , SafepointPredicate filter ,
265
+ SafepointAction action ) {
260
266
if (lock .isHeldByCurrentThread ()) {
261
267
throw new IllegalStateException ("Re-entered SafepointManager" );
262
268
}
@@ -266,20 +272,22 @@ public void pauseAllThreadsAndExecute(String reason, Node currentNode, Safepoint
266
272
poll (language , currentNode );
267
273
}
268
274
275
+ final SafepointAction deferredAction ;
269
276
try {
270
- pauseAllThreadsAndExecuteInternal (reason , currentNode , action );
277
+ deferredAction = pauseAllThreadsAndExecuteInternal (reason , currentNode , filter , action );
271
278
} finally {
272
279
lock .unlock ();
273
280
}
274
281
275
282
// Run deferred actions after leaving the SafepointManager lock.
276
- if (SafepointAction . isDeferred ( action ) ) {
283
+ if (deferredAction != null ) {
277
284
action .accept (context .getThreadManager ().getCurrentThread (), currentNode );
278
285
}
279
286
}
280
287
281
288
@ TruffleBoundary
282
- public void pauseAllThreadsAndExecuteFromNonRubyThread (String reason , SafepointAction action ) {
289
+ public void pauseAllThreadsAndExecuteFromNonRubyThread (String reason , SafepointPredicate filter ,
290
+ SafepointAction action ) {
283
291
if (lock .isHeldByCurrentThread ()) {
284
292
throw new IllegalStateException ("Re-entered SafepointManager" );
285
293
}
@@ -292,7 +300,7 @@ public void pauseAllThreadsAndExecuteFromNonRubyThread(String reason, SafepointA
292
300
try {
293
301
enterThread ();
294
302
try {
295
- pauseAllThreadsAndExecuteInternal (reason , null , action );
303
+ pauseAllThreadsAndExecuteInternal (reason , null , filter , action );
296
304
} finally {
297
305
leaveThread ();
298
306
}
@@ -318,27 +326,20 @@ public void pauseRubyThreadAndExecute(String reason, RubyThread rubyThread, Node
318
326
// fast path if we are already the right thread
319
327
action .accept (rubyThread , currentNode );
320
328
} else {
321
- final SafepointAction filteredAction ;
322
- if (action instanceof SafepointAction .Pure ) {
323
- filteredAction = (SafepointAction .Pure ) (thread , threadCurrentNode ) -> {
324
- if (thread == rubyThread &&
325
- threadManager .getRubyFiberFromCurrentJavaThread () == fiberManager .getCurrentFiber ()) {
326
- action .accept (thread , threadCurrentNode );
327
- }
328
- };
329
- } else {
330
- filteredAction = (thread , threadCurrentNode ) -> {
331
- if (thread == rubyThread &&
332
- threadManager .getRubyFiberFromCurrentJavaThread () == fiberManager .getCurrentFiber ()) {
333
- action .accept (thread , threadCurrentNode );
334
- }
335
- };
336
- }
337
- pauseAllThreadsAndExecute (reason , currentNode , filteredAction );
329
+ pauseAllThreadsAndExecute (
330
+ reason ,
331
+ currentNode ,
332
+ SafepointPredicate .currentFiberOfThread (context , rubyThread ),
333
+ action );
338
334
}
339
335
}
340
336
341
- private void pauseAllThreadsAndExecuteInternal (String reason , Node currentNode , SafepointAction action ) {
337
+ private SafepointAction pauseAllThreadsAndExecuteInternal (String reason , Node currentNode ,
338
+ SafepointPredicate filter ,
339
+ SafepointAction action ) {
340
+ assert lock .isHeldByCurrentThread ();
341
+
342
+ this .filter = filter ;
342
343
this .action = action ;
343
344
344
345
/* We need to invalidate first so the interrupted threads see the invalidation in poll() in their
@@ -347,7 +348,7 @@ private void pauseAllThreadsAndExecuteInternal(String reason, Node currentNode,
347
348
language .invalidateSafepointAssumption (reason );
348
349
interruptOtherThreads ();
349
350
350
- step (currentNode , true , reason );
351
+ return step (currentNode , true , reason );
351
352
}
352
353
353
354
private void interruptOtherThreads () {
0 commit comments