Skip to content

Commit c31e356

Browse files
authored
gh-100720: refactor calculation of number of frame slots for a code object into the new function _PyFrame_NumSlotsForCodeObject (#100722)
1 parent 5fb1c08 commit c31e356

File tree

5 files changed

+15
-4
lines changed

5 files changed

+15
-4
lines changed

Include/internal/pycore_frame.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,16 @@ static inline void _PyFrame_StackPush(_PyInterpreterFrame *f, PyObject *value) {
9292
f->stacktop++;
9393
}
9494

95-
#define FRAME_SPECIALS_SIZE ((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *))
95+
#define FRAME_SPECIALS_SIZE ((int)((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)))
96+
97+
static inline int
98+
_PyFrame_NumSlotsForCodeObject(PyCodeObject *code)
99+
{
100+
/* This function needs to remain in sync with the calculation of
101+
* co_framesize in Tools/build/deepfreeze.py */
102+
assert(code->co_framesize >= FRAME_SPECIALS_SIZE);
103+
return code->co_framesize - FRAME_SPECIALS_SIZE;
104+
}
96105

97106
void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest);
98107

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added ``_PyFrame_NumSlotsForCodeObject``, which returns the number of slots needed in a frame for a given code object.

Objects/frameobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
946946
Py_ssize_t res;
947947
res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus);
948948
PyCodeObject *code = f->f_frame->f_code;
949-
res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *);
949+
res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *);
950950
return PyLong_FromSsize_t(res);
951951
}
952952

Objects/genobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ gen_sizeof(PyGenObject *gen, PyObject *Py_UNUSED(ignored))
769769
Py_ssize_t res;
770770
res = offsetof(PyGenObject, gi_iframe) + offsetof(_PyInterpreterFrame, localsplus);
771771
PyCodeObject *code = gen->gi_code;
772-
res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *);
772+
res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *);
773773
return PyLong_FromSsize_t(res);
774774
}
775775

@@ -850,7 +850,7 @@ static PyObject *
850850
make_gen(PyTypeObject *type, PyFunctionObject *func)
851851
{
852852
PyCodeObject *code = (PyCodeObject *)func->func_code;
853-
int slots = code->co_nlocalsplus + code->co_stacksize;
853+
int slots = _PyFrame_NumSlotsForCodeObject(code);
854854
PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, slots);
855855
if (gen == NULL) {
856856
return NULL;

Tools/build/deepfreeze.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
262262
self.field(code, "co_argcount")
263263
self.field(code, "co_posonlyargcount")
264264
self.field(code, "co_kwonlyargcount")
265+
# The following should remain in sync with _PyFrame_NumSlotsForCodeObject
265266
self.write(f".co_framesize = {code.co_stacksize + len(localsplusnames)} + FRAME_SPECIALS_SIZE,")
266267
self.field(code, "co_stacksize")
267268
self.field(code, "co_firstlineno")

0 commit comments

Comments
 (0)