Skip to content

Commit

Permalink
bpo-44032: Move pointer to code object from frame-object to frame spe…
Browse files Browse the repository at this point in the history
…cials array. (GH-26771)
  • Loading branch information
markshannon committed Jun 18, 2021
1 parent 7f01f77 commit 0982ded
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 41 deletions.
1 change: 0 additions & 1 deletion Include/cpython/frameobject.h
Expand Up @@ -22,7 +22,6 @@ typedef signed char PyFrameState;
struct _frame {
PyObject_HEAD
struct _frame *f_back; /* previous frame, or NULL */
PyCodeObject *f_code; /* code segment */
PyObject **f_valuestack; /* points after the last local */
PyObject *f_trace; /* Trace function */
/* Borrowed reference to a generator, or NULL */
Expand Down
10 changes: 9 additions & 1 deletion Include/internal/pycore_frame.h
Expand Up @@ -8,7 +8,8 @@ enum {
FRAME_SPECIALS_GLOBALS_OFFSET = 0,
FRAME_SPECIALS_BUILTINS_OFFSET = 1,
FRAME_SPECIALS_LOCALS_OFFSET = 2,
FRAME_SPECIALS_SIZE = 3
FRAME_SPECIALS_CODE_OFFSET = 3,
FRAME_SPECIALS_SIZE = 4
};

static inline PyObject **
Expand All @@ -30,6 +31,13 @@ _PyFrame_GetBuiltins(PyFrameObject *f)
return _PyFrame_Specials(f)[FRAME_SPECIALS_BUILTINS_OFFSET];
}

/* Returns a *borrowed* reference. */
static inline PyCodeObject *
_PyFrame_GetCode(PyFrameObject *f)
{
return (PyCodeObject *)_PyFrame_Specials(f)[FRAME_SPECIALS_CODE_OFFSET];
}

int _PyFrame_TakeLocals(PyFrameObject *f);

#ifdef __cplusplus
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_sys.py
Expand Up @@ -1275,7 +1275,7 @@ class C(object): pass
# frame
import inspect
x = inspect.currentframe()
check(x, size('5P3i4cP'))
check(x, size('4P3i4cP'))
# function
def func(): pass
check(func, size('14P'))
Expand Down
39 changes: 23 additions & 16 deletions Objects/frameobject.c
Expand Up @@ -46,7 +46,7 @@ PyFrame_GetLineNumber(PyFrameObject *f)
return f->f_lineno;
}
else {
return PyCode_Addr2Line(f->f_code, f->f_lasti*2);
return PyCode_Addr2Line(_PyFrame_GetCode(f), f->f_lasti*2);
}
}

Expand Down Expand Up @@ -472,7 +472,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
}
new_lineno = (int)l_new_lineno;

