Skip to content

Commit d105cac

Browse files
committed
Trim frame and generator by word each.
1 parent c33abbf commit d105cac

File tree

6 files changed

+19
-23
lines changed

6 files changed

+19
-23
lines changed

Include/cpython/genobject.h

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ extern "C" {
1313
and coroutine objects. */
1414
#define _PyGenObject_HEAD(prefix) \
1515
PyObject_HEAD \
16-
/* Note: gi_frame can be NULL if the generator is "finished" */ \
1716
/* The code object backing the generator */ \
1817
PyCodeObject *prefix##_code; \
1918
/* List of weak reference. */ \

Include/internal/pycore_frame.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ typedef struct _interpreter_frame {
4141
PyObject *f_locals; /* Strong reference, may be NULL */
4242
PyCodeObject *f_code; /* Strong reference */
4343
PyFrameObject *frame_obj; /* Strong reference, may be NULL */
44-
PyObject *generator; /* Borrowed reference, may be NULL */
4544
struct _interpreter_frame *previous;
4645
int f_lasti; /* Last instruction if called */
4746
int stacktop; /* Offset of TOS from localsplus */
4847
PyFrameState f_state; /* What state the frame is in */
4948
bool is_entry; // Whether this is the "root" frame for the current CFrame.
49+
bool is_generator;
5050
PyObject *localsplus[1];
5151
} InterpreterFrame;
5252

@@ -100,10 +100,10 @@ _PyFrame_InitializeSpecials(
100100
frame->f_locals = Py_XNewRef(locals);
101101
frame->stacktop = nlocalsplus;
102102
frame->frame_obj = NULL;
103-
frame->generator = NULL;
104103
frame->f_lasti = -1;
105104
frame->f_state = FRAME_CREATED;
106105
frame->is_entry = false;
106+
frame->is_generator = false;
107107
}
108108

109109
/* Gets the pointer to the locals array

Objects/frameobject.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ frame_dealloc(PyFrameObject *f)
626626
{
627627
/* It is the responsibility of the owning generator/coroutine
628628
* to have cleared the generator pointer */
629-
assert(f->f_frame->generator == NULL);
629+
assert(!f->f_frame->is_generator);
630630

631631
if (_PyObject_GC_IS_TRACKED(f)) {
632632
_PyObject_GC_UNTRACK(f);
@@ -699,8 +699,10 @@ frame_clear(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
699699
"cannot clear an executing frame");
700700
return NULL;
701701
}
702-
if (f->f_frame->generator) {
703-
_PyGen_Finalize(f->f_frame->generator);
702+
if (f->f_frame->is_generator) {
703+
assert(!f->f_owns_frame);
704+
PyObject *gen = (PyObject *)(((char *)f->f_frame)-offsetof(PyGenObject, gi_iframe));
705+
_PyGen_Finalize(gen);
704706
}
705707
(void)frame_tp_clear(f);
706708
Py_RETURN_NONE;

Objects/genobject.c

+9-13
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ gen_dealloc(PyGenObject *gen)
133133
if (gen->gi_frame_valid) {
134134
InterpreterFrame *frame = (InterpreterFrame *)gen->gi_iframe;
135135
gen->gi_frame_valid = 0;
136-
frame->generator = NULL;
136+
frame->is_generator = false;
137137
frame->previous = NULL;
138138
_PyFrame_Clear(frame);
139139
}
@@ -265,7 +265,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
265265
/* first clean reference cycle through stored exception traceback */
266266
_PyErr_ClearExcState(&gen->gi_exc_state);
267267

268-
frame->generator = NULL;
268+
frame->is_generator = false;
269269
gen->gi_frame_valid = 0;
270270
_PyFrame_Clear(frame);
271271
*presult = result;
@@ -896,16 +896,12 @@ make_gen(PyTypeObject *type, PyFunctionObject *func)
896896
gen->gi_weakreflist = NULL;
897897
gen->gi_exc_state.exc_value = NULL;
898898
gen->gi_exc_state.previous_item = NULL;
899-
if (func->func_name != NULL)
900-
gen->gi_name = func->func_name;
901-
else
902-
gen->gi_name = gen->gi_code->co_name;
903-
Py_INCREF(gen->gi_name);
904-
if (func->func_qualname != NULL)
905-
gen->gi_qualname = func->func_qualname;
906-
else
907-
gen->gi_qualname = gen->gi_name;
908-
Py_INCREF(gen->gi_qualname);
899+
assert(func->func_name != NULL);
900+
Py_INCREF(func->func_name);
901+
gen->gi_name = func->func_name;
902+
assert(func->func_qualname != NULL);
903+
Py_INCREF(func->func_qualname);
904+
gen->gi_qualname = func->func_qualname;
909905
_PyObject_GC_TRACK(gen);
910906
return (PyObject *)gen;
911907
}
@@ -976,7 +972,7 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
976972
assert(frame->frame_obj == f);
977973
f->f_owns_frame = 0;
978974
f->f_frame = frame;
979-
frame->generator = (PyObject *) gen;
975+
frame->is_generator = true;
980976
assert(PyObject_GC_IsTracked((PyObject *)f));
981977
gen->gi_code = PyFrame_GetCode(f);
982978
Py_INCREF(gen->gi_code);

Python/ceval.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5056,7 +5056,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
50565056
assert(frame->frame_obj == NULL);
50575057
frame->f_locals = NULL;
50585058
gen->gi_frame_valid = 1;
5059-
gen_frame->generator = (PyObject *)gen;
5059+
gen_frame->is_generator = true;
50605060
gen_frame->f_state = FRAME_CREATED;
50615061
_Py_LeaveRecursiveCall(tstate);
50625062
if (!frame->is_entry) {

Python/frame.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ _PyFrame_Copy(InterpreterFrame *src, InterpreterFrame *dest)
5555
static inline void
5656
clear_specials(InterpreterFrame *frame)
5757
{
58-
frame->generator = NULL;
5958
Py_XDECREF(frame->frame_obj);
6059
Py_XDECREF(frame->f_locals);
6160
Py_DECREF(frame->f_func);
@@ -95,8 +94,8 @@ void
9594
_PyFrame_Clear(InterpreterFrame * frame)
9695
{
9796
/* It is the responsibility of the owning generator/coroutine
98-
* to have cleared the generator pointer */
99-
assert(frame->generator == NULL);
97+
* to have cleared the enclosing generator, if any. */
98+
assert(!frame->is_generator);
10099
if (frame->frame_obj) {
101100
PyFrameObject *f = frame->frame_obj;
102101
frame->frame_obj = NULL;

0 commit comments

Comments
 (0)