From 25420fe290b98171e6d30edf9350292c21ef700e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 20 Nov 2017 18:12:22 -0800 Subject: bpo-32030: Add more options to _PyCoreConfig (#4485) Py_Main() now handles two more -X options: * -X showrefcount: new _PyCoreConfig.show_ref_count field * -X showalloccount: new _PyCoreConfig.show_alloc_count field --- Include/object.h | 1 - Include/pystate.h | 20 ++++++++++++-------- Modules/main.c | 10 +++++++++- Objects/listobject.c | 11 +++-------- Objects/object.c | 23 +++-------------------- Objects/tupleobject.c | 11 +++-------- Python/import.c | 7 +++---- Python/pylifecycle.c | 9 +++------ Python/pythonrun.c | 6 +++++- 9 files changed, 41 insertions(+), 57 deletions(-) diff --git a/Include/object.h b/Include/object.h index c65f948..7db5bfe 100644 --- a/Include/object.h +++ b/Include/object.h @@ -728,7 +728,6 @@ PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void); /* Py_REF_DEBUG also controls the display of refcounts and memory block * allocations at the interactive prompt and at interpreter shutdown */ -PyAPI_FUNC(PyObject *) _PyDebug_XOptionShowRefCount(void); PyAPI_FUNC(void) _PyDebug_PrintTotalRefs(void); #else #define _Py_INC_REFTOTAL diff --git a/Include/pystate.h b/Include/pystate.h index 2081ff5..a3840c9 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -25,15 +25,17 @@ typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int); typedef struct { - int ignore_environment; - int use_hash_seed; + int ignore_environment; /* -E */ + int use_hash_seed; /* PYTHONHASHSEED=x */ unsigned long hash_seed; int _disable_importlib; /* Needed by freeze_importlib */ - char *allocator; - int faulthandler; - int tracemalloc; /* Number of saved frames, 0=don't trace */ - int importtime; /* -X importtime */ + const char *allocator; /* Memory allocator: _PyMem_SetupAllocators() */ int dev_mode; /* -X dev */ + int faulthandler; /* -X faulthandler */ + int tracemalloc; /* -X tracemalloc=N */ + int import_time; /* -X importtime */ + int show_ref_count; /* -X showrefcount */ + int show_alloc_count; /* -X showalloccount */ } _PyCoreConfig; #define _PyCoreConfig_INIT \ @@ -42,10 +44,12 @@ typedef struct { .hash_seed = 0, \ ._disable_importlib = 0, \ .allocator = NULL, \ + .dev_mode = 0, \ .faulthandler = 0, \ .tracemalloc = 0, \ - .importtime = 0, \ - .dev_mode = 0} + .import_time = 0, \ + .show_ref_count = 0, \ + .show_alloc_count = 0} /* Placeholders while working on the new configuration API * diff --git a/Modules/main.c b/Modules/main.c index 70c1c3d..e5e4f33 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1384,6 +1384,14 @@ pymain_parse_envvars(_PyMain *pymain) } core_config->allocator = Py_GETENV("PYTHONMALLOC"); + /* -X options */ + if (pymain_get_xoption(pymain, L"showrefcount")) { + core_config->show_ref_count = 1; + } + if (pymain_get_xoption(pymain, L"showalloccount")) { + core_config->show_alloc_count = 1; + } + /* More complex options: env var and/or -X option */ if (pymain_get_env_var("PYTHONFAULTHANDLER") || pymain_get_xoption(pymain, L"faulthandler")) { @@ -1391,7 +1399,7 @@ pymain_parse_envvars(_PyMain *pymain) } if (pymain_get_env_var("PYTHONPROFILEIMPORTTIME") || pymain_get_xoption(pymain, L"importtime")) { - core_config->importtime = 1; + core_config->import_time = 1; } if (pymain_init_tracemalloc(pymain) < 0) { return -1; diff --git a/Objects/listobject.c b/Objects/listobject.c index 7eba61e..8576b7a 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -85,15 +85,10 @@ static size_t count_reuse = 0; static void show_alloc(void) { - PyObject *xoptions, *value; - _Py_IDENTIFIER(showalloccount); - - xoptions = PySys_GetXOptions(); - if (xoptions == NULL) - return; - value = _PyDict_GetItemId(xoptions, &PyId_showalloccount); - if (value != Py_True) + PyInterpreterState *interp = PyThreadState_GET()->interp; + if (!inter->core_config.show_alloc_count) { return; + } fprintf(stderr, "List allocations: %" PY_FORMAT_SIZE_T "d\n", count_alloc); diff --git a/Objects/object.c b/Objects/object.c index ed8a62a..674180d 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -29,17 +29,6 @@ _Py_GetRefTotal(void) return total; } -PyObject * -_PyDebug_XOptionShowRefCount(void) -{ - PyObject *xoptions = PySys_GetXOptions(); - if (xoptions == NULL) - return NULL; - - _Py_IDENTIFIER(showrefcount); - return _PyDict_GetItemId(xoptions, &PyId_showrefcount); -} - void _PyDebug_PrintTotalRefs(void) { fprintf(stderr, @@ -106,16 +95,10 @@ extern Py_ssize_t null_strings, one_strings; void dump_counts(FILE* f) { - PyTypeObject *tp; - PyObject *xoptions, *value; - _Py_IDENTIFIER(showalloccount); - - xoptions = PySys_GetXOptions(); - if (xoptions == NULL) - return; - value = _PyDict_GetItemId(xoptions, &PyId_showalloccount); - if (value != Py_True) + PyInterpreterState *interp = PyThreadState_GET()->interp; + if (!inter->core_config.show_alloc_count) { return; + } for (tp = type_list; tp; tp = tp->tp_next) fprintf(f, "%s alloc'd: %" PY_FORMAT_SIZE_T "d, " diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 35decd8..964db3b 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -44,15 +44,10 @@ static Py_ssize_t count_tracked = 0; static void show_track(void) { - PyObject *xoptions, *value; - _Py_IDENTIFIER(showalloccount); - - xoptions = PySys_GetXOptions(); - if (xoptions == NULL) - return; - value = _PyDict_GetItemId(xoptions, &PyId_showalloccount); - if (value != Py_True) + PyInterpreterState *interp = PyThreadState_GET()->interp; + if (!inter->core_config.show_alloc_count) { return; + } fprintf(stderr, "Tuples created: %" PY_FORMAT_SIZE_T "d\n", count_tracked + count_untracked); diff --git a/Python/import.c b/Python/import.c index fef6398..d2ed785 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1674,8 +1674,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } } else { - /* 1 -- true, 0 -- false, -1 -- not initialized */ - int importtime = interp->core_config.importtime; + int import_time = interp->core_config.import_time; static int import_level; static _PyTime_t accumulated; @@ -1686,7 +1685,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, * Anyway, importlib._find_and_load is much slower than * _PyDict_GetItemIdWithError(). */ - if (importtime) { + if (import_time) { static int header = 1; if (header) { fputs("import time: self [us] | cumulative | imported package\n", @@ -1712,7 +1711,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, PyDTrace_IMPORT_FIND_LOAD_DONE(PyUnicode_AsUTF8(abs_name), mod != NULL); - if (importtime) { + if (import_time) { _PyTime_t cum = _PyTime_GetPerfCounter() - t1; import_level--; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 14fe75e..36fcf61 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1101,10 +1101,6 @@ Py_FinalizeEx(void) /* nothing */; #endif -#ifdef Py_REF_DEBUG - PyObject *showrefcount = _PyDebug_XOptionShowRefCount(); -#endif - /* Destroy all modules */ PyImport_Cleanup(); @@ -1153,8 +1149,9 @@ Py_FinalizeEx(void) _PyHash_Fini(); #ifdef Py_REF_DEBUG - if (showrefcount == Py_True) - _PyDebug_PrintTotalRefs(); + if (interp->core_config.show_ref_count) { + _PyDebug_PrintTotalRefs(); + } #endif #ifdef Py_TRACE_REFS diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 90b29cb..b528575 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -91,6 +91,9 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags * int ret, err; PyCompilerFlags local_flags; int nomem_count = 0; +#ifdef Py_REF_DEBUG + int show_ref_count = PyThreadState_GET()->interp->core_config.show_ref_count; +#endif filename = PyUnicode_DecodeFSDefault(filename_str); if (filename == NULL) { @@ -134,8 +137,9 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename_str, PyCompilerFlags * nomem_count = 0; } #ifdef Py_REF_DEBUG - if (_PyDebug_XOptionShowRefCount() == Py_True) + if (show_ref_count) { _PyDebug_PrintTotalRefs(); + } #endif } while (ret != E_EOF); Py_DECREF(filename); -- cgit v0.12