diff options
author | Guido van Rossum <guido@python.org> | 2023-08-08 04:36:25 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-08 04:36:25 (GMT) |
commit | 328d925244511b2134d5ac926e307e4486ff4500 (patch) | |
tree | 5664372efae8658277c3a175bbd42065b533d362 /Python | |
parent | 2df58dcd500dbedc61d0630374f9e94c522fe523 (diff) | |
download | cpython-328d925244511b2134d5ac926e307e4486ff4500.zip cpython-328d925244511b2134d5ac926e307e4486ff4500.tar.gz cpython-328d925244511b2134d5ac926e307e4486ff4500.tar.bz2 |
gh-107758: Improvements to lltrace feature (#107757)
- The `dump_stack()` method could call a `__repr__` method implemented in Python,
causing (infinite) recursion.
I rewrote it to only print out the values for some fundamental types (`int`, `str`, etc.);
for everything else it just prints `<type_name @ 0xdeadbeef>`.
- The lltrace-like feature for uops wrote to `stderr`, while the one in `ceval.c` writes to `stdout`;
I changed the uops to write to stdout as well.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 34 | ||||
-rw-r--r-- | Python/executor.c | 2 | ||||
-rw-r--r-- | Python/optimizer.c | 2 |
3 files changed, 30 insertions, 8 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 30f722e..1dc4fd8 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -109,11 +109,24 @@ dump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer) if (ptr != stack_base) { printf(", "); } - if (PyObject_Print(*ptr, stdout, 0) != 0) { + if (*ptr == NULL) { + printf("<nil>"); + continue; + } + if ( + *ptr == Py_None + || PyBool_Check(*ptr) + || PyLong_CheckExact(*ptr) + || PyFloat_CheckExact(*ptr) + || PyUnicode_CheckExact(*ptr) + ) { + if (PyObject_Print(*ptr, stdout, 0) == 0) { + continue; + } PyErr_Clear(); - printf("<%s object at %p>", - Py_TYPE(*ptr)->tp_name, (void *)(*ptr)); } + // Don't call __repr__(), it might recurse into the interpreter. + printf("<%s at %p>", Py_TYPE(*ptr)->tp_name, (void *)(*ptr)); } printf("]\n"); fflush(stdout); @@ -128,9 +141,6 @@ lltrace_instruction(_PyInterpreterFrame *frame, if (frame->owner == FRAME_OWNED_BY_CSTACK) { return; } - /* This dump_stack() operation is risky, since the repr() of some - objects enters the interpreter recursively. It is also slow. - So you might want to comment it out. */ dump_stack(frame, stack_pointer); int oparg = next_instr->op.arg; int opcode = next_instr->op.code; @@ -729,6 +739,13 @@ resume_frame: goto exit_unwind; } lltrace = r; + if (!lltrace) { + // When tracing executed uops, also trace bytecode + char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG"); + if (uop_debug != NULL && *uop_debug >= '0') { + lltrace = (*uop_debug - '0') >= 4; // TODO: Parse an int and all that + } + } } if (lltrace) { lltrace_resume_frame(frame); @@ -896,6 +913,11 @@ exception_unwind: goto exception_unwind; } /* Resume normal execution */ +#ifdef LLTRACE + if (lltrace) { + lltrace_resume_frame(frame); + } +#endif DISPATCH(); } } diff --git a/Python/executor.c b/Python/executor.c index 57525df..4a18618 100644 --- a/Python/executor.c +++ b/Python/executor.c @@ -41,7 +41,7 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject lltrace = *uop_debug - '0'; // TODO: Parse an int and all that } #define DPRINTF(level, ...) \ - if (lltrace >= (level)) { fprintf(stderr, __VA_ARGS__); } + if (lltrace >= (level)) { printf(__VA_ARGS__); } #else #define DPRINTF(level, ...) #endif diff --git a/Python/optimizer.c b/Python/optimizer.c index d2ed8df..6c730aa 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -391,7 +391,7 @@ translate_bytecode_to_trace( #ifdef Py_DEBUG #define DPRINTF(level, ...) \ - if (lltrace >= (level)) { fprintf(stderr, __VA_ARGS__); } + if (lltrace >= (level)) { printf(__VA_ARGS__); } #else #define DPRINTF(level, ...) #endif |