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 */
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 **
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
# frame
import inspect
x = inspect.currentframe()
- check(x, size('5P3i4cP'))
+ check(x, size('4P3i4cP'))
# function
def func(): pass
check(func, size('14P'))
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);
}
}
}
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);
/* 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;
}
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;
}
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 */
PyMem_Free(f->f_localsptr);
f->f_own_locals_memory = 0;
}
+ f->f_localsptr = NULL;
}
f->f_stackdepth = 0;
Py_XDECREF(f->f_back);
PyObject_GC_Del(f);
}
- Py_DECREF(co);
+ Py_XDECREF(co);
Py_TRASHCAN_SAFE_END(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]);
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);
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);
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);
_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;
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];
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++) {
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;
/* 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) {
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);
}
}
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);
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;
}
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];
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);
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);
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);
FRAME_SPECIALS_GLOBAL_OFFSET = 0
FRAME_SPECIALS_BUILTINS_OFFSET = 1
+FRAME_SPECIALS_CODE_OFFSET = 3
+FRAME_SPECIALS_SIZE = 4
class PyFrameObjectPtr(PyObjectPtr):
_typename = 'PyFrameObject'
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')
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):
'''
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