if (new_lineno < f->f_code->co_firstlineno) {
if (new_lineno < _PyFrame_GetCode(f)->co_firstlineno) {
PyErr_Format(PyExc_ValueError,
"line %d comes before the current code block",
new_lineno);
Expand All @@ -481,8 +481,8 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore

/* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this
* should never overflow. */
int len = (int)(PyBytes_GET_SIZE(f->f_code->co_code) / sizeof(_Py_CODEUNIT));
int *lines = marklines(f->f_code, len);
int len = (int)(PyBytes_GET_SIZE(_PyFrame_GetCode(f)->co_code) / sizeof(_Py_CODEUNIT));
int *lines = marklines(_PyFrame_GetCode(f), len);
if (lines == NULL) {
return -1;
}
Expand All @@ -496,7 +496,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
return -1;
}

int64_t *stacks = mark_stacks(f->f_code, len);
int64_t *stacks = mark_stacks(_PyFrame_GetCode(f), len);
if (stacks == NULL) {
PyMem_Free(lines);
return -1;
Expand Down Expand Up @@ -610,11 +610,17 @@ frame_dealloc(PyFrameObject *f)
}

Py_TRASHCAN_SAFE_BEGIN(f)
PyCodeObject *co = f->f_code;
PyCodeObject *co = NULL;

/* Kill all local variables including specials. */
if (f->f_localsptr) {
for (int i = 0; i < co->co_nlocalsplus+FRAME_SPECIALS_SIZE; i++) {
/* Don't clear code object until the end */
co = _PyFrame_GetCode(f);
PyObject **specials = _PyFrame_Specials(f);
Py_CLEAR(specials[FRAME_SPECIALS_GLOBALS_OFFSET]);
Py_CLEAR(specials[FRAME_SPECIALS_BUILTINS_OFFSET]);
Py_CLEAR(specials[FRAME_SPECIALS_LOCALS_OFFSET]);
for (int i = 0; i < co->co_nlocalsplus; i++) {
Py_CLEAR(f->f_localsptr[i]);
}
/* Free items on stack */
Expand All @@ -625,6 +631,7 @@ frame_dealloc(PyFrameObject *f)
PyMem_Free(f->f_localsptr);
f->f_own_locals_memory = 0;
}
f->f_localsptr = NULL;
}
f->f_stackdepth = 0;
Py_XDECREF(f->f_back);
Expand All @@ -643,7 +650,7 @@ frame_dealloc(PyFrameObject *f)
PyObject_GC_Del(f);
}

Py_DECREF(co);
Py_XDECREF(co);
Py_TRASHCAN_SAFE_END(f)
}

Expand Down Expand Up @@ -683,7 +690,7 @@ frame_tp_clear(PyFrameObject *f)
f->f_state = FRAME_CLEARED;

