diff options
author | Mark Shannon <mark@hotpy.org> | 2021-11-29 12:34:59 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-29 12:34:59 (GMT) |
commit | 60929576e40038ec71d896230f69e4411c82be4b (patch) | |
tree | 34dc24d0a73ef0205514202820d66c152260dc22 /Objects | |
parent | 7431448b817d3bf87f71661cf8f3d537807ab2e2 (diff) | |
download | cpython-60929576e40038ec71d896230f69e4411c82be4b.zip cpython-60929576e40038ec71d896230f69e4411c82be4b.tar.gz cpython-60929576e40038ec71d896230f69e4411c82be4b.tar.bz2 |
bpo-45786: Allocate space for frame in frame object. (GH-29729)
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/frameobject.c | 141 | ||||
-rw-r--r-- | Objects/genobject.c | 22 |
2 files changed, 41 insertions, 122 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 2a283b3..926a32a 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -610,7 +610,7 @@ static PyGetSetDef frame_getsetlist[] = { f_back next item on free list, or NULL */ -static void _Py_HOT_FUNCTION +static void frame_dealloc(PyFrameObject *f) { if (_PyObject_GC_IS_TRACKED(f)) { @@ -621,9 +621,10 @@ frame_dealloc(PyFrameObject *f) PyCodeObject *co = NULL; /* Kill all local variables including specials, if we own them */ - if (f->f_own_locals_memory) { - f->f_own_locals_memory = 0; - InterpreterFrame *frame = f->f_frame; + if (f->f_owns_frame) { + f->f_owns_frame = 0; + assert(f->f_frame == (InterpreterFrame *)f->_f_frame_data); + InterpreterFrame *frame = (InterpreterFrame *)f->_f_frame_data; /* Don't clear code object until the end */ co = frame->f_code; frame->f_code = NULL; @@ -633,27 +634,10 @@ frame_dealloc(PyFrameObject *f) for (int i = 0; i < frame->stacktop; i++) { Py_CLEAR(locals[i]); } - PyMem_Free(frame); } Py_CLEAR(f->f_back); Py_CLEAR(f->f_trace); -#if PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = get_frame_state(); -#ifdef Py_DEBUG - // frame_dealloc() must not be called after _PyFrame_Fini() - assert(state->numfree != -1); -#endif - if (state->numfree < PyFrame_MAXFREELIST) { - ++state->numfree; - f->f_back = state->free_list; - state->free_list = f; - } - else -#endif - { - PyObject_GC_Del(f); - } - + PyObject_GC_Del(f); Py_XDECREF(co); Py_TRASHCAN_END; } @@ -663,7 +647,7 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg) { Py_VISIT(f->f_back); Py_VISIT(f->f_trace); - if (f->f_own_locals_memory == 0) { + if (f->f_owns_frame == 0) { return 0; } assert(f->f_frame->frame_obj == NULL); @@ -715,11 +699,9 @@ static PyObject * frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) { Py_ssize_t res; - res = sizeof(PyFrameObject); - if (f->f_own_locals_memory) { - PyCodeObject *code = f->f_frame->f_code; - res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *); - } + res = offsetof(PyFrameObject, _f_frame_data) + offsetof(InterpreterFrame, localsplus); + PyCodeObject *code = f->f_frame->f_code; + res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *); return PyLong_FromSsize_t(res); } @@ -747,7 +729,8 @@ static PyMethodDef frame_methods[] = { PyTypeObject PyFrame_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "frame", - sizeof(PyFrameObject), + offsetof(PyFrameObject, _f_frame_data) + + offsetof(InterpreterFrame, localsplus), sizeof(PyObject *), (destructor)frame_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ @@ -781,67 +764,21 @@ PyTypeObject PyFrame_Type = { _Py_IDENTIFIER(__builtins__); -static InterpreterFrame * -allocate_heap_frame(PyFunctionObject *func, PyObject *locals) +static void +init_frame(InterpreterFrame *frame, PyFunctionObject *func, PyObject *locals) { PyCodeObject *code = (PyCodeObject *)func->func_code; - int size = code->co_nlocalsplus+code->co_stacksize + FRAME_SPECIALS_SIZE; - InterpreterFrame *frame = (InterpreterFrame *)PyMem_Malloc(sizeof(PyObject *)*size); - if (frame == NULL) { - PyErr_NoMemory(); - return NULL; - } _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); for (Py_ssize_t i = 0; i < code->co_nlocalsplus; i++) { frame->localsplus[i] = NULL; } - return frame; } -static inline PyFrameObject* -frame_alloc(InterpreterFrame *frame, int owns) -{ - PyFrameObject *f; -#if PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = get_frame_state(); - if (state->free_list == NULL) -#endif - { - f = PyObject_GC_New(PyFrameObject, &PyFrame_Type); - if (f == NULL) { - if (owns) { - Py_XDECREF(frame->f_code); - Py_XDECREF(frame->f_builtins); - Py_XDECREF(frame->f_globals); - Py_XDECREF(frame->f_locals); - PyMem_Free(frame); - } - return NULL; - } - } -#if PyFrame_MAXFREELIST > 0 - else - { -#ifdef Py_DEBUG - // frame_alloc() must not be called after _PyFrame_Fini() - assert(state->numfree != -1); -#endif - assert(state->numfree > 0); - --state->numfree; - f = state->free_list; - state->free_list = state->free_list->f_back; - _Py_NewReference((PyObject *)f); - } -#endif - f->f_frame = frame; - f->f_own_locals_memory = owns; - return f; -} - -PyFrameObject* _Py_HOT_FUNCTION -_PyFrame_New_NoTrack(InterpreterFrame *frame, int owns) +PyFrameObject* +_PyFrame_New_NoTrack(PyCodeObject *code) { - PyFrameObject *f = frame_alloc(frame, owns); + int slots = code->co_nlocalsplus + code->co_stacksize; + PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots); if (f == NULL) { return NULL; } @@ -876,15 +813,16 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, if (func == NULL) { return NULL; } - InterpreterFrame *frame = allocate_heap_frame(func, locals); - Py_DECREF(func); - if (frame == NULL) { + PyFrameObject *f = _PyFrame_New_NoTrack(code); + if (f == NULL) { + Py_DECREF(func); return NULL; } - PyFrameObject *f = _PyFrame_New_NoTrack(frame, 1); - if (f) { - _PyObject_GC_TRACK(f); - } + init_frame((InterpreterFrame *)f->_f_frame_data, func, locals); + f->f_frame = (InterpreterFrame *)f->_f_frame_data; + f->f_owns_frame = 1; + Py_DECREF(func); + _PyObject_GC_TRACK(f); return f; } @@ -1087,42 +1025,15 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear) _PyFrame_LocalsToFast(f->f_frame, clear); } -/* Clear out the free list */ -void -_PyFrame_ClearFreeList(PyInterpreterState *interp) -{ -#if PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = &interp->frame; - while (state->free_list != NULL) { - PyFrameObject *f = state->free_list; - state->free_list = state->free_list->f_back; - PyObject_GC_Del(f); - --state->numfree; - } - assert(state->numfree == 0); -#endif -} - void _PyFrame_Fini(PyInterpreterState *interp) { - _PyFrame_ClearFreeList(interp); -#if defined(Py_DEBUG) && PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = &interp->frame; - state->numfree = -1; -#endif } /* Print summary info about the state of the optimized allocator */ void _PyFrame_DebugMallocStats(FILE *out) { -#if PyFrame_MAXFREELIST > 0 - struct _Py_frame_state *state = get_frame_state(); - _PyDebugAllocatorStats(out, - "free PyFrameObject", - state->numfree, sizeof(PyFrameObject)); -#endif } diff --git a/Objects/genobject.c b/Objects/genobject.c index 24d5f35..04d98a2 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -38,7 +38,7 @@ gen_traverse(PyGenObject *gen, visitproc visit, void *arg) Py_VISIT(gen->gi_qualname); InterpreterFrame *frame = gen->gi_xframe; if (frame != NULL) { - assert(frame->frame_obj == NULL || frame->frame_obj->f_own_locals_memory == 0); + assert(frame->frame_obj == NULL || frame->frame_obj->f_owns_frame == 0); int err = _PyFrame_Traverse(frame, visit, arg); if (err) { return err; @@ -136,7 +136,8 @@ gen_dealloc(PyGenObject *gen) gen->gi_xframe = NULL; frame->generator = NULL; frame->previous = NULL; - _PyFrame_Clear(frame, 1); + _PyFrame_Clear(frame); + PyMem_Free(frame); } if (((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE) { Py_CLEAR(((PyCoroObject *)gen)->cr_origin); @@ -254,7 +255,8 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, frame->generator = NULL; gen->gi_xframe = NULL; - _PyFrame_Clear(frame, 1); + _PyFrame_Clear(frame); + PyMem_Free(frame); *presult = result; return result ? PYGEN_RETURN : PYGEN_ERROR; } @@ -845,7 +847,8 @@ make_gen(PyTypeObject *type, PyFunctionObject *func, InterpreterFrame *frame) PyGenObject *gen = PyObject_GC_New(PyGenObject, type); if (gen == NULL) { assert(frame->frame_obj == NULL); - _PyFrame_Clear(frame, 1); + _PyFrame_Clear(frame); + PyMem_Free(frame); return NULL; } gen->gi_xframe = frame; @@ -929,10 +932,15 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, /* Take ownership of the frame */ assert(f->f_frame->frame_obj == NULL); - assert(f->f_own_locals_memory); - gen->gi_xframe = f->f_frame; + assert(f->f_owns_frame); + gen->gi_xframe = _PyFrame_Copy((InterpreterFrame *)f->_f_frame_data); + if (gen->gi_xframe == NULL) { + Py_DECREF(f); + Py_DECREF(gen); + return NULL; + } gen->gi_xframe->frame_obj = f; - f->f_own_locals_memory = 0; + f->f_owns_frame = 0; gen->gi_xframe->generator = (PyObject *) gen; assert(PyObject_GC_IsTracked((PyObject *)f)); |