From 299f63f37f397c149a3067f4069903941529e376 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 31 Oct 2024 14:04:57 +0300 Subject: [PATCH 1/9] gh-126220: Fix crash on calls to `_lsprof.Profiler` methods with 0 args --- Lib/test/test_cprofile.py | 16 + ...-10-31-14-06-28.gh-issue-126220.uJAJCU.rst | 2 + Modules/_lsprof.c | 230 ++++++----- Modules/clinic/_lsprof.c.h | 357 +++++++++++++++++- 4 files changed, 506 insertions(+), 99 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py index b2595eccc82f70..2d592a68b04ba8 100644 --- a/Lib/test/test_cprofile.py +++ b/Lib/test/test_cprofile.py @@ -30,6 +30,22 @@ def test_bad_counter_during_dealloc(self): self.assertEqual(cm.unraisable.exc_type, TypeError) + def test_crash_on_no_args(self): + # gh-126220 + import _lsprof + + for profile in [_lsprof.Profiler(), cProfile.Profile()]: + for method in [ + "_pystart_callback", + "_pyreturn_callback", + "_ccall_callback", + "_creturn_callback", + ]: + with self.subTest(profile=profile, method=method): + method_obj = getattr(profile, method) + with self.assertRaises(TypeError): + method_obj() # should not crash + def test_evil_external_timer(self): # gh-120289 # Disabling profiler in external timer should not crash diff --git a/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst b/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst new file mode 100644 index 00000000000000..f1f4a7083843b0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst @@ -0,0 +1,2 @@ +Fix crash of :class:`cProfile.Profile` and ``_lsprof.Profiler`` when their +callbacks were directly called with 0 arguments. diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 8b6906234bdc25..2c2b322fe46583 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -606,17 +606,41 @@ setBuiltins(ProfilerObject *pObj, int nvalue) return 0; } -PyObject* pystart_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size) +/*[clinic input] +_lsprof.Profiler._pystart_callback + + code: object + obj: object + / + +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler__pystart_callback_impl(ProfilerObject *self, PyObject *code, + PyObject *obj) +/*[clinic end generated code: output=f6b04ac9658deb04 input=2a8a6a7b163e253d]*/ { - PyObject* code = args[0]; - ptrace_enter_call((PyObject*)self, (void *)code, (PyObject *)code); + ptrace_enter_call((PyObject*)self, (void *)code, code); Py_RETURN_NONE; } -PyObject* pyreturn_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size) +/*[clinic input] +_lsprof.Profiler._pyreturn_callback + + code: object + obj: object + retval: object + / + +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler__pyreturn_callback_impl(ProfilerObject *self, + PyObject *code, PyObject *obj, + PyObject *retval) +/*[clinic end generated code: output=dc0488deec84f7fc input=203c2cf434ae6ceb]*/ { - PyObject* code = args[0]; ptrace_leave_call((PyObject*)self, (void *)code); Py_RETURN_NONE; @@ -649,12 +673,24 @@ PyObject* get_cfunc_from_callable(PyObject* callable, PyObject* self_arg, PyObje return NULL; } -PyObject* ccall_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size) +/*[clinic input] +_lsprof.Profiler._ccall_callback + + code: object + obj: object + callable: object + self_arg: object + / + +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler__ccall_callback_impl(ProfilerObject *self, PyObject *code, + PyObject *obj, PyObject *callable, + PyObject *self_arg) +/*[clinic end generated code: output=8d50bf59970d2a7e input=9b1560dce1c1a3c8]*/ { if (self->flags & POF_BUILTINS) { - PyObject* callable = args[2]; - PyObject* self_arg = args[3]; - PyObject* cfunc = get_cfunc_from_callable(callable, self_arg, self->missing); if (cfunc) { @@ -667,12 +703,24 @@ PyObject* ccall_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t Py_RETURN_NONE; } -PyObject* creturn_callback(ProfilerObject* self, PyObject *const *args, Py_ssize_t size) +/*[clinic input] +_lsprof.Profiler._creturn_callback + + code: object + obj: object + callable: object + self_arg: object + / + +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler__creturn_callback_impl(ProfilerObject *self, PyObject *code, + PyObject *obj, PyObject *callable, + PyObject *self_arg) +/*[clinic end generated code: output=4c1f245bd3804b9a input=83e727bf01749202]*/ { if (self->flags & POF_BUILTINS) { - PyObject* callable = args[2]; - PyObject* self_arg = args[3]; - PyObject* cfunc = get_cfunc_from_callable(callable, self_arg, self->missing); if (cfunc) { @@ -700,31 +748,27 @@ static const struct { {0, NULL} }; -PyDoc_STRVAR(enable_doc, "\ -enable(subcalls=True, builtins=True)\n\ -\n\ -Start collecting profiling information.\n\ -If 'subcalls' is True, also records for each function\n\ -statistics separated according to its current caller.\n\ -If 'builtins' is True, records the time spent in\n\ -built-in functions separately from their caller.\n\ -"); - -static PyObject* -profiler_enable(ProfilerObject *self, PyObject *args, PyObject *kwds) +/*[clinic input] +_lsprof.Profiler.enable + + subcalls: bool = True + builtins: bool = True + +Start collecting profiling information. + +If 'subcalls' is True, also records for each function +statistics separated according to its current caller. +If 'builtins' is True, records the time spent in +built-in functions separately from their caller. +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, + int builtins) +/*[clinic end generated code: output=1e747f9dc1edd571 input=0b6049b4e398781f]*/ { - int subcalls = -1; - int builtins = -1; - static char *kwlist[] = {"subcalls", "builtins", 0}; int all_events = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|pp:enable", - kwlist, &subcalls, &builtins)) - return NULL; - if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { - return NULL; - } - PyObject* monitoring = _PyImport_GetModuleAttrString("sys", "monitoring"); if (!monitoring) { return NULL; @@ -776,14 +820,15 @@ flush_unmatched(ProfilerObject *pObj) } -PyDoc_STRVAR(disable_doc, "\ -disable()\n\ -\n\ -Stop collecting profiling information.\n\ -"); +/*[clinic input] +_lsprof.Profiler.disable + +Stop collecting profiling information. +[clinic start generated code]*/ -static PyObject* -profiler_disable(ProfilerObject *self, PyObject* noarg) +static PyObject * +_lsprof_Profiler_disable_impl(ProfilerObject *self) +/*[clinic end generated code: output=838cffef7f651870 input=05700b3fc68d1f50]*/ { if (self->flags & POF_EXT_TIMER) { PyErr_SetString(PyExc_RuntimeError, @@ -834,21 +879,22 @@ profiler_disable(ProfilerObject *self, PyObject* noarg) Py_RETURN_NONE; } -PyDoc_STRVAR(clear_doc, "\ -clear()\n\ -\n\ -Clear all profiling information collected so far.\n\ -"); +/*[clinic input] +_lsprof.Profiler.clear + +Clear all profiling information collected so far. +[clinic start generated code]*/ -static PyObject* -profiler_clear(ProfilerObject *pObj, PyObject* noarg) +static PyObject * +_lsprof_Profiler_clear_impl(ProfilerObject *self) +/*[clinic end generated code: output=dd1c668fb84b1335 input=fbe1f88c28be4f98]*/ { - if (pObj->flags & POF_EXT_TIMER) { + if (self->flags & POF_EXT_TIMER) { PyErr_SetString(PyExc_RuntimeError, "cannot clear profiler in external timer"); return NULL; } - clearEntries(pObj); + clearEntries(self); Py_RETURN_NONE; } @@ -879,74 +925,62 @@ profiler_dealloc(ProfilerObject *op) Py_DECREF(tp); } +/*[clinic input] +_lsprof.Profiler.__init__ + + timer: object(c_default='NULL') = None + timeunit: double = 0.0 + subcalls: bool = True + builtins: bool = True + +Builds a profiler object using the specified timer function. + +The default timer is a fast built-in one based on real time. +For custom timer functions returning integers, timeunit can +be a float specifying a scale (i.e. how long each integer unit +is, in seconds). +[clinic start generated code]*/ + static int -profiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw) +_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, + double timeunit, int subcalls, int builtins) +/*[clinic end generated code: output=ab5498359fd34283 input=40225117dd22d4d7]*/ { - PyObject *timer = NULL; - double timeunit = 0.0; - int subcalls = 1; - int builtins = 1; - static char *kwlist[] = {"timer", "timeunit", - "subcalls", "builtins", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Odpp:Profiler", kwlist, - &timer, &timeunit, - &subcalls, &builtins)) - return -1; - - if (setSubcalls(pObj, subcalls) < 0 || setBuiltins(pObj, builtins) < 0) + if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) return -1; - pObj->externalTimerUnit = timeunit; - Py_XSETREF(pObj->externalTimer, Py_XNewRef(timer)); - pObj->tool_id = PY_MONITORING_PROFILER_ID; + self->externalTimerUnit = timeunit; + Py_XSETREF(self->externalTimer, Py_XNewRef(timer)); + self->tool_id = PY_MONITORING_PROFILER_ID; PyObject* monitoring = _PyImport_GetModuleAttrString("sys", "monitoring"); if (!monitoring) { return -1; } - pObj->missing = PyObject_GetAttrString(monitoring, "MISSING"); - if (!pObj->missing) { - Py_DECREF(monitoring); + self->missing = PyObject_GetAttrString(monitoring, "MISSING"); + Py_DECREF(monitoring); + if (!self->missing) { return -1; } - Py_DECREF(monitoring); return 0; } static PyMethodDef profiler_methods[] = { _LSPROF_PROFILER_GETSTATS_METHODDEF - {"enable", _PyCFunction_CAST(profiler_enable), - METH_VARARGS | METH_KEYWORDS, enable_doc}, - {"disable", (PyCFunction)profiler_disable, - METH_NOARGS, disable_doc}, - {"clear", (PyCFunction)profiler_clear, - METH_NOARGS, clear_doc}, - {"_pystart_callback", _PyCFunction_CAST(pystart_callback), - METH_FASTCALL, NULL}, - {"_pyreturn_callback", _PyCFunction_CAST(pyreturn_callback), - METH_FASTCALL, NULL}, - {"_ccall_callback", _PyCFunction_CAST(ccall_callback), - METH_FASTCALL, NULL}, - {"_creturn_callback", _PyCFunction_CAST(creturn_callback), - METH_FASTCALL, NULL}, + _LSPROF_PROFILER_ENABLE_METHODDEF + _LSPROF_PROFILER_DISABLE_METHODDEF + _LSPROF_PROFILER_CLEAR_METHODDEF + _LSPROF_PROFILER__PYSTART_CALLBACK_METHODDEF + _LSPROF_PROFILER__PYRETURN_CALLBACK_METHODDEF + _LSPROF_PROFILER__CCALL_CALLBACK_METHODDEF + _LSPROF_PROFILER__CRETURN_CALLBACK_METHODDEF {NULL, NULL} }; -PyDoc_STRVAR(profiler_doc, "\ -Profiler(timer=None, timeunit=None, subcalls=True, builtins=True)\n\ -\n\ - Builds a profiler object using the specified timer function.\n\ - The default timer is a fast built-in one based on real time.\n\ - For custom timer functions returning integers, timeunit can\n\ - be a float specifying a scale (i.e. how long each integer unit\n\ - is, in seconds).\n\ -"); - static PyType_Slot _lsprof_profiler_type_spec_slots[] = { - {Py_tp_doc, (void *)profiler_doc}, + {Py_tp_doc, (void *)_lsprof_Profiler___init____doc__}, {Py_tp_methods, profiler_methods}, {Py_tp_dealloc, profiler_dealloc}, - {Py_tp_init, profiler_init}, + {Py_tp_init, _lsprof_Profiler___init__}, {Py_tp_traverse, profiler_traverse}, {0, 0} }; diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h index b3b7fda5660bfd..7d9b6496db356d 100644 --- a/Modules/clinic/_lsprof.c.h +++ b/Modules/clinic/_lsprof.c.h @@ -2,6 +2,12 @@ preserve [clinic start generated code]*/ +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif +#include "pycore_modsupport.h" // _PyArg_CheckPositional() + PyDoc_STRVAR(_lsprof_Profiler_getstats__doc__, "getstats($self, /)\n" "--\n" @@ -45,4 +51,353 @@ _lsprof_Profiler_getstats(ProfilerObject *self, PyTypeObject *cls, PyObject *con } return _lsprof_Profiler_getstats_impl(self, cls); } -/*[clinic end generated code: output=5c9d87d89863dc83 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_lsprof_Profiler__pystart_callback__doc__, +"_pystart_callback($self, code, obj, /)\n" +"--\n" +"\n"); + +#define _LSPROF_PROFILER__PYSTART_CALLBACK_METHODDEF \ + {"_pystart_callback", _PyCFunction_CAST(_lsprof_Profiler__pystart_callback), METH_FASTCALL, _lsprof_Profiler__pystart_callback__doc__}, + +static PyObject * +_lsprof_Profiler__pystart_callback_impl(ProfilerObject *self, PyObject *code, + PyObject *obj); + +static PyObject * +_lsprof_Profiler__pystart_callback(ProfilerObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *code; + PyObject *obj; + + if (!_PyArg_CheckPositional("_pystart_callback", nargs, 2, 2)) { + goto exit; + } + code = args[0]; + obj = args[1]; + return_value = _lsprof_Profiler__pystart_callback_impl(self, code, obj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_lsprof_Profiler__pyreturn_callback__doc__, +"_pyreturn_callback($self, code, obj, retval, /)\n" +"--\n" +"\n"); + +#define _LSPROF_PROFILER__PYRETURN_CALLBACK_METHODDEF \ + {"_pyreturn_callback", _PyCFunction_CAST(_lsprof_Profiler__pyreturn_callback), METH_FASTCALL, _lsprof_Profiler__pyreturn_callback__doc__}, + +static PyObject * +_lsprof_Profiler__pyreturn_callback_impl(ProfilerObject *self, + PyObject *code, PyObject *obj, + PyObject *retval); + +static PyObject * +_lsprof_Profiler__pyreturn_callback(ProfilerObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *code; + PyObject *obj; + PyObject *retval; + + if (!_PyArg_CheckPositional("_pyreturn_callback", nargs, 3, 3)) { + goto exit; + } + code = args[0]; + obj = args[1]; + retval = args[2]; + return_value = _lsprof_Profiler__pyreturn_callback_impl(self, code, obj, retval); + +exit: + return return_value; +} + +PyDoc_STRVAR(_lsprof_Profiler__ccall_callback__doc__, +"_ccall_callback($self, code, obj, callable, self_arg, /)\n" +"--\n" +"\n"); + +#define _LSPROF_PROFILER__CCALL_CALLBACK_METHODDEF \ + {"_ccall_callback", _PyCFunction_CAST(_lsprof_Profiler__ccall_callback), METH_FASTCALL, _lsprof_Profiler__ccall_callback__doc__}, + +static PyObject * +_lsprof_Profiler__ccall_callback_impl(ProfilerObject *self, PyObject *code, + PyObject *obj, PyObject *callable, + PyObject *self_arg); + +static PyObject * +_lsprof_Profiler__ccall_callback(ProfilerObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *code; + PyObject *obj; + PyObject *callable; + PyObject *self_arg; + + if (!_PyArg_CheckPositional("_ccall_callback", nargs, 4, 4)) { + goto exit; + } + code = args[0]; + obj = args[1]; + callable = args[2]; + self_arg = args[3]; + return_value = _lsprof_Profiler__ccall_callback_impl(self, code, obj, callable, self_arg); + +exit: + return return_value; +} + +PyDoc_STRVAR(_lsprof_Profiler__creturn_callback__doc__, +"_creturn_callback($self, code, obj, callable, self_arg, /)\n" +"--\n" +"\n"); + +#define _LSPROF_PROFILER__CRETURN_CALLBACK_METHODDEF \ + {"_creturn_callback", _PyCFunction_CAST(_lsprof_Profiler__creturn_callback), METH_FASTCALL, _lsprof_Profiler__creturn_callback__doc__}, + +static PyObject * +_lsprof_Profiler__creturn_callback_impl(ProfilerObject *self, PyObject *code, + PyObject *obj, PyObject *callable, + PyObject *self_arg); + +static PyObject * +_lsprof_Profiler__creturn_callback(ProfilerObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *code; + PyObject *obj; + PyObject *callable; + PyObject *self_arg; + + if (!_PyArg_CheckPositional("_creturn_callback", nargs, 4, 4)) { + goto exit; + } + code = args[0]; + obj = args[1]; + callable = args[2]; + self_arg = args[3]; + return_value = _lsprof_Profiler__creturn_callback_impl(self, code, obj, callable, self_arg); + +exit: + return return_value; +} + +PyDoc_STRVAR(_lsprof_Profiler_enable__doc__, +"enable($self, /, subcalls=True, builtins=True)\n" +"--\n" +"\n" +"Start collecting profiling information.\n" +"\n" +"If \'subcalls\' is True, also records for each function\n" +"statistics separated according to its current caller.\n" +"If \'builtins\' is True, records the time spent in\n" +"built-in functions separately from their caller."); + +#define _LSPROF_PROFILER_ENABLE_METHODDEF \ + {"enable", _PyCFunction_CAST(_lsprof_Profiler_enable), METH_FASTCALL|METH_KEYWORDS, _lsprof_Profiler_enable__doc__}, + +static PyObject * +_lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, + int builtins); + +static PyObject * +_lsprof_Profiler_enable(ProfilerObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(subcalls), &_Py_ID(builtins), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"subcalls", "builtins", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "enable", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int subcalls = 1; + int builtins = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + subcalls = PyObject_IsTrue(args[0]); + if (subcalls < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + builtins = PyObject_IsTrue(args[1]); + if (builtins < 0) { + goto exit; + } +skip_optional_pos: + return_value = _lsprof_Profiler_enable_impl(self, subcalls, builtins); + +exit: + return return_value; +} + +PyDoc_STRVAR(_lsprof_Profiler_disable__doc__, +"disable($self, /)\n" +"--\n" +"\n" +"Stop collecting profiling information."); + +#define _LSPROF_PROFILER_DISABLE_METHODDEF \ + {"disable", (PyCFunction)_lsprof_Profiler_disable, METH_NOARGS, _lsprof_Profiler_disable__doc__}, + +static PyObject * +_lsprof_Profiler_disable_impl(ProfilerObject *self); + +static PyObject * +_lsprof_Profiler_disable(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _lsprof_Profiler_disable_impl(self); +} + +PyDoc_STRVAR(_lsprof_Profiler_clear__doc__, +"clear($self, /)\n" +"--\n" +"\n" +"Clear all profiling information collected so far."); + +#define _LSPROF_PROFILER_CLEAR_METHODDEF \ + {"clear", (PyCFunction)_lsprof_Profiler_clear, METH_NOARGS, _lsprof_Profiler_clear__doc__}, + +static PyObject * +_lsprof_Profiler_clear_impl(ProfilerObject *self); + +static PyObject * +_lsprof_Profiler_clear(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _lsprof_Profiler_clear_impl(self); +} + +PyDoc_STRVAR(_lsprof_Profiler___init____doc__, +"Profiler(timer=None, timeunit=0.0, subcalls=True, builtins=True)\n" +"--\n" +"\n" +"Builds a profiler object using the specified timer function.\n" +"\n" +"The default timer is a fast built-in one based on real time.\n" +"For custom timer functions returning integers, timeunit can\n" +"be a float specifying a scale (i.e. how long each integer unit\n" +"is, in seconds)."); + +static int +_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, + double timeunit, int subcalls, int builtins); + +static int +_lsprof_Profiler___init__(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(timer), &_Py_ID(timeunit), &_Py_ID(subcalls), &_Py_ID(builtins), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"timer", "timeunit", "subcalls", "builtins", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "Profiler", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; + PyObject *timer = NULL; + double timeunit = 0.0; + int subcalls = 1; + int builtins = 1; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 4, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (fastargs[0]) { + timer = fastargs[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[1]) { + if (PyFloat_CheckExact(fastargs[1])) { + timeunit = PyFloat_AS_DOUBLE(fastargs[1]); + } + else + { + timeunit = PyFloat_AsDouble(fastargs[1]); + if (timeunit == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[2]) { + subcalls = PyObject_IsTrue(fastargs[2]); + if (subcalls < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + builtins = PyObject_IsTrue(fastargs[3]); + if (builtins < 0) { + goto exit; + } +skip_optional_pos: + return_value = _lsprof_Profiler___init___impl((ProfilerObject *)self, timer, timeunit, subcalls, builtins); + +exit: + return return_value; +} +/*[clinic end generated code: output=787298ede73ff273 input=a9049054013a1b77]*/ From af78745c8ae8132387b48a2689e04caa75d34bb6 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 31 Oct 2024 14:22:10 +0300 Subject: [PATCH 2/9] Fix CI --- .../internal/pycore_global_objects_fini_generated.h | 3 +++ Include/internal/pycore_global_strings.h | 3 +++ Include/internal/pycore_runtime_init_generated.h | 3 +++ Include/internal/pycore_unicodeobject_generated.h | 12 ++++++++++++ .../2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst | 2 +- 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 2fd7d5d13a98b2..e4f0138e17edfa 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1231,6 +1231,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(strict_mode)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(string)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sub_key)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(subcalls)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(symmetric_difference_update)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tabsize)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tag)); @@ -1248,8 +1249,10 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(threading)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(throw)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timeout)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timer)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(times)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timetuple)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timeunit)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(top)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(trace_callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(traceback)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index fc3871570cc49d..e70f11e2a26cd5 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -720,6 +720,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(strict_mode) STRUCT_FOR_ID(string) STRUCT_FOR_ID(sub_key) + STRUCT_FOR_ID(subcalls) STRUCT_FOR_ID(symmetric_difference_update) STRUCT_FOR_ID(tabsize) STRUCT_FOR_ID(tag) @@ -737,8 +738,10 @@ struct _Py_global_strings { STRUCT_FOR_ID(threading) STRUCT_FOR_ID(throw) STRUCT_FOR_ID(timeout) + STRUCT_FOR_ID(timer) STRUCT_FOR_ID(times) STRUCT_FOR_ID(timetuple) + STRUCT_FOR_ID(timeunit) STRUCT_FOR_ID(top) STRUCT_FOR_ID(trace_callback) STRUCT_FOR_ID(traceback) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 3b80e265b0ca50..5d404c8fd91ca6 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1229,6 +1229,7 @@ extern "C" { INIT_ID(strict_mode), \ INIT_ID(string), \ INIT_ID(sub_key), \ + INIT_ID(subcalls), \ INIT_ID(symmetric_difference_update), \ INIT_ID(tabsize), \ INIT_ID(tag), \ @@ -1246,8 +1247,10 @@ extern "C" { INIT_ID(threading), \ INIT_ID(throw), \ INIT_ID(timeout), \ + INIT_ID(timer), \ INIT_ID(times), \ INIT_ID(timetuple), \ + INIT_ID(timeunit), \ INIT_ID(top), \ INIT_ID(trace_callback), \ INIT_ID(traceback), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index eb2eca06ec4d4f..d0bc8d7186c053 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -2676,6 +2676,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(subcalls); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(symmetric_difference_update); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2744,6 +2748,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(timer); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(times); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2752,6 +2760,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(timeunit); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(top); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst b/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst index f1f4a7083843b0..005ae603d058a8 100644 --- a/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst +++ b/Misc/NEWS.d/next/Library/2024-10-31-14-06-28.gh-issue-126220.uJAJCU.rst @@ -1,2 +1,2 @@ -Fix crash of :class:`cProfile.Profile` and ``_lsprof.Profiler`` when their +Fix crash of ``cProfile.Profile`` and ``_lsprof.Profiler`` when their callbacks were directly called with 0 arguments. From 3fddc30482af22a061cba9e2c61767c893b0bd1c Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 31 Oct 2024 22:06:34 +0300 Subject: [PATCH 3/9] Only fix 4 crashers --- .../pycore_global_objects_fini_generated.h | 3 - Include/internal/pycore_global_strings.h | 3 - .../internal/pycore_runtime_init_generated.h | 3 - .../internal/pycore_unicodeobject_generated.h | 12 - Modules/_lsprof.c | 144 ++++++------ Modules/clinic/_lsprof.c.h | 222 +----------------- 6 files changed, 78 insertions(+), 309 deletions(-) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index e4f0138e17edfa..2fd7d5d13a98b2 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1231,7 +1231,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(strict_mode)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(string)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sub_key)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(subcalls)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(symmetric_difference_update)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tabsize)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tag)); @@ -1249,10 +1248,8 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(threading)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(throw)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timeout)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timer)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(times)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timetuple)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timeunit)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(top)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(trace_callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(traceback)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index e70f11e2a26cd5..fc3871570cc49d 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -720,7 +720,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(strict_mode) STRUCT_FOR_ID(string) STRUCT_FOR_ID(sub_key) - STRUCT_FOR_ID(subcalls) STRUCT_FOR_ID(symmetric_difference_update) STRUCT_FOR_ID(tabsize) STRUCT_FOR_ID(tag) @@ -738,10 +737,8 @@ struct _Py_global_strings { STRUCT_FOR_ID(threading) STRUCT_FOR_ID(throw) STRUCT_FOR_ID(timeout) - STRUCT_FOR_ID(timer) STRUCT_FOR_ID(times) STRUCT_FOR_ID(timetuple) - STRUCT_FOR_ID(timeunit) STRUCT_FOR_ID(top) STRUCT_FOR_ID(trace_callback) STRUCT_FOR_ID(traceback) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 5d404c8fd91ca6..3b80e265b0ca50 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1229,7 +1229,6 @@ extern "C" { INIT_ID(strict_mode), \ INIT_ID(string), \ INIT_ID(sub_key), \ - INIT_ID(subcalls), \ INIT_ID(symmetric_difference_update), \ INIT_ID(tabsize), \ INIT_ID(tag), \ @@ -1247,10 +1246,8 @@ extern "C" { INIT_ID(threading), \ INIT_ID(throw), \ INIT_ID(timeout), \ - INIT_ID(timer), \ INIT_ID(times), \ INIT_ID(timetuple), \ - INIT_ID(timeunit), \ INIT_ID(top), \ INIT_ID(trace_callback), \ INIT_ID(traceback), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index d0bc8d7186c053..eb2eca06ec4d4f 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -2676,10 +2676,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); - string = &_Py_ID(subcalls); - _PyUnicode_InternStatic(interp, &string); - assert(_PyUnicode_CheckConsistency(string, 1)); - assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(symmetric_difference_update); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2748,10 +2744,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); - string = &_Py_ID(timer); - _PyUnicode_InternStatic(interp, &string); - assert(_PyUnicode_CheckConsistency(string, 1)); - assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(times); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2760,10 +2752,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); - string = &_Py_ID(timeunit); - _PyUnicode_InternStatic(interp, &string); - assert(_PyUnicode_CheckConsistency(string, 1)); - assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(top); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 2c2b322fe46583..73c955744f9ef9 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -748,27 +748,31 @@ static const struct { {0, NULL} }; -/*[clinic input] -_lsprof.Profiler.enable - - subcalls: bool = True - builtins: bool = True - -Start collecting profiling information. - -If 'subcalls' is True, also records for each function -statistics separated according to its current caller. -If 'builtins' is True, records the time spent in -built-in functions separately from their caller. -[clinic start generated code]*/ - -static PyObject * -_lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, - int builtins) -/*[clinic end generated code: output=1e747f9dc1edd571 input=0b6049b4e398781f]*/ +PyDoc_STRVAR(enable_doc, "\ +enable(subcalls=True, builtins=True)\n\ +\n\ +Start collecting profiling information.\n\ +If 'subcalls' is True, also records for each function\n\ +statistics separated according to its current caller.\n\ +If 'builtins' is True, records the time spent in\n\ +built-in functions separately from their caller.\n\ +"); + +static PyObject* +profiler_enable(ProfilerObject *self, PyObject *args, PyObject *kwds) { + int subcalls = -1; + int builtins = -1; + static char *kwlist[] = {"subcalls", "builtins", 0}; int all_events = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|pp:enable", + kwlist, &subcalls, &builtins)) + return NULL; + if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { + return NULL; + } + PyObject* monitoring = _PyImport_GetModuleAttrString("sys", "monitoring"); if (!monitoring) { return NULL; @@ -820,15 +824,14 @@ flush_unmatched(ProfilerObject *pObj) } -/*[clinic input] -_lsprof.Profiler.disable - -Stop collecting profiling information. -[clinic start generated code]*/ +PyDoc_STRVAR(disable_doc, "\ +disable()\n\ +\n\ +Stop collecting profiling information.\n\ +"); -static PyObject * -_lsprof_Profiler_disable_impl(ProfilerObject *self) -/*[clinic end generated code: output=838cffef7f651870 input=05700b3fc68d1f50]*/ +static PyObject* +profiler_disable(ProfilerObject *self, PyObject* Py_UNUSED(unused)) { if (self->flags & POF_EXT_TIMER) { PyErr_SetString(PyExc_RuntimeError, @@ -879,22 +882,21 @@ _lsprof_Profiler_disable_impl(ProfilerObject *self) Py_RETURN_NONE; } -/*[clinic input] -_lsprof.Profiler.clear - -Clear all profiling information collected so far. -[clinic start generated code]*/ +PyDoc_STRVAR(clear_doc, "\ +clear()\n\ +\n\ +Clear all profiling information collected so far.\n\ +"); -static PyObject * -_lsprof_Profiler_clear_impl(ProfilerObject *self) -/*[clinic end generated code: output=dd1c668fb84b1335 input=fbe1f88c28be4f98]*/ +static PyObject* +profiler_clear(ProfilerObject *pObj, PyObject* noarg) { - if (self->flags & POF_EXT_TIMER) { + if (pObj->flags & POF_EXT_TIMER) { PyErr_SetString(PyExc_RuntimeError, "cannot clear profiler in external timer"); return NULL; } - clearEntries(self); + clearEntries(pObj); Py_RETURN_NONE; } @@ -925,50 +927,48 @@ profiler_dealloc(ProfilerObject *op) Py_DECREF(tp); } -/*[clinic input] -_lsprof.Profiler.__init__ - - timer: object(c_default='NULL') = None - timeunit: double = 0.0 - subcalls: bool = True - builtins: bool = True - -Builds a profiler object using the specified timer function. - -The default timer is a fast built-in one based on real time. -For custom timer functions returning integers, timeunit can -be a float specifying a scale (i.e. how long each integer unit -is, in seconds). -[clinic start generated code]*/ - static int -_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, - double timeunit, int subcalls, int builtins) -/*[clinic end generated code: output=ab5498359fd34283 input=40225117dd22d4d7]*/ +profiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw) { - if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) + PyObject *timer = NULL; + double timeunit = 0.0; + int subcalls = 1; + int builtins = 1; + static char *kwlist[] = {"timer", "timeunit", + "subcalls", "builtins", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "|Odpp:Profiler", kwlist, + &timer, &timeunit, + &subcalls, &builtins)) + return -1; + + if (setSubcalls(pObj, subcalls) < 0 || setBuiltins(pObj, builtins) < 0) return -1; - self->externalTimerUnit = timeunit; - Py_XSETREF(self->externalTimer, Py_XNewRef(timer)); - self->tool_id = PY_MONITORING_PROFILER_ID; + pObj->externalTimerUnit = timeunit; + Py_XSETREF(pObj->externalTimer, Py_XNewRef(timer)); + pObj->tool_id = PY_MONITORING_PROFILER_ID; PyObject* monitoring = _PyImport_GetModuleAttrString("sys", "monitoring"); if (!monitoring) { return -1; } - self->missing = PyObject_GetAttrString(monitoring, "MISSING"); - Py_DECREF(monitoring); - if (!self->missing) { + pObj->missing = PyObject_GetAttrString(monitoring, "MISSING"); + if (!pObj->missing) { + Py_DECREF(monitoring); return -1; } + Py_DECREF(monitoring); return 0; } static PyMethodDef profiler_methods[] = { _LSPROF_PROFILER_GETSTATS_METHODDEF - _LSPROF_PROFILER_ENABLE_METHODDEF - _LSPROF_PROFILER_DISABLE_METHODDEF - _LSPROF_PROFILER_CLEAR_METHODDEF + {"enable", _PyCFunction_CAST(profiler_enable), + METH_VARARGS | METH_KEYWORDS, enable_doc}, + {"disable", (PyCFunction)profiler_disable, + METH_NOARGS, disable_doc}, + {"clear", (PyCFunction)profiler_clear, + METH_NOARGS, clear_doc}, _LSPROF_PROFILER__PYSTART_CALLBACK_METHODDEF _LSPROF_PROFILER__PYRETURN_CALLBACK_METHODDEF _LSPROF_PROFILER__CCALL_CALLBACK_METHODDEF @@ -976,11 +976,21 @@ static PyMethodDef profiler_methods[] = { {NULL, NULL} }; +PyDoc_STRVAR(profiler_doc, "\ +Profiler(timer=None, timeunit=None, subcalls=True, builtins=True)\n\ +\n\ + Builds a profiler object using the specified timer function.\n\ + The default timer is a fast built-in one based on real time.\n\ + For custom timer functions returning integers, timeunit can\n\ + be a float specifying a scale (i.e. how long each integer unit\n\ + is, in seconds).\n\ +"); + static PyType_Slot _lsprof_profiler_type_spec_slots[] = { - {Py_tp_doc, (void *)_lsprof_Profiler___init____doc__}, + {Py_tp_doc, (void *)profiler_doc}, {Py_tp_methods, profiler_methods}, {Py_tp_dealloc, profiler_dealloc}, - {Py_tp_init, _lsprof_Profiler___init__}, + {Py_tp_init, profiler_init}, {Py_tp_traverse, profiler_traverse}, {0, 0} }; diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h index 7d9b6496db356d..dfba178265994f 100644 --- a/Modules/clinic/_lsprof.c.h +++ b/Modules/clinic/_lsprof.c.h @@ -2,10 +2,6 @@ preserve [clinic start generated code]*/ -#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) -# include "pycore_gc.h" // PyGC_Head -# include "pycore_runtime.h" // _Py_ID() -#endif #include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_lsprof_Profiler_getstats__doc__, @@ -184,220 +180,4 @@ _lsprof_Profiler__creturn_callback(ProfilerObject *self, PyObject *const *args, exit: return return_value; } - -PyDoc_STRVAR(_lsprof_Profiler_enable__doc__, -"enable($self, /, subcalls=True, builtins=True)\n" -"--\n" -"\n" -"Start collecting profiling information.\n" -"\n" -"If \'subcalls\' is True, also records for each function\n" -"statistics separated according to its current caller.\n" -"If \'builtins\' is True, records the time spent in\n" -"built-in functions separately from their caller."); - -#define _LSPROF_PROFILER_ENABLE_METHODDEF \ - {"enable", _PyCFunction_CAST(_lsprof_Profiler_enable), METH_FASTCALL|METH_KEYWORDS, _lsprof_Profiler_enable__doc__}, - -static PyObject * -_lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, - int builtins); - -static PyObject * -_lsprof_Profiler_enable(ProfilerObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 2 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(subcalls), &_Py_ID(builtins), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"subcalls", "builtins", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "enable", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - int subcalls = 1; - int builtins = 1; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf); - if (!args) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[0]) { - subcalls = PyObject_IsTrue(args[0]); - if (subcalls < 0) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - builtins = PyObject_IsTrue(args[1]); - if (builtins < 0) { - goto exit; - } -skip_optional_pos: - return_value = _lsprof_Profiler_enable_impl(self, subcalls, builtins); - -exit: - return return_value; -} - -PyDoc_STRVAR(_lsprof_Profiler_disable__doc__, -"disable($self, /)\n" -"--\n" -"\n" -"Stop collecting profiling information."); - -#define _LSPROF_PROFILER_DISABLE_METHODDEF \ - {"disable", (PyCFunction)_lsprof_Profiler_disable, METH_NOARGS, _lsprof_Profiler_disable__doc__}, - -static PyObject * -_lsprof_Profiler_disable_impl(ProfilerObject *self); - -static PyObject * -_lsprof_Profiler_disable(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _lsprof_Profiler_disable_impl(self); -} - -PyDoc_STRVAR(_lsprof_Profiler_clear__doc__, -"clear($self, /)\n" -"--\n" -"\n" -"Clear all profiling information collected so far."); - -#define _LSPROF_PROFILER_CLEAR_METHODDEF \ - {"clear", (PyCFunction)_lsprof_Profiler_clear, METH_NOARGS, _lsprof_Profiler_clear__doc__}, - -static PyObject * -_lsprof_Profiler_clear_impl(ProfilerObject *self); - -static PyObject * -_lsprof_Profiler_clear(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) -{ - return _lsprof_Profiler_clear_impl(self); -} - -PyDoc_STRVAR(_lsprof_Profiler___init____doc__, -"Profiler(timer=None, timeunit=0.0, subcalls=True, builtins=True)\n" -"--\n" -"\n" -"Builds a profiler object using the specified timer function.\n" -"\n" -"The default timer is a fast built-in one based on real time.\n" -"For custom timer functions returning integers, timeunit can\n" -"be a float specifying a scale (i.e. how long each integer unit\n" -"is, in seconds)."); - -static int -_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, - double timeunit, int subcalls, int builtins); - -static int -_lsprof_Profiler___init__(PyObject *self, PyObject *args, PyObject *kwargs) -{ - int return_value = -1; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 4 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(timer), &_Py_ID(timeunit), &_Py_ID(subcalls), &_Py_ID(builtins), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"timer", "timeunit", "subcalls", "builtins", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "Profiler", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[4]; - PyObject * const *fastargs; - Py_ssize_t nargs = PyTuple_GET_SIZE(args); - Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; - PyObject *timer = NULL; - double timeunit = 0.0; - int subcalls = 1; - int builtins = 1; - - fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 4, 0, argsbuf); - if (!fastargs) { - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (fastargs[0]) { - timer = fastargs[0]; - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (fastargs[1]) { - if (PyFloat_CheckExact(fastargs[1])) { - timeunit = PyFloat_AS_DOUBLE(fastargs[1]); - } - else - { - timeunit = PyFloat_AsDouble(fastargs[1]); - if (timeunit == -1.0 && PyErr_Occurred()) { - goto exit; - } - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (fastargs[2]) { - subcalls = PyObject_IsTrue(fastargs[2]); - if (subcalls < 0) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - builtins = PyObject_IsTrue(fastargs[3]); - if (builtins < 0) { - goto exit; - } -skip_optional_pos: - return_value = _lsprof_Profiler___init___impl((ProfilerObject *)self, timer, timeunit, subcalls, builtins); - -exit: - return return_value; -} -/*[clinic end generated code: output=787298ede73ff273 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=79b2515a0d296f7d input=a9049054013a1b77]*/ From 4ffecddb286d69133cfcef4e9ed2d4e22bd0b212 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 31 Oct 2024 22:08:30 +0300 Subject: [PATCH 4/9] Use `instruction_offset` arg name --- Modules/_lsprof.c | 28 ++++++++++++----------- Modules/clinic/_lsprof.c.h | 47 ++++++++++++++++++++------------------ 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 73c955744f9ef9..fa26d2b4f77a58 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -610,15 +610,15 @@ setBuiltins(ProfilerObject *pObj, int nvalue) _lsprof.Profiler._pystart_callback code: object - obj: object + instruction_offset: object / [clinic start generated code]*/ static PyObject * _lsprof_Profiler__pystart_callback_impl(ProfilerObject *self, PyObject *code, - PyObject *obj) -/*[clinic end generated code: output=f6b04ac9658deb04 input=2a8a6a7b163e253d]*/ + PyObject *instruction_offset) +/*[clinic end generated code: output=5fec8b7ad5ed25e8 input=b166e6953c579cda]*/ { ptrace_enter_call((PyObject*)self, (void *)code, code); @@ -629,7 +629,7 @@ _lsprof_Profiler__pystart_callback_impl(ProfilerObject *self, PyObject *code, _lsprof.Profiler._pyreturn_callback code: object - obj: object + instruction_offset: object retval: object / @@ -637,9 +637,10 @@ _lsprof.Profiler._pyreturn_callback static PyObject * _lsprof_Profiler__pyreturn_callback_impl(ProfilerObject *self, - PyObject *code, PyObject *obj, + PyObject *code, + PyObject *instruction_offset, PyObject *retval) -/*[clinic end generated code: output=dc0488deec84f7fc input=203c2cf434ae6ceb]*/ +/*[clinic end generated code: output=9e2f6fc1b882c51e input=667ffaeb2fa6fd1f]*/ { ptrace_leave_call((PyObject*)self, (void *)code); @@ -677,7 +678,7 @@ PyObject* get_cfunc_from_callable(PyObject* callable, PyObject* self_arg, PyObje _lsprof.Profiler._ccall_callback code: object - obj: object + instruction_offset: object callable: object self_arg: object / @@ -686,9 +687,9 @@ _lsprof.Profiler._ccall_callback static PyObject * _lsprof_Profiler__ccall_callback_impl(ProfilerObject *self, PyObject *code, - PyObject *obj, PyObject *callable, - PyObject *self_arg) -/*[clinic end generated code: output=8d50bf59970d2a7e input=9b1560dce1c1a3c8]*/ + PyObject *instruction_offset, + PyObject *callable, PyObject *self_arg) +/*[clinic end generated code: output=152db83cabd18cad input=0e66687cfb95c001]*/ { if (self->flags & POF_BUILTINS) { PyObject* cfunc = get_cfunc_from_callable(callable, self_arg, self->missing); @@ -707,7 +708,7 @@ _lsprof_Profiler__ccall_callback_impl(ProfilerObject *self, PyObject *code, _lsprof.Profiler._creturn_callback code: object - obj: object + instruction_offset: object callable: object self_arg: object / @@ -716,9 +717,10 @@ _lsprof.Profiler._creturn_callback static PyObject * _lsprof_Profiler__creturn_callback_impl(ProfilerObject *self, PyObject *code, - PyObject *obj, PyObject *callable, + PyObject *instruction_offset, + PyObject *callable, PyObject *self_arg) -/*[clinic end generated code: output=4c1f245bd3804b9a input=83e727bf01749202]*/ +/*[clinic end generated code: output=1e886dde8fed8fb0 input=b18afe023746923a]*/ { if (self->flags & POF_BUILTINS) { PyObject* cfunc = get_cfunc_from_callable(callable, self_arg, self->missing); diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h index dfba178265994f..b35c5e12bdeb44 100644 --- a/Modules/clinic/_lsprof.c.h +++ b/Modules/clinic/_lsprof.c.h @@ -49,7 +49,7 @@ _lsprof_Profiler_getstats(ProfilerObject *self, PyTypeObject *cls, PyObject *con } PyDoc_STRVAR(_lsprof_Profiler__pystart_callback__doc__, -"_pystart_callback($self, code, obj, /)\n" +"_pystart_callback($self, code, instruction_offset, /)\n" "--\n" "\n"); @@ -58,28 +58,28 @@ PyDoc_STRVAR(_lsprof_Profiler__pystart_callback__doc__, static PyObject * _lsprof_Profiler__pystart_callback_impl(ProfilerObject *self, PyObject *code, - PyObject *obj); + PyObject *instruction_offset); static PyObject * _lsprof_Profiler__pystart_callback(ProfilerObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *code; - PyObject *obj; + PyObject *instruction_offset; if (!_PyArg_CheckPositional("_pystart_callback", nargs, 2, 2)) { goto exit; } code = args[0]; - obj = args[1]; - return_value = _lsprof_Profiler__pystart_callback_impl(self, code, obj); + instruction_offset = args[1]; + return_value = _lsprof_Profiler__pystart_callback_impl(self, code, instruction_offset); exit: return return_value; } PyDoc_STRVAR(_lsprof_Profiler__pyreturn_callback__doc__, -"_pyreturn_callback($self, code, obj, retval, /)\n" +"_pyreturn_callback($self, code, instruction_offset, retval, /)\n" "--\n" "\n"); @@ -88,7 +88,8 @@ PyDoc_STRVAR(_lsprof_Profiler__pyreturn_callback__doc__, static PyObject * _lsprof_Profiler__pyreturn_callback_impl(ProfilerObject *self, - PyObject *code, PyObject *obj, + PyObject *code, + PyObject *instruction_offset, PyObject *retval); static PyObject * @@ -96,23 +97,23 @@ _lsprof_Profiler__pyreturn_callback(ProfilerObject *self, PyObject *const *args, { PyObject *return_value = NULL; PyObject *code; - PyObject *obj; + PyObject *instruction_offset; PyObject *retval; if (!_PyArg_CheckPositional("_pyreturn_callback", nargs, 3, 3)) { goto exit; } code = args[0]; - obj = args[1]; + instruction_offset = args[1]; retval = args[2]; - return_value = _lsprof_Profiler__pyreturn_callback_impl(self, code, obj, retval); + return_value = _lsprof_Profiler__pyreturn_callback_impl(self, code, instruction_offset, retval); exit: return return_value; } PyDoc_STRVAR(_lsprof_Profiler__ccall_callback__doc__, -"_ccall_callback($self, code, obj, callable, self_arg, /)\n" +"_ccall_callback($self, code, instruction_offset, callable, self_arg, /)\n" "--\n" "\n"); @@ -121,15 +122,15 @@ PyDoc_STRVAR(_lsprof_Profiler__ccall_callback__doc__, static PyObject * _lsprof_Profiler__ccall_callback_impl(ProfilerObject *self, PyObject *code, - PyObject *obj, PyObject *callable, - PyObject *self_arg); + PyObject *instruction_offset, + PyObject *callable, PyObject *self_arg); static PyObject * _lsprof_Profiler__ccall_callback(ProfilerObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *code; - PyObject *obj; + PyObject *instruction_offset; PyObject *callable; PyObject *self_arg; @@ -137,17 +138,18 @@ _lsprof_Profiler__ccall_callback(ProfilerObject *self, PyObject *const *args, Py goto exit; } code = args[0]; - obj = args[1]; + instruction_offset = args[1]; callable = args[2]; self_arg = args[3]; - return_value = _lsprof_Profiler__ccall_callback_impl(self, code, obj, callable, self_arg); + return_value = _lsprof_Profiler__ccall_callback_impl(self, code, instruction_offset, callable, self_arg); exit: return return_value; } PyDoc_STRVAR(_lsprof_Profiler__creturn_callback__doc__, -"_creturn_callback($self, code, obj, callable, self_arg, /)\n" +"_creturn_callback($self, code, instruction_offset, callable, self_arg,\n" +" /)\n" "--\n" "\n"); @@ -156,7 +158,8 @@ PyDoc_STRVAR(_lsprof_Profiler__creturn_callback__doc__, static PyObject * _lsprof_Profiler__creturn_callback_impl(ProfilerObject *self, PyObject *code, - PyObject *obj, PyObject *callable, + PyObject *instruction_offset, + PyObject *callable, PyObject *self_arg); static PyObject * @@ -164,7 +167,7 @@ _lsprof_Profiler__creturn_callback(ProfilerObject *self, PyObject *const *args, { PyObject *return_value = NULL; PyObject *code; - PyObject *obj; + PyObject *instruction_offset; PyObject *callable; PyObject *self_arg; @@ -172,12 +175,12 @@ _lsprof_Profiler__creturn_callback(ProfilerObject *self, PyObject *const *args, goto exit; } code = args[0]; - obj = args[1]; + instruction_offset = args[1]; callable = args[2]; self_arg = args[3]; - return_value = _lsprof_Profiler__creturn_callback_impl(self, code, obj, callable, self_arg); + return_value = _lsprof_Profiler__creturn_callback_impl(self, code, instruction_offset, callable, self_arg); exit: return return_value; } -/*[clinic end generated code: output=79b2515a0d296f7d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ee788c83b5c85fb1 input=a9049054013a1b77]*/ From e3160e3d08e82e8a414660169b88f29501362d07 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 2 Nov 2024 01:08:39 +0300 Subject: [PATCH 5/9] Convert all methods --- .../pycore_global_objects_fini_generated.h | 3 + Include/internal/pycore_global_strings.h | 3 + .../internal/pycore_runtime_init_generated.h | 3 + .../internal/pycore_unicodeobject_generated.h | 12 + Modules/_lsprof.c | 140 ++++++----- Modules/clinic/_lsprof.c.h | 222 +++++++++++++++++- 6 files changed, 310 insertions(+), 73 deletions(-) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 2fd7d5d13a98b2..e4f0138e17edfa 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -1231,6 +1231,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(strict_mode)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(string)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(sub_key)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(subcalls)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(symmetric_difference_update)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tabsize)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tag)); @@ -1248,8 +1249,10 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(threading)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(throw)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timeout)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timer)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(times)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timetuple)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(timeunit)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(top)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(trace_callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(traceback)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index fc3871570cc49d..e70f11e2a26cd5 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -720,6 +720,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(strict_mode) STRUCT_FOR_ID(string) STRUCT_FOR_ID(sub_key) + STRUCT_FOR_ID(subcalls) STRUCT_FOR_ID(symmetric_difference_update) STRUCT_FOR_ID(tabsize) STRUCT_FOR_ID(tag) @@ -737,8 +738,10 @@ struct _Py_global_strings { STRUCT_FOR_ID(threading) STRUCT_FOR_ID(throw) STRUCT_FOR_ID(timeout) + STRUCT_FOR_ID(timer) STRUCT_FOR_ID(times) STRUCT_FOR_ID(timetuple) + STRUCT_FOR_ID(timeunit) STRUCT_FOR_ID(top) STRUCT_FOR_ID(trace_callback) STRUCT_FOR_ID(traceback) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 3b80e265b0ca50..5d404c8fd91ca6 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -1229,6 +1229,7 @@ extern "C" { INIT_ID(strict_mode), \ INIT_ID(string), \ INIT_ID(sub_key), \ + INIT_ID(subcalls), \ INIT_ID(symmetric_difference_update), \ INIT_ID(tabsize), \ INIT_ID(tag), \ @@ -1246,8 +1247,10 @@ extern "C" { INIT_ID(threading), \ INIT_ID(throw), \ INIT_ID(timeout), \ + INIT_ID(timer), \ INIT_ID(times), \ INIT_ID(timetuple), \ + INIT_ID(timeunit), \ INIT_ID(top), \ INIT_ID(trace_callback), \ INIT_ID(traceback), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index eb2eca06ec4d4f..d0bc8d7186c053 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -2676,6 +2676,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(subcalls); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(symmetric_difference_update); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2744,6 +2748,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(timer); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(times); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2752,6 +2760,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(timeunit); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(top); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index fa26d2b4f77a58..614a49b4619b49 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -750,27 +750,27 @@ static const struct { {0, NULL} }; -PyDoc_STRVAR(enable_doc, "\ -enable(subcalls=True, builtins=True)\n\ -\n\ -Start collecting profiling information.\n\ -If 'subcalls' is True, also records for each function\n\ -statistics separated according to its current caller.\n\ -If 'builtins' is True, records the time spent in\n\ -built-in functions separately from their caller.\n\ -"); - -static PyObject* -profiler_enable(ProfilerObject *self, PyObject *args, PyObject *kwds) + +/*[clinic input] +_lsprof.Profiler.enable + + subcalls: bool = True + builtins: bool = True + +Start collecting profiling information. + +If 'subcalls' is True, also records for each function +statistics separated according to its current caller. +If 'builtins' is True, records the time spent in +built-in functions separately from their caller. +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, + int builtins) +/*[clinic end generated code: output=1e747f9dc1edd571 input=0b6049b4e398781f]*/ { - int subcalls = -1; - int builtins = -1; - static char *kwlist[] = {"subcalls", "builtins", 0}; int all_events = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|pp:enable", - kwlist, &subcalls, &builtins)) - return NULL; if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { return NULL; } @@ -826,14 +826,16 @@ flush_unmatched(ProfilerObject *pObj) } -PyDoc_STRVAR(disable_doc, "\ -disable()\n\ -\n\ -Stop collecting profiling information.\n\ -"); -static PyObject* -profiler_disable(ProfilerObject *self, PyObject* Py_UNUSED(unused)) +/*[clinic input] +_lsprof.Profiler.disable + +Stop collecting profiling information. +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler_disable_impl(ProfilerObject *self) +/*[clinic end generated code: output=838cffef7f651870 input=05700b3fc68d1f50]*/ { if (self->flags & POF_EXT_TIMER) { PyErr_SetString(PyExc_RuntimeError, @@ -884,21 +886,22 @@ profiler_disable(ProfilerObject *self, PyObject* Py_UNUSED(unused)) Py_RETURN_NONE; } -PyDoc_STRVAR(clear_doc, "\ -clear()\n\ -\n\ -Clear all profiling information collected so far.\n\ -"); +/*[clinic input] +_lsprof.Profiler.clear + +Clear all profiling information collected so far. +[clinic start generated code]*/ -static PyObject* -profiler_clear(ProfilerObject *pObj, PyObject* noarg) +static PyObject * +_lsprof_Profiler_clear_impl(ProfilerObject *self) +/*[clinic end generated code: output=dd1c668fb84b1335 input=fbe1f88c28be4f98]*/ { - if (pObj->flags & POF_EXT_TIMER) { + if (self->flags & POF_EXT_TIMER) { PyErr_SetString(PyExc_RuntimeError, "cannot clear profiler in external timer"); return NULL; } - clearEntries(pObj); + clearEntries(self); Py_RETURN_NONE; } @@ -929,33 +932,39 @@ profiler_dealloc(ProfilerObject *op) Py_DECREF(tp); } +/*[clinic input] +_lsprof.Profiler.__init__ + + timer: object(c_default='NULL') = None + timeunit: double = 0.0 + subcalls: bool = True + builtins: bool = True + +Builds a profiler object using the specified timer function. + +The default timer is a fast built-in one based on real time. +For custom timer functions returning integers, timeunit can +be a float specifying a scale (i.e. how long each integer unit +is, in seconds). +[clinic start generated code]*/ + static int -profiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw) +_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, + double timeunit, int subcalls, int builtins) +/*[clinic end generated code: output=ab5498359fd34283 input=40225117dd22d4d7]*/ { - PyObject *timer = NULL; - double timeunit = 0.0; - int subcalls = 1; - int builtins = 1; - static char *kwlist[] = {"timer", "timeunit", - "subcalls", "builtins", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Odpp:Profiler", kwlist, - &timer, &timeunit, - &subcalls, &builtins)) + if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) return -1; - - if (setSubcalls(pObj, subcalls) < 0 || setBuiltins(pObj, builtins) < 0) - return -1; - pObj->externalTimerUnit = timeunit; - Py_XSETREF(pObj->externalTimer, Py_XNewRef(timer)); - pObj->tool_id = PY_MONITORING_PROFILER_ID; + self->externalTimerUnit = timeunit; + Py_XSETREF(self->externalTimer, Py_XNewRef(timer)); + self->tool_id = PY_MONITORING_PROFILER_ID; PyObject* monitoring = _PyImport_GetModuleAttrString("sys", "monitoring"); if (!monitoring) { return -1; } - pObj->missing = PyObject_GetAttrString(monitoring, "MISSING"); - if (!pObj->missing) { + self->missing = PyObject_GetAttrString(monitoring, "MISSING"); + if (!self->missing) { Py_DECREF(monitoring); return -1; } @@ -965,12 +974,9 @@ profiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw) static PyMethodDef profiler_methods[] = { _LSPROF_PROFILER_GETSTATS_METHODDEF - {"enable", _PyCFunction_CAST(profiler_enable), - METH_VARARGS | METH_KEYWORDS, enable_doc}, - {"disable", (PyCFunction)profiler_disable, - METH_NOARGS, disable_doc}, - {"clear", (PyCFunction)profiler_clear, - METH_NOARGS, clear_doc}, + _LSPROF_PROFILER_ENABLE_METHODDEF + _LSPROF_PROFILER_DISABLE_METHODDEF + _LSPROF_PROFILER_CLEAR_METHODDEF _LSPROF_PROFILER__PYSTART_CALLBACK_METHODDEF _LSPROF_PROFILER__PYRETURN_CALLBACK_METHODDEF _LSPROF_PROFILER__CCALL_CALLBACK_METHODDEF @@ -978,21 +984,11 @@ static PyMethodDef profiler_methods[] = { {NULL, NULL} }; -PyDoc_STRVAR(profiler_doc, "\ -Profiler(timer=None, timeunit=None, subcalls=True, builtins=True)\n\ -\n\ - Builds a profiler object using the specified timer function.\n\ - The default timer is a fast built-in one based on real time.\n\ - For custom timer functions returning integers, timeunit can\n\ - be a float specifying a scale (i.e. how long each integer unit\n\ - is, in seconds).\n\ -"); - static PyType_Slot _lsprof_profiler_type_spec_slots[] = { - {Py_tp_doc, (void *)profiler_doc}, + {Py_tp_doc, (void *)_lsprof_Profiler___init____doc__}, {Py_tp_methods, profiler_methods}, {Py_tp_dealloc, profiler_dealloc}, - {Py_tp_init, profiler_init}, + {Py_tp_init, _lsprof_Profiler___init__}, {Py_tp_traverse, profiler_traverse}, {0, 0} }; diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h index b35c5e12bdeb44..b6f829441fd3d6 100644 --- a/Modules/clinic/_lsprof.c.h +++ b/Modules/clinic/_lsprof.c.h @@ -2,6 +2,10 @@ preserve [clinic start generated code]*/ +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif #include "pycore_modsupport.h" // _PyArg_CheckPositional() PyDoc_STRVAR(_lsprof_Profiler_getstats__doc__, @@ -183,4 +187,220 @@ _lsprof_Profiler__creturn_callback(ProfilerObject *self, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=ee788c83b5c85fb1 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_lsprof_Profiler_enable__doc__, +"enable($self, /, subcalls=True, builtins=True)\n" +"--\n" +"\n" +"Start collecting profiling information.\n" +"\n" +"If \'subcalls\' is True, also records for each function\n" +"statistics separated according to its current caller.\n" +"If \'builtins\' is True, records the time spent in\n" +"built-in functions separately from their caller."); + +#define _LSPROF_PROFILER_ENABLE_METHODDEF \ + {"enable", _PyCFunction_CAST(_lsprof_Profiler_enable), METH_FASTCALL|METH_KEYWORDS, _lsprof_Profiler_enable__doc__}, + +static PyObject * +_lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, + int builtins); + +static PyObject * +_lsprof_Profiler_enable(ProfilerObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(subcalls), &_Py_ID(builtins), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"subcalls", "builtins", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "enable", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int subcalls = 1; + int builtins = 1; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + subcalls = PyObject_IsTrue(args[0]); + if (subcalls < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + builtins = PyObject_IsTrue(args[1]); + if (builtins < 0) { + goto exit; + } +skip_optional_pos: + return_value = _lsprof_Profiler_enable_impl(self, subcalls, builtins); + +exit: + return return_value; +} + +PyDoc_STRVAR(_lsprof_Profiler_disable__doc__, +"disable($self, /)\n" +"--\n" +"\n" +"Stop collecting profiling information."); + +#define _LSPROF_PROFILER_DISABLE_METHODDEF \ + {"disable", (PyCFunction)_lsprof_Profiler_disable, METH_NOARGS, _lsprof_Profiler_disable__doc__}, + +static PyObject * +_lsprof_Profiler_disable_impl(ProfilerObject *self); + +static PyObject * +_lsprof_Profiler_disable(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _lsprof_Profiler_disable_impl(self); +} + +PyDoc_STRVAR(_lsprof_Profiler_clear__doc__, +"clear($self, /)\n" +"--\n" +"\n" +"Clear all profiling information collected so far."); + +#define _LSPROF_PROFILER_CLEAR_METHODDEF \ + {"clear", (PyCFunction)_lsprof_Profiler_clear, METH_NOARGS, _lsprof_Profiler_clear__doc__}, + +static PyObject * +_lsprof_Profiler_clear_impl(ProfilerObject *self); + +static PyObject * +_lsprof_Profiler_clear(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _lsprof_Profiler_clear_impl(self); +} + +PyDoc_STRVAR(_lsprof_Profiler___init____doc__, +"Profiler(timer=None, timeunit=0.0, subcalls=True, builtins=True)\n" +"--\n" +"\n" +"Builds a profiler object using the specified timer function.\n" +"\n" +"The default timer is a fast built-in one based on real time.\n" +"For custom timer functions returning integers, timeunit can\n" +"be a float specifying a scale (i.e. how long each integer unit\n" +"is, in seconds)."); + +static int +_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, + double timeunit, int subcalls, int builtins); + +static int +_lsprof_Profiler___init__(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(timer), &_Py_ID(timeunit), &_Py_ID(subcalls), &_Py_ID(builtins), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"timer", "timeunit", "subcalls", "builtins", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "Profiler", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0; + PyObject *timer = NULL; + double timeunit = 0.0; + int subcalls = 1; + int builtins = 1; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 0, 4, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (fastargs[0]) { + timer = fastargs[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[1]) { + if (PyFloat_CheckExact(fastargs[1])) { + timeunit = PyFloat_AS_DOUBLE(fastargs[1]); + } + else + { + timeunit = PyFloat_AsDouble(fastargs[1]); + if (timeunit == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (fastargs[2]) { + subcalls = PyObject_IsTrue(fastargs[2]); + if (subcalls < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + builtins = PyObject_IsTrue(fastargs[3]); + if (builtins < 0) { + goto exit; + } +skip_optional_pos: + return_value = _lsprof_Profiler___init___impl((ProfilerObject *)self, timer, timeunit, subcalls, builtins); + +exit: + return return_value; +} +/*[clinic end generated code: output=c0861e64aeb19d43 input=a9049054013a1b77]*/ From 3cea189c3614618d20a74edf31dece03b3bc00e0 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 2 Nov 2024 08:30:53 +0300 Subject: [PATCH 6/9] Apply suggestions from code review Co-authored-by: Erlend E. Aasland --- Modules/_lsprof.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 614a49b4619b49..6c8212c7076cd1 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -940,11 +940,11 @@ _lsprof.Profiler.__init__ subcalls: bool = True builtins: bool = True -Builds a profiler object using the specified timer function. +Build a profiler object using the specified timer function. The default timer is a fast built-in one based on real time. -For custom timer functions returning integers, timeunit can -be a float specifying a scale (i.e. how long each integer unit +For custom timer functions returning integers, 'timeunit' can +be a float specifying a scale (that is, how long each integer unit is, in seconds). [clinic start generated code]*/ From b84dde3911e6965cca84013d49b6814839f0fe65 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 2 Nov 2024 08:35:25 +0300 Subject: [PATCH 7/9] Address review --- Modules/_lsprof.c | 12 ++++++------ Modules/clinic/_lsprof.c.h | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 6c8212c7076cd1..53bbdd371a4eaf 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -933,7 +933,7 @@ profiler_dealloc(ProfilerObject *op) } /*[clinic input] -_lsprof.Profiler.__init__ +_lsprof.Profiler.__init__ as profile_init timer: object(c_default='NULL') = None timeunit: double = 0.0 @@ -949,9 +949,9 @@ is, in seconds). [clinic start generated code]*/ static int -_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, - double timeunit, int subcalls, int builtins) -/*[clinic end generated code: output=ab5498359fd34283 input=40225117dd22d4d7]*/ +profile_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, + int subcalls, int builtins) +/*[clinic end generated code: output=123b1ff3fc783e14 input=25202b9566e5441c]*/ { if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) return -1; @@ -985,10 +985,10 @@ static PyMethodDef profiler_methods[] = { }; static PyType_Slot _lsprof_profiler_type_spec_slots[] = { - {Py_tp_doc, (void *)_lsprof_Profiler___init____doc__}, + {Py_tp_doc, (void *)profile_init__doc__}, {Py_tp_methods, profiler_methods}, {Py_tp_dealloc, profiler_dealloc}, - {Py_tp_init, _lsprof_Profiler___init__}, + {Py_tp_init, profile_init}, {Py_tp_traverse, profiler_traverse}, {0, 0} }; diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h index b6f829441fd3d6..2a14889a2fd531 100644 --- a/Modules/clinic/_lsprof.c.h +++ b/Modules/clinic/_lsprof.c.h @@ -303,23 +303,23 @@ _lsprof_Profiler_clear(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) return _lsprof_Profiler_clear_impl(self); } -PyDoc_STRVAR(_lsprof_Profiler___init____doc__, +PyDoc_STRVAR(profile_init__doc__, "Profiler(timer=None, timeunit=0.0, subcalls=True, builtins=True)\n" "--\n" "\n" -"Builds a profiler object using the specified timer function.\n" +"Build a profiler object using the specified timer function.\n" "\n" "The default timer is a fast built-in one based on real time.\n" -"For custom timer functions returning integers, timeunit can\n" -"be a float specifying a scale (i.e. how long each integer unit\n" +"For custom timer functions returning integers, \'timeunit\' can\n" +"be a float specifying a scale (that is, how long each integer unit\n" "is, in seconds)."); static int -_lsprof_Profiler___init___impl(ProfilerObject *self, PyObject *timer, - double timeunit, int subcalls, int builtins); +profile_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, + int subcalls, int builtins); static int -_lsprof_Profiler___init__(PyObject *self, PyObject *args, PyObject *kwargs) +profile_init(PyObject *self, PyObject *args, PyObject *kwargs) { int return_value = -1; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) @@ -398,9 +398,9 @@ _lsprof_Profiler___init__(PyObject *self, PyObject *args, PyObject *kwargs) goto exit; } skip_optional_pos: - return_value = _lsprof_Profiler___init___impl((ProfilerObject *)self, timer, timeunit, subcalls, builtins); + return_value = profile_init_impl((ProfilerObject *)self, timer, timeunit, subcalls, builtins); exit: return return_value; } -/*[clinic end generated code: output=c0861e64aeb19d43 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1d1db1dcbb6b10d7 input=a9049054013a1b77]*/ From bf3e120d199a0620896d262c8c36821592032547 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 2 Nov 2024 08:36:51 +0300 Subject: [PATCH 8/9] Typo --- Modules/_lsprof.c | 12 ++++++------ Modules/clinic/_lsprof.c.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 53bbdd371a4eaf..3b123f4d2d8c9d 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -933,7 +933,7 @@ profiler_dealloc(ProfilerObject *op) } /*[clinic input] -_lsprof.Profiler.__init__ as profile_init +_lsprof.Profiler.__init__ as profiler_init timer: object(c_default='NULL') = None timeunit: double = 0.0 @@ -949,9 +949,9 @@ is, in seconds). [clinic start generated code]*/ static int -profile_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, - int subcalls, int builtins) -/*[clinic end generated code: output=123b1ff3fc783e14 input=25202b9566e5441c]*/ +profiler_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, + int subcalls, int builtins) +/*[clinic end generated code: output=ac523803ec9f9df2 input=8285ca746f96a414]*/ { if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) return -1; @@ -985,10 +985,10 @@ static PyMethodDef profiler_methods[] = { }; static PyType_Slot _lsprof_profiler_type_spec_slots[] = { - {Py_tp_doc, (void *)profile_init__doc__}, + {Py_tp_doc, (void *)profiler_init__doc__}, {Py_tp_methods, profiler_methods}, {Py_tp_dealloc, profiler_dealloc}, - {Py_tp_init, profile_init}, + {Py_tp_init, profiler_init}, {Py_tp_traverse, profiler_traverse}, {0, 0} }; diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h index 2a14889a2fd531..65a2577e7078db 100644 --- a/Modules/clinic/_lsprof.c.h +++ b/Modules/clinic/_lsprof.c.h @@ -303,7 +303,7 @@ _lsprof_Profiler_clear(ProfilerObject *self, PyObject *Py_UNUSED(ignored)) return _lsprof_Profiler_clear_impl(self); } -PyDoc_STRVAR(profile_init__doc__, +PyDoc_STRVAR(profiler_init__doc__, "Profiler(timer=None, timeunit=0.0, subcalls=True, builtins=True)\n" "--\n" "\n" @@ -315,11 +315,11 @@ PyDoc_STRVAR(profile_init__doc__, "is, in seconds)."); static int -profile_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, - int subcalls, int builtins); +profiler_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, + int subcalls, int builtins); static int -profile_init(PyObject *self, PyObject *args, PyObject *kwargs) +profiler_init(PyObject *self, PyObject *args, PyObject *kwargs) { int return_value = -1; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) @@ -398,9 +398,9 @@ profile_init(PyObject *self, PyObject *args, PyObject *kwargs) goto exit; } skip_optional_pos: - return_value = profile_init_impl((ProfilerObject *)self, timer, timeunit, subcalls, builtins); + return_value = profiler_init_impl((ProfilerObject *)self, timer, timeunit, subcalls, builtins); exit: return return_value; } -/*[clinic end generated code: output=1d1db1dcbb6b10d7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3750676abdc066ae input=a9049054013a1b77]*/ From 0d35f6074483fdd94e7485ac1269d8e5391db99a Mon Sep 17 00:00:00 2001 From: sobolevn Date: Mon, 4 Nov 2024 11:37:21 +0300 Subject: [PATCH 9/9] Address review --- Modules/_lsprof.c | 15 ++++++++------- Modules/clinic/_lsprof.c.h | 12 +++++++----- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index 3b123f4d2d8c9d..4f996c7230e16d 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -755,20 +755,20 @@ static const struct { _lsprof.Profiler.enable subcalls: bool = True + If True, also records for each function + statistics separated according to its current caller. + builtins: bool = True + If True, records the time spent in + built-in functions separately from their caller. Start collecting profiling information. - -If 'subcalls' is True, also records for each function -statistics separated according to its current caller. -If 'builtins' is True, records the time spent in -built-in functions separately from their caller. [clinic start generated code]*/ static PyObject * _lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls, int builtins) -/*[clinic end generated code: output=1e747f9dc1edd571 input=0b6049b4e398781f]*/ +/*[clinic end generated code: output=1e747f9dc1edd571 input=9ab81405107ab7f1]*/ { int all_events = 0; if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { @@ -953,8 +953,9 @@ profiler_init_impl(ProfilerObject *self, PyObject *timer, double timeunit, int subcalls, int builtins) /*[clinic end generated code: output=ac523803ec9f9df2 input=8285ca746f96a414]*/ { - if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) + if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { return -1; + } self->externalTimerUnit = timeunit; Py_XSETREF(self->externalTimer, Py_XNewRef(timer)); self->tool_id = PY_MONITORING_PROFILER_ID; diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h index 65a2577e7078db..234cc9ef3c0eaf 100644 --- a/Modules/clinic/_lsprof.c.h +++ b/Modules/clinic/_lsprof.c.h @@ -194,10 +194,12 @@ PyDoc_STRVAR(_lsprof_Profiler_enable__doc__, "\n" "Start collecting profiling information.\n" "\n" -"If \'subcalls\' is True, also records for each function\n" -"statistics separated according to its current caller.\n" -"If \'builtins\' is True, records the time spent in\n" -"built-in functions separately from their caller."); +" subcalls\n" +" If True, also records for each function\n" +" statistics separated according to its current caller.\n" +" builtins\n" +" If True, records the time spent in\n" +" built-in functions separately from their caller."); #define _LSPROF_PROFILER_ENABLE_METHODDEF \ {"enable", _PyCFunction_CAST(_lsprof_Profiler_enable), METH_FASTCALL|METH_KEYWORDS, _lsprof_Profiler_enable__doc__}, @@ -403,4 +405,4 @@ profiler_init(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=3750676abdc066ae input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0b71f52bee9a7bb1 input=a9049054013a1b77]*/ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy