Issue #29049: Call _PyObject_GC_TRACK() lazily when calling Python function.

Calling function is up to 5% faster.
This commit is contained in:
INADA Naoki 2016-12-24 20:19:08 +09:00
parent 2585443b6f
commit 5a625d0aa6
4 changed files with 45 additions and 15 deletions

View file

@ -3931,7 +3931,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
/* Create the frame */
tstate = PyThreadState_GET();
assert(tstate != NULL);
f = PyFrame_New(tstate, co, globals, locals);
f = _PyFrame_New_NoTrack(tstate, co, globals, locals);
if (f == NULL) {
return NULL;
}
@ -4176,9 +4176,15 @@ fail: /* Jump here from prelude on failure */
so recursion_depth must be boosted for the duration.
*/
assert(tstate != NULL);
++tstate->recursion_depth;
Py_DECREF(f);
--tstate->recursion_depth;
if (Py_REFCNT(f) > 1) {
Py_DECREF(f);
_PyObject_GC_TRACK(f);
}
else {
++tstate->recursion_depth;
Py_DECREF(f);
--tstate->recursion_depth;
}
return retval;
}
@ -4904,11 +4910,11 @@ _PyFunction_FastCall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
assert(globals != NULL);
/* XXX Perhaps we should create a specialized
PyFrame_New() that doesn't take locals, but does
_PyFrame_New_NoTrack() that doesn't take locals, but does
take builtins without sanity checking them.
*/
assert(tstate != NULL);
f = PyFrame_New(tstate, co, globals, NULL);
f = _PyFrame_New_NoTrack(tstate, co, globals, NULL);
if (f == NULL) {
return NULL;
}
@ -4921,10 +4927,15 @@ _PyFunction_FastCall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
}
result = PyEval_EvalFrameEx(f,0);
++tstate->recursion_depth;
Py_DECREF(f);
--tstate->recursion_depth;
if (Py_REFCNT(f) > 1) {
Py_DECREF(f);
_PyObject_GC_TRACK(f);
}
else {
++tstate->recursion_depth;
Py_DECREF(f);
--tstate->recursion_depth;
}
return result;
}