bpo-34125: Enable profiling of method_descriptor in all cases (GH-8416)
`list.append([], None)` was profiled but `list.append([], None, **{})` was not profiled. Enable profiling for later case. https://bugs.python.org/issue34125
This commit is contained in:
parent
b3b8cb419e
commit
e89de73987
|
@ -350,6 +350,24 @@ class ProfileSimulatorTestCase(TestCaseBase):
|
||||||
self.check_events(f, [(1, 'call', f_ident),
|
self.check_events(f, [(1, 'call', f_ident),
|
||||||
(1, 'return', f_ident)])
|
(1, 'return', f_ident)])
|
||||||
|
|
||||||
|
# Test an invalid call (bpo-34125)
|
||||||
|
def test_unbound_method_no_args(self):
|
||||||
|
kwargs = {}
|
||||||
|
def f(p):
|
||||||
|
dict.get(**kwargs)
|
||||||
|
f_ident = ident(f)
|
||||||
|
self.check_events(f, [(1, 'call', f_ident),
|
||||||
|
(1, 'return', f_ident)])
|
||||||
|
|
||||||
|
# Test an invalid call (bpo-34125)
|
||||||
|
def test_unbound_method_invalid_args(self):
|
||||||
|
kwargs = {}
|
||||||
|
def f(p):
|
||||||
|
dict.get(print, 42, **kwargs)
|
||||||
|
f_ident = ident(f)
|
||||||
|
self.check_events(f, [(1, 'call', f_ident),
|
||||||
|
(1, 'return', f_ident)])
|
||||||
|
|
||||||
|
|
||||||
def ident(function):
|
def ident(function):
|
||||||
if hasattr(function, "f_code"):
|
if hasattr(function, "f_code"):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Profiling of unbound built-in methods now works when ``**kwargs`` is given.
|
|
@ -4642,15 +4642,39 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
|
do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
|
||||||
{
|
{
|
||||||
if (PyCFunction_Check(func)) {
|
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
|
if (PyCFunction_Check(func)) {
|
||||||
PyThreadState *tstate = PyThreadState_GET();
|
PyThreadState *tstate = PyThreadState_GET();
|
||||||
C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
|
C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else {
|
else if (Py_TYPE(func) == &PyMethodDescr_Type) {
|
||||||
return PyObject_Call(func, callargs, kwdict);
|
PyThreadState *tstate = PyThreadState_GET();
|
||||||
|
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);
|
||||||
|
if (nargs > 0 && tstate->use_tracing) {
|
||||||
|
/* We need to create a temporary bound method as argument
|
||||||
|
for profiling.
|
||||||
|
|
||||||
|
If nargs == 0, then this cannot work because we have no
|
||||||
|
"self". In any case, the call itself would raise
|
||||||
|
TypeError (foo needs an argument), so we just skip
|
||||||
|
profiling. */
|
||||||
|
PyObject *self = PyTuple_GET_ITEM(callargs, 0);
|
||||||
|
func = Py_TYPE(func)->tp_descr_get(func, self, (PyObject*)Py_TYPE(self));
|
||||||
|
if (func == NULL) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
C_TRACE(result, _PyCFunction_FastCallDict(func,
|
||||||
|
&PyTuple_GET_ITEM(callargs, 1),
|
||||||
|
nargs - 1,
|
||||||
|
kwdict));
|
||||||
|
Py_DECREF(func);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PyObject_Call(func, callargs, kwdict);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract a slice index from a PyLong or an object with the
|
/* Extract a slice index from a PyLong or an object with the
|
||||||
|
|
Loading…
Reference in New Issue