Skip to content

Commit ca74971

Browse files
committed
Move to primitives for extension call stack and value wrapping.
1 parent d01f9b0 commit ca74971

File tree

3 files changed

+77
-34
lines changed

3 files changed

+77
-34
lines changed

lib/truffle/truffle/cext.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,11 @@ def to_native
200200
end
201201

202202
def [](index)
203-
Truffle::CExt.rb_tr_wrap(array[index])
203+
Truffle.invoke_primitive( :cext_wrap, array[index])
204204
end
205205

206206
def []=(index, value)
207-
array[index] = Truffle::CExt.rb_tr_unwrap(value)
207+
array[index] = Truffle.invoke_primitive( :cext_unwrap, value)
208208
end
209209

210210
def native?
@@ -1055,8 +1055,8 @@ def rb_path_to_class(path)
10551055

10561056
def rb_proc_new(function, value)
10571057
Proc.new do |*args|
1058-
Truffle::CExt.rb_tr_unwrap(
1059-
Truffle.invoke_primitive(:call_with_c_mutex, function, args.map! { |arg| Truffle::CExt.rb_tr_wrap(arg) }))
1058+
Truffle.invoke_primitive( :cext_unwrap,
1059+
Truffle.invoke_primitive(:call_with_c_mutex, function, args.map! { |arg| Truffle.invoke_primitive( :cext_wrap, arg) }))
10601060
end
10611061
end
10621062

@@ -1281,7 +1281,7 @@ def rb_eval_string(str)
12811281

12821282
def rb_define_alloc_func(ruby_class, function)
12831283
ruby_class.singleton_class.define_method(:__allocate__) do
1284-
Truffle::CExt.rb_tr_unwrap(Truffle.invoke_primitive(:call_with_c_mutex, function, [Truffle::CExt.rb_tr_wrap(self)]))
1284+
Truffle.invoke_primitive( :cext_unwrap, Truffle.invoke_primitive(:call_with_c_mutex, function, [Truffle.invoke_primitive( :cext_wrap, self)]))
12851285
end
12861286
class << ruby_class
12871287
private :__allocate__
@@ -1837,4 +1837,12 @@ def rb_sprintf(format, *args)
18371837
sprintf(f, *args) rescue raise ArgumentError, "Bad format string #{f}."
18381838
end
18391839

1840+
def rb_tr_wrap(obj)
1841+
Truffle.invoke_primitive :cext_wrap, obj
1842+
end
1843+
1844+
def rb_tr_unwrap(wrapper)
1845+
Truffle.invoke_primitive :cext_unwrap, wrapper
1846+
end
1847+
18401848
end

lib/truffle/truffle/cext_ruby.rb

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,22 @@ def rb_define_method(mod, name, function, argc)
1919

2020
method_body = Truffle::Graal.copy_captured_locals -> *args, &block do
2121
if argc == -1 # (int argc, VALUE *argv, VALUE obj)
22-
args = [args.size, Truffle::CExt.RARRAY_PTR(args), Truffle::CExt.rb_tr_wrap(self)]
22+
args = [args.size, Truffle::CExt.RARRAY_PTR(args), Truffle.invoke_primitive( :cext_wrap, self)]
2323
elsif argc == -2 # (VALUE obj, VALUE rubyArrayArgs)
24-
args = [Truffle::CExt.rb_tr_wrap(self), Truffle::CExt.rb_tr_wrap(args)]
24+
args = [Truffle.invoke_primitive( :cext_wrap, self), Truffle.invoke_primitive( :cext_wrap, args)]
2525
elsif argc >= 0 # (VALUE obj); (VALUE obj, VALUE arg1); (VALUE obj, VALUE arg1, VALUE arg2); ...
2626
if args.size != argc
2727
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected #{argc})"
2828
end
29-
args = [Truffle::CExt.rb_tr_wrap(self), *args.map! { |arg| Truffle::CExt.rb_tr_wrap(arg) }]
29+
args = [Truffle.invoke_primitive( :cext_wrap, self), *args.map! { |arg| Truffle.invoke_primitive( :cext_wrap, arg) }]
3030
end
3131

3232
# Using raw execute instead of #call here to avoid argument conversion
33-
Truffle::CExt.push_extension_call_frame(block)
34-
begin
35-
# We must call explicitly with the block argument if given
36-
# here so that the `rb_block_*` functions will be able to find
37-
# it by walking the stack.
38-
if block
39-
Truffle::CExt.rb_tr_unwrap(Truffle.invoke_primitive(:call_with_c_mutex, function, args, &block))
40-
else
41-
Truffle::CExt.rb_tr_unwrap(Truffle.invoke_primitive(:call_with_c_mutex, function, args))
42-
end
43-
ensure
44-
Truffle::CExt.pop_extension_call_frame
45-
end
33+
34+
# We must set block argument if given here so that the
35+
# `rb_block_*` functions will be able to find it by walking the
36+
# stack.
37+
Truffle.invoke_primitive( :cext_unwrap, Truffle.invoke_primitive(:call_with_c_mutex_and_frame, function, args, block))
4638
end
4739

4840
mod.define_method(name, method_body)
@@ -51,12 +43,7 @@ def rb_define_method(mod, name, function, argc)
5143
private
5244

5345
def rb_iterate_call_block(callback, block_arg, callback_arg, &block)
54-
Truffle::CExt.push_extension_call_frame(block)
55-
begin
56-
rb_tr_unwrap(Truffle.invoke_primitive(:call_with_c_mutex, callback, [rb_tr_wrap(block_arg), rb_tr_wrap(callback_arg)]))
57-
ensure
58-
Truffle::CExt.pop_extension_call_frame
59-
end
46+
rb_tr_unwrap(Truffle.invoke_primitive(:call_with_c_mutex_and_frame, callback, [rb_tr_wrap(block_arg), rb_tr_wrap(callback_arg)], block))
6047
end
6148

