|
30 | 30 | import org.truffleruby.builtins.Primitive;
|
31 | 31 | import org.truffleruby.builtins.PrimitiveArrayArgumentsNode;
|
32 | 32 | import org.truffleruby.builtins.YieldingCoreMethodNode;
|
33 |
| -import org.truffleruby.cext.CExtNodesFactory.CallWithCExtLockNodeFactory; |
34 | 33 | import org.truffleruby.cext.CExtNodesFactory.StringToNativeNodeGen;
|
35 | 34 | import org.truffleruby.cext.UnwrapNode.UnwrapCArrayNode;
|
36 | 35 | import org.truffleruby.core.MarkingService.ExtensionCallStack;
|
@@ -165,26 +164,56 @@ private static long getNativeStringCapacity(Pointer pointer) {
|
165 | 164 | @Primitive(name = "call_with_c_mutex_and_frame")
|
166 | 165 | public abstract static class CallWithCExtLockAndFrameNode extends PrimitiveArrayArgumentsNode {
|
167 | 166 |
|
168 |
| - @Child protected CallWithCExtLockNode callCextNode = CallWithCExtLockNodeFactory.create(RubyNode.EMPTY_ARRAY); |
169 | 167 | @Child protected MarkingServiceNodes.RunMarkOnExitNode runMarksNode = MarkingServiceNodes.RunMarkOnExitNode
|
170 | 168 | .create();
|
171 | 169 |
|
172 |
| - @Specialization |
| 170 | + @Specialization(limit = "getCacheLimit()") |
173 | 171 | protected Object callWithCExtLockAndFrame(
|
174 |
| - VirtualFrame frame, Object receiver, RubyArray argsArray, Object specialVariables, Object block) { |
175 |
| - final ExtensionCallStack extensionStack = getLanguage().getCurrentFiber().extensionCallStack; |
| 172 | + VirtualFrame frame, Object receiver, RubyArray argsArray, Object specialVariables, Object block, |
| 173 | + @CachedLibrary("receiver") InteropLibrary receivers, |
| 174 | + @Cached ArrayToObjectArrayNode arrayToObjectArrayNode, |
| 175 | + @Cached TranslateInteropExceptionNode translateInteropExceptionNode, |
| 176 | + @Cached ConditionProfile ownedProfile, |
| 177 | + @Cached MarkingServiceNodes.RunMarkOnExitNode runMarksNode) { |
| 178 | + final ExtensionCallStack extensionStack = getLanguage() |
| 179 | + .getCurrentThread() |
| 180 | + .getCurrentFiber().extensionCallStack; |
176 | 181 | final boolean keywordsGiven = RubyArguments.getDescriptor(frame) instanceof KeywordArgumentsDescriptor;
|
177 | 182 | extensionStack.push(keywordsGiven, specialVariables, block);
|
178 | 183 | try {
|
179 |
| - try { |
180 |
| - return callCextNode.execute(receiver, argsArray); |
181 |
| - } finally { |
182 |
| - runMarksNode.execute(extensionStack); |
| 184 | + final Object[] args = arrayToObjectArrayNode.executeToObjectArray(argsArray); |
| 185 | + |
| 186 | + if (getContext().getOptions().CEXT_LOCK) { |
| 187 | + final ReentrantLock lock = getContext().getCExtensionsLock(); |
| 188 | + boolean owned = ownedProfile.profile(lock.isHeldByCurrentThread()); |
| 189 | + |
| 190 | + if (!owned) { |
| 191 | + MutexOperations.lockInternal(getContext(), lock, this); |
| 192 | + } |
| 193 | + try { |
| 194 | + return InteropNodes.execute(receiver, args, receivers, translateInteropExceptionNode); |
| 195 | + } finally { |
| 196 | + runMarksNode.execute(extensionStack); |
| 197 | + if (!owned) { |
| 198 | + MutexOperations.unlockInternal(lock); |
| 199 | + } |
| 200 | + } |
| 201 | + } else { |
| 202 | + try { |
| 203 | + return InteropNodes.execute(receiver, args, receivers, translateInteropExceptionNode); |
| 204 | + } finally { |
| 205 | + runMarksNode.execute(extensionStack); |
| 206 | + } |
183 | 207 | }
|
| 208 | + |
184 | 209 | } finally {
|
185 | 210 | extensionStack.pop();
|
186 | 211 | }
|
187 | 212 | }
|
| 213 | + |
| 214 | + protected int getCacheLimit() { |
| 215 | + return getLanguage().options.DISPATCH_CACHE; |
| 216 | + } |
188 | 217 | }
|
189 | 218 |
|
190 | 219 | @Primitive(name = "call_with_c_mutex_and_frame_and_unwrap")
|
|
0 commit comments