8000 bpo-45786: Allocate space for frame in frame object. by markshannon · Pull Request #29729 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-45786: Allocate space for frame in frame object. #29729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Store interpreter frame in frameobject. Avoids allocation when frameo…
…bject outlive activation. WORK IN PROGRESS.
  • Loading branch information
markshannon committed Nov 23, 2021
commit 9da334f71eb283cc345133a133912fcdce9188b2
4 changes: 3 additions & 1 deletion Include/cpython/frameobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ struct _frame {
int f_lineno; /* Current line number. Only valid if non-zero */
char f_trace_lines; /* Emit per-line trace events? */
char f_trace_opcodes; /* Emit per-opcode trace events? */
char f_own_locals_memory; /* This frame owns the memory for the locals */
char f_owns_frame; /* This frame owns the frame */
/* The frame date, if this frame object owns the frame */
PyObject *_f_frame_data[1];
};

/* Standard object interface */
Expand Down
3 changes: 1 addition & 2 deletions Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ static inline void _PyFrame_StackPush(InterpreterFrame *f, PyObject *value) {

#define FRAME_SPECIALS_SIZE ((sizeof(InterpreterFrame)-1)/sizeof(PyObject *))

InterpreterFrame *
_PyInterpreterFrame_HeapAlloc(PyFrameConstructor *con, PyObject *locals);
InterpreterFrame *_PyFrame_Copy(InterpreterFrame *frame);

static inline void
_PyFrame_InitializeSpecials(
Expand Down
12 changes: 6 additions & 6 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -620,9 +620,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;
Expand All @@ -633,7 +634,6 @@ 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);
Expand Down Expand Up @@ -663,7 +663,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);
Expand Down Expand Up @@ -716,7 +716,7 @@ frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
{
Py_ssize_t res;
res = sizeof(PyFrameObject);
if (f->f_own_locals_memory) {
if (f->f_owns_frame) {
PyCodeObject *code = f->f_frame->f_code;
res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *);
}
Expand Down
13 changes: 9 additions & 4 deletions Objects/genobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -929,10 +929,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));

Expand Down
5 changes: 2 additions & 3 deletions Python/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ _PyFrame_MakeAndSetFrameObject(InterpreterFrame *frame)
return f;
}


static InterpreterFrame *
copy_frame_to_heap(InterpreterFrame *frame)
InterpreterFrame *
_PyFrame_Copy(InterpreterFrame *frame)
{
assert(frame->stacktop >= frame->f_code->co_nlocalsplus);
Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;
Expand Down
0