From c31e356a10aa60b5967b9aaf80b9984059e46461 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Wed, 4 Jan 2023 13:37:06 +0000 Subject: [PATCH] gh-100720: refactor calculation of number of frame slots for a code object into the new function _PyFrame_NumSlotsForCodeObject (#100722) --- Include/internal/pycore_frame.h | 11 ++++++++++- .../2023-01-03-16-50-42.gh-issue-100720.UhE7P-.rst | 1 + Objects/frameobject.c | 2 +- Objects/genobject.c | 4 ++-- Tools/build/deepfreeze.py | 1 + 5 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-03-16-50-42.gh-issue-100720.UhE7P-.rst diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index f18723b303224f..d5c1dcc82a883d 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -92,7 +92,16 @@ static inline void _PyFrame_StackPush(_PyInterpreterFrame *f, PyObject *value) { f->stacktop++; } -#define FRAME_SPECIALS_SIZE ((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)) +#define FRAME_SPECIALS_SIZE ((int)((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *))) + +static inline int +_PyFrame_NumSlotsForCodeObject(PyCodeObject *code) +{ + /* This function needs to remain in sync with the calculation of + * co_framesize in Tools/build/deepfreeze.py */ + assert(code->co_framesize >= FRAME_SPECIALS_SIZE); + return code->co_framesize - FRAME_SPECIALS_SIZE; +} void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest); diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-03-16-50-42.gh-issue-100720.UhE7P-.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-03-16-50-42.gh-issue-100720.UhE7P-.rst new file mode 100644 index 00000000000000..4c194eccf8a5cc --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-01-03-16-50-42.gh-issue-100720.UhE7P-.rst @@ -0,0 +1 @@ +Added ``_PyFrame_NumSlotsForCodeObject``, which returns the number of slots needed in a frame for a given code object. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index eab85c08fc0165..98f0b3838723da 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -946,7 +946,7 @@ frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) Py_ssize_t res; res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus); PyCodeObject *code = f->f_frame->f_code; - res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *); + res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *); return PyLong_FromSsize_t(res); } diff --git a/Objects/genobject.c b/Objects/genobject.c index c006f1af2177f9..ea3382d3e31a34 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -769,7 +769,7 @@ gen_sizeof(PyGenObject *gen, PyObject *Py_UNUSED(ignored)) Py_ssize_t res; res = offsetof(PyGenObject, gi_iframe) + offsetof(_PyInterpreterFrame, localsplus); PyCodeObject *code = gen->gi_code; - res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *); + res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *); return PyLong_FromSsize_t(res); } @@ -850,7 +850,7 @@ static PyObject * make_gen(PyTypeObject *type, PyFunctionObject *func) { PyCodeObject *code = (PyCodeObject *)func->func_code; - int slots = code->co_nlocalsplus + code->co_stacksize; + int slots = _PyFrame_NumSlotsForCodeObject(code); PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, slots); if (gen == NULL) { return NULL; diff --git a/Tools/build/deepfreeze.py b/Tools/build/deepfreeze.py index 7f4e24280133f2..e4b422820f7db7 100644 --- a/Tools/build/deepfreeze.py +++ b/Tools/build/deepfreeze.py @@ -262,6 +262,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str: self.field(code, "co_argcount") self.field(code, "co_posonlyargcount") self.field(code, "co_kwonlyargcount") + # The following should remain in sync with _PyFrame_NumSlotsForCodeObject self.write(f".co_framesize = {code.co_stacksize + len(localsplusnames)} + FRAME_SPECIALS_SIZE,") self.field(code, "co_stacksize") self.field(code, "co_firstlineno")