[Python-checkins] bpo-44032: Move pointer to code object from frame-object to frame specials array. (GH-26771)
markshannon
webhook-mailer at python.org
Fri Jun 18 06:00:50 EDT 2021
https://github.com/python/cpython/commit/0982ded179f280176868c1c4eccf77bf70687816
commit: 0982ded179f280176868c1c4eccf77bf70687816
branch: main
author: Mark Shannon <mark at hotpy.org>
committer: markshannon <mark at hotpy.org>
date: 2021-06-18T11:00:29+01:00
summary:
bpo-44032: Move pointer to code object from frame-object to frame specials array. (GH-26771)
files:
M Include/cpython/frameobject.h
M Include/internal/pycore_frame.h
M Lib/test/test_sys.py
M Objects/frameobject.c
M Python/ceval.c
M Tools/gdb/libpython.py
diff --git a/Include/cpython/frameobject.h b/Include/cpython/frameobject.h
index fc20bc2ff89b0c..2bf458cab35451 100644
--- a/Include/cpython/frameobject.h
+++ b/Include/cpython/frameobject.h
@@ -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 */
diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h
index 44f58fb6948712..e30e3c89bfb62b 100644
--- a/Include/internal/pycore_frame.h
+++ b/Include/internal/pycore_frame.h
@@ -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 **
@@ -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
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 40fb721f3fa595..a549d44c5210fc 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -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'))
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 5057313870c60b..f9090d8cb14d27 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -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);
}
}
@@ -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);
@@ -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;
}
@@ -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;
@@ -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 */
@@ -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);
@@ -643,7 +650,7 @@ frame_dealloc(PyFrameObject *f)
PyObject_GC_Del(f);
}
- Py_DECREF(co);
+ Py_XDECREF(co);
Py_TRASHCAN_SAFE_END(f)
}
@@ -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]);
@@ -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);
@@ -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);
@@ -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);
@@ -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;
@@ -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];
@@ -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++) {
@@ -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;
diff --git a/Python/ceval.c b/Python/ceval.c
index a9b9aca0399035..699cd865faa1be 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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) {
@@ -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);
}
}
@@ -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);
@@ -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;
@@ -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];
@@ -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);
@@ -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);
@@ -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);
diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py
index 756b52c3c57a61..0198500265be41 100755
--- a/Tools/gdb/libpython.py
+++ b/Tools/gdb/libpython.py
@@ -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'
@@ -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')
@@ -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):
'''
@@ -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
More information about the Python-checkins
mailing list