mirror of https://github.com/python/cpython
GH-100987: Allow objects other than code objects as the "executable" of an internal frame. (GH-105727)
* Add table describing possible executable classes for out-of-process debuggers. * Remove shim code object creation code as it is no longer needed. * Make lltrace a bit more robust w.r.t. non-standard frames.
This commit is contained in:
parent
ad56340b66
commit
7199584ac8
|
@ -447,19 +447,6 @@ adaptive_counter_backoff(uint16_t counter) {
|
||||||
return adaptive_counter_bits(value, backoff);
|
return adaptive_counter_bits(value, backoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Line array cache for tracing */
|
|
||||||
|
|
||||||
typedef struct _PyShimCodeDef {
|
|
||||||
const uint8_t *code;
|
|
||||||
int codelen;
|
|
||||||
int stacksize;
|
|
||||||
const char *cname;
|
|
||||||
} _PyShimCodeDef;
|
|
||||||
|
|
||||||
extern PyCodeObject *
|
|
||||||
_Py_MakeShimCode(const _PyShimCodeDef *code);
|
|
||||||
|
|
||||||
extern uint32_t _Py_next_func_version;
|
extern uint32_t _Py_next_func_version;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ enum _frameowner {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _PyInterpreterFrame {
|
typedef struct _PyInterpreterFrame {
|
||||||
PyCodeObject *f_code; /* Strong reference */
|
PyObject *f_executable; /* Strong reference */
|
||||||
struct _PyInterpreterFrame *previous;
|
struct _PyInterpreterFrame *previous;
|
||||||
PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
|
PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
|
||||||
PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
|
PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
|
||||||
|
@ -73,20 +73,25 @@ typedef struct _PyInterpreterFrame {
|
||||||
} _PyInterpreterFrame;
|
} _PyInterpreterFrame;
|
||||||
|
|
||||||
#define _PyInterpreterFrame_LASTI(IF) \
|
#define _PyInterpreterFrame_LASTI(IF) \
|
||||||
((int)((IF)->prev_instr - _PyCode_CODE((IF)->f_code)))
|
((int)((IF)->prev_instr - _PyCode_CODE(_PyFrame_GetCode(IF))))
|
||||||
|
|
||||||
|
static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) {
|
||||||
|
assert(PyCode_Check(f->f_executable));
|
||||||
|
return (PyCodeObject *)f->f_executable;
|
||||||
|
}
|
||||||
|
|
||||||
static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) {
|
static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) {
|
||||||
return f->localsplus + f->f_code->co_nlocalsplus;
|
return f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline PyObject *_PyFrame_StackPeek(_PyInterpreterFrame *f) {
|
static inline PyObject *_PyFrame_StackPeek(_PyInterpreterFrame *f) {
|
||||||
assert(f->stacktop > f->f_code->co_nlocalsplus);
|
assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
|
||||||
assert(f->localsplus[f->stacktop-1] != NULL);
|
assert(f->localsplus[f->stacktop-1] != NULL);
|
||||||
return f->localsplus[f->stacktop-1];
|
return f->localsplus[f->stacktop-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline PyObject *_PyFrame_StackPop(_PyInterpreterFrame *f) {
|
static inline PyObject *_PyFrame_StackPop(_PyInterpreterFrame *f) {
|
||||||
assert(f->stacktop > f->f_code->co_nlocalsplus);
|
assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
|
||||||
f->stacktop--;
|
f->stacktop--;
|
||||||
return f->localsplus[f->stacktop];
|
return f->localsplus[f->stacktop];
|
||||||
}
|
}
|
||||||
|
@ -119,7 +124,7 @@ _PyFrame_Initialize(
|
||||||
PyObject *locals, PyCodeObject *code, int null_locals_from)
|
PyObject *locals, PyCodeObject *code, int null_locals_from)
|
||||||
{
|
{
|
||||||
frame->f_funcobj = (PyObject *)func;
|
frame->f_funcobj = (PyObject *)func;
|
||||||
frame->f_code = (PyCodeObject *)Py_NewRef(code);
|
frame->f_executable = Py_NewRef(code);
|
||||||
frame->f_builtins = func->func_builtins;
|
frame->f_builtins = func->func_builtins;
|
||||||
frame->f_globals = func->func_globals;
|
frame->f_globals = func->func_globals;
|
||||||
frame->f_locals = locals;
|
frame->f_locals = locals;
|
||||||
|
@ -172,8 +177,11 @@ _PyFrame_SetStackPointer(_PyInterpreterFrame *frame, PyObject **stack_pointer)
|
||||||
static inline bool
|
static inline bool
|
||||||
_PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
|
_PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
|
||||||
{
|
{
|
||||||
|
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return frame->owner != FRAME_OWNED_BY_GENERATOR &&
|
return frame->owner != FRAME_OWNED_BY_GENERATOR &&
|
||||||
frame->prev_instr < _PyCode_CODE(frame->f_code) + frame->f_code->_co_firsttraceable;
|
frame->prev_instr < _PyCode_CODE(_PyFrame_GetCode(frame)) + _PyFrame_GetCode(frame)->_co_firsttraceable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline _PyInterpreterFrame *
|
static inline _PyInterpreterFrame *
|
||||||
|
@ -272,6 +280,14 @@ PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
|
||||||
return (PyGenObject *)(((char *)frame) - offset_in_gen);
|
return (PyGenObject *)(((char *)frame) - offset_in_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PY_EXECUTABLE_KIND_SKIP 0
|
||||||
|
#define PY_EXECUTABLE_KIND_PY_FUNCTION 1
|
||||||
|
#define PY_EXECUTABLE_KIND_BUILTIN_FUNCTION 3
|
||||||
|
#define PY_EXECUTABLE_KIND_METHOD_DESCRIPTOR 4
|
||||||
|
#define PY_EXECUTABLE_KINDS 5
|
||||||
|
|
||||||
|
PyAPI_DATA(const PyTypeObject *) const PyUnstable_ExecutableKinds[PY_EXECUTABLE_KINDS+1];
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -565,7 +565,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(newline));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(newline));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(open_br));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(open_br));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(percent));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(percent));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(shim_name));
|
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(type_params));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(type_params));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(utf_8));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(utf_8));
|
||||||
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(CANCELLED));
|
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(CANCELLED));
|
||||||
|
|
|
@ -51,7 +51,6 @@ struct _Py_global_strings {
|
||||||
STRUCT_FOR_STR(newline, "\n")
|
STRUCT_FOR_STR(newline, "\n")
|
||||||
STRUCT_FOR_STR(open_br, "{")
|
STRUCT_FOR_STR(open_br, "{")
|
||||||
STRUCT_FOR_STR(percent, "%")
|
STRUCT_FOR_STR(percent, "%")
|
||||||
STRUCT_FOR_STR(shim_name, "<shim>")
|
|
||||||
STRUCT_FOR_STR(type_params, ".type_params")
|
STRUCT_FOR_STR(type_params, ".type_params")
|
||||||
STRUCT_FOR_STR(utf_8, "utf-8")
|
STRUCT_FOR_STR(utf_8, "utf-8")
|
||||||
} literals;
|
} literals;
|
||||||
|
|
|
@ -159,7 +159,6 @@ struct _is {
|
||||||
struct ast_state ast;
|
struct ast_state ast;
|
||||||
struct types_state types;
|
struct types_state types;
|
||||||
struct callable_cache callable_cache;
|
struct callable_cache callable_cache;
|
||||||
PyCodeObject *interpreter_trampoline;
|
|
||||||
_PyOptimizerObject *optimizer;
|
_PyOptimizerObject *optimizer;
|
||||||
uint16_t optimizer_resume_threshold;
|
uint16_t optimizer_resume_threshold;
|
||||||
uint16_t optimizer_backedge_threshold;
|
uint16_t optimizer_backedge_threshold;
|
||||||
|
|
|
@ -557,7 +557,6 @@ extern "C" {
|
||||||
INIT_STR(newline, "\n"), \
|
INIT_STR(newline, "\n"), \
|
||||||
INIT_STR(open_br, "{"), \
|
INIT_STR(open_br, "{"), \
|
||||||
INIT_STR(percent, "%"), \
|
INIT_STR(percent, "%"), \
|
||||||
INIT_STR(shim_name, "<shim>"), \
|
|
||||||
INIT_STR(type_params, ".type_params"), \
|
INIT_STR(type_params, ".type_params"), \
|
||||||
INIT_STR(utf_8, "utf-8"), \
|
INIT_STR(utf_8, "utf-8"), \
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Allow objects other than code objects as the "executable" in internal
|
||||||
|
frames. In the long term, this can help tools like Cython and PySpy interact
|
||||||
|
more efficiently. In the shorter term, it allows us to perform some
|
||||||
|
optimizations more simply.
|
|
@ -2316,76 +2316,3 @@ _PyStaticCode_Init(PyCodeObject *co)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_CODE_UNITS_PER_LOC_ENTRY 8
|
#define MAX_CODE_UNITS_PER_LOC_ENTRY 8
|
||||||
|
|
||||||
PyCodeObject *
|
|
||||||
_Py_MakeShimCode(const _PyShimCodeDef *codedef)
|
|
||||||
{
|
|
||||||
PyObject *name = NULL;
|
|
||||||
PyObject *co_code = NULL;
|
|
||||||
PyObject *lines = NULL;
|
|
||||||
PyCodeObject *codeobj = NULL;
|
|
||||||
uint8_t *loc_table = NULL;
|
|
||||||
|
|
||||||
name = _PyUnicode_FromASCII(codedef->cname, strlen(codedef->cname));
|
|
||||||
if (name == NULL) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
co_code = PyBytes_FromStringAndSize(
|
|
||||||
(const char *)codedef->code, codedef->codelen);
|
|
||||||
if (co_code == NULL) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
int code_units = codedef->codelen / sizeof(_Py_CODEUNIT);
|
|
||||||
int loc_entries = (code_units + MAX_CODE_UNITS_PER_LOC_ENTRY - 1) /
|
|
||||||
MAX_CODE_UNITS_PER_LOC_ENTRY;
|
|
||||||
loc_table = PyMem_Malloc(loc_entries);
|
|
||||||
if (loc_table == NULL) {
|
|
||||||
PyErr_NoMemory();
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < loc_entries-1; i++) {
|
|
||||||
loc_table[i] = 0x80 | (PY_CODE_LOCATION_INFO_NONE << 3) | 7;
|
|
||||||
code_units -= MAX_CODE_UNITS_PER_LOC_ENTRY;
|
|
||||||
}
|
|
||||||
assert(loc_entries > 0);
|
|
||||||
assert(code_units > 0 && code_units <= MAX_CODE_UNITS_PER_LOC_ENTRY);
|
|
||||||
loc_table[loc_entries-1] = 0x80 |
|
|
||||||
(PY_CODE_LOCATION_INFO_NONE << 3) | (code_units-1);
|
|
||||||
lines = PyBytes_FromStringAndSize((const char *)loc_table, loc_entries);
|
|
||||||
PyMem_Free(loc_table);
|
|
||||||
if (lines == NULL) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
_Py_DECLARE_STR(shim_name, "<shim>");
|
|
||||||
struct _PyCodeConstructor con = {
|
|
||||||
.filename = &_Py_STR(shim_name),
|
|
||||||
.name = name,
|
|
||||||
.qualname = name,
|
|
||||||
.flags = CO_NEWLOCALS | CO_OPTIMIZED,
|
|
||||||
|
|
||||||
.code = co_code,
|
|
||||||
.firstlineno = 1,
|
|
||||||
.linetable = lines,
|
|
||||||
|
|
||||||
.consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
|
|
||||||
.names = (PyObject *)&_Py_SINGLETON(tuple_empty),
|
|
||||||
|
|
||||||
.localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
|
|
||||||
.localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
|
|
||||||
|
|
||||||
.argcount = 0,
|
|
||||||
.posonlyargcount = 0,
|
|
||||||
.kwonlyargcount = 0,
|
|
||||||
|
|
||||||
.stacksize = codedef->stacksize,
|
|
||||||
|
|
||||||
.exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
|
|
||||||
};
|
|
||||||
|
|
||||||
codeobj = _PyCode_New(&con);
|
|
||||||
cleanup:
|
|
||||||
Py_XDECREF(name);
|
|
||||||
Py_XDECREF(co_code);
|
|
||||||
Py_XDECREF(lines);
|
|
||||||
return codeobj;
|
|
||||||
}
|
|
||||||
|
|
|
@ -642,6 +642,7 @@ _PyFrame_GetState(PyFrameObject *frame)
|
||||||
static int
|
static int
|
||||||
frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignored))
|
frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
|
PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
|
||||||
if (p_new_lineno == NULL) {
|
if (p_new_lineno == NULL) {
|
||||||
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
|
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -719,7 +720,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
|
||||||
}
|
}
|
||||||
new_lineno = (int)l_new_lineno;
|
new_lineno = (int)l_new_lineno;
|
||||||
|
|
||||||
if (new_lineno < f->f_frame->f_code->co_firstlineno) {
|
if (new_lineno < code->co_firstlineno) {
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"line %d comes before the current code block",
|
"line %d comes before the current code block",
|
||||||
new_lineno);
|
new_lineno);
|
||||||
|
@ -728,8 +729,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
|
/* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this
|
||||||
* should never overflow. */
|
* should never overflow. */
|
||||||
int len = (int)Py_SIZE(f->f_frame->f_code);
|
int len = (int)Py_SIZE(code);
|
||||||
int *lines = marklines(f->f_frame->f_code, len);
|
int *lines = marklines(code, len);
|
||||||
if (lines == NULL) {
|
if (lines == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -743,7 +744,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t *stacks = mark_stacks(f->f_frame->f_code, len);
|
int64_t *stacks = mark_stacks(code, len);
|
||||||
if (stacks == NULL) {
|
if (stacks == NULL) {
|
||||||
PyMem_Free(lines);
|
PyMem_Free(lines);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -788,7 +789,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
|
||||||
// in the new location. Rather than crashing or changing co_code, just bind
|
// in the new location. Rather than crashing or changing co_code, just bind
|
||||||
// None instead:
|
// None instead:
|
||||||
int unbound = 0;
|
int unbound = 0;
|
||||||
for (int i = 0; i < f->f_frame->f_code->co_nlocalsplus; i++) {
|
for (int i = 0; i < code->co_nlocalsplus; i++) {
|
||||||
// Counting every unbound local is overly-cautious, but a full flow
|
// Counting every unbound local is overly-cautious, but a full flow
|
||||||
// analysis (like we do in the compiler) is probably too expensive:
|
// analysis (like we do in the compiler) is probably too expensive:
|
||||||
unbound += f->f_frame->localsplus[i] == NULL;
|
unbound += f->f_frame->localsplus[i] == NULL;
|
||||||
|
@ -801,7 +802,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
|
||||||
}
|
}
|
||||||
// Do this in a second pass to avoid writing a bunch of Nones when
|
// Do this in a second pass to avoid writing a bunch of Nones when
|
||||||
// warnings are being treated as errors and the previous bit raises:
|
// warnings are being treated as errors and the previous bit raises:
|
||||||
for (int i = 0; i < f->f_frame->f_code->co_nlocalsplus; i++) {
|
for (int i = 0; i < code->co_nlocalsplus; i++) {
|
||||||
if (f->f_frame->localsplus[i] == NULL) {
|
if (f->f_frame->localsplus[i] == NULL) {
|
||||||
f->f_frame->localsplus[i] = Py_NewRef(Py_None);
|
f->f_frame->localsplus[i] = Py_NewRef(Py_None);
|
||||||
unbound--;
|
unbound--;
|
||||||
|
@ -832,7 +833,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
|
||||||
}
|
}
|
||||||
/* Finally set the new lasti and return OK. */
|
/* Finally set the new lasti and return OK. */
|
||||||
f->f_lineno = 0;
|
f->f_lineno = 0;
|
||||||
f->f_frame->prev_instr = _PyCode_CODE(f->f_frame->f_code) + best_addr;
|
f->f_frame->prev_instr = _PyCode_CODE(code) + best_addr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -886,15 +887,15 @@ frame_dealloc(PyFrameObject *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_TRASHCAN_BEGIN(f, frame_dealloc);
|
Py_TRASHCAN_BEGIN(f, frame_dealloc);
|
||||||
PyCodeObject *co = NULL;
|
PyObject *co = NULL;
|
||||||
|
|
||||||
/* Kill all local variables including specials, if we own them */
|
/* Kill all local variables including specials, if we own them */
|
||||||
if (f->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT) {
|
if (f->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT) {
|
||||||
assert(f->f_frame == (_PyInterpreterFrame *)f->_f_frame_data);
|
assert(f->f_frame == (_PyInterpreterFrame *)f->_f_frame_data);
|
||||||
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)f->_f_frame_data;
|
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)f->_f_frame_data;
|
||||||
/* Don't clear code object until the end */
|
/* Don't clear code object until the end */
|
||||||
co = frame->f_code;
|
co = frame->f_executable;
|
||||||
frame->f_code = NULL;
|
frame->f_executable = NULL;
|
||||||
Py_CLEAR(frame->f_funcobj);
|
Py_CLEAR(frame->f_funcobj);
|
||||||
Py_CLEAR(frame->f_locals);
|
Py_CLEAR(frame->f_locals);
|
||||||
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
||||||
|
@ -968,7 +969,7 @@ frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
Py_ssize_t res;
|
Py_ssize_t res;
|
||||||
res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus);
|
res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus);
|
||||||
PyCodeObject *code = f->f_frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
|
||||||
res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *);
|
res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *);
|
||||||
return PyLong_FromSsize_t(res);
|
return PyLong_FromSsize_t(res);
|
||||||
}
|
}
|
||||||
|
@ -980,7 +981,7 @@ static PyObject *
|
||||||
frame_repr(PyFrameObject *f)
|
frame_repr(PyFrameObject *f)
|
||||||
{
|
{
|
||||||
int lineno = PyFrame_GetLineNumber(f);
|
int lineno = PyFrame_GetLineNumber(f);
|
||||||
PyCodeObject *code = f->f_frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
|
||||||
return PyUnicode_FromFormat(
|
return PyUnicode_FromFormat(
|
||||||
"<frame at %p, file %R, line %d, code %S>",
|
"<frame at %p, file %R, line %d, code %S>",
|
||||||
f, code->co_filename, lineno, code->co_name);
|
f, code->co_filename, lineno, code->co_name);
|
||||||
|
@ -1102,7 +1103,7 @@ _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
|
||||||
// This only works when opcode is a non-quickened form:
|
// This only works when opcode is a non-quickened form:
|
||||||
assert(_PyOpcode_Deopt[opcode] == opcode);
|
assert(_PyOpcode_Deopt[opcode] == opcode);
|
||||||
int check_oparg = 0;
|
int check_oparg = 0;
|
||||||
for (_Py_CODEUNIT *instruction = _PyCode_CODE(frame->f_code);
|
for (_Py_CODEUNIT *instruction = _PyCode_CODE(_PyFrame_GetCode(frame));
|
||||||
instruction < frame->prev_instr; instruction++)
|
instruction < frame->prev_instr; instruction++)
|
||||||
{
|
{
|
||||||
int check_opcode = _PyOpcode_Deopt[instruction->op.code];
|
int check_opcode = _PyOpcode_Deopt[instruction->op.code];
|
||||||
|
@ -1128,7 +1129,7 @@ frame_init_get_vars(_PyInterpreterFrame *frame)
|
||||||
{
|
{
|
||||||
// COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
|
// COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
|
||||||
// here:
|
// here:
|
||||||
PyCodeObject *co = frame->f_code;
|
PyCodeObject *co = _PyFrame_GetCode(frame);
|
||||||
int lasti = _PyInterpreterFrame_LASTI(frame);
|
int lasti = _PyInterpreterFrame_LASTI(frame);
|
||||||
if (!(lasti < 0 && _PyCode_CODE(co)->op.code == COPY_FREE_VARS
|
if (!(lasti < 0 && _PyCode_CODE(co)->op.code == COPY_FREE_VARS
|
||||||
&& PyFunction_Check(frame->f_funcobj)))
|
&& PyFunction_Check(frame->f_funcobj)))
|
||||||
|
@ -1145,7 +1146,7 @@ frame_init_get_vars(_PyInterpreterFrame *frame)
|
||||||
frame->localsplus[offset + i] = Py_NewRef(o);
|
frame->localsplus[offset + i] = Py_NewRef(o);
|
||||||
}
|
}
|
||||||
// COPY_FREE_VARS doesn't have inline CACHEs, either:
|
// COPY_FREE_VARS doesn't have inline CACHEs, either:
|
||||||
frame->prev_instr = _PyCode_CODE(frame->f_code);
|
frame->prev_instr = _PyCode_CODE(_PyFrame_GetCode(frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1213,7 +1214,7 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
|
||||||
|
|
||||||
frame_init_get_vars(frame);
|
frame_init_get_vars(frame);
|
||||||
|
|
||||||
PyCodeObject *co = frame->f_code;
|
PyCodeObject *co = _PyFrame_GetCode(frame);
|
||||||
for (int i = 0; i < co->co_nlocalsplus; i++) {
|
for (int i = 0; i < co->co_nlocalsplus; i++) {
|
||||||
PyObject *value; // borrowed reference
|
PyObject *value; // borrowed reference
|
||||||
if (!frame_get_var(frame, co, i, &value)) {
|
if (!frame_get_var(frame, co, i, &value)) {
|
||||||
|
@ -1257,7 +1258,7 @@ PyFrame_GetVar(PyFrameObject *frame_obj, PyObject *name)
|
||||||
_PyInterpreterFrame *frame = frame_obj->f_frame;
|
_PyInterpreterFrame *frame = frame_obj->f_frame;
|
||||||
frame_init_get_vars(frame);
|
frame_init_get_vars(frame);
|
||||||
|
|
||||||
PyCodeObject *co = frame->f_code;
|
PyCodeObject *co = _PyFrame_GetCode(frame);
|
||||||
for (int i = 0; i < co->co_nlocalsplus; i++) {
|
for (int i = 0; i < co->co_nlocalsplus; i++) {
|
||||||
PyObject *var_name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
|
PyObject *var_name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
|
||||||
if (!_PyUnicode_Equal(var_name, name)) {
|
if (!_PyUnicode_Equal(var_name, name)) {
|
||||||
|
@ -1331,7 +1332,7 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fast = _PyFrame_GetLocalsArray(frame);
|
fast = _PyFrame_GetLocalsArray(frame);
|
||||||
co = frame->f_code;
|
co = _PyFrame_GetCode(frame);
|
||||||
|
|
||||||
PyObject *exc = PyErr_GetRaisedException();
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
for (int i = 0; i < co->co_nlocalsplus; i++) {
|
for (int i = 0; i < co->co_nlocalsplus; i++) {
|
||||||
|
@ -1417,7 +1418,7 @@ PyFrame_GetCode(PyFrameObject *frame)
|
||||||
{
|
{
|
||||||
assert(frame != NULL);
|
assert(frame != NULL);
|
||||||
assert(!_PyFrame_IsIncomplete(frame->f_frame));
|
assert(!_PyFrame_IsIncomplete(frame->f_frame));
|
||||||
PyCodeObject *code = frame->f_frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(frame->f_frame);
|
||||||
assert(code != NULL);
|
assert(code != NULL);
|
||||||
return (PyCodeObject*)Py_NewRef(code);
|
return (PyCodeObject*)Py_NewRef(code);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ static const char *ASYNC_GEN_IGNORED_EXIT_MSG =
|
||||||
static inline PyCodeObject *
|
static inline PyCodeObject *
|
||||||
_PyGen_GetCode(PyGenObject *gen) {
|
_PyGen_GetCode(PyGenObject *gen) {
|
||||||
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)(gen->gi_iframe);
|
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)(gen->gi_iframe);
|
||||||
return frame->f_code;
|
return _PyFrame_GetCode(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyCodeObject *
|
PyCodeObject *
|
||||||
|
@ -957,7 +957,7 @@ static PyObject *
|
||||||
gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
|
gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
|
||||||
PyObject *name, PyObject *qualname)
|
PyObject *name, PyObject *qualname)
|
||||||
{
|
{
|
||||||
PyCodeObject *code = f->f_frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
|
||||||
int size = code->co_nlocalsplus + code->co_stacksize;
|
int size = code->co_nlocalsplus + code->co_stacksize;
|
||||||
PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, size);
|
PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, size);
|
||||||
if (gen == NULL) {
|
if (gen == NULL) {
|
||||||
|
@ -1339,7 +1339,7 @@ compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame)
|
||||||
}
|
}
|
||||||
frame = current_frame;
|
frame = current_frame;
|
||||||
for (int i = 0; i < frame_count; ++i) {
|
for (int i = 0; i < frame_count; ++i) {
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
int line = PyUnstable_InterpreterFrame_GetLine(frame);
|
int line = PyUnstable_InterpreterFrame_GetLine(frame);
|
||||||
PyObject *frameinfo = Py_BuildValue("OiO", code->co_filename, line,
|
PyObject *frameinfo = Py_BuildValue("OiO", code->co_filename, line,
|
||||||
code->co_name);
|
code->co_name);
|
||||||
|
|
|
@ -10405,7 +10405,7 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(cframe->f_code->co_nlocalsplus > 0);
|
assert(_PyFrame_GetCode(cframe)->co_nlocalsplus > 0);
|
||||||
PyObject *firstarg = _PyFrame_GetLocalsArray(cframe)[0];
|
PyObject *firstarg = _PyFrame_GetLocalsArray(cframe)[0];
|
||||||
// The first argument might be a cell.
|
// The first argument might be a cell.
|
||||||
if (firstarg != NULL && (_PyLocals_GetKind(co->co_localspluskinds, 0) & CO_FAST_CELL)) {
|
if (firstarg != NULL && (_PyLocals_GetKind(co->co_localspluskinds, 0) & CO_FAST_CELL)) {
|
||||||
|
@ -10498,7 +10498,7 @@ super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj) {
|
||||||
"super(): no current frame");
|
"super(): no current frame");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int res = super_init_without_args(frame, frame->f_code, &type, &obj);
|
int res = super_init_without_args(frame, _PyFrame_GetCode(frame), &type, &obj);
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -898,7 +898,7 @@ setup_context(Py_ssize_t stack_level,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
globals = f->f_frame->f_globals;
|
globals = f->f_frame->f_globals;
|
||||||
*filename = Py_NewRef(f->f_frame->f_code->co_filename);
|
*filename = Py_NewRef(_PyFrame_GetCode(f->f_frame)->co_filename);
|
||||||
*lineno = PyFrame_GetLineNumber(f);
|
*lineno = PyFrame_GetLineNumber(f);
|
||||||
Py_DECREF(f);
|
Py_DECREF(f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,8 +137,8 @@ dummy_func(
|
||||||
assert(tstate->cframe == &cframe);
|
assert(tstate->cframe == &cframe);
|
||||||
assert(frame == cframe.current_frame);
|
assert(frame == cframe.current_frame);
|
||||||
/* Possibly combine this with eval breaker */
|
/* Possibly combine this with eval breaker */
|
||||||
if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {
|
if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
|
||||||
int err = _Py_Instrument(frame->f_code, tstate->interp);
|
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||||
ERROR_IF(err, error);
|
ERROR_IF(err, error);
|
||||||
next_instr--;
|
next_instr--;
|
||||||
}
|
}
|
||||||
|
@ -152,8 +152,8 @@ dummy_func(
|
||||||
* We need to check the eval breaker anyway, can we
|
* We need to check the eval breaker anyway, can we
|
||||||
* combine the instrument verison check and the eval breaker test?
|
* combine the instrument verison check and the eval breaker test?
|
||||||
*/
|
*/
|
||||||
if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {
|
if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) {
|
||||||
if (_Py_Instrument(frame->f_code, tstate->interp)) {
|
if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
next_instr--;
|
next_instr--;
|
||||||
|
@ -666,8 +666,6 @@ dummy_func(
|
||||||
inst(INTERPRETER_EXIT, (retval --)) {
|
inst(INTERPRETER_EXIT, (retval --)) {
|
||||||
assert(frame == &entry_frame);
|
assert(frame == &entry_frame);
|
||||||
assert(_PyFrame_IsIncomplete(frame));
|
assert(_PyFrame_IsIncomplete(frame));
|
||||||
STACK_SHRINK(1); // Since we're not going to DISPATCH()
|
|
||||||
assert(EMPTY());
|
|
||||||
/* Restore previous cframe and return. */
|
/* Restore previous cframe and return. */
|
||||||
tstate->cframe = cframe.previous;
|
tstate->cframe = cframe.previous;
|
||||||
assert(tstate->cframe->current_frame == frame->previous);
|
assert(tstate->cframe->current_frame == frame->previous);
|
||||||
|
@ -971,7 +969,7 @@ dummy_func(
|
||||||
if (oparg) {
|
if (oparg) {
|
||||||
PyObject *lasti = values[0];
|
PyObject *lasti = values[0];
|
||||||
if (PyLong_Check(lasti)) {
|
if (PyLong_Check(lasti)) {
|
||||||
frame->prev_instr = _PyCode_CODE(frame->f_code) + PyLong_AsLong(lasti);
|
frame->prev_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + PyLong_AsLong(lasti);
|
||||||
assert(!_PyErr_Occurred(tstate));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1385,7 +1383,7 @@ dummy_func(
|
||||||
// Can't use ERROR_IF here.
|
// Can't use ERROR_IF here.
|
||||||
// Fortunately we don't need its superpower.
|
// Fortunately we don't need its superpower.
|
||||||
if (oldobj == NULL) {
|
if (oldobj == NULL) {
|
||||||
format_exc_unbound(tstate, frame->f_code, oparg);
|
format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
PyCell_SET(cell, NULL);
|
PyCell_SET(cell, NULL);
|
||||||
|
@ -1395,8 +1393,8 @@ dummy_func(
|
||||||
inst(LOAD_FROM_DICT_OR_DEREF, (class_dict -- value)) {
|
inst(LOAD_FROM_DICT_OR_DEREF, (class_dict -- value)) {
|
||||||
PyObject *name;
|
PyObject *name;
|
||||||
assert(class_dict);
|
assert(class_dict);
|
||||||
assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
|
assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus);
|
||||||
name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);
|
name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg);
|
||||||
if (PyDict_CheckExact(class_dict)) {
|
if (PyDict_CheckExact(class_dict)) {
|
||||||
value = PyDict_GetItemWithError(class_dict, name);
|
value = PyDict_GetItemWithError(class_dict, name);
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
|
@ -1422,7 +1420,7 @@ dummy_func(
|
||||||
PyObject *cell = GETLOCAL(oparg);
|
PyObject *cell = GETLOCAL(oparg);
|
||||||
value = PyCell_GET(cell);
|
value = PyCell_GET(cell);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
format_exc_unbound(tstate, frame->f_code, oparg);
|
format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
Py_INCREF(value);
|
Py_INCREF(value);
|
||||||
|
@ -1433,7 +1431,7 @@ dummy_func(
|
||||||
PyObject *cell = GETLOCAL(oparg);
|
PyObject *cell = GETLOCAL(oparg);
|
||||||
value = PyCell_GET(cell);
|
value = PyCell_GET(cell);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
format_exc_unbound(tstate, frame->f_code, oparg);
|
format_exc_unbound(tstate, _PyFrame_GetCode(frame), oparg);
|
||||||
ERROR_IF(true, error);
|
ERROR_IF(true, error);
|
||||||
}
|
}
|
||||||
Py_INCREF(value);
|
Py_INCREF(value);
|
||||||
|
@ -1448,7 +1446,7 @@ dummy_func(
|
||||||
|
|
||||||
inst(COPY_FREE_VARS, (--)) {
|
inst(COPY_FREE_VARS, (--)) {
|
||||||
/* Copy closure variables to free variables */
|
/* Copy closure variables to free variables */
|
||||||
PyCodeObject *co = frame->f_code;
|
PyCodeObject *co = _PyFrame_GetCode(frame);
|
||||||
assert(PyFunction_Check(frame->f_funcobj));
|
assert(PyFunction_Check(frame->f_funcobj));
|
||||||
PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
|
PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
|
||||||
assert(oparg == co->co_nfreevars);
|
assert(oparg == co->co_nfreevars);
|
||||||
|
@ -2175,7 +2173,8 @@ dummy_func(
|
||||||
};
|
};
|
||||||
|
|
||||||
inst(ENTER_EXECUTOR, (--)) {
|
inst(ENTER_EXECUTOR, (--)) {
|
||||||
_PyExecutorObject *executor = (_PyExecutorObject *)frame->f_code->co_executors->executors[oparg];
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
|
_PyExecutorObject *executor = (_PyExecutorObject *)code->co_executors->executors[oparg];
|
||||||
Py_INCREF(executor);
|
Py_INCREF(executor);
|
||||||
frame = executor->execute(executor, frame, stack_pointer);
|
frame = executor->execute(executor, frame, stack_pointer);
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
|
@ -2292,7 +2291,7 @@ dummy_func(
|
||||||
/* before: [obj]; after [getiter(obj)] */
|
/* before: [obj]; after [getiter(obj)] */
|
||||||
if (PyCoro_CheckExact(iterable)) {
|
if (PyCoro_CheckExact(iterable)) {
|
||||||
/* `iterable` is a coroutine */
|
/* `iterable` is a coroutine */
|
||||||
if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
|
if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
|
||||||
/* and it is used in a 'yield from' expression of a
|
/* and it is used in a 'yield from' expression of a
|
||||||
regular generator. */
|
regular generator. */
|
||||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||||
|
|
|
@ -129,6 +129,9 @@ lltrace_instruction(_PyInterpreterFrame *frame,
|
||||||
PyObject **stack_pointer,
|
PyObject **stack_pointer,
|
||||||
_Py_CODEUNIT *next_instr)
|
_Py_CODEUNIT *next_instr)
|
||||||
{
|
{
|
||||||
|
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* This dump_stack() operation is risky, since the repr() of some
|
/* This dump_stack() operation is risky, since the repr() of some
|
||||||
objects enters the interpreter recursively. It is also slow.
|
objects enters the interpreter recursively. It is also slow.
|
||||||
So you might want to comment it out. */
|
So you might want to comment it out. */
|
||||||
|
@ -137,7 +140,7 @@ lltrace_instruction(_PyInterpreterFrame *frame,
|
||||||
int opcode = next_instr->op.code;
|
int opcode = next_instr->op.code;
|
||||||
const char *opname = _PyOpcode_OpName[opcode];
|
const char *opname = _PyOpcode_OpName[opcode];
|
||||||
assert(opname != NULL);
|
assert(opname != NULL);
|
||||||
int offset = (int)(next_instr - _PyCode_CODE(frame->f_code));
|
int offset = (int)(next_instr - _PyCode_CODE(_PyFrame_GetCode(frame)));
|
||||||
if (HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
|
if (HAS_ARG((int)_PyOpcode_Deopt[opcode])) {
|
||||||
printf("%d: %s %d\n", offset * 2, opname, oparg);
|
printf("%d: %s %d\n", offset * 2, opname, oparg);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +153,7 @@ static void
|
||||||
lltrace_resume_frame(_PyInterpreterFrame *frame)
|
lltrace_resume_frame(_PyInterpreterFrame *frame)
|
||||||
{
|
{
|
||||||
PyObject *fobj = frame->f_funcobj;
|
PyObject *fobj = frame->f_funcobj;
|
||||||
if (frame->owner == FRAME_OWNED_BY_CSTACK ||
|
if (!PyCode_Check(frame->f_executable) ||
|
||||||
fobj == NULL ||
|
fobj == NULL ||
|
||||||
!PyFunction_Check(fobj)
|
!PyFunction_Check(fobj)
|
||||||
) {
|
) {
|
||||||
|
@ -621,6 +624,13 @@ static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate) {
|
||||||
tstate->py_recursion_remaining++;
|
tstate->py_recursion_remaining++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const _Py_CODEUNIT _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = {
|
||||||
|
/* Put a NOP at the start, so that the IP points into
|
||||||
|
* the code, rather than before it */
|
||||||
|
{ .op.code = NOP, .op.arg = 0 },
|
||||||
|
{ .op.code = INTERPRETER_EXIT, .op.arg = 0 },
|
||||||
|
{ .op.code = RESUME, .op.arg = 0 }
|
||||||
|
};
|
||||||
|
|
||||||
/* Disable unused label warnings. They are handy for debugging, even
|
/* Disable unused label warnings. They are handy for debugging, even
|
||||||
if computed gotos aren't used. */
|
if computed gotos aren't used. */
|
||||||
|
@ -668,7 +678,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
||||||
cframe.previous = prev_cframe;
|
cframe.previous = prev_cframe;
|
||||||
tstate->cframe = &cframe;
|
tstate->cframe = &cframe;
|
||||||
|
|
||||||
assert(tstate->interp->interpreter_trampoline != NULL);
|
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
/* Set these to invalid but identifiable values for debugging. */
|
/* Set these to invalid but identifiable values for debugging. */
|
||||||
entry_frame.f_funcobj = (PyObject*)0xaaa0;
|
entry_frame.f_funcobj = (PyObject*)0xaaa0;
|
||||||
|
@ -677,9 +686,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
||||||
entry_frame.f_globals = (PyObject*)0xaaa3;
|
entry_frame.f_globals = (PyObject*)0xaaa3;
|
||||||
entry_frame.f_builtins = (PyObject*)0xaaa4;
|
entry_frame.f_builtins = (PyObject*)0xaaa4;
|
||||||
#endif
|
#endif
|
||||||
entry_frame.f_code = tstate->interp->interpreter_trampoline;
|
entry_frame.f_executable = Py_None;
|
||||||
entry_frame.prev_instr =
|
entry_frame.prev_instr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS;
|
||||||
_PyCode_CODE(tstate->interp->interpreter_trampoline);
|
|
||||||
entry_frame.stacktop = 0;
|
entry_frame.stacktop = 0;
|
||||||
entry_frame.owner = FRAME_OWNED_BY_CSTACK;
|
entry_frame.owner = FRAME_OWNED_BY_CSTACK;
|
||||||
entry_frame.return_offset = 0;
|
entry_frame.return_offset = 0;
|
||||||
|
@ -701,7 +709,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
||||||
}
|
}
|
||||||
/* Because this avoids the RESUME,
|
/* Because this avoids the RESUME,
|
||||||
* we need to update instrumentation */
|
* we need to update instrumentation */
|
||||||
_Py_Instrument(frame->f_code, tstate->interp);
|
_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
|
||||||
monitor_throw(tstate, frame, frame->prev_instr);
|
monitor_throw(tstate, frame, frame->prev_instr);
|
||||||
/* TO DO -- Monitor throw entry. */
|
/* TO DO -- Monitor throw entry. */
|
||||||
goto resume_with_error;
|
goto resume_with_error;
|
||||||
|
@ -715,7 +723,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
||||||
|
|
||||||
/* Sets the above local variables from the frame */
|
/* Sets the above local variables from the frame */
|
||||||
#define SET_LOCALS_FROM_FRAME() \
|
#define SET_LOCALS_FROM_FRAME() \
|
||||||
assert(_PyInterpreterFrame_LASTI(frame) >= -1); \
|
|
||||||
/* Jump back to the last instruction executed... */ \
|
/* Jump back to the last instruction executed... */ \
|
||||||
next_instr = frame->prev_instr + 1; \
|
next_instr = frame->prev_instr + 1; \
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
@ -874,7 +881,7 @@ handle_eval_breaker:
|
||||||
opcode = next_instr->op.code;
|
opcode = next_instr->op.code;
|
||||||
_PyErr_Format(tstate, PyExc_SystemError,
|
_PyErr_Format(tstate, PyExc_SystemError,
|
||||||
"%U:%d: unknown opcode %d",
|
"%U:%d: unknown opcode %d",
|
||||||
frame->f_code->co_filename,
|
_PyFrame_GetCode(frame)->co_filename,
|
||||||
PyUnstable_InterpreterFrame_GetLine(frame),
|
PyUnstable_InterpreterFrame_GetLine(frame),
|
||||||
opcode);
|
opcode);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -889,7 +896,7 @@ unbound_local_error:
|
||||||
{
|
{
|
||||||
format_exc_check_arg(tstate, PyExc_UnboundLocalError,
|
format_exc_check_arg(tstate, PyExc_UnboundLocalError,
|
||||||
UNBOUNDLOCAL_ERROR_MSG,
|
UNBOUNDLOCAL_ERROR_MSG,
|
||||||
PyTuple_GetItem(frame->f_code->co_localsplusnames, oparg)
|
PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg)
|
||||||
);
|
);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -929,7 +936,7 @@ exception_unwind:
|
||||||
/* We can't use frame->f_lasti here, as RERAISE may have set it */
|
/* We can't use frame->f_lasti here, as RERAISE may have set it */
|
||||||
int offset = INSTR_OFFSET()-1;
|
int offset = INSTR_OFFSET()-1;
|
||||||
int level, handler, lasti;
|
int level, handler, lasti;
|
||||||
if (get_exception_handler(frame->f_code, offset, &level, &handler, &lasti) == 0) {
|
if (get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti) == 0) {
|
||||||
// No handlers, so exit.
|
// No handlers, so exit.
|
||||||
assert(_PyErr_Occurred(tstate));
|
assert(_PyErr_Occurred(tstate));
|
||||||
|
|
||||||
|
@ -1523,12 +1530,12 @@ clear_thread_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)
|
||||||
assert(frame->owner == FRAME_OWNED_BY_THREAD);
|
assert(frame->owner == FRAME_OWNED_BY_THREAD);
|
||||||
// Make sure that this is, indeed, the top frame. We can't check this in
|
// Make sure that this is, indeed, the top frame. We can't check this in
|
||||||
// _PyThreadState_PopFrame, since f_code is already cleared at that point:
|
// _PyThreadState_PopFrame, since f_code is already cleared at that point:
|
||||||
assert((PyObject **)frame + frame->f_code->co_framesize ==
|
assert((PyObject **)frame + _PyFrame_GetCode(frame)->co_framesize ==
|
||||||
tstate->datastack_top);
|
tstate->datastack_top);
|
||||||
tstate->c_recursion_remaining--;
|
tstate->c_recursion_remaining--;
|
||||||
assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
|
assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);
|
||||||
_PyFrame_ClearExceptCode(frame);
|
_PyFrame_ClearExceptCode(frame);
|
||||||
Py_DECREF(frame->f_code);
|
Py_DECREF(frame->f_executable);
|
||||||
tstate->c_recursion_remaining++;
|
tstate->c_recursion_remaining++;
|
||||||
_PyThreadState_PopFrame(tstate, frame);
|
_PyThreadState_PopFrame(tstate, frame);
|
||||||
}
|
}
|
||||||
|
@ -2013,7 +2020,7 @@ do_monitor_exc(PyThreadState *tstate, _PyInterpreterFrame *frame,
|
||||||
static inline int
|
static inline int
|
||||||
no_tools_for_event(PyThreadState *tstate, _PyInterpreterFrame *frame, int event)
|
no_tools_for_event(PyThreadState *tstate, _PyInterpreterFrame *frame, int event)
|
||||||
{
|
{
|
||||||
_PyCoMonitoringData *data = frame->f_code->_co_monitoring;
|
_PyCoMonitoringData *data = _PyFrame_GetCode(frame)->_co_monitoring;
|
||||||
if (data) {
|
if (data) {
|
||||||
if (data->active_monitors.tools[event] == 0) {
|
if (data->active_monitors.tools[event] == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2331,7 +2338,7 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
|
||||||
int result = cf->cf_flags != 0;
|
int result = cf->cf_flags != 0;
|
||||||
|
|
||||||
if (current_frame != NULL) {
|
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;
|
const int compilerflags = codeflags & PyCF_MASK;
|
||||||
if (compilerflags) {
|
if (compilerflags) {
|
||||||
result = 1;
|
result = 1;
|
||||||
|
|
|
@ -138,13 +138,13 @@ GETITEM(PyObject *v, Py_ssize_t i) {
|
||||||
/* Code access macros */
|
/* Code access macros */
|
||||||
|
|
||||||
/* The integer overflow is checked by an assertion below. */
|
/* The integer overflow is checked by an assertion below. */
|
||||||
#define INSTR_OFFSET() ((int)(next_instr - _PyCode_CODE(frame->f_code)))
|
#define INSTR_OFFSET() ((int)(next_instr - _PyCode_CODE(_PyFrame_GetCode(frame))))
|
||||||
#define NEXTOPARG() do { \
|
#define NEXTOPARG() do { \
|
||||||
_Py_CODEUNIT word = *next_instr; \
|
_Py_CODEUNIT word = *next_instr; \
|
||||||
opcode = word.op.code; \
|
opcode = word.op.code; \
|
||||||
oparg = word.op.arg; \
|
oparg = word.op.arg; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define JUMPTO(x) (next_instr = _PyCode_CODE(frame->f_code) + (x))
|
#define JUMPTO(x) (next_instr = _PyCode_CODE(_PyFrame_GetCode(frame)) + (x))
|
||||||
#define JUMPBY(x) (next_instr += (x))
|
#define JUMPBY(x) (next_instr += (x))
|
||||||
|
|
||||||
/* OpCode prediction macros
|
/* OpCode prediction macros
|
||||||
|
@ -182,7 +182,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
|
||||||
/* The stack can grow at most MAXINT deep, as co_nlocals and
|
/* The stack can grow at most MAXINT deep, as co_nlocals and
|
||||||
co_stacksize are ints. */
|
co_stacksize are ints. */
|
||||||
#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
|
#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
|
||||||
#define STACK_SIZE() (frame->f_code->co_stacksize)
|
#define STACK_SIZE() (_PyFrame_GetCode(frame)->co_stacksize)
|
||||||
#define EMPTY() (STACK_LEVEL() == 0)
|
#define EMPTY() (STACK_LEVEL() == 0)
|
||||||
#define TOP() (stack_pointer[-1])
|
#define TOP() (stack_pointer[-1])
|
||||||
#define SECOND() (stack_pointer[-2])
|
#define SECOND() (stack_pointer[-2])
|
||||||
|
@ -221,8 +221,8 @@ GETITEM(PyObject *v, Py_ssize_t i) {
|
||||||
|
|
||||||
|
|
||||||
/* Data access macros */
|
/* Data access macros */
|
||||||
#define FRAME_CO_CONSTS (frame->f_code->co_consts)
|
#define FRAME_CO_CONSTS (_PyFrame_GetCode(frame)->co_consts)
|
||||||
#define FRAME_CO_NAMES (frame->f_code->co_names)
|
#define FRAME_CO_NAMES (_PyFrame_GetCode(frame)->co_names)
|
||||||
|
|
||||||
/* Local variable macros */
|
/* Local variable macros */
|
||||||
|
|
||||||
|
@ -270,6 +270,8 @@ GETITEM(PyObject *v, Py_ssize_t i) {
|
||||||
#define GLOBALS() frame->f_globals
|
#define GLOBALS() frame->f_globals
|
||||||
#define BUILTINS() frame->f_builtins
|
#define BUILTINS() frame->f_builtins
|
||||||
#define LOCALS() frame->f_locals
|
#define LOCALS() frame->f_locals
|
||||||
|
#define CONSTS() _PyFrame_GetCode(frame)->co_consts
|
||||||
|
#define NAMES() _PyFrame_GetCode(frame)->co_names
|
||||||
|
|
||||||
#define DTRACE_FUNCTION_ENTRY() \
|
#define DTRACE_FUNCTION_ENTRY() \
|
||||||
if (PyDTrace_FUNCTION_ENTRY_ENABLED()) { \
|
if (PyDTrace_FUNCTION_ENTRY_ENABLED()) { \
|
||||||
|
|
|
@ -14,7 +14,7 @@ _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg)
|
||||||
Py_VISIT(frame->frame_obj);
|
Py_VISIT(frame->frame_obj);
|
||||||
Py_VISIT(frame->f_locals);
|
Py_VISIT(frame->f_locals);
|
||||||
Py_VISIT(frame->f_funcobj);
|
Py_VISIT(frame->f_funcobj);
|
||||||
Py_VISIT(frame->f_code);
|
Py_VISIT(_PyFrame_GetCode(frame));
|
||||||
/* locals */
|
/* locals */
|
||||||
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
PyObject **locals = _PyFrame_GetLocalsArray(frame);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -31,7 +31,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
|
||||||
assert(frame->frame_obj == NULL);
|
assert(frame->frame_obj == NULL);
|
||||||
PyObject *exc = PyErr_GetRaisedException();
|
PyObject *exc = PyErr_GetRaisedException();
|
||||||
|
|
||||||
PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code);
|
PyFrameObject *f = _PyFrame_New_NoTrack(_PyFrame_GetCode(frame));
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
Py_XDECREF(exc);
|
Py_XDECREF(exc);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -65,7 +65,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
|
||||||
void
|
void
|
||||||
_PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
|
_PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
|
||||||
{
|
{
|
||||||
assert(src->stacktop >= src->f_code->co_nlocalsplus);
|
assert(src->stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
|
||||||
Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src;
|
Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src;
|
||||||
memcpy(dest, src, size);
|
memcpy(dest, src, size);
|
||||||
// Don't leave a dangling pointer to the old frame when creating generators
|
// Don't leave a dangling pointer to the old frame when creating generators
|
||||||
|
@ -81,7 +81,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
|
||||||
assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
|
assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
|
||||||
assert(frame->owner != FRAME_CLEARED);
|
assert(frame->owner != FRAME_CLEARED);
|
||||||
Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;
|
Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;
|
||||||
Py_INCREF(frame->f_code);
|
Py_INCREF(_PyFrame_GetCode(frame));
|
||||||
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
|
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
|
||||||
frame = (_PyInterpreterFrame *)f->_f_frame_data;
|
frame = (_PyInterpreterFrame *)f->_f_frame_data;
|
||||||
f->f_frame = frame;
|
f->f_frame = frame;
|
||||||
|
@ -89,7 +89,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
|
||||||
if (_PyFrame_IsIncomplete(frame)) {
|
if (_PyFrame_IsIncomplete(frame)) {
|
||||||
// This may be a newly-created generator or coroutine frame. Since it's
|
// This may be a newly-created generator or coroutine frame. Since it's
|
||||||
// dead anyways, just pretend that the first RESUME ran:
|
// dead anyways, just pretend that the first RESUME ran:
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable;
|
frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable;
|
||||||
}
|
}
|
||||||
assert(!_PyFrame_IsIncomplete(frame));
|
assert(!_PyFrame_IsIncomplete(frame));
|
||||||
|
@ -149,7 +149,7 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
|
||||||
PyObject *
|
PyObject *
|
||||||
PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)
|
PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)
|
||||||
{
|
{
|
||||||
PyObject *code = (PyObject *)frame->f_code;
|
PyObject *code = frame->f_executable;
|
||||||
Py_INCREF(code);
|
Py_INCREF(code);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -164,5 +164,13 @@ int
|
||||||
PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
|
PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)
|
||||||
{
|
{
|
||||||
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
|
||||||
return PyCode_Addr2Line(frame->f_code, addr);
|
return PyCode_Addr2Line(_PyFrame_GetCode(frame), addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PyTypeObject *const PyUnstable_ExecutableKinds[PY_EXECUTABLE_KINDS+1] = {
|
||||||
|
[PY_EXECUTABLE_KIND_SKIP] = &_PyNone_Type,
|
||||||
|
[PY_EXECUTABLE_KIND_PY_FUNCTION] = &PyCode_Type,
|
||||||
|
[PY_EXECUTABLE_KIND_BUILTIN_FUNCTION] = &PyMethod_Type,
|
||||||
|
[PY_EXECUTABLE_KIND_METHOD_DESCRIPTOR] = &PyMethodDescr_Type,
|
||||||
|
[PY_EXECUTABLE_KINDS] = NULL,
|
||||||
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -936,7 +936,7 @@ call_instrumentation_vector(
|
||||||
}
|
}
|
||||||
assert(!_PyErr_Occurred(tstate));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
assert(args[0] == NULL);
|
assert(args[0] == NULL);
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
assert(code->_co_instrumentation_version == tstate->interp->monitoring_version);
|
assert(code->_co_instrumentation_version == tstate->interp->monitoring_version);
|
||||||
assert(is_version_up_to_date(code, tstate->interp));
|
assert(is_version_up_to_date(code, tstate->interp));
|
||||||
assert(instrumentation_cross_checks(tstate->interp, code));
|
assert(instrumentation_cross_checks(tstate->interp, code));
|
||||||
|
@ -1017,7 +1017,7 @@ _Py_call_instrumentation_jump(
|
||||||
assert(frame->prev_instr == instr);
|
assert(frame->prev_instr == instr);
|
||||||
/* Event should occur after the jump */
|
/* Event should occur after the jump */
|
||||||
frame->prev_instr = target;
|
frame->prev_instr = target;
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
int to = (int)(target - _PyCode_CODE(code));
|
int to = (int)(target - _PyCode_CODE(code));
|
||||||
PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT));
|
PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT));
|
||||||
if (to_obj == NULL) {
|
if (to_obj == NULL) {
|
||||||
|
@ -1094,7 +1094,7 @@ int
|
||||||
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
|
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)
|
||||||
{
|
{
|
||||||
frame->prev_instr = instr;
|
frame->prev_instr = instr;
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
assert(is_version_up_to_date(code, tstate->interp));
|
assert(is_version_up_to_date(code, tstate->interp));
|
||||||
assert(instrumentation_cross_checks(tstate->interp, code));
|
assert(instrumentation_cross_checks(tstate->interp, code));
|
||||||
int i = (int)(instr - _PyCode_CODE(code));
|
int i = (int)(instr - _PyCode_CODE(code));
|
||||||
|
@ -1162,7 +1162,7 @@ done:
|
||||||
int
|
int
|
||||||
_Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr)
|
_Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr)
|
||||||
{
|
{
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||||
assert(is_version_up_to_date(code, tstate->interp));
|
assert(is_version_up_to_date(code, tstate->interp));
|
||||||
assert(instrumentation_cross_checks(tstate->interp, code));
|
assert(instrumentation_cross_checks(tstate->interp, code));
|
||||||
int offset = (int)(instr - _PyCode_CODE(code));
|
int offset = (int)(instr - _PyCode_CODE(code));
|
||||||
|
@ -1632,7 +1632,7 @@ instrument_all_executing_code_objects(PyInterpreterState *interp) {
|
||||||
_PyInterpreterFrame *frame = ts->cframe->current_frame;
|
_PyInterpreterFrame *frame = ts->cframe->current_frame;
|
||||||
while (frame) {
|
while (frame) {
|
||||||
if (frame->owner != FRAME_OWNED_BY_CSTACK) {
|
if (frame->owner != FRAME_OWNED_BY_CSTACK) {
|
||||||
if (_Py_Instrument(frame->f_code, interp)) {
|
if (_Py_Instrument(_PyFrame_GetCode(frame), interp)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,14 +148,14 @@ stopiteration_error(PyThreadState* tstate, PyObject *exc)
|
||||||
const char *msg = NULL;
|
const char *msg = NULL;
|
||||||
if (PyErr_GivenExceptionMatches(exc, PyExc_StopIteration)) {
|
if (PyErr_GivenExceptionMatches(exc, PyExc_StopIteration)) {
|
||||||
msg = "generator raised StopIteration";
|
msg = "generator raised StopIteration";
|
||||||
if (frame->f_code->co_flags & CO_ASYNC_GENERATOR) {
|
if (_PyFrame_GetCode(frame)->co_flags & CO_ASYNC_GENERATOR) {
|
||||||
msg = "async generator raised StopIteration";
|
msg = "async generator raised StopIteration";
|
||||||
}
|
}
|
||||||
else if (frame->f_code->co_flags & CO_COROUTINE) {
|
else if (_PyFrame_GetCode(frame)->co_flags & CO_COROUTINE) {
|
||||||
msg = "coroutine raised StopIteration";
|
msg = "coroutine raised StopIteration";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((frame->f_code->co_flags & CO_ASYNC_GENERATOR) &&
|
else if ((_PyFrame_GetCode(frame)->co_flags & CO_ASYNC_GENERATOR) &&
|
||||||
PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration))
|
PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration))
|
||||||
{
|
{
|
||||||
/* code in `gen` raised a StopAsyncIteration error:
|
/* code in `gen` raised a StopAsyncIteration error:
|
||||||
|
|
|
@ -244,7 +244,7 @@ sys_trace_line_func(
|
||||||
"Missing frame when calling trace function.");
|
"Missing frame when calling trace function.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
assert(args[0] == (PyObject *)frame->f_frame->f_code);
|
assert(args[0] == (PyObject *)_PyFrame_GetCode(frame->f_frame));
|
||||||
return trace_line(tstate, self, frame, line);
|
return trace_line(tstate, self, frame, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +286,6 @@ sys_trace_jump_func(
|
||||||
"Missing frame when calling trace function.");
|
"Missing frame when calling trace function.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
assert(code == frame->f_frame->f_code);
|
|
||||||
if (!frame->f_trace_lines) {
|
if (!frame->f_trace_lines) {
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,15 +148,17 @@ PyUnstable_SetOptimizer(_PyOptimizerObject *optimizer)
|
||||||
_PyInterpreterFrame *
|
_PyInterpreterFrame *
|
||||||
_PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer)
|
_PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer)
|
||||||
{
|
{
|
||||||
|
PyCodeObject *code = (PyCodeObject *)frame->f_executable;
|
||||||
|
assert(PyCode_Check(code));
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyInterpreterState *interp = PyInterpreterState_Get();
|
||||||
int index = get_executor_index(frame->f_code, src);
|
int index = get_executor_index(code, src);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
_PyOptimizerObject *opt = interp->optimizer;
|
_PyOptimizerObject *opt = interp->optimizer;
|
||||||
_PyExecutorObject *executor;
|
_PyExecutorObject *executor;
|
||||||
int err = opt->optimize(opt, frame->f_code, dest, &executor);
|
int err = opt->optimize(opt, code, dest, &executor);
|
||||||
if (err <= 0) {
|
if (err <= 0) {
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -164,7 +166,7 @@ _PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNI
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
insert_executor(frame->f_code, src, index, executor);
|
insert_executor(code, src, index, executor);
|
||||||
return executor->execute(executor, frame, stack_pointer);
|
return executor->execute(executor, frame, stack_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -335,7 +335,7 @@ py_trampoline_evaluator(PyThreadState *ts, _PyInterpreterFrame *frame,
|
||||||
perf_status == PERF_STATUS_NO_INIT) {
|
perf_status == PERF_STATUS_NO_INIT) {
|
||||||
goto default_eval;
|
goto default_eval;
|
||||||
}
|
}
|
||||||
PyCodeObject *co = frame->f_code;
|
PyCodeObject *co = _PyFrame_GetCode(frame);
|
||||||
py_trampoline f = NULL;
|
py_trampoline f = NULL;
|
||||||
assert(extra_code_index != -1);
|
assert(extra_code_index != -1);
|
||||||
int ret = _PyCode_GetExtra((PyObject *)co, extra_code_index, (void **)&f);
|
int ret = _PyCode_GetExtra((PyObject *)co, extra_code_index, (void **)&f);
|
||||||
|
|
|
@ -737,22 +737,6 @@ pycore_init_types(PyInterpreterState *interp)
|
||||||
return _PyStatus_OK();
|
return _PyStatus_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = {
|
|
||||||
/* Put a NOP at the start, so that the IP points into
|
|
||||||
* the code, rather than before it */
|
|
||||||
NOP, 0,
|
|
||||||
INTERPRETER_EXIT, 0,
|
|
||||||
/* RESUME at end makes sure that the frame appears incomplete */
|
|
||||||
RESUME, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const _PyShimCodeDef INTERPRETER_TRAMPOLINE_CODEDEF = {
|
|
||||||
INTERPRETER_TRAMPOLINE_INSTRUCTIONS,
|
|
||||||
sizeof(INTERPRETER_TRAMPOLINE_INSTRUCTIONS),
|
|
||||||
1,
|
|
||||||
"<interpreter trampoline>"
|
|
||||||
};
|
|
||||||
|
|
||||||
static PyStatus
|
static PyStatus
|
||||||
pycore_init_builtins(PyThreadState *tstate)
|
pycore_init_builtins(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
|
@ -786,10 +770,6 @@ pycore_init_builtins(PyThreadState *tstate)
|
||||||
PyObject *object__getattribute__ = _PyType_Lookup(&PyBaseObject_Type, &_Py_ID(__getattribute__));
|
PyObject *object__getattribute__ = _PyType_Lookup(&PyBaseObject_Type, &_Py_ID(__getattribute__));
|
||||||
assert(object__getattribute__);
|
assert(object__getattribute__);
|
||||||
interp->callable_cache.object__getattribute__ = object__getattribute__;
|
interp->callable_cache.object__getattribute__ = object__getattribute__;
|
||||||
interp->interpreter_trampoline = _Py_MakeShimCode(&INTERPRETER_TRAMPOLINE_CODEDEF);
|
|
||||||
if (interp->interpreter_trampoline == NULL) {
|
|
||||||
return _PyStatus_ERR("failed to create interpreter trampoline.");
|
|
||||||
}
|
|
||||||
if (_PyBuiltins_AddExceptions(bimod) < 0) {
|
if (_PyBuiltins_AddExceptions(bimod) < 0) {
|
||||||
return _PyStatus_ERR("failed to add exceptions to builtins");
|
return _PyStatus_ERR("failed to add exceptions to builtins");
|
||||||
}
|
}
|
||||||
|
|
|
@ -892,7 +892,6 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
|
||||||
PyDict_Clear(interp->builtins);
|
PyDict_Clear(interp->builtins);
|
||||||
Py_CLEAR(interp->sysdict);
|
Py_CLEAR(interp->sysdict);
|
||||||
Py_CLEAR(interp->builtins);
|
Py_CLEAR(interp->builtins);
|
||||||
Py_CLEAR(interp->interpreter_trampoline);
|
|
||||||
|
|
||||||
if (tstate->interp == interp) {
|
if (tstate->interp == interp) {
|
||||||
/* We are now safe to fix tstate->_status.cleared. */
|
/* We are now safe to fix tstate->_status.cleared. */
|
||||||
|
|
|
@ -785,7 +785,7 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen
|
||||||
}
|
}
|
||||||
|
|
||||||
int code_offset = tb->tb_lasti;
|
int code_offset = tb->tb_lasti;
|
||||||
PyCodeObject* code = frame->f_frame->f_code;
|
PyCodeObject* code = _PyFrame_GetCode(frame->f_frame);
|
||||||
const Py_ssize_t source_line_len = PyUnicode_GET_LENGTH(source_line);
|
const Py_ssize_t source_line_len = PyUnicode_GET_LENGTH(source_line);
|
||||||
|
|
||||||
int start_line;
|
int start_line;
|
||||||
|
@ -1164,7 +1164,7 @@ done:
|
||||||
static void
|
static void
|
||||||
dump_frame(int fd, _PyInterpreterFrame *frame)
|
dump_frame(int fd, _PyInterpreterFrame *frame)
|
||||||
{
|
{
|
||||||
PyCodeObject *code = frame->f_code;
|
PyCodeObject *code =_PyFrame_GetCode(frame);
|
||||||
PUTS(fd, " File ");
|
PUTS(fd, " File ");
|
||||||
if (code->co_filename != NULL
|
if (code->co_filename != NULL
|
||||||
&& PyUnicode_Check(code->co_filename))
|
&& PyUnicode_Check(code->co_filename))
|
||||||
|
|
|
@ -249,6 +249,7 @@ hashtable_compare_traceback(const void *key1, const void *key2)
|
||||||
static void
|
static void
|
||||||
tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
|
tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
|
||||||
{
|
{
|
||||||
|
assert(PyCode_Check(pyframe->f_executable));
|
||||||
frame->filename = &_Py_STR(anon_unknown);
|
frame->filename = &_Py_STR(anon_unknown);
|
||||||
int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);
|
int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);
|
||||||
if (lineno < 0) {
|
if (lineno < 0) {
|
||||||
|
@ -256,7 +257,7 @@ tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
|
||||||
}
|
}
|
||||||
frame->lineno = (unsigned int)lineno;
|
frame->lineno = (unsigned int)lineno;
|
||||||
|
|
||||||
PyObject *filename = pyframe->f_code->co_filename;
|
PyObject *filename = filename = ((PyCodeObject *)pyframe->f_executable)->co_filename;
|
||||||
|
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
#ifdef TRACE_DEBUG
|
#ifdef TRACE_DEBUG
|
||||||
|
|
|
@ -327,6 +327,7 @@ Parser/parser.c - soft_keywords -
|
||||||
Parser/tokenizer.c - type_comment_prefix -
|
Parser/tokenizer.c - type_comment_prefix -
|
||||||
Python/ast_opt.c fold_unaryop ops -
|
Python/ast_opt.c fold_unaryop ops -
|
||||||
Python/ceval.c - binary_ops -
|
Python/ceval.c - binary_ops -
|
||||||
|
Python/ceval.c - _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS -
|
||||||
Python/codecs.c - Py_hexdigits -
|
Python/codecs.c - Py_hexdigits -
|
||||||
Python/codecs.c - ucnhash_capi -
|
Python/codecs.c - ucnhash_capi -
|
||||||
Python/codecs.c _PyCodecRegistry_Init methods -
|
Python/codecs.c _PyCodecRegistry_Init methods -
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
|
@ -1009,14 +1009,18 @@ class PyFramePtr:
|
||||||
self._gdbval = gdbval
|
self._gdbval = gdbval
|
||||||
|
|
||||||
if not self.is_optimized_out():
|
if not self.is_optimized_out():
|
||||||
self.co = self._f_code()
|
try:
|
||||||
self.co_name = self.co.pyop_field('co_name')
|
self.co = self._f_code()
|
||||||
self.co_filename = self.co.pyop_field('co_filename')
|
self.co_name = self.co.pyop_field('co_name')
|
||||||
|
self.co_filename = self.co.pyop_field('co_filename')
|
||||||
|
|
||||||
self.f_lasti = self._f_lasti()
|
self.f_lasti = self._f_lasti()
|
||||||
self.co_nlocals = int_from_int(self.co.field('co_nlocals'))
|
self.co_nlocals = int_from_int(self.co.field('co_nlocals'))
|
||||||
pnames = self.co.field('co_localsplusnames')
|
pnames = self.co.field('co_localsplusnames')
|
||||||
self.co_localsplusnames = PyTupleObjectPtr.from_pyobject_ptr(pnames)
|
self.co_localsplusnames = PyTupleObjectPtr.from_pyobject_ptr(pnames)
|
||||||
|
self._is_code = True
|
||||||
|
except:
|
||||||
|
self._is_code = False
|
||||||
|
|
||||||
def is_optimized_out(self):
|
def is_optimized_out(self):
|
||||||
return self._gdbval.is_optimized_out
|
return self._gdbval.is_optimized_out
|
||||||
|
@ -1051,7 +1055,10 @@ class PyFramePtr:
|
||||||
return self._f_special("f_builtins")
|
return self._f_special("f_builtins")
|
||||||
|
|
||||||
def _f_code(self):
|
def _f_code(self):
|
||||||
return self._f_special("f_code", PyCodeObjectPtr.from_pyobject_ptr)
|
return self._f_special("f_executable", PyCodeObjectPtr.from_pyobject_ptr)
|
||||||
|
|
||||||
|
def _f_executable(self):
|
||||||
|
return self._f_special("f_executable")
|
||||||
|
|
||||||
def _f_nlocalsplus(self):
|
def _f_nlocalsplus(self):
|
||||||
return self._f_special("nlocalsplus", int_from_int)
|
return self._f_special("nlocalsplus", int_from_int)
|
||||||
|
|
Loading…
Reference in New Issue