[Python-checkins] cpython: _PyFunction_FastCallDict() supports keyword args

victor.stinner python-checkins at python.org
Mon Aug 22 17:22:19 EDT 2016


https://hg.python.org/cpython/rev/1aefb4c4a7b4
changeset: 102842:1aefb4c4a7b4
user: Victor Stinner <victor.stinner at gmail.com>
date: Mon Aug 22 23:15:44 2016 +0200
summary:
 _PyFunction_FastCallDict() supports keyword args
Issue #27809:
* Rename _PyFunction_FastCall() to _PyFunction_FastCallDict()
* Rename _PyCFunction_FastCall() to _PyCFunction_FastCallDict()
* _PyFunction_FastCallDict() now supports keyword arguments
files:
 Include/funcobject.h | 2 +-
 Include/methodobject.h | 2 +-
 Objects/abstract.c | 11 ++---
 Objects/methodobject.c | 6 +-
 Python/ceval.c | 52 ++++++++++++++++++++++++-----
 5 files changed, 52 insertions(+), 21 deletions(-)
diff --git a/Include/funcobject.h b/Include/funcobject.h
--- a/Include/funcobject.h
+++ b/Include/funcobject.h
@@ -59,7 +59,7 @@
 PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *);
 
 #ifndef Py_LIMITED_API
-PyAPI_FUNC(PyObject *) _PyFunction_FastCall(
+PyAPI_FUNC(PyObject *) _PyFunction_FastCallDict(
 PyObject *func,
 PyObject **args, int nargs,
 PyObject *kwargs);
diff --git a/Include/methodobject.h b/Include/methodobject.h
--- a/Include/methodobject.h
+++ b/Include/methodobject.h
@@ -38,7 +38,7 @@
 PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *);
 
 #ifndef Py_LIMITED_API
-PyAPI_FUNC(PyObject *) _PyCFunction_FastCall(PyObject *func,
+PyAPI_FUNC(PyObject *) _PyCFunction_FastCallDict(PyObject *func,
 PyObject **args, int nargs,
 PyObject *kwargs);
 #endif
diff --git a/Objects/abstract.c b/Objects/abstract.c
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2255,7 +2255,8 @@
 }
 
 PyObject *
-_PyObject_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwargs)
+_PyObject_FastCallDict(PyObject *func, PyObject **args, int nargs,
+ PyObject *kwargs)
 {
 ternaryfunc call;
 PyObject *result = NULL;
@@ -2268,19 +2269,17 @@
 assert(func != NULL);
 assert(nargs >= 0);
 assert(nargs == 0 || args != NULL);
- /* issue #27128: support for keywords will come later:
- _PyFunction_FastCall() doesn't support keyword arguments yet */
- assert(kwargs == NULL);
+ assert(kwargs == NULL || PyDict_Check(kwargs));
 
 if (Py_EnterRecursiveCall(" while calling a Python object")) {
 return NULL;
 }
 
 if (PyFunction_Check(func)) {
- result = _PyFunction_FastCall(func, args, nargs, kwargs);
+ result = _PyFunction_FastCallDict(func, args, nargs, kwargs);
 }
 else if (PyCFunction_Check(func)) {
- result = _PyCFunction_FastCall(func, args, nargs, kwargs);
+ result = _PyCFunction_FastCallDict(func, args, nargs, kwargs);
 }
 else {
 PyObject *tuple;
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -146,8 +146,8 @@
 }
 
 PyObject *
-_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, int nargs,
- PyObject *kwargs)
+_PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, int nargs,
+ PyObject *kwargs)
 {
 PyCFunctionObject* func = (PyCFunctionObject*)func_obj;
 PyCFunction meth = PyCFunction_GET_FUNCTION(func);
@@ -155,7 +155,7 @@
 PyObject *result;
 int flags;
 
- /* _PyCFunction_FastCall() must not be called with an exception set,
+ /* _PyCFunction_FastCallDict() must not be called with an exception set,
 because it may clear it (directly or indirectly) and so the
 caller loses its exception */
 assert(!PyErr_Occurred());
diff --git a/Python/ceval.c b/Python/ceval.c
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -4889,24 +4889,29 @@
 }
 
 PyObject *
-_PyFunction_FastCall(PyObject *func, PyObject **args, int nargs, PyObject *kwargs)
+_PyFunction_FastCallDict(PyObject *func, PyObject **args, int nargs,
+ PyObject *kwargs)
 {
 PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
 PyObject *globals = PyFunction_GET_GLOBALS(func);
 PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
 PyObject *kwdefs, *closure, *name, *qualname;
+ PyObject *kwtuple, **k;
 PyObject **d;
 int nd;
+ Py_ssize_t nk;
+ PyObject *result;
 
 PCALL(PCALL_FUNCTION);
 PCALL(PCALL_FAST_FUNCTION);
 
- /* issue #27128: support for keywords will come later */
- assert(kwargs == NULL);
-
- if (co->co_kwonlyargcount == 0 && kwargs == NULL &&
+ assert(kwargs == NULL || PyDict_Check(kwargs));
+
+ if (co->co_kwonlyargcount == 0 &&
+ (kwargs == NULL || PyDict_Size(kwargs) == 0) &&
 co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
 {
+ /* Fast paths */
 if (argdefs == NULL && co->co_argcount == nargs) {
 return _PyFunction_FastCallNoKw(co, args, nargs, globals);
 }
@@ -4920,6 +4925,30 @@
 }
 }
 
+ if (kwargs != NULL) {
+ Py_ssize_t pos, i;
+ nk = PyDict_Size(kwargs);
+
+ kwtuple = PyTuple_New(2 * nk);
+ if (kwtuple == NULL) {
+ return NULL;
+ }
+
+ k = &PyTuple_GET_ITEM(kwtuple, 0);
+ pos = i = 0;
+ while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) {
+ Py_INCREF(k[i]);
+ Py_INCREF(k[i+1]);
+ i += 2;
+ }
+ nk = i / 2;
+ }
+ else {
+ kwtuple = NULL;
+ k = NULL;
+ nk = 0;
+ }
+
 kwdefs = PyFunction_GET_KW_DEFAULTS(func);
 closure = PyFunction_GET_CLOSURE(func);
 name = ((PyFunctionObject *)func) -> func_name;
@@ -4933,11 +4962,14 @@
 d = NULL;
 nd = 0;
 }
- return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
- args, nargs,
- NULL, 0,
- d, nd, kwdefs,
- closure, name, qualname);
+
+ result = _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
+ args, nargs,
+ k, (int)nk,
+ d, nd, kwdefs,
+ closure, name, qualname);
+ Py_XDECREF(kwtuple);
+ return result;
 }
 
 static PyObject *
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /