Skip to content
Snippets Groups Projects
Commit d783b03d authored by Stepan Sindelar's avatar Stepan Sindelar
Browse files

[GR-2798] Update docs of RCaller and RArguments.

PullRequest: fastr/1593
parents 59822812 2897fed7
No related branches found
No related tags found
No related merge requests found
......@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
* +--------------------+
* INDEX_FUNCTION -> | RFunction |
* +--------------------+
* INDEX_CALL_SRC -> | SourceSection |
* INDEX_CALL -> | RCaller |
* +--------------------+
* INDEX_CALLER_FRAME -> | MaterializedFrame |
* +--------------------+
......@@ -81,11 +81,7 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
* to how the supplied arguments were permuted. The purpose of this slot is to store the names in the
* original signature (especially positional vs. named) for later use in UseMethod.
*
* N.B. The depth is always a monotonically increasing value and unique across the active set of stack frames.
* Promise evaluation requires some special support as the stack must reflect the "logical" stack depth,
* else code like {@code sys.frames} does not work correctly, but it must be possible to access the initial frame
* that was associated with the promise else condition handling does not work correctly. Accordingly the
* stack frames associated with a promise evaluation maintain the INDEX_PROMISE_FRAME field for that access.
* @see RCaller
*/
// @formatter:on
public final class RArguments {
......
......@@ -41,6 +41,42 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
* NOTE: It is important to create new caller instances for each stack frame, so that
* {@link ReturnException#getTarget()} can uniquely identify the target frame.
*
* Example:
*
* <pre>
* foo <- function(a) a
* bar <- function() foo(promiseFun(1))
* promiseFun <- function(a) a+1
* bar()
* </pre>
*
* When {@code promiseFun} is entered (which is at the point where {@code a} is evaluated in
* {@code foo}), the stack frames will look like:
*
* <pre>
* promiseFun (depth = 3, parent = bar, payload = "promiseFun(1)")
* internal frame (depth = 2, parent = global, payload = RCaller:bar) <-- this may not be a real Truffle execution frame!
* foo (depth = 2, parent = bar, payload = "foo(promiseFun(1))")
* bar (depth = 1, parent = global, payload = "bar()")
* global (depth = 0, parent = null, payload = null)
* </pre>
*
* Where the 'internal frame' wraps the frame of bar so that the promise code can access all the
* local variables of bar, but the {@link RCaller} can be different: the depth that would normally
* be 1 is 2, and parent and payload are different (see docs of {@link #isPromise()}). The purpose
* of {@link #payload} in such frames is that we can use it to reach the actual frame where the
* promise is logically evaluated, should the promise call some stack introspection built-in, e.g.
* {@code parent.frame()}. The reason why depths is 2 is that any consecutive function call uses
* current depth + 1 as the new depth and we need the new depth to be 3.
*
* Note that the 'internal frame' may not be on the real execution stack (i.e. not iterable by
* Truffle). The {@code InlineCacheNode} directly injects the AST of the promise into the calling
* function AST (foo in this case), but passes the 'internal frame' to the execute method instead of
* the current {@code VirtualFrame} (so that the injected AST thinks that it is executed inside bar
* and not foo). If the cache is full, then the {@code InlineCacheNode} creates a new
* {@link com.oracle.truffle.api.CallTarget} and calls it with 'internal frame', in which case the
* 'internal frame' appears in Truffle frames iteration.
*
* @see RArguments
*/
public final class RCaller {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment