@@ -29,11 +29,15 @@ into the interpreter has a `PFrame.Reference` with no caller.
29
29
30
30
###### ExecutionContext.CallContext and ExecutionContext.CalleeContext
31
31
32
- If we're only calling between Python, we always pass our ` PFrame.Reference ` as
33
- implicit argument to any callees. On entry, they will create their own
34
- ` PFrame.Reference ` as the next link in this backwards-connected
35
- linked-list. Usually the ` PFrame.Reference ` doesn't hold anything else, so this
36
- is pretty cheap even in the not inlined case.
32
+ If we're only calling between Python, we pass our ` PFrame.Reference ` as implicit
33
+ argument to any callees. On entry, they will create their own ` PFrame.Reference `
34
+ as the next link in this backwards-connected linked-list. As an optimization, we
35
+ use assumptions both on the calling node as well as on the callee root node to
36
+ avoid passing the reference (in the caller) and linking it (on the callee
37
+ side). This assumption is invalidated the first time the reference is actually
38
+ needed. But even then, often the ` PFrame.Reference ` doesn't hold on to anything
39
+ else, because it was only used for traversal, so this is pretty cheap even in
40
+ the not inlined case.
37
41
38
42
When an event forces the frame to materialize on the heap, the reference is
39
43
filled. This is usually only the case when someone uses ` sys._getframe ` or
@@ -44,10 +48,10 @@ frames that are no longer live, e.g. when an exception was a few frames up. To
44
48
ensure this, we set a boolean flag on ` PFrame.Reference ` to mark it as "escaped"
45
49
when it is attached to an exception (or anything else), but not accessed,
46
50
yet. Whenever a Python call returns and its ` PFrame.Reference ` was marked such,
47
- the "PyFrame" is also filled in. This way, the stack is lazily forced to the
48
- heap as we return from functions. If we're lucky and it is never actually
49
- accessed * and* the calls are all inlined, those fill-in operations can be
50
- escape-analyzed away.
51
+ the "PyFrame" is also filled in by copying from the VirtualFrame. This way, the
52
+ stack is lazily forced to the heap as we return from functions. If we're lucky
53
+ and it is never actually accessed * and* the calls are all inlined, those fill-in
54
+ operations can be escape-analyzed away.
51
55
52
56
To implement all this, we use the ExecutionContext.CallContext and
53
57
ExecutionContext.CalleeContext classes. These also use profiling information to
0 commit comments