diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index e11d1f05129c67..b379322be0450e 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -312,9 +312,10 @@ typedef struct _stats { } PyStats; extern PyStats _py_stats; +extern int _enable_spec_stats; -#define STAT_INC(opname, name) _py_stats.opcode_stats[opname].specialization.name++ -#define STAT_DEC(opname, name) _py_stats.opcode_stats[opname].specialization.name-- +#define STAT_INC(opname, name) _enable_spec_stats && _py_stats.opcode_stats[opname].specialization.name++ +#define STAT_DEC(opname, name) _enable_spec_stats && _py_stats.opcode_stats[opname].specialization.name-- #define OPCODE_EXE_INC(opname) _py_stats.opcode_stats[opname].execution_count++ #define CALL_STAT_INC(name) _py_stats.call_stats.name++ #define OBJECT_STAT_INC(name) _py_stats.object_stats.name++ @@ -325,6 +326,9 @@ extern void _Py_PrintSpecializationStats(int to_file); // Used by the _opcode extension which is built as a shared library PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void); +PyAPI_FUNC(void) _Py_ClearSpecializationStats(void); +PyAPI_FUNC(void) _Py_EnableSpecializationStats(void); +PyAPI_FUNC(void) _Py_DisableSpecializationStats(void); #else #define STAT_INC(opname, name) ((void)0) diff --git a/Modules/_opcode.c b/Modules/_opcode.c index 4812716c672718..aa23039574c0a0 100644 --- a/Modules/_opcode.c +++ b/Modules/_opcode.c @@ -76,6 +76,59 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg, /*[clinic input] +_opcode.enable_specialization_stats + +Enable the specialization stats +[clinic start generated code]*/ + +static PyObject * +_opcode_enable_specialization_stats_impl(PyObject *module) +/*[clinic end generated code: output=02d8385bbafb7b63 input=62e09e133581bdad]*/ +{ +#ifdef Py_STATS + _Py_EnableSpecializationStats(); +#endif + Py_RETURN_NONE; +} + + +/*[clinic input] + +_opcode.disable_specialization_stats + +Disable the specialization stats +[clinic start generated code]*/ + +static PyObject * +_opcode_disable_specialization_stats_impl(PyObject *module) +/*[clinic end generated code: output=14ca17e44089d7a3 input=3213ea9f684d5f3b]*/ +{ +#ifdef Py_STATS + _Py_DisableSpecializationStats(); +#endif + Py_RETURN_NONE; +} + +/*[clinic input] + +_opcode.init_specialization_stats + +Initialize the specialization stats +[clinic start generated code]*/ + +static PyObject * +_opcode_init_specialization_stats_impl(PyObject *module) +/*[clinic end generated code: output=b067640d0e5de6a5 input=94c13e3ae8629a21]*/ +{ +#ifdef Py_STATS + _Py_ClearSpecializationStats(); + _Py_DisableSpecializationStats(); +#endif + Py_RETURN_NONE; +} + +/*[clinic input] + _opcode.get_specialization_stats Return the specialization stats @@ -96,6 +149,9 @@ static PyMethodDef opcode_functions[] = { _OPCODE_STACK_EFFECT_METHODDEF _OPCODE_GET_SPECIALIZATION_STATS_METHODDEF + _OPCODE_ENABLE_SPECIALIZATION_STATS_METHODDEF + _OPCODE_DISABLE_SPECIALIZATION_STATS_METHODDEF + _OPCODE_INIT_SPECIALIZATION_STATS_METHODDEF {NULL, NULL, 0, NULL} }; diff --git a/Modules/clinic/_opcode.c.h b/Modules/clinic/_opcode.c.h index d7e96a95c084fe..fce634f588ad3b 100644 --- a/Modules/clinic/_opcode.c.h +++ b/Modules/clinic/_opcode.c.h @@ -57,6 +57,60 @@ _opcode_stack_effect(PyObject *module, PyObject *const *args, Py_ssize_t nargs, return return_value; } +PyDoc_STRVAR(_opcode_enable_specialization_stats__doc__, +"enable_specialization_stats($module, /)\n" +"--\n" +"\n" +"Enable the specialization stats"); + +#define _OPCODE_ENABLE_SPECIALIZATION_STATS_METHODDEF \ + {"enable_specialization_stats", (PyCFunction)_opcode_enable_specialization_stats, METH_NOARGS, _opcode_enable_specialization_stats__doc__}, + +static PyObject * +_opcode_enable_specialization_stats_impl(PyObject *module); + +static PyObject * +_opcode_enable_specialization_stats(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _opcode_enable_specialization_stats_impl(module); +} + +PyDoc_STRVAR(_opcode_disable_specialization_stats__doc__, +"disable_specialization_stats($module, /)\n" +"--\n" +"\n" +"Disable the specialization stats"); + +#define _OPCODE_DISABLE_SPECIALIZATION_STATS_METHODDEF \ + {"disable_specialization_stats", (PyCFunction)_opcode_disable_specialization_stats, METH_NOARGS, _opcode_disable_specialization_stats__doc__}, + +static PyObject * +_opcode_disable_specialization_stats_impl(PyObject *module); + +static PyObject * +_opcode_disable_specialization_stats(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _opcode_disable_specialization_stats_impl(module); +} + +PyDoc_STRVAR(_opcode_init_specialization_stats__doc__, +"init_specialization_stats($module, /)\n" +"--\n" +"\n" +"Initialize the specialization stats"); + +#define _OPCODE_INIT_SPECIALIZATION_STATS_METHODDEF \ + {"init_specialization_stats", (PyCFunction)_opcode_init_specialization_stats, METH_NOARGS, _opcode_init_specialization_stats__doc__}, + +static PyObject * +_opcode_init_specialization_stats_impl(PyObject *module); + +static PyObject * +_opcode_init_specialization_stats(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _opcode_init_specialization_stats_impl(module); +} + PyDoc_STRVAR(_opcode_get_specialization_stats__doc__, "get_specialization_stats($module, /)\n" "--\n" @@ -74,4 +128,4 @@ _opcode_get_specialization_stats(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _opcode_get_specialization_stats_impl(module); } -/*[clinic end generated code: output=b904260bf022f953 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5db5d2cfd7ed8eec input=a9049054013a1b77]*/ diff --git a/Python/specialize.c b/Python/specialize.c index fa42993606fd63..9e3ca2f10d8e00 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -34,6 +34,8 @@ uint8_t _PyOpcode_Adaptive[256] = { Py_ssize_t _Py_QuickenedCount = 0; #ifdef Py_STATS PyStats _py_stats = { 0 }; +/* Enable specialization stats by default */ +int _enable_spec_stats = 1; #define ADD_STAT_TO_DICT(res, field) \ do { \ @@ -128,6 +130,26 @@ _Py_GetSpecializationStats(void) { } return stats; } + +void +_Py_ClearSpecializationStats() +{ + for (Py_ssize_t i = 0; i < 256; i++) { + memset(&_py_stats.opcode_stats[i].specialization, 0, sizeof(SpecializationStats)); + } +} + +void +_Py_EnableSpecializationStats(void) +{ + _enable_spec_stats = 1; +} +void +_Py_DisableSpecializationStats(void) +{ + _enable_spec_stats = 0; +} + #endif