Skip to content

Commit 748261d

Browse files
committed
Use Primitive.use_cext_lock? to find out if the C ext lock should be used
1 parent eaaa1ce commit 748261d

File tree

6 files changed

+49
-61
lines changed

6 files changed

+49
-61
lines changed

lib/truffle/truffle/cext.rb

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,12 +1772,13 @@ def rb_data_object_wrap(ruby_class, data, mark, free)
17721772
def rb_data_typed_object_wrap(ruby_class, data, data_type, mark, free, size)
17731773
ruby_class = Object unless ruby_class
17741774
object = ruby_class.__send__(:__layout_allocate__)
1775+
use_cext_lock = Primitive.use_cext_lock?
17751776

17761777
rtypeddata = LIBTRUFFLERUBY.rb_tr_rtypeddata_create(data_type, data)
17771778
Primitive.object_hidden_var_set object, DATA_STRUCT, rtypeddata
17781779
Primitive.object_hidden_var_set object, DATA_MARKER, data_marker(LIBTRUFFLERUBY[:rb_tr_rtypeddata_run_marker], rtypeddata)
17791780
# Could use a simpler finalizer if Truffle::Interop.null?(free)
1780-
Primitive.objectspace_define_data_finalizer object, LIBTRUFFLERUBY[:rb_tr_rtypeddata_run_finalizer], rtypeddata
1781+
Primitive.objectspace_define_data_finalizer object, LIBTRUFFLERUBY[:rb_tr_rtypeddata_run_finalizer], rtypeddata, use_cext_lock
17811782

17821783
unless Truffle::Interop.null?(size)
17831784
Primitive.object_hidden_var_set object, DATA_MEMSIZER, data_sizer(LIBTRUFFLERUBY[:rb_tr_rtypeddata_run_memsizer], rtypeddata)
@@ -1789,10 +1790,8 @@ def rb_data_typed_object_wrap(ruby_class, data, data_type, mark, free, size)
17891790
object
17901791
end
17911792

1792-
def run_data_finalizer(function, data)
1793-
# TODO: Maybe we should not hold the C extension lock here, and instead save the result of Primitive.use_cext_lock?
1794-
# in DataObjectFinalizerReference from rb_data_object_wrap/rb_data_typed_object_wrap.
1795-
Primitive.call_with_cext_lock_and_frame POINTER_TO_VOID_WRAPPER, [function, data], nil, nil, CEXT_LOCK
1793+
def run_data_finalizer(function, data, use_cext_lock)
1794+
Primitive.call_with_cext_lock_and_frame POINTER_TO_VOID_WRAPPER, [function, data], nil, nil, use_cext_lock
17961795
end
17971796

17981797
def run_marker(obj)
@@ -1848,6 +1847,8 @@ def send_splatted(object, method, args)
18481847
end
18491848

18501849
def rb_block_call(object, method, args, func, data)
1850+
use_cext_lock = Primitive.use_cext_lock?
1851+
18511852
object.__send__(method, *args) do |*block_args|
18521853
Primitive.cext_unwrap(Primitive.call_with_cext_lock(RB_BLOCK_CALL_FUNC_WRAPPER, [ # Probably need to save the frame here for blocks.
18531854
func,
@@ -1856,7 +1857,7 @@ def rb_block_call(object, method, args, func, data)
18561857
block_args.size, # argc
18571858
Truffle::CExt.RARRAY_PTR(block_args), # argv
18581859
nil, # blockarg
1859-
]))
1860+
], use_cext_lock))
18601861
end
18611862
end
18621863

@@ -1933,6 +1934,8 @@ def rb_exec_recursive(func, obj, arg)
19331934
Truffle::Graal.always_split instance_method(:rb_exec_recursive)
19341935

19351936
def rb_catch_obj(tag, func, data)
1937+
use_cext_lock = Primitive.use_cext_lock?
1938+
19361939
catch tag do |caught|
19371940
Primitive.cext_unwrap(Primitive.call_with_cext_lock(RB_BLOCK_CALL_FUNC_WRAPPER, [
19381941
func,
@@ -1941,7 +1944,7 @@ def rb_catch_obj(tag, func, data)
19411944
0, # argc
19421945
nil, # argv
19431946
nil, # blockarg
1944-
]))
1947+
], use_cext_lock))
19451948
end
19461949
end
19471950

@@ -2026,7 +2029,8 @@ def rb_thread_create(fn, args)
20262029
end
20272030

20282031
def rb_thread_call_with_gvl(function, data)
2029-
Primitive.call_with_cext_lock(POINTER_TO_POINTER_WRAPPER, [function, data])
2032+
use_cext_lock = Primitive.use_cext_lock?
2033+
Primitive.call_with_cext_lock(POINTER_TO_POINTER_WRAPPER, [function, data], use_cext_lock)
20302034
end
20312035

20322036
def rb_thread_call_without_gvl(function, data1, unblock, data2)

lib/truffle/truffle/cext_ruby.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,7 @@ def rb_define_method(mod, name, function, argc)
3636

3737
# We must set block argument if given here so that the
3838
# `rb_block_*` functions will be able to find it by walking the stack.
39-
if use_cext_lock
40-
Primitive.call_with_cext_lock_and_frame_and_unwrap(wrapper, args, Primitive.caller_special_variables_if_available, block)
41-
else
42-
Primitive.call_with_frame_and_unwrap(wrapper, args, Primitive.caller_special_variables_if_available, block)
43-
end
39+
Primitive.call_with_cext_lock_and_frame_and_unwrap(wrapper, args, Primitive.caller_special_variables_if_available, block, use_cext_lock)
4440
end
4541

4642
# Even if the argc is -2, the arity number

src/main/java/org/truffleruby/cext/CExtNodes.java

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ Object callWithCExtLockAndFrame(
192192
@CachedLibrary(limit = "getCacheLimit()") InteropLibrary receivers,
193193
@Cached ArrayToObjectArrayNode arrayToObjectArrayNode,
194194
@Cached TranslateInteropExceptionNode translateInteropExceptionNode,
195+
@Cached InlinedConditionProfile lockCExtProfile,
195196
@Cached InlinedConditionProfile ownedProfile,
196197
@Cached RunMarkOnExitNode runMarksNode) {
197198
final ExtensionCallStack extensionStack = getLanguage()
@@ -201,8 +202,10 @@ Object callWithCExtLockAndFrame(
201202
extensionStack.push(keywordsGiven, specialVariables, block);
202203
try {
203204
final Object[] args = arrayToObjectArrayNode.executeToObjectArray(argsArray);
205+
final boolean lockCExt = lockCExtProfile.profile(this,
206+
getContext().getOptions().CEXT_LOCK && useCExtLock);
204207

205-
if (getContext().getOptions().CEXT_LOCK && useCExtLock) {
208+
if (lockCExt) {
206209
final ReentrantLock lock = getContext().getCExtensionsLock();
207210
boolean owned = ownedProfile.profile(this, lock.isHeldByCurrentThread());
208211

@@ -235,47 +238,21 @@ protected int getCacheLimit() {
235238
}
236239
}
237240

238-
@Primitive(name = "call_with_frame_and_unwrap")
239-
public abstract static class CallWithFrameAndUnwrapNode extends PrimitiveArrayArgumentsNode {
240-
241-
@Specialization
242-
Object callWithFrame(
243-
VirtualFrame frame, Object receiver, RubyArray argsArray, Object specialVariables, Object block,
244-
@CachedLibrary(limit = "getCacheLimit()") InteropLibrary receivers,
245-
@Cached ArrayToObjectArrayNode arrayToObjectArrayNode,
246-
@Cached TranslateInteropExceptionNode translateInteropExceptionNode,
247-
@Cached RunMarkOnExitNode runMarksNode,
248-
@Cached UnwrapNode unwrapNode) {
249-
final ExtensionCallStack extensionStack = getLanguage().getCurrentFiber().extensionCallStack;
250-
final boolean keywordsGiven = RubyArguments.getDescriptor(frame) instanceof KeywordArgumentsDescriptor;
251-
extensionStack.push(keywordsGiven, specialVariables, block);
252-
try {
253-
final Object[] args = arrayToObjectArrayNode.executeToObjectArray(argsArray);
254-
try {
255-
return unwrapNode.execute(this,
256-
InteropNodes.execute(this, receiver, args, receivers, translateInteropExceptionNode));
257-
} finally {
258-
runMarksNode.execute(this, extensionStack);
259-
}
260-
} finally {
261-
extensionStack.pop();
262-
}
263-
}
264-
265-
protected int getCacheLimit() {
266-
return getLanguage().options.DISPATCH_CACHE;
267-
}
268-
}
269-
270241
@Primitive(name = "call_with_cext_lock_and_frame_and_unwrap")
271242
public abstract static class CallWithCExtLockAndFrameAndUnwrapNode extends PrimitiveArrayArgumentsNode {
272243

273244
@Specialization
274245
Object callWithCExtLockAndFrame(
275-
VirtualFrame frame, Object receiver, RubyArray argsArray, Object specialVariables, Object block,
246+
VirtualFrame frame,
247+
Object receiver,
248+
RubyArray argsArray,
249+
Object specialVariables,
250+
Object block,
251+
boolean useCExtLock,
276252
@CachedLibrary(limit = "getCacheLimit()") InteropLibrary receivers,
277253
@Cached ArrayToObjectArrayNode arrayToObjectArrayNode,
278254
@Cached TranslateInteropExceptionNode translateInteropExceptionNode,
255+
@Cached InlinedConditionProfile lockCExtProfile,
279256
@Cached InlinedConditionProfile ownedProfile,
280257
@Cached RunMarkOnExitNode runMarksNode,
281258
@Cached UnwrapNode unwrapNode) {
@@ -284,8 +261,10 @@ Object callWithCExtLockAndFrame(
284261
extensionStack.push(keywordsGiven, specialVariables, block);
285262
try {
286263
final Object[] args = arrayToObjectArrayNode.executeToObjectArray(argsArray);
264+
final boolean lockCExt = lockCExtProfile.profile(this,
265+
getContext().getOptions().CEXT_LOCK && useCExtLock);
287266

288-
if (getContext().getOptions().CEXT_LOCK) {
267+
if (lockCExt) {
289268
final ReentrantLock lock = getContext().getCExtensionsLock();
290269
boolean owned = ownedProfile.profile(this, lock.isHeldByCurrentThread());
291270

@@ -323,17 +302,19 @@ protected int getCacheLimit() {
323302
@Primitive(name = "call_with_cext_lock")
324303
public abstract static class CallWithCExtLockNode extends PrimitiveArrayArgumentsNode {
325304

326-
public abstract Object execute(Object receiver, RubyArray argsArray);
305+
public abstract Object execute(Object receiver, RubyArray argsArray, boolean useCExtLock);
327306

328307
@Specialization
329-
Object callWithCExtLock(Object receiver, RubyArray argsArray,
308+
Object callWithCExtLock(Object receiver, RubyArray argsArray, boolean useCExtLock,
330309
@CachedLibrary(limit = "getCacheLimit()") InteropLibrary receivers,
331310
@Cached ArrayToObjectArrayNode arrayToObjectArrayNode,
332311
@Cached TranslateInteropExceptionNode translateInteropExceptionNode,
312+
@Cached InlinedConditionProfile lockCExtProfile,
333313
@Cached InlinedConditionProfile ownedProfile) {
334314
Object[] args = arrayToObjectArrayNode.executeToObjectArray(argsArray);
315+
final boolean lockCExt = lockCExtProfile.profile(this, getContext().getOptions().CEXT_LOCK && useCExtLock);
335316

336-
if (getContext().getOptions().CEXT_LOCK) {
317+
if (lockCExt) {
337318
final ReentrantLock lock = getContext().getCExtensionsLock();
338319
boolean owned = ownedProfile.profile(this, lock.isHeldByCurrentThread());
339320

@@ -496,15 +477,15 @@ boolean startNewHandleBlock() {
496477
}
497478
}
498479

499-
@CoreMethod(names = "cext_lock_owned?", onSingleton = true)
480+
@Primitive(name = "cext_lock_owned?")
500481
public abstract static class IsCExtLockOwnedPrimitiveNode extends PrimitiveArrayArgumentsNode {
501482
@Specialization
502483
boolean isCExtLockOwned() {
503484
return getContext().getCExtensionsLock().isHeldByCurrentThread();
504485
}
505486
}
506487

507-
@CoreMethod(names = "use_cext_lock?", onSingleton = true)
488+
@Primitive(name = "use_cext_lock?")
508489
public abstract static class UseCExtLockNode extends PrimitiveArrayArgumentsNode {
509490
@Specialization
510491
boolean useCExtLock() {

src/main/java/org/truffleruby/core/DataObjectFinalizationService.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public Object execute(DataObjectFinalizerReference ref) {
5050
if (!getContext().isFinalizing()) {
5151
try {
5252
callNode.invokeMember(getContext().getCoreLibrary().truffleCExtModule, "run_data_finalizer",
53-
ref.finalizerCFunction, ref.dataStruct);
53+
ref.finalizerCFunction, ref.dataStruct, ref.useCExtLock);
5454
} catch (InteropException e) {
5555
throw CompilerDirectives.shouldNotReachHere(e);
5656
}
@@ -73,17 +73,19 @@ public DataObjectFinalizationService(RubyLanguage language, ReferenceProcessor r
7373

7474
@TruffleBoundary
7575
public DataObjectFinalizerReference addFinalizer(RubyContext context, Object object, Object finalizerCFunction,
76-
Object dataStruct) {
77-
final DataObjectFinalizerReference newRef = createRef(object, finalizerCFunction, dataStruct);
76+
Object dataStruct, boolean useCExtLock) {
77+
final DataObjectFinalizerReference newRef = createRef(object, finalizerCFunction, dataStruct, useCExtLock);
7878

7979
add(newRef);
8080
context.getReferenceProcessor().processReferenceQueue(this);
8181

8282
return newRef;
8383
}
8484

85-
public DataObjectFinalizerReference createRef(Object object, Object finalizerCFunction, Object dataStruct) {
86-
return new DataObjectFinalizerReference(object, processingQueue, this, finalizerCFunction, dataStruct);
85+
public DataObjectFinalizerReference createRef(Object object, Object finalizerCFunction, Object dataStruct,
86+
boolean useCExtLock) {
87+
return new DataObjectFinalizerReference(object, processingQueue, this, finalizerCFunction, dataStruct,
88+
useCExtLock);
8789
}
8890

8991
@Override

src/main/java/org/truffleruby/core/DataObjectFinalizerReference.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,19 @@ public final class DataObjectFinalizerReference
1919

2020
public final Object finalizerCFunction;
2121
public final Object dataStruct;
22+
/** Run a finalizer with or without c-extension lock. It depends on a context where a finalizer was registered. */
23+
public final boolean useCExtLock;
2224

2325
DataObjectFinalizerReference(
2426
Object object,
2527
ReferenceQueue<? super Object> queue,
2628
DataObjectFinalizationService service,
2729
Object finalizerCFunction,
28-
Object dataStruct) {
30+
Object dataStruct,
31+
boolean useCExtLock) {
2932
super(object, queue, service);
3033
this.finalizerCFunction = finalizerCFunction;
3134
this.dataStruct = dataStruct;
35+
this.useCExtLock = useCExtLock;
3236
}
3337
}

src/main/java/org/truffleruby/core/objectspace/ObjectSpaceNodes.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,12 @@ private void defineFinalizer(RubyDynamicObject object, Object finalizer) {
263263
public abstract static class DefineDataObjectFinalizerNode extends PrimitiveArrayArgumentsNode {
264264

265265
@Specialization
266-
Object defineFinalizer(RubyDynamicObject object, Object finalizerCFunction, Object dataStruct,
266+
Object defineFinalizer(
267+
RubyDynamicObject object, Object finalizerCFunction, Object dataStruct, boolean useCExtLock,
267268
@CachedLibrary(limit = "1") DynamicObjectLibrary objectLibrary) {
268269
DataObjectFinalizerReference newRef = getContext()
269270
.getDataObjectFinalizationService()
270-
.addFinalizer(getContext(), object, finalizerCFunction, dataStruct);
271+
.addFinalizer(getContext(), object, finalizerCFunction, dataStruct, useCExtLock);
271272

272273
objectLibrary.put(object, Layouts.DATA_OBJECT_FINALIZER_REF_IDENTIFIER, newRef);
273274

0 commit comments

Comments
 (0)