Py_CLEAR(f->f_trace);
PyCodeObject *co = f->f_code;
PyCodeObject *co = _PyFrame_GetCode(f);
/* locals */
for (int i = 0; i < co->co_nlocalsplus; i++) {
Py_CLEAR(f->f_localsptr[i]);
Expand Down Expand Up @@ -722,7 +729,7 @@ 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_code;
PyCodeObject *code = _PyFrame_GetCode(f);
res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *);
}
return PyLong_FromSsize_t(res);
Expand All @@ -735,7 +742,7 @@ static PyObject *
frame_repr(PyFrameObject *f)
{
int lineno = PyFrame_GetLineNumber(f);
PyCodeObject *code = f->f_code;
PyCodeObject *code = _PyFrame_GetCode(f);
return PyUnicode_FromFormat(
"<frame at %p, file %R, line %d, code %S>",
f, code->co_filename, lineno, code->co_name);
Expand Down Expand Up @@ -876,7 +883,7 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyFrameConstructor *con, PyObject *l
PyObject **specials = f->f_localsptr + code->co_nlocalsplus;
f->f_valuestack = specials + FRAME_SPECIALS_SIZE;
f->f_back = (PyFrameObject*)Py_XNewRef(tstate->frame);
f->f_code = (PyCodeObject *)Py_NewRef(con->fc_code);
specials[FRAME_SPECIALS_CODE_OFFSET] = Py_NewRef(con->fc_code);
specials[FRAME_SPECIALS_BUILTINS_OFFSET] = Py_NewRef(con->fc_builtins);
specials[FRAME_SPECIALS_GLOBALS_OFFSET] = Py_NewRef(con->fc_globals);
specials[FRAME_SPECIALS_LOCALS_OFFSET] = Py_XNewRef(locals);
Expand Down Expand Up @@ -921,7 +928,7 @@ static int
_PyFrame_OpAlreadyRan(PyFrameObject *f, int opcode, int oparg)
{
const _Py_CODEUNIT *code =
(const _Py_CODEUNIT *)PyBytes_AS_STRING(f->f_code->co_code);
(const _Py_CODEUNIT *)PyBytes_AS_STRING(_PyFrame_GetCode(f)->co_code);
for (int i = 0; i < f->f_lasti; i++) {
if (_Py_OPCODE(code[i]) == opcode && _Py_OPARG(code[i]) == oparg) {
return 1;
Expand All @@ -948,7 +955,7 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f)
if (locals == NULL)
return -1;
}
co = f->f_code;
co = _PyFrame_GetCode(f);
fast = f->f_localsptr;
for (int i = 0; i < co->co_nlocalsplus; i++) {
_PyLocalsPlusKind kind = co->co_localspluskinds[i];
Expand Down Expand Up @@ -1041,7 +1048,7 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
if (locals == NULL)
return;
fast = f->f_localsptr;
co = f->f_code;
co = _PyFrame_GetCode(f);

PyErr_Fetch(&error_type, &error_value, &error_traceback);
for (int i = 0; i < co->co_nlocalsplus; i++) {
Expand Down Expand Up @@ -1134,7 +1141,7 @@ PyCodeObject *
PyFrame_GetCode(PyFrameObject *frame)
{
assert(frame != NULL);
PyCodeObject *code = frame->f_code;
PyCodeObject *code = _PyFrame_GetCode(frame);
assert(code != NULL);
Py_INCREF(code);
return code;
Expand Down
23 changes: 12 additions & 11 deletions Python/ceval.c
Expand Up @@ -1451,7 +1451,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
/* push frame */
tstate->frame = f;
specials = f->f_valuestack - FRAME_SPECIALS_SIZE;
co = f->f_code;
co = (PyCodeObject *)specials[FRAME_SPECIALS_CODE_OFFSET];

if (cframe.use_tracing) {
if (tstate->c_tracefunc != NULL) {
Expand Down Expand Up @@ -5388,9 +5388,10 @@ call_trace_protected(Py_tracefunc func, PyObject *obj,
static void
initialize_trace_info(PyTraceInfo *trace_info, PyFrameObject *frame)
{
if (trace_info->code != frame->f_code) {
trace_info->code = frame->f_code;
_PyCode_InitAddressRange(frame->f_code, &trace_info->bounds);
PyCodeObject *code = _PyFrame_GetCode(frame);
if (trace_info->code != code) {
trace_info->code = code;
_PyCode_InitAddressRange(code, &trace_info->bounds);
}
}

Expand All @@ -5405,7 +5406,7 @@ call_trace(Py_tracefunc func, PyObject *obj,
tstate->tracing++;
tstate->cframe->use_tracing = 0;
if (frame->f_lasti < 0) {
frame->f_lineno = frame->f_code->co_firstlineno;
frame->f_lineno = _PyFrame_GetCode(frame)->co_firstlineno;
}
else {
initialize_trace_info(&tstate->trace_info, frame);
Expand Down Expand Up @@ -5684,7 +5685,7 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
int result = cf->cf_flags != 0;

if (current_frame != NULL) {
const int codeflags = current_frame->f_code->co_flags;
const int codeflags = _PyFrame_GetCode(current_frame)->co_flags;
const int compilerflags = codeflags & PyCF_MASK;
if (compilerflags) {
result = 1;
Expand Down Expand Up @@ -6289,7 +6290,7 @@ unicode_concatenate(PyThreadState *tstate, PyObject *v, PyObject *w,
}
case STORE_NAME:
{
PyObject *names = f->f_code->co_names;
PyObject *names = _PyFrame_GetCode(f)->co_names;
PyObject *name = GETITEM(names, oparg);
PyObject *locals = f->f_valuestack[
FRAME_SPECIALS_LOCALS_OFFSET-FRAME_SPECIALS_SIZE];
Expand Down Expand Up @@ -6376,7 +6377,7 @@ dtrace_function_entry(PyFrameObject *f)
const char *funcname;
int lineno;

PyCodeObject *code = f->f_code;
PyCodeObject *code = _PyFrame_GetCode(f);
filename = PyUnicode_AsUTF8(code->co_filename);
funcname = PyUnicode_AsUTF8(code->co_name);
lineno = PyFrame_GetLineNumber(f);
Expand All @@ -6391,7 +6392,7 @@ dtrace_function_return(PyFrameObject *f)
const char *funcname;
int lineno;

PyCodeObject *code = f->f_code;
PyCodeObject *code = _PyFrame_GetCode(f);
filename = PyUnicode_AsUTF8(code->co_filename);
funcname = PyUnicode_AsUTF8(code->co_name);
lineno = PyFrame_GetLineNumber(f);
Expand All @@ -6418,10 +6419,10 @@ maybe_dtrace_line(PyFrameObject *frame,
if (line != frame->f_lineno || frame->f_lasti < instr_prev) {
if (line != -1) {
frame->f_lineno = line;
co_filename = PyUnicode_AsUTF8(frame->f_code->co_filename);
co_filename = PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_filename);
if (!co_filename)
co_filename = "?";
co_name = PyUnicode_AsUTF8(frame->f_code->co_name);
co_name = PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_name);
if (!co_name)
co_name = "?";
PyDTrace_LINE(co_filename, co_name, line);
Expand Down
25 changes: 14 additions & 11 deletions Tools/gdb/libpython.py
Expand Up @@ -856,6 +856,8 @@ def proxyval(self, visited):

FRAME_SPECIALS_GLOBAL_OFFSET = 0
FRAME_SPECIALS_BUILTINS_OFFSET = 1
FRAME_SPECIALS_CODE_OFFSET = 3
FRAME_SPECIALS_SIZE = 4

class PyFrameObjectPtr(PyObjectPtr):
_typename = 'PyFrameObject'
Expand All @@ -864,7 +866,7 @@ def __init__(self, gdbval, cast_to=None):
PyObjectPtr.__init__(self, gdbval, cast_to)

if not self.is_optimized_out():
self.co = PyCodeObjectPtr.from_pyobject_ptr(self.field('f_code'))
self.co = self._f_code()
self.co_name = self.co.pyop_field('co_name')
self.co_filename = self.co.pyop_field('co_filename')

Expand All @@ -890,11 +892,18 @@ def iter_locals(self):
pyop_name = PyObjectPtr.from_pyobject_ptr(self.co_localsplusnames[i])
yield (pyop_name, pyop_value)

def _f_specials(self, index, cls=PyObjectPtr):
f_valuestack = self.field('f_valuestack')
return cls.from_pyobject_ptr(f_valuestack[index - FRAME_SPECIALS_SIZE])

def _f_globals(self):
f_localsplus = self.field('f_localsptr')
nlocalsplus = int_from_int(self.co.field('co_nlocalsplus'))
index = nlocalsplus + FRAME_SPECIALS_GLOBAL_OFFSET
return PyObjectPtr.from_pyobject_ptr(f_localsplus[index])
return self._f_specials(FRAME_SPECIALS_GLOBAL_OFFSET)

def _f_builtins(self):
return self._f_specials(FRAME_SPECIALS_BUILTINS_OFFSET)

def _f_code(self):
return self._f_specials(FRAME_SPECIALS_CODE_OFFSET, PyCodeObjectPtr)

def iter_globals(self):
'''
Expand All @@ -907,12 +916,6 @@ def iter_globals(self):
pyop_globals = self._f_globals()
return pyop_globals.iteritems()

def _f_builtins(self):
f_localsplus = self.field('f_localsptr')
nlocalsplus = int_from_int(self.co.field('co_nlocalsplus'))
index = nlocalsplus + FRAME_SPECIALS_BUILTINS_OFFSET
return PyObjectPtr.from_pyobject_ptr(f_localsplus[index])

def iter_builtins(self):
'''
Yield a sequence of (name,value) pairs of PyObjectPtr instances, for
Expand Down

0 comments on commit 0982ded

Please sign in to comment.