|
53 | 53 | import com.oracle.truffle.api.dsl.NodeChild;
|
54 | 54 | import com.oracle.truffle.api.dsl.Specialization;
|
55 | 55 | import com.oracle.truffle.api.frame.FrameDescriptor;
|
| 56 | +import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; |
56 | 57 | import com.oracle.truffle.api.frame.FrameSlot;
|
57 | 58 | import com.oracle.truffle.api.frame.FrameSlotKind;
|
58 | 59 | import com.oracle.truffle.api.frame.FrameUtil;
|
59 | 60 | import com.oracle.truffle.api.frame.MaterializedFrame;
|
60 | 61 | import com.oracle.truffle.api.frame.VirtualFrame;
|
61 | 62 | import com.oracle.truffle.api.nodes.IndirectCallNode;
|
| 63 | +import com.oracle.truffle.api.nodes.Node; |
| 64 | +import com.oracle.truffle.api.nodes.RootNode; |
62 | 65 | import com.oracle.truffle.api.profiles.ConditionProfile;
|
| 66 | +import com.oracle.truffle.api.Truffle; |
63 | 67 |
|
64 | 68 | @CoreModule("Truffle::KernelOperations")
|
65 | 69 | public abstract class TruffleKernelNodes {
|
@@ -323,6 +327,38 @@ protected Object storage(VirtualFrame frame) {
|
323 | 327 | }
|
324 | 328 | }
|
325 | 329 |
|
| 330 | + /* When getting special variables from the wrong side of a C call we know it's going to be slow. */ |
| 331 | + @Primitive(name = "ruby_caller_special_variables") |
| 332 | + public abstract static class GetSlowCallerSpecialVariableStorage extends PrimitiveArrayArgumentsNode { |
| 333 | + |
| 334 | + @Child GetSpecialVariableStorage getStorageNode = GetSpecialVariableStorage.create(); |
| 335 | + |
| 336 | + @Specialization |
| 337 | + @TruffleBoundary |
| 338 | + protected Object storage() { |
| 339 | + return getStorageNode.execute(Truffle.getRuntime().iterateFrames(frameInstance -> { |
| 340 | + final Node callNode = frameInstance.getCallNode(); |
| 341 | + |
| 342 | + if (callNode != null) { |
| 343 | + final RootNode rootNode = callNode.getRootNode(); |
| 344 | + // Skip Ruby frames in cext.rb file since they are implementing methods which are implemented |
| 345 | + // with C in MRI, and therefore are also implicitly skipped when when looking up the block passed |
| 346 | + // to a C API function. |
| 347 | + if (rootNode instanceof RubyRootNode && |
| 348 | + rootNode.getSourceSection().isAvailable() && |
| 349 | + !rootNode.getSourceSection().getSource().getName().endsWith("cext.rb") && |
| 350 | + !rootNode.getSourceSection().getSource().getName().endsWith("cext_ruby.rb") && |
| 351 | + !getContext().getCoreLibrary().isSend( |
| 352 | + RubyArguments.tryGetMethod(frameInstance.getFrame(FrameAccess.READ_ONLY)))) { |
| 353 | + return frameInstance.getFrame(FrameAccess.MATERIALIZE).materialize(); |
| 354 | + } |
| 355 | + } |
| 356 | + |
| 357 | + return null; |
| 358 | + })); |
| 359 | + } |
| 360 | + } |
| 361 | + |
326 | 362 | @Primitive(name = "proc_special_variables")
|
327 | 363 | public abstract static class GetProcSpecialVariableStorage extends PrimitiveArrayArgumentsNode {
|
328 | 364 |
|
|
0 commit comments