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

Side by Side Diff: Objects/typeobject.c

Issue 29259: Add tp_fastcall to PyTypeObject: support FASTCALL calling convention for all callable objects
Patch Set: Created 3 years, 2 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:
View unified diff | Download patch
« no previous file with comments | « Objects/methodobject.c ('k') | Objects/weakrefobject.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Type object implementation */ 1 /* Type object implementation */
2 2
3 #include "Python.h" 3 #include "Python.h"
4 #include "frameobject.h" 4 #include "frameobject.h"
5 #include "structmember.h" 5 #include "structmember.h"
6 6
7 #include <ctype.h> 7 #include <ctype.h>
8 8
9 9
10 /* Support type attribute cache */ 10 /* Support type attribute cache */
(...skipping 4670 matching lines...) Expand 10 before | Expand all | Expand 10 after
4681 { 4681 {
4682 PyObject *dict = type->tp_dict; 4682 PyObject *dict = type->tp_dict;
4683 _Py_IDENTIFIER(__eq__); 4683 _Py_IDENTIFIER(__eq__);
4684 4684
4685 assert(dict != NULL); 4685 assert(dict != NULL);
4686 if (_PyDict_GetItemId(dict, &PyId___eq__) != NULL) 4686 if (_PyDict_GetItemId(dict, &PyId___eq__) != NULL)
4687 return 1; 4687 return 1;
4688 if (_PyDict_GetItemId(dict, &PyId___hash__) != NULL) 4688 if (_PyDict_GetItemId(dict, &PyId___hash__) != NULL)
4689 return 1; 4689 return 1;
4690 return 0; 4690 return 0;
4691 }
4692
4693 /* tp_call slot calling tp_fastcall */
4694 static PyObject *
4695 fastcall_wrapper(PyObject *callable, PyObject *args_tuple, PyObject *kwargs)
4696 {
4697 PyTypeObject *type;
4698 PyObject *result;
4699
4700 type = Py_TYPE(callable);
4701 while (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_FASTCALL)
4702 || type->tp_fastcall == NULL) {
4703 PyTypeObject *base = type->tp_base;
4704 if (base == type || base == NULL) {
4705 PyErr_SetString(PyExc_SystemError,
4706 "unable to find tp_fastcall in a base classes");
4707 return NULL;
4708 }
4709 type = base;
4710 }
4711
4712 result = _Py_RawFastCallDict(callable,
4713 type->tp_fastcall,
4714 &PyTuple_GET_ITEM(args_tuple, 0),
4715 PyTuple_GET_SIZE(args_tuple),
4716 kwargs);
4717
4718 result = _Py_CheckFunctionResult(callable, result, NULL);
4719 return result;
4691 } 4720 }
4692 4721
4693 static void 4722 static void
4694 inherit_slots(PyTypeObject *type, PyTypeObject *base) 4723 inherit_slots(PyTypeObject *type, PyTypeObject *base)
4695 { 4724 {
4696 PyTypeObject *basebase; 4725 PyTypeObject *basebase;
4697 4726
4698 #undef SLOTDEFINED 4727 #undef SLOTDEFINED
4699 #undef COPYSLOT 4728 #undef COPYSLOT
4700 #undef COPYNUM 4729 #undef COPYNUM
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
4806 type->tp_getattr = base->tp_getattr; 4835 type->tp_getattr = base->tp_getattr;
4807 type->tp_getattro = base->tp_getattro; 4836 type->tp_getattro = base->tp_getattro;
4808 } 4837 }
4809 if (type->tp_setattr == NULL && type->tp_setattro == NULL) { 4838 if (type->tp_setattr == NULL && type->tp_setattro == NULL) {
4810 type->tp_setattr = base->tp_setattr; 4839 type->tp_setattr = base->tp_setattr;
4811 type->tp_setattro = base->tp_setattro; 4840 type->tp_setattro = base->tp_setattro;
4812 } 4841 }
4813 /* tp_reserved is ignored */ 4842 /* tp_reserved is ignored */
4814 COPYSLOT(tp_repr); 4843 COPYSLOT(tp_repr);
4815 /* tp_hash see tp_richcompare */ 4844 /* tp_hash see tp_richcompare */
4816 COPYSLOT(tp_call); 4845
4846 if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_FASTCALL)
4847 && PyType_HasFeature(base, Py_TPFLAGS_HAVE_FASTCALL)
4848 /* don't inherit tp_fastcall if tp_call is defined */
4849 && (type->tp_call == NULL || type->tp_call != fastcall_wrapper)) {
4850 COPYSLOT(tp_fastcall);
4851 }
4852
4853 if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_FASTCALL)
4854 || type->tp_call != fastcall_wrapper) {
4855 COPYSLOT(tp_call);
4856 }
4857
4817 COPYSLOT(tp_str); 4858 COPYSLOT(tp_str);
4818 { 4859 {
4819 /* Copy comparison-related slots only when 4860 /* Copy comparison-related slots only when
4820 not overriding them anywhere */ 4861 not overriding them anywhere */
4821 if (type->tp_richcompare == NULL && 4862 if (type->tp_richcompare == NULL &&
4822 type->tp_hash == NULL && 4863 type->tp_hash == NULL &&
4823 !overrides_hash(type)) 4864 !overrides_hash(type))
4824 { 4865 {
4825 type->tp_richcompare = base->tp_richcompare; 4866 type->tp_richcompare = base->tp_richcompare;
4826 type->tp_hash = base->tp_hash; 4867 type->tp_hash = base->tp_hash;
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
4933 type->tp_bases = bases; 4974 type->tp_bases = bases;
4934 } 4975 }
4935 4976
4936 /* Initialize tp_dict */ 4977 /* Initialize tp_dict */
4937 dict = type->tp_dict; 4978 dict = type->tp_dict;
4938 if (dict == NULL) { 4979 if (dict == NULL) {
4939 dict = PyDict_New(); 4980 dict = PyDict_New();
4940 if (dict == NULL) 4981 if (dict == NULL)
4941 goto error; 4982 goto error;
4942 type->tp_dict = dict; 4983 type->tp_dict = dict;
4984 }
4985
4986 if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_FASTCALL)
4987 && type->tp_fastcall && !type->tp_call) {
4988 /* tp_fastcall defined, but not tp_call: tp_call will use a wrapper
4989 calling tp_fastcall. We need to define tp_call before calling
4990 add_operators(), otherwise the __call__ descriptor is not
4991 defined. */
4992 type->tp_call = fastcall_wrapper;
4943 } 4993 }
4944 4994
4945 /* Add type-specific descriptors to tp_dict */ 4995 /* Add type-specific descriptors to tp_dict */
4946 if (add_operators(type) < 0) 4996 if (add_operators(type) < 0)
4947 goto error; 4997 goto error;
4948 if (type->tp_methods != NULL) { 4998 if (type->tp_methods != NULL) {
4949 if (add_methods(type, type->tp_methods) < 0) 4999 if (add_methods(type, type->tp_methods) < 0)
4950 goto error; 5000 goto error;
4951 } 5001 }
4952 if (type->tp_members != NULL) { 5002 if (type->tp_members != NULL) {
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
5488 return NULL; 5538 return NULL;
5489 return PyLong_FromSsize_t(res); 5539 return PyLong_FromSsize_t(res);
5490 } 5540 }
5491 5541
5492 static PyObject * 5542 static PyObject *
5493 wrap_call(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds) 5543 wrap_call(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds)
5494 { 5544 {
5495 ternaryfunc func = (ternaryfunc)wrapped; 5545 ternaryfunc func = (ternaryfunc)wrapped;
5496 5546
5497 return (*func)(self, args, kwds); 5547 return (*func)(self, args, kwds);
5548 }
5549
5550 static PyObject *
5551 wrap_fastcall(PyObject *self, void *wrapped,
5552 PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
5553 {
5554 fastternaryfunc func = (fastternaryfunc)wrapped;
5555
5556 return (*func)(self, args, nargs, kwnames);
5498 } 5557 }
5499 5558
5500 static PyObject * 5559 static PyObject *
5501 wrap_del(PyObject *self, PyObject *args, void *wrapped) 5560 wrap_del(PyObject *self, PyObject *args, void *wrapped)
5502 { 5561 {
5503 destructor func = (destructor)wrapped; 5562 destructor func = (destructor)wrapped;
5504 5563
5505 if (!check_num_args(args, 0)) 5564 if (!check_num_args(args, 0))
5506 return NULL; 5565 return NULL;
5507 5566
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after
6150 _Py_IDENTIFIER(__call__); 6209 _Py_IDENTIFIER(__call__);
6151 PyObject *meth = lookup_method(self, &PyId___call__); 6210 PyObject *meth = lookup_method(self, &PyId___call__);
6152 PyObject *res; 6211 PyObject *res;
6153 6212
6154 if (meth == NULL) 6213 if (meth == NULL)
6155 return NULL; 6214 return NULL;
6156 6215
6157 res = PyObject_Call(meth, args, kwds); 6216 res = PyObject_Call(meth, args, kwds);
6158 6217
6159 Py_DECREF(meth); 6218 Py_DECREF(meth);
6219 return res;
6220 }
6221
6222 static PyObject *
6223 slot_tp_fastcall(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kw names)
6224 {
6225 _Py_IDENTIFIER(__call__);
6226 PyObject *meth = lookup_method(self, &PyId___call__);
6227 PyObject *res;
6228
6229 if (meth == NULL)
6230 return NULL;
6231
6232 res = _PyObject_FastCallKeywords(meth, args, nargs, kwnames);
6233
6234 Py_DECREF(meth);
6160 return res; 6235 return res;
6161 } 6236 }
6162 6237
6163 /* There are two slot dispatch functions for tp_getattro. 6238 /* There are two slot dispatch functions for tp_getattro.
6164 6239
6165 - slot_tp_getattro() is used when __getattribute__ is overridden 6240 - slot_tp_getattro() is used when __getattribute__ is overridden
6166 but no __getattr__ hook is present; 6241 but no __getattr__ hook is present;
6167 6242
6168 - slot_tp_getattr_hook() is used when a __getattr__ hook is present. 6243 - slot_tp_getattr_hook() is used when a __getattr__ hook is present.
6169 6244
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
6506 #undef ETSLOT 6581 #undef ETSLOT
6507 #undef SQSLOT 6582 #undef SQSLOT
6508 #undef MPSLOT 6583 #undef MPSLOT
6509 #undef NBSLOT 6584 #undef NBSLOT
6510 #undef UNSLOT 6585 #undef UNSLOT
6511 #undef IBSLOT 6586 #undef IBSLOT
6512 #undef BINSLOT 6587 #undef BINSLOT
6513 #undef RBINSLOT 6588 #undef RBINSLOT
6514 6589
6515 #define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ 6590 #define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
6516 {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ 6591 {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, NULL, \
6517 PyDoc_STR(DOC)} 6592 PyDoc_STR(DOC)}
6518 #define FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS) \ 6593 #define FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS) \
6519 {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ 6594 {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, NULL, \
6595 PyDoc_STR(DOC), FLAGS}
6596 #define FLSLOT_FAST(NAME, SLOT, FUNCTION, WRAPPER, FAST_WRAPPER, DOC, FLAGS) \
6597 {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, FAST_WRAPP ER, \
6520 PyDoc_STR(DOC), FLAGS} 6598 PyDoc_STR(DOC), FLAGS}
6521 #define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ 6599 #define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
6522 {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \ 6600 {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, NULL, \
6523 PyDoc_STR(DOC)} 6601 PyDoc_STR(DOC)}
6524 #define AMSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ 6602 #define AMSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
6525 ETSLOT(NAME, as_async.SLOT, FUNCTION, WRAPPER, DOC) 6603 ETSLOT(NAME, as_async.SLOT, FUNCTION, WRAPPER, DOC)
6526 #define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ 6604 #define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
6527 ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC) 6605 ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC)
6528 #define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ 6606 #define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
6529 ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER, DOC) 6607 ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER, DOC)
6530 #define NBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ 6608 #define NBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
6531 ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, DOC) 6609 ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, DOC)
6532 #define UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ 6610 #define UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
(...skipping 17 matching lines...) Expand all
6550 6628
6551 static slotdef slotdefs[] = { 6629 static slotdef slotdefs[] = {
6552 TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""), 6630 TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""),
6553 TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""), 6631 TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),
6554 TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""), 6632 TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""),
6555 TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""), 6633 TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""),
6556 TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc, 6634 TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc,
6557 "__repr__($self, /)\n--\n\nReturn repr(self)."), 6635 "__repr__($self, /)\n--\n\nReturn repr(self)."),
6558 TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc, 6636 TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc,
6559 "__hash__($self, /)\n--\n\nReturn hash(self)."), 6637 "__hash__($self, /)\n--\n\nReturn hash(self)."),
6560 FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call, 6638 FLSLOT_FAST("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call, wrap_ fastcall,
6561 "__call__($self, /, *args, **kwargs)\n--\n\nCall self as a function." , 6639 "__call__($self, /, *args, **kwargs)\n--\n\nCall self as a function." ,
6562 PyWrapperFlag_KEYWORDS), 6640 PyWrapperFlag_KEYWORDS),
6563 TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc, 6641 TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc,
6564 "__str__($self, /)\n--\n\nReturn str(self)."), 6642 "__str__($self, /)\n--\n\nReturn str(self)."),
6565 TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook, 6643 TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook,
6566 wrap_binaryfunc, 6644 wrap_binaryfunc,
6567 "__getattribute__($self, name, /)\n--\n\nReturn getattr(self, name)." ), 6645 "__getattribute__($self, name, /)\n--\n\nReturn getattr(self, name)." ),
6568 TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""), 6646 TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""),
6569 TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr, 6647 TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr,
6570 "__setattr__($self, name, value, /)\n--\n\nImplement setattr(self, na me, value)."), 6648 "__setattr__($self, name, value, /)\n--\n\nImplement setattr(self, na me, value)."),
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
6824 the slot.) Return a pointer to the next slotdef with a different offset, 6902 the slot.) Return a pointer to the next slotdef with a different offset,
6825 because that's convenient for fixup_slot_dispatchers(). */ 6903 because that's convenient for fixup_slot_dispatchers(). */
6826 static slotdef * 6904 static slotdef *
6827 update_one_slot(PyTypeObject *type, slotdef *p) 6905 update_one_slot(PyTypeObject *type, slotdef *p)
6828 { 6906 {
6829 PyObject *descr; 6907 PyObject *descr;
6830 PyWrapperDescrObject *d; 6908 PyWrapperDescrObject *d;
6831 void *generic = NULL, *specific = NULL; 6909 void *generic = NULL, *specific = NULL;
6832 int use_generic = 0; 6910 int use_generic = 0;
6833 int offset = p->offset; 6911 int offset = p->offset;
6834 void **ptr = slotptr(type, offset); 6912 void **ptr = slotptr(type, offset), **ptr2 = NULL;
6835 6913
6836 if (ptr == NULL) { 6914 if (ptr == NULL) {
6837 do { 6915 do {
6838 ++p; 6916 ++p;
6839 } while (p->offset == offset); 6917 } while (p->offset == offset);
6840 return p; 6918 return p;
6841 } 6919 }
6920
6842 do { 6921 do {
6843 descr = _PyType_Lookup(type, p->name_strobj); 6922 descr = _PyType_Lookup(type, p->name_strobj);
6844 if (descr == NULL) { 6923 if (descr == NULL) {
6845 if (ptr == (void**)&type->tp_iternext) { 6924 if (ptr == (void**)&type->tp_iternext) {
6925 ptr2 = NULL;
6846 specific = (void *)_PyObject_NextNotImplemented; 6926 specific = (void *)_PyObject_NextNotImplemented;
6847 } 6927 }
6848 continue; 6928 continue;
6849 } 6929 }
6850 if (Py_TYPE(descr) == &PyWrapperDescr_Type && 6930 if (Py_TYPE(descr) == &PyWrapperDescr_Type &&
6851 ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_stro bj) { 6931 ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_stro bj) {
6852 void **tptr = resolve_slotdups(type, p->name_strobj); 6932 void **tptr = resolve_slotdups(type, p->name_strobj);
6933 int same_wrapper;
6934
6853 if (tptr == NULL || tptr == ptr) 6935 if (tptr == NULL || tptr == ptr)
6854 generic = p->function; 6936 generic = p->function;
6855 d = (PyWrapperDescrObject *)descr; 6937 d = (PyWrapperDescrObject *)descr;
6856 if (d->d_base->wrapper == p->wrapper && 6938
6939 if (d->d_use_fastwrapper) {
6940 same_wrapper = (d->d_base->fastwrapper == p->fastwrapper);
6941
6942 assert(p->wrapper == (void *)wrap_call);
6943 ptr2 = (void **)&type->tp_fastcall;
6944 }
6945 else {
6946 same_wrapper = (d->d_base->wrapper == p->wrapper);
6947 }
6948
6949 if (same_wrapper &&
6857 PyType_IsSubtype(type, PyDescr_TYPE(d))) 6950 PyType_IsSubtype(type, PyDescr_TYPE(d)))
6858 { 6951 {
6859 if (specific == NULL || 6952 if (specific == NULL ||
6860 specific == d->d_wrapped) 6953 specific == d->d_wrapped)
6861 specific = d->d_wrapped; 6954 specific = d->d_wrapped;
6862 else 6955 else
6863 use_generic = 1; 6956 use_generic = 1;
6864 } 6957 }
6865 } 6958 }
6866 else if (Py_TYPE(descr) == &PyCFunction_Type && 6959 else if (Py_TYPE(descr) == &PyCFunction_Type &&
6867 PyCFunction_GET_FUNCTION(descr) == 6960 PyCFunction_GET_FUNCTION(descr) ==
6868 (PyCFunction)tp_new_wrapper && 6961 (PyCFunction)tp_new_wrapper &&
6869 ptr == (void**)&type->tp_new) 6962 ptr == (void**)&type->tp_new)
6870 { 6963 {
6871 /* The __new__ wrapper is not a wrapper descriptor, 6964 /* The __new__ wrapper is not a wrapper descriptor,
6872 so must be special-cased differently. 6965 so must be special-cased differently.
6873 If we don't do this, creating an instance will 6966 If we don't do this, creating an instance will
6874 always use slot_tp_new which will look up 6967 always use slot_tp_new which will look up
6875 __new__ in the MRO which will call tp_new_wrapper 6968 __new__ in the MRO which will call tp_new_wrapper
6876 which will look through the base classes looking 6969 which will look through the base classes looking
6877 for a static base and call its tp_new (usually 6970 for a static base and call its tp_new (usually
6878 PyType_GenericNew), after performing various 6971 PyType_GenericNew), after performing various
6879 sanity checks and constructing a new argument 6972 sanity checks and constructing a new argument
6880 list. Cut all that nonsense short -- this speeds 6973 list. Cut all that nonsense short -- this speeds
6881 up instance creation tremendously. */ 6974 up instance creation tremendously. */
6975
6882 specific = (void *)type->tp_new; 6976 specific = (void *)type->tp_new;
6977 ptr2 = NULL;
6978
6883 /* XXX I'm not 100% sure that there isn't a hole 6979 /* XXX I'm not 100% sure that there isn't a hole
6884 in this reasoning that requires additional 6980 in this reasoning that requires additional
6885 sanity checks. I'll buy the first person to 6981 sanity checks. I'll buy the first person to
6886 point out a bug in this reasoning a beer. */ 6982 point out a bug in this reasoning a beer. */
6887 } 6983 }
6888 else if (descr == Py_None && 6984 else if (descr == Py_None &&
6889 ptr == (void**)&type->tp_hash) { 6985 ptr == (void**)&type->tp_hash) {
6890 /* We specifically allow __hash__ to be set to None 6986 /* We specifically allow __hash__ to be set to None
6891 to prevent inheritance of the default 6987 to prevent inheritance of the default
6892 implementation from object.__hash__ */ 6988 implementation from object.__hash__ */
6893 specific = (void *)PyObject_HashNotImplemented; 6989 specific = (void *)PyObject_HashNotImplemented;
6990 ptr2 = NULL;
6894 } 6991 }
6895 else { 6992 else {
6896 use_generic = 1; 6993 use_generic = 1;
6897 generic = p->function; 6994 generic = p->function;
6898 } 6995 }
6899 } while ((++p)->offset == offset); 6996 } while ((++p)->offset == offset);
6900 if (specific && !use_generic) 6997
6998 if (specific && !use_generic) {
6999 if (ptr2 != NULL) {
7000 ptr = ptr2;
7001 }
6901 *ptr = specific; 7002 *ptr = specific;
6902 else 7003 }
7004 else {
6903 *ptr = generic; 7005 *ptr = generic;
7006 }
7007
7008 if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_FASTCALL)) {
7009 /* synchronize tp_call and tp_fastcall slots */
7010 if (ptr == (void **)&type->tp_call) {
7011 if (type->tp_call == slot_tp_call) {
7012 type->tp_fastcall = slot_tp_fastcall;
7013 }
7014 }
7015 else if (ptr == (void **)&type->tp_fastcall) {
7016 type->tp_call = fastcall_wrapper;
7017 }
7018 }
7019
6904 return p; 7020 return p;
6905 } 7021 }
6906 7022
6907 /* In the type, update the slots whose slotdefs are gathered in the pp array. 7023 /* In the type, update the slots whose slotdefs are gathered in the pp array.
6908 This is a callback for update_subclasses(). */ 7024 This is a callback for update_subclasses(). */
6909 static int 7025 static int
6910 update_slots_callback(PyTypeObject *type, void *data) 7026 update_slots_callback(PyTypeObject *type, void *data)
6911 { 7027 {
6912 slotdef **pp = (slotdef **)data; 7028 slotdef **pp = (slotdef **)data;
6913 7029
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
6985 7101
6986 /* Store the proper functions in the slot dispatches at class (type) 7102 /* Store the proper functions in the slot dispatches at class (type)
6987 definition time, based upon which operations the class overrides in its 7103 definition time, based upon which operations the class overrides in its
6988 dict. */ 7104 dict. */
6989 static void 7105 static void
6990 fixup_slot_dispatchers(PyTypeObject *type) 7106 fixup_slot_dispatchers(PyTypeObject *type)
6991 { 7107 {
6992 slotdef *p; 7108 slotdef *p;
6993 7109
6994 init_slotdefs(); 7110 init_slotdefs();
6995 for (p = slotdefs; p->name; ) 7111 for (p = slotdefs; p->name; ) {
6996 p = update_one_slot(type, p); 7112 p = update_one_slot(type, p);
7113 }
6997 } 7114 }
6998 7115
6999 static void 7116 static void
7000 update_all_slots(PyTypeObject* type) 7117 update_all_slots(PyTypeObject* type)
7001 { 7118 {
7002 slotdef *p; 7119 slotdef *p;
7003 7120
7004 init_slotdefs(); 7121 init_slotdefs();
7005 for (p = slotdefs; p->name; p++) { 7122 for (p = slotdefs; p->name; p++) {
7006 /* update_slot returns int but can't actually fail */ 7123 /* update_slot returns int but can't actually fail */
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
7166 if (PyDict_GetItem(dict, p->name_strobj)) 7283 if (PyDict_GetItem(dict, p->name_strobj))
7167 continue; 7284 continue;
7168 if (*ptr == (void *)PyObject_HashNotImplemented) { 7285 if (*ptr == (void *)PyObject_HashNotImplemented) {
7169 /* Classes may prevent the inheritance of the tp_hash 7286 /* Classes may prevent the inheritance of the tp_hash
7170 slot by storing PyObject_HashNotImplemented in it. Make it 7287 slot by storing PyObject_HashNotImplemented in it. Make it
7171 visible as a None value for the __hash__ attribute. */ 7288 visible as a None value for the __hash__ attribute. */
7172 if (PyDict_SetItem(dict, p->name_strobj, Py_None) < 0) 7289 if (PyDict_SetItem(dict, p->name_strobj, Py_None) < 0)
7173 return -1; 7290 return -1;
7174 } 7291 }
7175 else { 7292 else {
7176 descr = PyDescr_NewWrapper(type, p, *ptr); 7293 int use_fastwrapper;
7294 void *wrapped;
7295
7296 if (*ptr == fastcall_wrapper) {
7297 /* A wrapper must not call fastcall_wrapper() but the specific
7298 tp_fastcall. fastcall_wrapper() is called with an instance.
7299 From an instance, it's not possible to find the specific
7300 function. */
7301 use_fastwrapper = 1;
7302 wrapped = type->tp_fastcall;
7303 }
7304 else {
7305 use_fastwrapper = 0;
7306 wrapped = *ptr;
7307 }
7308 assert(wrapped != NULL);
7309
7310 descr = _PyDescr_NewWrapperEx(type, p, wrapped, use_fastwrapper);
7177 if (descr == NULL) 7311 if (descr == NULL)
7178 return -1; 7312 return -1;
7179 if (PyDict_SetItem(dict, p->name_strobj, descr) < 0) { 7313 if (PyDict_SetItem(dict, p->name_strobj, descr) < 0) {
7180 Py_DECREF(descr); 7314 Py_DECREF(descr);
7181 return -1; 7315 return -1;
7182 } 7316 }
7183 Py_DECREF(descr); 7317 Py_DECREF(descr);
7184 } 7318 }
7185 } 7319 }
7186 if (type->tp_new != NULL) { 7320 if (type->tp_new != NULL) {
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
7575 0, /* tp_base */ 7709 0, /* tp_base */
7576 0, /* tp_dict */ 7710 0, /* tp_dict */
7577 super_descr_get, /* tp_descr_get */ 7711 super_descr_get, /* tp_descr_get */
7578 0, /* tp_descr_set */ 7712 0, /* tp_descr_set */
7579 0, /* tp_dictoffset */ 7713 0, /* tp_dictoffset */
7580 super_init, /* tp_init */ 7714 super_init, /* tp_init */
7581 PyType_GenericAlloc, /* tp_alloc */ 7715 PyType_GenericAlloc, /* tp_alloc */
7582 PyType_GenericNew, /* tp_new */ 7716 PyType_GenericNew, /* tp_new */
7583 PyObject_GC_Del, /* tp_free */ 7717 PyObject_GC_Del, /* tp_free */
7584 }; 7718 };
OLDNEW
« no previous file with comments | « Objects/methodobject.c ('k') | Objects/weakrefobject.c » ('j') | no next file with comments »

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