[Python-checkins] cpython: Issue #29049: Call _PyObject_GC_TRACK() lazily when calling Python function.

inada.naoki python-checkins at python.org
Sat Dec 24 06:19:22 EST 2016


https://hg.python.org/cpython/rev/f5eb0c4f5d37
changeset:   105813:f5eb0c4f5d37
user:        INADA Naoki <songofacandy at gmail.com>
date:        Sat Dec 24 20:19:08 2016 +0900
summary:
  Issue #29049: Call _PyObject_GC_TRACK() lazily when calling Python function.

Calling function is up to 5% faster.

files:
  Include/frameobject.h |   6 +++++-
  Misc/NEWS             |   3 +++
  Objects/frameobject.c |  20 ++++++++++++++++----
  Python/ceval.c        |  31 +++++++++++++++++++++----------
  4 files changed, 45 insertions(+), 15 deletions(-)


diff --git a/Include/frameobject.h b/Include/frameobject.h
--- a/Include/frameobject.h
+++ b/Include/frameobject.h
@@ -60,7 +60,11 @@
 #define PyFrame_Check(op) (Py_TYPE(op) == &PyFrame_Type)
 
 PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *,
-                                       PyObject *, PyObject *);
+                                        PyObject *, PyObject *);
+
+/* only internal use */
+PyFrameObject* _PyFrame_New_NoTrack(PyThreadState *, PyCodeObject *,
+                                    PyObject *, PyObject *);
 
 
 /* The rest of the interface is specific for frame objects */
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #29049: Call _PyObject_GC_TRACK() lazily when calling Python function.
+  Calling function is up to 5% faster.
+
 - Issue #28927: bytes.fromhex() and bytearray.fromhex() now ignore all ASCII
   whitespace, not only spaces.  Patch by Robert Xiao.
 
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -415,7 +415,9 @@
     PyObject **p, **valuestack;
     PyCodeObject *co;
 
-    PyObject_GC_UnTrack(f);
+    if (_PyObject_GC_IS_TRACKED(f))
+        _PyObject_GC_UNTRACK(f);
+
     Py_TRASHCAN_SAFE_BEGIN(f)
     /* Kill all local variables */
     valuestack = f->f_valuestack;
@@ -606,8 +608,8 @@
 }
 
 PyFrameObject* _Py_HOT_FUNCTION
-PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
-            PyObject *locals)
+_PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code,
+                     PyObject *globals, PyObject *locals)
 {
     PyFrameObject *back = tstate->frame;
     PyFrameObject *f;
@@ -727,10 +729,20 @@
     f->f_executing = 0;
     f->f_gen = NULL;
 
-    _PyObject_GC_TRACK(f);
     return f;
 }
 
+PyFrameObject*
+PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
+            PyObject *globals, PyObject *locals)
+{
+    PyFrameObject *f = _PyFrame_New_NoTrack(tstate, code, globals, locals);
+    if (f)
+        _PyObject_GC_TRACK(f);
+    return f;
+}
+
+
 /* Block management */
 
 void
diff --git a/Python/ceval.c b/Python/ceval.c
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3931,7 +3931,7 @@
     /* 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 @@
        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 @@
 
     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 @@
     }
     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;
 }
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list