Skip to content

Commit

Permalink
bpo-34125: enable profiling of method_descriptor in all cases
Browse files Browse the repository at this point in the history
  • Loading branch information
jdemeyer committed Sep 18, 2018
1 parent 0185f34 commit ec8743f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 3 deletions.
18 changes: 18 additions & 0 deletions Lib/test/test_sys_setprofile.py
Expand Up @@ -350,6 +350,24 @@ def f(p):
self.check_events(f, [(1, 'call', 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):
if hasattr(function, "f_code"):
Expand Down
@@ -0,0 +1 @@
Profiling of unbound built-in methods now works when ``**kwargs`` is given.
30 changes: 27 additions & 3 deletions Python/ceval.c
Expand Up @@ -4642,15 +4642,39 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
static PyObject *
do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
{
PyObject *result;

if (PyCFunction_Check(func)) {
PyObject *result;
PyThreadState *tstate = PyThreadState_GET();
C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
return result;
}
else {
return PyObject_Call(func, callargs, kwdict);
else if (Py_TYPE(func) == &PyMethodDescr_Type) {
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
Expand Down

0 comments on commit ec8743f

Please sign in to comment.