summaryrefslogtreecommitdiff
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorINADA Naoki <methane@users.noreply.github.com>2017-03-07 14:24:37 +0900
committerGitHub <noreply@github.com>2017-03-07 14:24:37 +0900
commit93fac8dd358cd0e85e7b59115db226ce685d3f6f (patch)
tree51cab83ce4e14a779fc2f2467cab142b331e8034 /Python/ceval.c
parentd36a71637cefdddc02efd884f1b2c204f370afaa (diff)
downloadcpython-git-93fac8dd358cd0e85e7b59115db226ce685d3f6f.tar.gz
bpo-29676: fix lsprof can't profile C method call. (GH523)
When LOAD_METHOD is used for calling C mehtod, PyMethodDescrObject was passed to profilefunc from 5566bbb. But lsprof traces only PyCFunctionObject. Additionally, there can be some third party extension which assumes passed arg is PyCFunctionObject without calling PyCFunction_Check(). So make PyCFunctionObject from PyMethodDescrObject when tstate->c_profilefunc is set.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 49177d8e05..e682fc1afd 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -4818,7 +4818,20 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
}
else if (Py_TYPE(func) == &PyMethodDescr_Type) {
PyThreadState *tstate = PyThreadState_GET();
- C_TRACE(x, _PyMethodDescr_FastCallKeywords(func, stack, nargs, kwnames));
+ if (tstate->use_tracing && tstate->c_profilefunc) {
+ // We need to create PyCFunctionObject for tracing.
+ PyMethodDescrObject *descr = (PyMethodDescrObject*)func;
+ func = PyCFunction_NewEx(descr->d_method, stack[0], NULL);
+ if (func == NULL) {
+ return NULL;
+ }
+ C_TRACE(x, _PyCFunction_FastCallKeywords(func, stack+1, nargs-1,
+ kwnames));
+ Py_DECREF(func);
+ }
+ else {
+ x = _PyMethodDescr_FastCallKeywords(func, stack, nargs, kwnames);
+ }
}
else {
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {