@@ -53,12 +53,19 @@ typedef struct _cframe {
5353} CFrame ;
5454
5555typedef struct _err_stackitem {
56- /* This struct represents an entry on the exception stack, which is a
57- * per-coroutine state. (Coroutine in the computer science sense,
58- * including the thread and generators).
59- * This ensures that the exception state is not impacted by "yields"
60- * from an except handler.
56+ /* This struct represents a single execution context where we might
57+ * be currently handling an exception. It is a per-coroutine state
58+ * (coroutine in the computer science sense, including the thread
59+ * and generators).
60+ *
61+ * This is used as an entry on the exception stack, where each
62+ * entry indicates if it is currently handling an exception.
63+ * This ensures that the exception state is not impacted
64+ * by "yields" from an except handler. The thread
65+ * always has an entry (the bottom-most one).
6166 */
67+
68+ /* The exception currently being handled in this context, if any. */
6269 PyObject * exc_value ;
6370
6471 struct _err_stackitem * previous_item ;
@@ -112,13 +119,9 @@ struct _ts {
112119 PyObject * curexc_value ;
113120 PyObject * curexc_traceback ;
114121
115- /* The exception currently being handled, if no coroutines/generators
116- * are present. Always last element on the stack referred to be exc_info.
117- */
118- _PyErr_StackItem exc_state ;
119-
120- /* Pointer to the top of the stack of the exceptions currently
121- * being handled */
122+ /* Pointer to the top of the exception stack for the exceptions
123+ * we may be currently handling. (See _PyErr_StackItem above.)
124+ * This is never NULL. */
122125 _PyErr_StackItem * exc_info ;
123126
124127 PyObject * dict ; /* Stores per-thread state */
@@ -174,13 +177,26 @@ struct _ts {
174177 /* Unique thread state id. */
175178 uint64_t id ;
176179
177- CFrame root_cframe ;
178180 PyTraceInfo trace_info ;
179181
180182 _PyStackChunk * datastack_chunk ;
181183 PyObject * * datastack_top ;
182184 PyObject * * datastack_limit ;
183185 /* XXX signal handlers should also be here */
186+
187+ /* The following fields are here to avoid allocation during init.
188+ The data is exposed through PyThreadState pointer fields.
189+ These fields should not be accessed directly outside of init.
190+
191+ All other PyInterpreterState pointer fields are populated when
192+ needed and default to NULL.
193+ */
194+
195+ /* The thread's exception stack entry. (Always the last entry.) */
196+ _PyErr_StackItem _exc_state ;
197+
198+ /* The bottom-most frame on the stack. */
199+ CFrame _root_cframe ;
184200};
185201
186202
0 commit comments