From ce7e6cd6b602523f177295916ed0beeb16c81bd0 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Wed, 13 Sep 2023 17:20:36 -0700 Subject: [PATCH 1/4] gh-109390: add dump_symtable utility under #if 0 --- Python/symtable.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/Python/symtable.c b/Python/symtable.c index d737c09203d31b..ce281c5f52b95b 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -251,6 +251,101 @@ static int symtable_visit_pattern(struct symtable *st, pattern_ty s); static int symtable_raise_if_annotation_block(struct symtable *st, const char *, expr_ty); static int symtable_raise_if_comprehension_block(struct symtable *st, expr_ty); +/* For debugging purposes only */ +#if 0 +static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) +{ + const char *blocktype = ""; + switch(ste->ste_type) { + case FunctionBlock: blocktype = "FunctionBlock"; break; + case ClassBlock: blocktype = "ClassBlock"; break; + case ModuleBlock: blocktype = "ModuleBlock"; break; + case AnnotationBlock: blocktype = "AnnotationBlock"; break; + case TypeVarBoundBlock: blocktype = "TypeVarBoundBlock"; break; + case TypeAliasBlock: blocktype = "TypeAliasBlock"; break; + case TypeParamBlock: blocktype = "TypeParamBlock"; break; + } + const char *comptype = ""; + switch(ste->ste_comprehension) { + case ListComprehension: comptype = " ListComprehension"; break; + case DictComprehension: comptype = " DictComprehension"; break; + case SetComprehension: comptype = " SetComprehension"; break; + case GeneratorExpression: comptype = " GeneratorExpression"; break; + } + PyObject* msg = PyUnicode_FromFormat( + ( + "%U=== Symtable for %U ===\n" + "%U%s%s\n" + "%U%s%s%s%s%s%s%s%s%s%s%s%s%s\n" + "%Ulineno: %d col_offset: %d\n" + "%U--- Symbols ---\n" + ), + prefix, + ste->ste_name, + prefix, + blocktype, + comptype, + prefix, + ste->ste_nested ? " nested" : "", + ste->ste_free ? " free" : "", + ste->ste_child_free ? " child_free" : "", + ste->ste_generator ? " generator" : "", + ste->ste_coroutine ? " coroutine" : "", + ste->ste_varargs ? " varargs" : "", + ste->ste_varkeywords ? " varkeywords" : "", + ste->ste_returns_value ? " returns_value" : "", + ste->ste_needs_class_closure ? " needs_class_closure" : "", + ste->ste_needs_classdict ? " needs_classdict" : "", + ste->ste_comp_inlined ? " comp_inlined" : "", + ste->ste_comp_iter_target ? " comp_iter_target" : "", + ste->ste_can_see_class_scope ? " can_see_class_scope" : "", + prefix, + ste->ste_lineno, + ste->ste_col_offset, + prefix + ); + printf(PyUnicode_AsUTF8(msg)); + PyObject *name, *value; + Py_ssize_t pos = 0; + while(PyDict_Next(ste->ste_symbols, &pos, &name, &value)) { + int scope = _PyST_GetScope(ste, name); + long flags = _PyST_GetSymbol(ste, name); + printf("%s %s: ", PyUnicode_AsUTF8(prefix), PyUnicode_AsUTF8(name)); + if (flags & DEF_GLOBAL) printf(" DEF_GLOBAL"); + if (flags & DEF_LOCAL) printf(" DEF_LOCAL"); + if (flags & DEF_PARAM) printf(" DEF_PARAM"); + if (flags & DEF_NONLOCAL) printf(" DEF_NONLOCAL"); + if (flags & USE) printf(" USE"); + if (flags & DEF_FREE) printf(" DEF_FREE"); + if (flags & DEF_FREE_CLASS) printf(" DEF_FREE_CLASS"); + if (flags & DEF_IMPORT) printf(" DEF_IMPORT"); + if (flags & DEF_ANNOT) printf(" DEF_ANNOT"); + if (flags & DEF_COMP_ITER) printf(" DEF_COMP_ITER"); + if (flags & DEF_TYPE_PARAM) printf(" DEF_TYPE_PARAM"); + if (flags & DEF_COMP_CELL) printf(" DEF_COMP_CELL"); + switch (scope) { + case LOCAL: printf(" LOCAL"); break; + case GLOBAL_EXPLICIT: printf(" GLOBAL_EXPLICIT"); break; + case GLOBAL_IMPLICIT: printf(" GLOBAL_IMPLICIT"); break; + case FREE: printf(" FREE"); break; + case CELL: printf(" CELL"); break; + } + printf("\n"); + } + printf("%s--- Children ---\n", PyUnicode_AsUTF8(prefix)); + PyObject *new_prefix = PyUnicode_FromFormat(" %U", prefix); + for (Py_ssize_t i = 0; i < PyList_GET_SIZE(ste->ste_children); i++) { + PyObject *child = PyList_GetItem(ste->ste_children, i); + assert(PySTEntry_Check(child)); + _dump_symtable((PySTEntryObject*)child, new_prefix); + } +} + +static void dump_symtable(PySTEntryObject* ste) +{ + _dump_symtable(ste, PyUnicode_FromString("")); +} +#endif #define DUPLICATE_ARGUMENT \ "duplicate argument '%U' in function definition" From bb0a0ddaf8650111dd9551978f83628f0f38e3d3 Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Thu, 14 Sep 2023 07:57:39 -0600 Subject: [PATCH 2/4] Apply suggestions from code review Co-authored-by: Jelle Zijlstra --- Python/symtable.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c index ce281c5f52b95b..d4e7bc397e284f 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -256,7 +256,7 @@ static int symtable_raise_if_comprehension_block(struct symtable *st, expr_ty); static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) { const char *blocktype = ""; - switch(ste->ste_type) { + switch (ste->ste_type) { case FunctionBlock: blocktype = "FunctionBlock"; break; case ClassBlock: blocktype = "ClassBlock"; break; case ModuleBlock: blocktype = "ModuleBlock"; break; @@ -266,7 +266,7 @@ static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) case TypeParamBlock: blocktype = "TypeParamBlock"; break; } const char *comptype = ""; - switch(ste->ste_comprehension) { + switch (ste->ste_comprehension) { case ListComprehension: comptype = " ListComprehension"; break; case DictComprehension: comptype = " DictComprehension"; break; case SetComprehension: comptype = " SetComprehension"; break; @@ -307,7 +307,7 @@ static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) printf(PyUnicode_AsUTF8(msg)); PyObject *name, *value; Py_ssize_t pos = 0; - while(PyDict_Next(ste->ste_symbols, &pos, &name, &value)) { + while (PyDict_Next(ste->ste_symbols, &pos, &name, &value)) { int scope = _PyST_GetScope(ste, name); long flags = _PyST_GetSymbol(ste, name); printf("%s %s: ", PyUnicode_AsUTF8(prefix), PyUnicode_AsUTF8(name)); From f0f2cd2cf3cb38ea44d29dd732cde42714e9a755 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 17 Sep 2023 20:33:14 -0700 Subject: [PATCH 3/4] Fix refleaks, add a #define --- Python/symtable.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c index d4e7bc397e284f..9893b2f608eaab 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -4,6 +4,8 @@ #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // PySTEntryObject +// Set this to 1 to dump all symtables to stdout for debugging +#define _PY_DUMP_SYMTABLE 0 /* error strings used for warnings */ #define GLOBAL_PARAM \ @@ -252,7 +254,7 @@ static int symtable_raise_if_annotation_block(struct symtable *st, const char *, static int symtable_raise_if_comprehension_block(struct symtable *st, expr_ty); /* For debugging purposes only */ -#if 0 +#if _PY_DUMP_SYMTABLE static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) { const char *blocktype = ""; @@ -271,6 +273,7 @@ static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) case DictComprehension: comptype = " DictComprehension"; break; case SetComprehension: comptype = " SetComprehension"; break; case GeneratorExpression: comptype = " GeneratorExpression"; break; + case NoComprehension: break; } PyObject* msg = PyUnicode_FromFormat( ( @@ -304,7 +307,8 @@ static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) ste->ste_col_offset, prefix ); - printf(PyUnicode_AsUTF8(msg)); + printf("%s", PyUnicode_AsUTF8(msg)); + Py_DECREF(msg); PyObject *name, *value; Py_ssize_t pos = 0; while (PyDict_Next(ste->ste_symbols, &pos, &name, &value)) { @@ -339,6 +343,7 @@ static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) assert(PySTEntry_Check(child)); _dump_symtable((PySTEntryObject*)child, new_prefix); } + Py_DECREF(new_prefix); } static void dump_symtable(PySTEntryObject* ste) @@ -455,8 +460,12 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, PyFutureFeatures *future) return NULL; } /* Make the second symbol analysis pass */ - if (symtable_analyze(st)) + if (symtable_analyze(st)) { +#if _PY_DUMP_SYMTABLE + dump_symtable(st->st_top); +#endif return st; + } _PySymtable_Free(st); return NULL; error: From aa50592f973b4f8a844dfb561dfd108a65f5c6bd Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 18 Sep 2023 09:47:23 -0700 Subject: [PATCH 4/4] Add another DECREF, add asserts --- Python/symtable.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c index 9893b2f608eaab..ca5155550ef7ac 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -307,6 +307,7 @@ static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) ste->ste_col_offset, prefix ); + assert(msg != NULL); printf("%s", PyUnicode_AsUTF8(msg)); Py_DECREF(msg); PyObject *name, *value; @@ -338,17 +339,21 @@ static void _dump_symtable(PySTEntryObject* ste, PyObject* prefix) } printf("%s--- Children ---\n", PyUnicode_AsUTF8(prefix)); PyObject *new_prefix = PyUnicode_FromFormat(" %U", prefix); + assert(new_prefix != NULL); for (Py_ssize_t i = 0; i < PyList_GET_SIZE(ste->ste_children); i++) { PyObject *child = PyList_GetItem(ste->ste_children, i); - assert(PySTEntry_Check(child)); - _dump_symtable((PySTEntryObject*)child, new_prefix); + assert(child != NULL && PySTEntry_Check(child)); + _dump_symtable((PySTEntryObject *)child, new_prefix); } Py_DECREF(new_prefix); } static void dump_symtable(PySTEntryObject* ste) { - _dump_symtable(ste, PyUnicode_FromString("")); + PyObject *empty = PyUnicode_FromString(""); + assert(empty != NULL); + _dump_symtable(ste, empty); + Py_DECREF(empty); } #endif