8000 gh-91462: Make lltrace output human-readable. by sweeneyde · Pull Request #91463 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-91462: Make lltrace output human-readable. #91463

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 16, 2022
Merged
Next Next commit
improve lltrace
  • Loading branch information
sweeneyde committed Apr 12, 2022
commit d64552cdad45ea32098b9f44d4893eed59901a55
113 changes: 78 additions & 35 deletions 10000 Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,74 @@ static PyObject * do_call_core(

#ifdef LLTRACE
static int lltrace;
static int prtrace(PyThreadState *, PyObject *, const char *);
static void lltrace_instruction(_PyInterpreterFrame *frame, int opcode, int oparg)
static void
dump_stack(_PyInterpreterFrame *frame, int stack_level)
{
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
PyObject **stack = _PyFrame_Stackbase(frame);
printf("[");
for (int i = 0; i < stack_level; i++) {
PyObject *obj = stack[i];
if (PyObject_Print(obj, stdout, 0) != 0) {
PyErr_Clear();
printf("???\n");
return;
}
printf(", ");
}
printf("]\n");
PyErr_Restore(type, value, traceback);
}

static void
lltrace_instruction(_PyInterpreterFrame *frame,
int opcode, int oparg, int stack_level)
{
dump_stack(frame, stack_level);
const char *opname = _PyOpcode_OpName[opcode];
int lasti = _PyInterpreterFrame_LASTI(frame);
if (opname == NULL) {
printf("%d: unknown opcode %d, %d",
lasti, opcode, oparg);
}
if (HAS_ARG(opcode)) {
printf("%d: %d, %d\n", _PyInterpreterFrame_LASTI(frame), opcode, oparg);
printf("%d: %s %d\n", lasti, opname, oparg);
}
else {
printf("%d: %d\n", _PyInterpreterFrame_LASTI(frame), opcode);
printf("%d: %s\n", lasti, opname);
}
}
static void
lltrace_resume_frame(_PyInterpreterFrame *frame)
{
PyFunctionObject *f = frame->f_func;
if (f == NULL) {
printf("Resuming frame.");
return;
}
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
PyObject *name = f->func_qualname;
if (name == NULL) {
name = f->func_name;
}
printf("Resuming frame");
if (name) {
printf(" for ");
if (PyObject_Print(name, stdout, 0) < 0) {
PyErr_Clear();
}
}
if (f->func_module) {
printf(" in module ");
if (PyObject_Print(f->func_module, stdout, 0) < 0) {
PyErr_Clear();
}
}
printf("\n");
PyErr_Restore(type, value, traceback);
}
#endif
static int call_trace(Py_tracefunc, PyObject *,
PyThreadState *, _PyInterpreterFrame *,
Expand Down Expand Up @@ -1266,7 +1324,7 @@ eval_frame_handle_pending(PyThreadState *tstate)

/* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */
#ifdef LLTRACE
#define PRE_DISPATCH_GOTO() if (lltrace) { lltrace_instruction(frame, opcode, oparg); }
#define PRE_DISPATCH_GOTO() if (lltrace) { lltrace_instruction(frame, opcode, oparg, STACK_LEVEL()); }
#else
#define PRE_DISPATCH_GOTO() ((void)0)
#endif
Expand Down Expand Up @@ -1375,6 +1433,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
/* The stack can grow at most MAXINT deep, as co_nlocals and
co_stacksize are ints. */
#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
#define STACK_SIZE() (frame->f_code->co_stacksize)
#define EMPTY() (STACK_LEVEL() == 0)
#define TOP() (stack_pointer[-1])
#define SECOND() (stack_pointer[-2])
Expand All @@ -1387,23 +1446,21 @@ eval_frame_handle_pending(PyThreadState *tstate)
#define BASIC_PUSH(v) (*stack_pointer++ = (v))
#define BASIC_POP() (*--stack_pointer)

#ifdef LLTRACE
#define PUSH(v) { (void)(BASIC_PUSH(v), \
lltrace && prtrace(tstate, TOP(), "push")); \
assert(STACK_LEVEL() <= frame->f_code->co_stacksize); }
#define POP() ((void)(lltrace && prtrace(tstate, TOP(), "pop")), \
BASIC_POP())
#ifdef Py_DEBUG
#define PUSH(v) do { \
BASIC_PUSH(v); \
assert(STACK_LEVEL() <= STACK_SIZE()); \
} while (0)
#define POP() (assert(STACK_LEVEL() > 0), BASIC_POP())
#define STACK_GROW(n) do { \
assert(n >= 0); \
(void)(BASIC_STACKADJ(n), \
lltrace && prtrace(tstate, TOP(), "stackadj")); \
assert(STACK_LEVEL() <= frame->f_code->co_stacksize); \
assert(n >= 0); \
BASIC_STACKADJ(n); \
assert(STACK_LEVEL() <= STACK_SIZE()); \
} while (0)
#define STACK_SHRINK(n) do { \
assert(n >= 0); \
(void)(lltrace && prtrace(tstate, TOP(), "stackadj")); \
(void)(BASIC_STACKADJ(-(n))); \
assert(STACK_LEVEL() <= frame->f_code->co_stacksize); \
assert(STACK_LEVEL() >= n); \
BASIC_STACKADJ(-(n)); \
} while (0)
#else
#define PUSH(v) BASIC_PUSH(v)
Expand Down Expand Up @@ -1673,6 +1730,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
lltrace = r;
}
if (lltrace) {
lltrace_resume_frame(frame);
}
#endif

#ifdef Py_DEBUG
Expand Down Expand Up @@ -6667,23 +6727,6 @@ unpack_iterable(PyThreadState *tstate, PyObject *v,
return 0;
}

#ifdef LLTRACE
static int
prtrace(PyThreadState *tstate, PyObject *v, const char *str)
{
printf("%s ", str);
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
if (PyObject_Print(v, stdout, 0) != 0) {
/* Don't know what else to do */
_PyErr_Clear(tstate);
}
printf("\n");
PyErr_Restore(type, value, traceback);
return 1;
}
#endif

static void
call_exc_trace(Py_tracefunc func, PyObject *self,
PyThreadState *tstate,
Expand Down
0