Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(19)

Unified Diff: Objects/descrobject.c

Issue 29259: Add tp_fastcall to PyTypeObject: support FASTCALL calling convention for all callable objects
Patch Set: Created 3 years ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
--- a/Objects/descrobject.c Wed Jan 25 23:33:27 2017 +0100
+++ b/Objects/descrobject.c Thu Jan 26 02:43:18 2017 +0100
@@ -210,14 +210,12 @@ getset_set(PyGetSetDescrObject *descr, P
}
static PyObject *
-methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
+methoddescr_call(PyMethodDescrObject *descr, PyObject **args, Py_ssize_t nargs,
+ PyObject *kwnames)
{
- Py_ssize_t nargs;
PyObject *self, *result;
/* Make sure that the first argument is acceptable as 'self' */
- assert(PyTuple_Check(args));
- nargs = PyTuple_GET_SIZE(args);
if (nargs < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' of '%.100s' "
@@ -226,7 +224,7 @@ methoddescr_call(PyMethodDescrObject *de
PyDescr_TYPE(descr)->tp_name);
return NULL;
}
- self = PyTuple_GET_ITEM(args, 0);
+ self = args[0];
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
(PyObject *)PyDescr_TYPE(descr))) {
PyErr_Format(PyExc_TypeError,
@@ -239,24 +237,21 @@ methoddescr_call(PyMethodDescrObject *de
return NULL;
}
- result = _PyMethodDef_RawFastCallDict(descr->d_method, self,
- &PyTuple_GET_ITEM(args, 1), nargs - 1,
- kwargs);
+ result = _PyMethodDef_RawFastCallKeywords(descr->d_method, self,
+ args + 1, nargs - 1,
+ kwnames);
result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
return result;
}
static PyObject *
-classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
- PyObject *kwds)
+classmethoddescr_call(PyMethodDescrObject *descr, PyObject **args,
+ Py_ssize_t nargs, PyObject *kwnames)
{
- Py_ssize_t argc;
- PyObject *self, *func, *result, **stack;
+ PyObject *self, *func, *result;
/* Make sure that the first argument is acceptable as 'self' */
- assert(PyTuple_Check(args));
- argc = PyTuple_GET_SIZE(args);
- if (argc < 1) {
+ if (nargs < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' of '%.100s' "
"object needs an argument",
@@ -264,7 +259,7 @@ classmethoddescr_call(PyMethodDescrObjec
PyDescr_TYPE(descr)->tp_name);
return NULL;
}
- self = PyTuple_GET_ITEM(args, 0);
+ self = args[0];
if (!PyType_Check(self)) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' requires a type "
@@ -288,22 +283,19 @@ classmethoddescr_call(PyMethodDescrObjec
func = PyCFunction_NewEx(descr->d_method, self, NULL);
if (func == NULL)
return NULL;
- stack = &PyTuple_GET_ITEM(args, 1);
- result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
+ result = _PyObject_FastCallKeywords(func, args + 1, nargs - 1, kwnames);
Py_DECREF(func);
return result;
}
static PyObject *
-wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
+wrapperdescr_call(PyMethodDescrObject *descr, PyObject **args, Py_ssize_t nargs,
+ PyObject *kwnames)
{
- Py_ssize_t argc;
- PyObject *self, *func, *result, **stack;
+ PyObject *self, *func, *result;
/* Make sure that the first argument is acceptable as 'self' */
- assert(PyTuple_Check(args));
- argc = PyTuple_GET_SIZE(args);
- if (argc < 1) {
+ if (nargs < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' of '%.100s' "
"object needs an argument",
@@ -311,7 +303,7 @@ wrapperdescr_call(PyWrapperDescrObject *
PyDescr_TYPE(descr)->tp_name);
return NULL;
}
- self = PyTuple_GET_ITEM(args, 0);
+ self = args[0];
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
(PyObject *)PyDescr_TYPE(descr))) {
PyErr_Format(PyExc_TypeError,
@@ -328,8 +320,7 @@ wrapperdescr_call(PyWrapperDescrObject *
if (func == NULL)
return NULL;
- stack = &PyTuple_GET_ITEM(args, 1);
- result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
+ result = _PyObject_FastCallKeywords(func, args + 1, nargs - 1, kwnames);
Py_DECREF(func);
return result;
}
@@ -487,7 +478,7 @@ PyTypeObject PyMethodDescr_Type = {
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
- (ternaryfunc)methoddescr_call, /* tp_call */
+ 0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
@@ -506,7 +497,8 @@ PyTypeObject PyMethodDescr_Type = {
0, /* tp_base */
0, /* tp_dict */
(descrgetfunc)method_get, /* tp_descr_get */
- 0, /* tp_descr_set */
+
+ .tp_fastcall = (fastternaryfunc)methoddescr_call,
};
/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
@@ -525,7 +517,7 @@ PyTypeObject PyClassMethodDescr_Type = {
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
- (ternaryfunc)classmethoddescr_call, /* tp_call */
+ 0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
@@ -544,7 +536,8 @@ PyTypeObject PyClassMethodDescr_Type = {
0, /* tp_base */
0, /* tp_dict */
(descrgetfunc)classmethod_get, /* tp_descr_get */
- 0, /* tp_descr_set */
+
+ .tp_fastcall = (fastternaryfunc)classmethoddescr_call,
};
PyTypeObject PyMemberDescr_Type = {
@@ -636,7 +629,7 @@ PyTypeObject PyWrapperDescr_Type = {
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
- (ternaryfunc)wrapperdescr_call, /* tp_call */
+ 0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
@@ -655,7 +648,8 @@ PyTypeObject PyWrapperDescr_Type = {
0, /* tp_base */
0, /* tp_dict */
(descrgetfunc)wrapperdescr_get, /* tp_descr_get */
- 0, /* tp_descr_set */
+
+ .tp_fastcall = (fastternaryfunc)wrapperdescr_call,
};
static PyDescrObject *
@@ -664,17 +658,19 @@ descr_new(PyTypeObject *descrtype, PyTyp
PyDescrObject *descr;
descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
- if (descr != NULL) {
- Py_XINCREF(type);
- descr->d_type = type;
- descr->d_name = PyUnicode_InternFromString(name);
- if (descr->d_name == NULL) {
- Py_DECREF(descr);
- descr = NULL;
- }
- else {
- descr->d_qualname = NULL;
- }
+ if (descr == NULL) {
+ return NULL;
+ }
+
+ Py_XINCREF(type);
+ descr->d_type = type;
+ descr->d_name = PyUnicode_InternFromString(name);
+ if (descr->d_name == NULL) {
+ Py_DECREF(descr);
+ descr = NULL;
+ }
+ else {
+ descr->d_qualname = NULL;
}
return descr;
}
@@ -728,19 +724,28 @@ PyDescr_NewGetSet(PyTypeObject *type, Py
}
PyObject *
-PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
+_PyDescr_NewWrapperEx(PyTypeObject *type, struct wrapperbase *base, void *wrapped, int use_fastwrapper)
haypo 2017/01/26 03:35:21 Maybe a new funtion is not worth it, the d_user_fa
{
PyWrapperDescrObject *descr;
descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
type, base->name);
- if (descr != NULL) {
- descr->d_base = base;
- descr->d_wrapped = wrapped;
+ if (descr == NULL) {
+ return NULL;
}
+
+ descr->d_base = base;
+ descr->d_wrapped = wrapped;
+ descr->d_use_fastwrapper = use_fastwrapper;
return (PyObject *)descr;
}
+PyObject *
+PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
+{
+ return _PyDescr_NewWrapperEx(type, base, wrapped, 0);
+}
+
/* --- mappingproxy: read-only proxy for mappings --- */
@@ -1159,23 +1164,48 @@ static PyGetSetDef wrapper_getsets[] = {
};
static PyObject *
-wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
+wrapper_call(wrapperobject *wp, PyObject **stack, Py_ssize_t nargs, PyObject *kwnames)
{
- wrapperfunc wrapper = wp->descr->d_base->wrapper;
+ wrapperfunc wrapper;
PyObject *self = wp->self;
+ PyObject *args, *kwargs, *result;
+ if (wp->descr->d_use_fastwrapper) {
+ wrapperfunc_fast wf = wp->descr->d_base->fastwrapper;
+
+ return (*wf)(self, wp->descr->d_wrapped, stack, nargs, kwnames);
+ }
+
+ wrapper = wp->descr->d_base->wrapper;
if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
- return (*wk)(self, args, wp->descr->d_wrapped, kwds);
+
+ if (_PyStack_AsTupleAndDict(stack, nargs, kwnames, &args, &kwargs) < 0) {
+ return NULL;
+ }
+
+ result = (*wk)(self, args, wp->descr->d_wrapped, kwargs);
+ Py_DECREF(args);
+ Py_XDECREF(kwargs);
+
+ return result;
}
- if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
+ if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) {
PyErr_Format(PyExc_TypeError,
"wrapper %s doesn't take keyword arguments",
wp->descr->d_base->name);
return NULL;
}
- return (*wrapper)(self, args, wp->descr->d_wrapped);
+
+ args = _PyStack_AsTuple(stack, nargs);
+ if (args == NULL) {
+ return NULL;
+ }
+
+ result = (*wrapper)(self, args, wp->descr->d_wrapped);
+ Py_DECREF(args);
+ return result;
}
static int
@@ -1203,7 +1233,7 @@ PyTypeObject _PyMethodWrapper_Type = {
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)wrapper_hash, /* tp_hash */
- (ternaryfunc)wrapper_call, /* tp_call */
+ 0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
@@ -1219,10 +1249,8 @@ PyTypeObject _PyMethodWrapper_Type = {
wrapper_methods, /* tp_methods */
wrapper_members, /* tp_members */
wrapper_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
+
+ .tp_fastcall = (fastternaryfunc)wrapper_call,
};
PyObject *
@@ -1355,10 +1383,8 @@ property_dealloc(PyObject *self)
static PyObject *
property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
{
- static PyObject * volatile cached_args = NULL;
- PyObject *args;
- PyObject *ret;
propertyobject *gs = (propertyobject *)self;
+ PyObject *args[1];
if (obj == NULL || obj == Py_None) {
Py_INCREF(self);
@@ -1368,29 +1394,9 @@ property_descr_get(PyObject *self, PyObj
PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
return NULL;
}
- args = cached_args;
- cached_args = NULL;
- if (!args) {
- args = PyTuple_New(1);
- if (!args)
- return NULL;
- _PyObject_GC_UNTRACK(args);
- }
- Py_INCREF(obj);
- PyTuple_SET_ITEM(args, 0, obj);
- ret = PyObject_Call(gs->prop_get, args, NULL);
- if (cached_args == NULL && Py_REFCNT(args) == 1) {
- assert(Py_SIZE(args) == 1);
- assert(PyTuple_GET_ITEM(args, 0) == obj);
- cached_args = args;
- Py_DECREF(obj);
- }
- else {
- assert(Py_REFCNT(args) >= 1);
- _PyObject_GC_TRACK(args);
- Py_DECREF(args);
- }
- return ret;
+
+ args[0] = obj;
+ return _PyObject_FastCall(gs->prop_get, args, 1);
}
static int

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+