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

Delta Between Two Patch Sets: Objects/descrobject.c

Issue 29259: Add tp_fastcall to PyTypeObject: support FASTCALL calling convention for all callable objects
Left Patch Set: Created 3 years ago
Right Patch Set: Created 2 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
1 /* Descriptors -- a new, flexible way to describe attributes */ 1 /* Descriptors -- a new, flexible way to describe attributes */
2 2
3 #include "Python.h" 3 #include "Python.h"
4 #include "structmember.h" /* Why is this not included in Python.h? */ 4 #include "structmember.h" /* Why is this not included in Python.h? */
5 5
6 static void 6 static void
7 descr_dealloc(PyDescrObject *descr) 7 descr_dealloc(PyDescrObject *descr)
8 { 8 {
9 _PyObject_GC_UNTRACK(descr); 9 _PyObject_GC_UNTRACK(descr);
10 Py_XDECREF(descr->d_type); 10 Py_XDECREF(descr->d_type);
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 "attribute '%V' of '%.100s' objects is not writable", 206 "attribute '%V' of '%.100s' objects is not writable",
207 descr_name((PyDescrObject *)descr), "?", 207 descr_name((PyDescrObject *)descr), "?",
208 PyDescr_TYPE(descr)->tp_name); 208 PyDescr_TYPE(descr)->tp_name);
209 return -1; 209 return -1;
210 } 210 }
211 211
212 static PyObject * 212 static PyObject *
213 methoddescr_call(PyMethodDescrObject *descr, PyObject **args, Py_ssize_t nargs, 213 methoddescr_call(PyMethodDescrObject *descr, PyObject **args, Py_ssize_t nargs,
214 PyObject *kwnames) 214 PyObject *kwnames)
215 { 215 {
216 PyObject *self, *func, *result; 216 PyObject *self, *result;
217 217
218 /* Make sure that the first argument is acceptable as 'self' */ 218 /* Make sure that the first argument is acceptable as 'self' */
219 if (nargs < 1) { 219 if (nargs < 1) {
220 PyErr_Format(PyExc_TypeError, 220 PyErr_Format(PyExc_TypeError,
221 "descriptor '%V' of '%.100s' " 221 "descriptor '%V' of '%.100s' "
222 "object needs an argument", 222 "object needs an argument",
223 descr_name((PyDescrObject *)descr), "?", 223 descr_name((PyDescrObject *)descr), "?",
224 PyDescr_TYPE(descr)->tp_name); 224 PyDescr_TYPE(descr)->tp_name);
225 return NULL; 225 return NULL;
226 } 226 }
227 self = args[0]; 227 self = args[0];
228 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), 228 if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
229 (PyObject *)PyDescr_TYPE(descr))) { 229 (PyObject *)PyDescr_TYPE(descr))) {
230 PyErr_Format(PyExc_TypeError, 230 PyErr_Format(PyExc_TypeError,
231 "descriptor '%V' " 231 "descriptor '%V' "
232 "requires a '%.100s' object " 232 "requires a '%.100s' object "
233 "but received a '%.100s'", 233 "but received a '%.100s'",
234 descr_name((PyDescrObject *)descr), "?", 234 descr_name((PyDescrObject *)descr), "?",
235 PyDescr_TYPE(descr)->tp_name, 235 PyDescr_TYPE(descr)->tp_name,
236 self->ob_type->tp_name); 236 self->ob_type->tp_name);
237 return NULL; 237 return NULL;
238 } 238 }
239 239
240 func = PyCFunction_NewEx(descr->d_method, self, NULL); 240 result = _PyMethodDef_RawFastCallKeywords(descr->d_method, self,
241 if (func == NULL) 241 args + 1, nargs - 1,
242 return NULL; 242 kwnames);
243 result = _PyCFunction_FastCallKeywords(func, args + 1, nargs - 1, kwnames); 243 result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
244 Py_DECREF(func);
245 return result; 244 return result;
246 } 245 }
247 246
248 static PyObject * 247 static PyObject *
249 classmethoddescr_call(PyMethodDescrObject *descr, PyObject **args, 248 classmethoddescr_call(PyMethodDescrObject *descr, PyObject **args,
250 Py_ssize_t nargs, PyObject *kwnames) 249 Py_ssize_t nargs, PyObject *kwnames)
251 { 250 {
252 PyObject *self, *func, *result; 251 PyObject *self, *func, *result;
253 252
254 /* Make sure that the first argument is acceptable as 'self' */ 253 /* Make sure that the first argument is acceptable as 'self' */
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 {"__doc__", (getter)method_get_doc}, 403 {"__doc__", (getter)method_get_doc},
405 {"__qualname__", (getter)descr_get_qualname}, 404 {"__qualname__", (getter)descr_get_qualname},
406 {"__text_signature__", (getter)method_get_text_signature}, 405 {"__text_signature__", (getter)method_get_text_signature},
407 {0} 406 {0}
408 }; 407 };
409 408
410 static PyObject * 409 static PyObject *
411 member_get_doc(PyMemberDescrObject *descr, void *closure) 410 member_get_doc(PyMemberDescrObject *descr, void *closure)
412 { 411 {
413 if (descr->d_member->doc == NULL) { 412 if (descr->d_member->doc == NULL) {
414 Py_INCREF(Py_None); 413 Py_RETURN_NONE;
415 return Py_None;
416 } 414 }
417 return PyUnicode_FromString(descr->d_member->doc); 415 return PyUnicode_FromString(descr->d_member->doc);
418 } 416 }
419 417
420 static PyGetSetDef member_getset[] = { 418 static PyGetSetDef member_getset[] = {
421 {"__doc__", (getter)member_get_doc}, 419 {"__doc__", (getter)member_get_doc},
422 {"__qualname__", (getter)descr_get_qualname}, 420 {"__qualname__", (getter)descr_get_qualname},
423 {0} 421 {0}
424 }; 422 };
425 423
426 static PyObject * 424 static PyObject *
427 getset_get_doc(PyGetSetDescrObject *descr, void *closure) 425 getset_get_doc(PyGetSetDescrObject *descr, void *closure)
428 { 426 {
429 if (descr->d_getset->doc == NULL) { 427 if (descr->d_getset->doc == NULL) {
430 Py_INCREF(Py_None); 428 Py_RETURN_NONE;
431 return Py_None;
432 } 429 }
433 return PyUnicode_FromString(descr->d_getset->doc); 430 return PyUnicode_FromString(descr->d_getset->doc);
434 } 431 }
435 432
436 static PyGetSetDef getset_getset[] = { 433 static PyGetSetDef getset_getset[] = {
437 {"__doc__", (getter)getset_get_doc}, 434 {"__doc__", (getter)getset_get_doc},
438 {"__qualname__", (getter)descr_get_qualname}, 435 {"__qualname__", (getter)descr_get_qualname},
439 {0} 436 {0}
440 }; 437 };
441 438
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 (reprfunc)method_repr, /* tp_repr */ 515 (reprfunc)method_repr, /* tp_repr */
519 0, /* tp_as_number */ 516 0, /* tp_as_number */
520 0, /* tp_as_sequence */ 517 0, /* tp_as_sequence */
521 0, /* tp_as_mapping */ 518 0, /* tp_as_mapping */
522 0, /* tp_hash */ 519 0, /* tp_hash */
523 0, /* tp_call */ 520 0, /* tp_call */
524 0, /* tp_str */ 521 0, /* tp_str */
525 PyObject_GenericGetAttr, /* tp_getattro */ 522 PyObject_GenericGetAttr, /* tp_getattro */
526 0, /* tp_setattro */ 523 0, /* tp_setattro */
527 0, /* tp_as_buffer */ 524 0, /* tp_as_buffer */
528 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 525 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
529 0, /* tp_doc */ 526 0, /* tp_doc */
530 descr_traverse, /* tp_traverse */ 527 descr_traverse, /* tp_traverse */
531 0, /* tp_clear */ 528 0, /* tp_clear */
532 0, /* tp_richcompare */ 529 0, /* tp_richcompare */
533 0, /* tp_weaklistoffset */ 530 0, /* tp_weaklistoffset */
534 0, /* tp_iter */ 531 0, /* tp_iter */
535 0, /* tp_iternext */ 532 0, /* tp_iternext */
536 descr_methods, /* tp_methods */ 533 descr_methods, /* tp_methods */
537 descr_members, /* tp_members */ 534 descr_members, /* tp_members */
538 method_getset, /* tp_getset */ 535 method_getset, /* tp_getset */
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 651
655 .tp_fastcall = (fastternaryfunc)wrapperdescr_call, 652 .tp_fastcall = (fastternaryfunc)wrapperdescr_call,
656 }; 653 };
657 654
658 static PyDescrObject * 655 static PyDescrObject *
659 descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name) 656 descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
660 { 657 {
661 PyDescrObject *descr; 658 PyDescrObject *descr;
662 659
663 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0); 660 descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
664 if (descr != NULL) { 661 if (descr == NULL) {
665 Py_XINCREF(type); 662 return NULL;
666 descr->d_type = type; 663 }
667 descr->d_name = PyUnicode_InternFromString(name); 664
668 if (descr->d_name == NULL) { 665 Py_XINCREF(type);
669 Py_DECREF(descr); 666 descr->d_type = type;
670 descr = NULL; 667 descr->d_name = PyUnicode_InternFromString(name);
671 } 668 if (descr->d_name == NULL) {
672 else { 669 Py_DECREF(descr);
673 descr->d_qualname = NULL; 670 descr = NULL;
674 } 671 }
672 else {
673 descr->d_qualname = NULL;
675 } 674 }
676 return descr; 675 return descr;
677 } 676 }
678 677
679 PyObject * 678 PyObject *
680 PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method) 679 PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
681 { 680 {
682 PyMethodDescrObject *descr; 681 PyMethodDescrObject *descr;
683 682
684 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type, 683 descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 PyGetSetDescrObject *descr; 717 PyGetSetDescrObject *descr;
719 718
720 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type, 719 descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
721 type, getset->name); 720 type, getset->name);
722 if (descr != NULL) 721 if (descr != NULL)
723 descr->d_getset = getset; 722 descr->d_getset = getset;
724 return (PyObject *)descr; 723 return (PyObject *)descr;
725 } 724 }
726 725
727 PyObject * 726 PyObject *
728 PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped) 727 _PyDescr_NewWrapperEx(PyTypeObject *type, struct wrapperbase *base, void *wrappe d, int use_fastwrapper)
haypo 2017/01/26 03:35:21 Maybe a new funtion is not worth it, the d_user_fa
729 { 728 {
730 PyWrapperDescrObject *descr; 729 PyWrapperDescrObject *descr;
731 730
732 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type, 731 descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
733 type, base->name); 732 type, base->name);
734 if (descr != NULL) { 733 if (descr == NULL) {
735 descr->d_base = base; 734 return NULL;
736 descr->d_wrapped = wrapped; 735 }
737 } 736
737 descr->d_base = base;
738 descr->d_wrapped = wrapped;
739 descr->d_use_fastwrapper = use_fastwrapper;
738 return (PyObject *)descr; 740 return (PyObject *)descr;
741 }
742
743 PyObject *
744 PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
745 {
746 return _PyDescr_NewWrapperEx(type, base, wrapped, 0);
739 } 747 }
740 748
741 749
742 /* --- mappingproxy: read-only proxy for mappings --- */ 750 /* --- mappingproxy: read-only proxy for mappings --- */
743 751
744 /* This has no reason to be in this file except that adding new files is a 752 /* This has no reason to be in this file except that adding new files is a
745 bit of a pain */ 753 bit of a pain */
746 754
747 typedef struct { 755 typedef struct {
748 PyObject_HEAD 756 PyObject_HEAD
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 static PyGetSetDef wrapper_getsets[] = { 1157 static PyGetSetDef wrapper_getsets[] = {
1150 {"__objclass__", (getter)wrapper_objclass}, 1158 {"__objclass__", (getter)wrapper_objclass},
1151 {"__name__", (getter)wrapper_name}, 1159 {"__name__", (getter)wrapper_name},
1152 {"__qualname__", (getter)wrapper_qualname}, 1160 {"__qualname__", (getter)wrapper_qualname},
1153 {"__doc__", (getter)wrapper_doc}, 1161 {"__doc__", (getter)wrapper_doc},
1154 {"__text_signature__", (getter)wrapper_text_signature}, 1162 {"__text_signature__", (getter)wrapper_text_signature},
1155 {0} 1163 {0}
1156 }; 1164 };
1157 1165
1158 static PyObject * 1166 static PyObject *
1159 wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds) 1167 wrapper_call(wrapperobject *wp, PyObject **stack, Py_ssize_t nargs, PyObject *kw names)
1160 { 1168 {
1161 wrapperfunc wrapper = wp->descr->d_base->wrapper; 1169 wrapperfunc wrapper;
1162 PyObject *self = wp->self; 1170 PyObject *self = wp->self;
1163 1171 PyObject *args, *kwargs, *result;
1172
1173 if (wp->descr->d_use_fastwrapper) {
1174 wrapperfunc_fast wf = wp->descr->d_base->fastwrapper;
1175
1176 return (*wf)(self, wp->descr->d_wrapped, stack, nargs, kwnames);
1177 }
1178
1179 wrapper = wp->descr->d_base->wrapper;
1164 if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) { 1180 if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
1165 wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper; 1181 wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
1166 return (*wk)(self, args, wp->descr->d_wrapped, kwds); 1182
1167 } 1183 if (_PyStack_AsTupleAndDict(stack, nargs, kwnames, &args, &kwargs) < 0) {
1168 1184 return NULL;
1169 if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) { 1185 }
1186
1187 result = (*wk)(self, args, wp->descr->d_wrapped, kwargs);
1188 Py_DECREF(args);
1189 Py_XDECREF(kwargs);
1190
1191 return result;
1192 }
1193
1194 if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) {
1170 PyErr_Format(PyExc_TypeError, 1195 PyErr_Format(PyExc_TypeError,
1171 "wrapper %s doesn't take keyword arguments", 1196 "wrapper %s doesn't take keyword arguments",
1172 wp->descr->d_base->name); 1197 wp->descr->d_base->name);
1173 return NULL; 1198 return NULL;
1174 } 1199 }
1175 return (*wrapper)(self, args, wp->descr->d_wrapped); 1200
1201 args = _PyStack_AsTuple(stack, nargs);
1202 if (args == NULL) {
1203 return NULL;
1204 }
1205
1206 result = (*wrapper)(self, args, wp->descr->d_wrapped);
1207 Py_DECREF(args);
1208 return result;
1176 } 1209 }
1177 1210
1178 static int 1211 static int
1179 wrapper_traverse(PyObject *self, visitproc visit, void *arg) 1212 wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1180 { 1213 {
1181 wrapperobject *wp = (wrapperobject *)self; 1214 wrapperobject *wp = (wrapperobject *)self;
1182 Py_VISIT(wp->descr); 1215 Py_VISIT(wp->descr);
1183 Py_VISIT(wp->self); 1216 Py_VISIT(wp->self);
1184 return 0; 1217 return 0;
1185 } 1218 }
1186 1219
1187 PyTypeObject _PyMethodWrapper_Type = { 1220 PyTypeObject _PyMethodWrapper_Type = {
1188 PyVarObject_HEAD_INIT(&PyType_Type, 0) 1221 PyVarObject_HEAD_INIT(&PyType_Type, 0)
1189 "method-wrapper", /* tp_name */ 1222 "method-wrapper", /* tp_name */
1190 sizeof(wrapperobject), /* tp_basicsize */ 1223 sizeof(wrapperobject), /* tp_basicsize */
1191 0, /* tp_itemsize */ 1224 0, /* tp_itemsize */
1192 /* methods */ 1225 /* methods */
1193 (destructor)wrapper_dealloc, /* tp_dealloc */ 1226 (destructor)wrapper_dealloc, /* tp_dealloc */
1194 0, /* tp_print */ 1227 0, /* tp_print */
1195 0, /* tp_getattr */ 1228 0, /* tp_getattr */
1196 0, /* tp_setattr */ 1229 0, /* tp_setattr */
1197 0, /* tp_reserved */ 1230 0, /* tp_reserved */
1198 (reprfunc)wrapper_repr, /* tp_repr */ 1231 (reprfunc)wrapper_repr, /* tp_repr */
1199 0, /* tp_as_number */ 1232 0, /* tp_as_number */
1200 0, /* tp_as_sequence */ 1233 0, /* tp_as_sequence */
1201 0, /* tp_as_mapping */ 1234 0, /* tp_as_mapping */
1202 (hashfunc)wrapper_hash, /* tp_hash */ 1235 (hashfunc)wrapper_hash, /* tp_hash */
1203 (ternaryfunc)wrapper_call, /* tp_call */ 1236 0, /* tp_call */
1204 0, /* tp_str */ 1237 0, /* tp_str */
1205 PyObject_GenericGetAttr, /* tp_getattro */ 1238 PyObject_GenericGetAttr, /* tp_getattro */
1206 0, /* tp_setattro */ 1239 0, /* tp_setattro */
1207 0, /* tp_as_buffer */ 1240 0, /* tp_as_buffer */
1208 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 1241 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1209 0, /* tp_doc */ 1242 0, /* tp_doc */
1210 wrapper_traverse, /* tp_traverse */ 1243 wrapper_traverse, /* tp_traverse */
1211 0, /* tp_clear */ 1244 0, /* tp_clear */
1212 wrapper_richcompare, /* tp_richcompare */ 1245 wrapper_richcompare, /* tp_richcompare */
1213 0, /* tp_weaklistoffset */ 1246 0, /* tp_weaklistoffset */
1214 0, /* tp_iter */ 1247 0, /* tp_iter */
1215 0, /* tp_iternext */ 1248 0, /* tp_iternext */
1216 wrapper_methods, /* tp_methods */ 1249 wrapper_methods, /* tp_methods */
1217 wrapper_members, /* tp_members */ 1250 wrapper_members, /* tp_members */
1218 wrapper_getsets, /* tp_getset */ 1251 wrapper_getsets, /* tp_getset */
1219 0, /* tp_base */ 1252
1220 0, /* tp_dict */ 1253 .tp_fastcall = (fastternaryfunc)wrapper_call,
1221 0, /* tp_descr_get */
1222 0, /* tp_descr_set */
1223 }; 1254 };
1224 1255
1225 PyObject * 1256 PyObject *
1226 PyWrapper_New(PyObject *d, PyObject *self) 1257 PyWrapper_New(PyObject *d, PyObject *self)
1227 { 1258 {
1228 wrapperobject *wp; 1259 wrapperobject *wp;
1229 PyWrapperDescrObject *descr; 1260 PyWrapperDescrObject *descr;
1230 1261
1231 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type)); 1262 assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1232 descr = (PyWrapperDescrObject *)d; 1263 descr = (PyWrapperDescrObject *)d;
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
1610 0, /* tp_base */ 1641 0, /* tp_base */
1611 0, /* tp_dict */ 1642 0, /* tp_dict */
1612 property_descr_get, /* tp_descr_get */ 1643 property_descr_get, /* tp_descr_get */
1613 property_descr_set, /* tp_descr_set */ 1644 property_descr_set, /* tp_descr_set */
1614 0, /* tp_dictoffset */ 1645 0, /* tp_dictoffset */
1615 property_init, /* tp_init */ 1646 property_init, /* tp_init */
1616 PyType_GenericAlloc, /* tp_alloc */ 1647 PyType_GenericAlloc, /* tp_alloc */
1617 PyType_GenericNew, /* tp_new */ 1648 PyType_GenericNew, /* tp_new */
1618 PyObject_GC_Del, /* tp_free */ 1649 PyObject_GC_Del, /* tp_free */
1619 }; 1650 };
LEFTRIGHT

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