Skip to content

Commit f9def19

Browse files
committed
move PythonObjectLibrary mention higher up
1 parent 6fc5c0c commit f9def19

File tree

1 file changed

+38
-38
lines changed

1 file changed

+38
-38
lines changed

docs/contributor/IMPLEMENTATION_DETAILS.md

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
11
# Implementation Details
22

3+
### Abstract Operations on Python Objects
4+
5+
Many generic operations on Python objects in CPython are defined in the header
6+
files `abstract.c` and `abstract.h`. These operations are widely used and their
7+
interplay and intricacies are the cause for the conversion, error message, and
8+
control flow bugs when not mimicked correctly. Our current approach is to
9+
provide many of these abstract operations as part of the
10+
`PythonObjectLibrary`. Usually, this means there are at least two messages for
11+
each operation - one that takes a `ThreadState` argument, and one that
12+
doesn't. The intent is to allow passing of exception state and caller
13+
information similar to how we do it with the `PFrame` argument even across
14+
library messages, which cannot take a VirtualFrame.
15+
16+
All nodes that are used in message implementations must allow uncached
17+
usage. Often (e.g. in the case of the generic `CallNode`) they offer execute
18+
methods with and without frames. If a `ThreadState` was passed to the message, a
19+
frame to pass to the node can be reconstructed using
20+
`PArguments.frameForCall(threadState)`. Here's an example:
21+
22+
```java
23+
@ExportMessage
24+
long messageWithState(ThreadState state,
25+
@Cached CallNode callNode) {
26+
Object callable = ...
27+
28+
if (state != null) {
29+
return callNode.execute(PArguments.frameForCall(state), callable, arguments);
30+
} else {
31+
return callNode.execute(callable, arguments);
32+
}
33+
}
34+
```
35+
36+
*Note*: It is **always** preferable to call an `execute` method with a
37+
`VirtualFrame` when both one with and without exist! The reason is that this
38+
avoids materialization of the frame state in more cases, as described on the
39+
section on Python's global thread state above.
40+
341
### Python Global Thread State
442

543
In CPython, each stack frame is allocated on the heap, and there's a global
@@ -79,41 +117,3 @@ as needed, we use the same mechanism to also pass the currently handled
79117
exception. Unlike CPython we do not use a stack of currently handled exceptions,
80118
instead we utilize the call stack of Java by always passing the current exception
81119
and holding on to the last (if any) in a local variable.
82-
83-
### Abstract Operations on Python Objects
84-
85-
Many generic operations on Python objects in CPython are defined in the header
86-
files `abstract.c` and `abstract.h`. These operations are widely used and their
87-
interplay and intricacies are the cause for the conversion, error message, and
88-
control flow bugs when not mimicked correctly. Our current approach is to
89-
provide many of these abstract operations as part of the
90-
`PythonObjectLibrary`. Usually, this means there are at least two messages for
91-
each operation - one that takes a `ThreadState` argument, and one that
92-
doesn't. The intent is to allow passing of exception state and caller
93-
information similar to how we do it with the `PFrame` argument even across
94-
library messages, which cannot take a VirtualFrame.
95-
96-
All nodes that are used in message implementations must allow uncached
97-
usage. Often (e.g. in the case of the generic `CallNode`) they offer execute
98-
methods with and without frames. If a `ThreadState` was passed to the message, a
99-
frame to pass to the node can be reconstructed using
100-
`PArguments.frameForCall(threadState)`. Here's an example:
101-
102-
```java
103-
@ExportMessage
104-
long messageWithState(ThreadState state,
105-
@Cached CallNode callNode) {
106-
Object callable = ...
107-
108-
if (state != null) {
109-
return callNode.execute(PArguments.frameForCall(state), callable, arguments);
110-
} else {
111-
return callNode.execute(callable, arguments);
112-
}
113-
}
114-
```
115-
116-
*Note*: It is **always** preferable to call an `execute` method with a
117-
`VirtualFrame` when both one with and without exist! The reason is that this
118-
avoids materialization of the frame state in more cases, as described on the
119-
section on Python's global thread state above.

0 commit comments

Comments
 (0)