6249
def call_with_thread_locally_stored_block(function, *args, &block)
@@ -65,13 +52,11 @@ def call_with_thread_locally_stored_block(function, *args, &block)
6552
# TODO (pitr-ch 14-Dec-2017): This is fixed just for rb_iterate with a rb_funcall in it combination
6653

6754
previous_block = Thread.current[:__C_BLOCK__]
68-
Truffle::CExt.push_extension_call_frame(block)
6955
begin
7056
Thread.current[:__C_BLOCK__] = block
71-
rb_tr_unwrap(Truffle.invoke_primitive(:call_with_c_mutex, function, args.map! { |arg| Truffle::CExt.rb_tr_wrap(arg) }, &block))
57+
rb_tr_unwrap(Truffle.invoke_primitive(:call_with_c_mutex_and_frame, function, args.map! { |arg| Truffle.invoke_primitive( :cext_wrap, arg) }, block))
7258
ensure
7359
Thread.current[:__C_BLOCK__] = previous_block
74-
Truffle::CExt.pop_extension_call_frame
7560
end
7661
end
7762

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

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.truffleruby.cext.CExtNodesFactory.StringToNativeNodeGen;
4848
import org.truffleruby.core.CoreLibrary;
4949
import org.truffleruby.core.MarkingServiceNodes;
50+
import org.truffleruby.core.MarkingService.ExtensionCallStack;
5051
import org.truffleruby.core.array.ArrayHelpers;
5152
import org.truffleruby.core.array.ArrayOperationNodes;
5253
import org.truffleruby.core.array.ArrayStrategy;
@@ -155,6 +156,55 @@ private Object execute(TruffleObject receiver, Object[] args, Node executeNode,
155156

156157
}
157158

159+
@ImportStatic(Message.class)
160+
@Primitive(name = "call_with_c_mutex_and_frame")
161+
public abstract static class CallCWithMuteAndFramexNode extends PrimitiveArrayArgumentsNode {
162+
163+
@Specialization
164+
public Object callCWithMutex(VirtualFrame frame, TruffleObject receiver, DynamicObject argsArray, DynamicObject block,
165+
@Cached("create()") ArrayToObjectArrayNode arrayToObjectArrayNode,
166+
@Cached("EXECUTE.createNode()") Node executeNode,
167+
@Cached("create()") BranchProfile exceptionProfile,
168+
@Cached("createBinaryProfile()") ConditionProfile ownedProfile,
169+
@Cached("create()") MarkingServiceNodes.GetMarkerThreadLocalDataNode getDataNode) {
170+
final Object[] args = arrayToObjectArrayNode.executeToObjectArray(argsArray);
171+
ExtensionCallStack extensionStack = getDataNode.execute(frame).getExtensionCallStack();
172+
extensionStack.push(block);
173+
174+
try {
175+
if (getContext().getOptions().CEXT_LOCK) {
176+
final ReentrantLock lock = getContext().getCExtensionsLock();
177+
boolean owned = lock.isHeldByCurrentThread();
178+
179+
if (ownedProfile.profile(!owned)) {
180+
MutexOperations.lockInternal(getContext(), lock, this);
181+
try {
182+
return execute(receiver, args, executeNode, exceptionProfile);
183+
} finally {
184+
MutexOperations.unlockInternal(lock);
185+
}
186+
} else {
187+
return execute(receiver, args, executeNode, exceptionProfile);
188+
}
189+
} else {
190+
return execute(receiver, args, executeNode, exceptionProfile);
191+
}
192+
} finally {
193+
extensionStack.pop();
194+
}
195+
}
196+
197+
private Object execute(TruffleObject receiver, Object[] args, Node executeNode, BranchProfile exceptionProfile) {
198+
try {
199+
return ForeignAccess.sendExecute(executeNode, receiver, args);
200+
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
201+
exceptionProfile.enter();
202+
throw new JavaException(e);
203+
}
204+
}
205+
206+
}
207+
158208
@ImportStatic(Message.class)
159209
@Primitive(name = "call_without_c_mutex")
160210
public abstract static class CallCWithoutMutexNode extends PrimitiveArrayArgumentsNode {
@@ -1335,8 +1385,8 @@ public DynamicObject newManagedStruct(Object type) {
13351385

13361386
}
13371387

1338-
@CoreMethod(names = "rb_tr_wrap", onSingleton = true, required = 1)
1339-
public abstract static class WrapValueNode extends CoreMethodArrayArgumentsNode {
1388+
@Primitive(name = "cext_wrap", needsSelf = false)
1389+
public abstract static class WrapValueNode extends PrimitiveArrayArgumentsNode {
13401390

13411391
@Specialization
13421392
public TruffleObject wrapInt(Object value,
@@ -1349,8 +1399,8 @@ protected WrapNode createWrapNode() {
13491399
}
13501400
}
13511401

1352-
@CoreMethod(names = "rb_tr_unwrap", onSingleton = true, required = 1)
1353-
public abstract static class UnwrapValueNode extends CoreMethodArrayArgumentsNode {
1402+
@Primitive(name = "cext_unwrap", needsSelf = false)
1403+
public abstract static class UnwrapValueNode extends PrimitiveArrayArgumentsNode {
13541404

13551405
@Specialization
13561406
public Object unwrap(TruffleObject value,

0 commit comments

Comments
 (0)