-
-
Notifications
You must be signed in to change notification settings - Fork 33.3k
bpo-30509: Clean up calling type slots. #1883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1398,29 +1398,23 @@ PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b) | |
| return type_is_subtype_base_chain(a, b); | ||
| } | ||
|
|
||
| /* Internal routines to do a method lookup in the type | ||
| without looking in the instance dictionary | ||
| (so we can't use PyObject_GetAttr) but still binding | ||
| it to the instance. The arguments are the object, | ||
| the method name as a C string, and the address of a | ||
| static variable used to cache the interned Python string. | ||
| /* Routines to do a method lookup in the type without looking in the | ||
| instance dictionary (so we can't use PyObject_GetAttr) but still | ||
| binding it to the instance. | ||
|
|
||
| Variants: | ||
|
|
||
| - lookup_maybe() returns NULL without raising an exception | ||
| - _PyObject_LookupSpecial() returns NULL without raising an exception | ||
| when the _PyType_Lookup() call fails; | ||
|
|
||
| - lookup_maybe_method() and lookup_method() are similar to | ||
| lookup_maybe(), but can return unbound PyFunction | ||
| - lookup_maybe_method() and lookup_method() are internal routines similar | ||
| to _PyObject_LookupSpecial(), but can return unbound PyFunction | ||
| to avoid temporary method object. Pass self as first argument when | ||
| unbound == 1. | ||
|
|
||
| - _PyObject_LookupSpecial() expose lookup_maybe for the benefit of | ||
| other places. | ||
| */ | ||
|
|
||
| static PyObject * | ||
| lookup_maybe(PyObject *self, _Py_Identifier *attrid) | ||
| PyObject * | ||
| _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) | ||
| { | ||
| PyObject *res; | ||
|
|
||
|
|
@@ -1471,12 +1465,6 @@ lookup_method(PyObject *self, _Py_Identifier *attrid, int *unbound) | |
| return res; | ||
| } | ||
|
|
||
| PyObject * | ||
| _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) | ||
| { | ||
| return lookup_maybe(self, attrid); | ||
| } | ||
|
|
||
| static PyObject* | ||
| call_unbound(int unbound, PyObject *func, PyObject *self, | ||
| PyObject **args, Py_ssize_t nargs) | ||
|
|
@@ -1501,23 +1489,19 @@ call_unbound_noarg(int unbound, PyObject *func, PyObject *self) | |
| } | ||
| } | ||
|
|
||
| /* A variation of PyObject_CallMethodObjArgs that uses lookup_maybe_method() | ||
| instead of PyObject_GetAttrString(). This uses the same convention | ||
| as lookup_maybe_method to cache the interned name string object. */ | ||
| /* A variation of PyObject_CallMethod* that uses lookup_maybe_method() | ||
| instead of PyObject_GetAttrString(). */ | ||
| static PyObject * | ||
| call_method(PyObject *obj, _Py_Identifier *name, | ||
| PyObject **args, Py_ssize_t nargs) | ||
| { | ||
| int unbound; | ||
| PyObject *func, *retval; | ||
|
|
||
| func = lookup_maybe_method(obj, name, &unbound); | ||
| func = lookup_method(obj, name, &unbound); | ||
| if (func == NULL) { | ||
| if (!PyErr_Occurred()) | ||
| PyErr_SetObject(PyExc_AttributeError, name->object); | ||
| return NULL; | ||
| } | ||
|
|
||
| retval = call_unbound(unbound, func, obj, args, nargs); | ||
| Py_DECREF(func); | ||
| return retval; | ||
|
|
@@ -5960,45 +5944,19 @@ slot_sq_length(PyObject *self) | |
| return len; | ||
| } | ||
|
|
||
| /* Super-optimized version of slot_sq_item. | ||
| Other slots could do the same... */ | ||
| static PyObject * | ||
| slot_sq_item(PyObject *self, Py_ssize_t i) | ||
| { | ||
| PyObject *func, *ival = NULL, *retval = NULL; | ||
| descrgetfunc f; | ||
|
|
||
| func = _PyType_LookupId(Py_TYPE(self), &PyId___getitem__); | ||
| if (func == NULL) { | ||
| PyObject *getitem_str = _PyUnicode_FromId(&PyId___getitem__); | ||
| PyErr_SetObject(PyExc_AttributeError, getitem_str); | ||
| return NULL; | ||
| } | ||
|
|
||
| f = Py_TYPE(func)->tp_descr_get; | ||
| if (f == NULL) { | ||
| Py_INCREF(func); | ||
| } | ||
| else { | ||
| func = f(func, self, (PyObject *)(Py_TYPE(self))); | ||
| if (func == NULL) { | ||
| return NULL; | ||
| } | ||
| } | ||
|
|
||
| ival = PyLong_FromSsize_t(i); | ||
| PyObject *retval; | ||
| PyObject *args[1]; | ||
| PyObject *ival = PyLong_FromSsize_t(i); | ||
| if (ival == NULL) { | ||
| goto error; | ||
| return NULL; | ||
| } | ||
|
|
||
| retval = PyObject_CallFunctionObjArgs(func, ival, NULL); | ||
| Py_DECREF(func); | ||
| args[0] = ival; | ||
| retval = call_method(self, &PyId___getitem__, args, 1); | ||
| Py_DECREF(ival); | ||
| return retval; | ||
|
|
||
| error: | ||
| Py_DECREF(func); | ||
| return NULL; | ||
| } | ||
|
|
||
| static int | ||
|
|
@@ -6223,7 +6181,7 @@ slot_tp_repr(PyObject *self) | |
| _Py_IDENTIFIER(__repr__); | ||
| int unbound; | ||
|
|
||
| func = lookup_method(self, &PyId___repr__, &unbound); | ||
| func = lookup_maybe_method(self, &PyId___repr__, &unbound); | ||
| if (func != NULL) { | ||
| res = call_unbound_noarg(unbound, func, self); | ||
| Py_DECREF(func); | ||
|
|
@@ -6243,7 +6201,7 @@ slot_tp_hash(PyObject *self) | |
| Py_ssize_t h; | ||
| int unbound; | ||
|
|
||
| func = lookup_method(self, &PyId___hash__, &unbound); | ||
| func = lookup_maybe_method(self, &PyId___hash__, &unbound); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok: Error handled below by PyObject_HashNotImplemented(). |
||
|
|
||
| if (func == Py_None) { | ||
| Py_DECREF(func); | ||
|
|
@@ -6422,7 +6380,7 @@ slot_tp_richcompare(PyObject *self, PyObject *other, int op) | |
| int unbound; | ||
| PyObject *func, *res; | ||
|
|
||
| func = lookup_method(self, &name_op[op], &unbound); | ||
| func = lookup_maybe_method(self, &name_op[op], &unbound); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok: exception ignored, PyErr_Clear(). |
||
| if (func == NULL) { | ||
| PyErr_Clear(); | ||
| Py_RETURN_NOTIMPLEMENTED; | ||
|
|
@@ -6441,7 +6399,7 @@ slot_tp_iter(PyObject *self) | |
| PyObject *func, *res; | ||
| _Py_IDENTIFIER(__iter__); | ||
|
|
||
| func = lookup_method(self, &PyId___iter__, &unbound); | ||
| func = lookup_maybe_method(self, &PyId___iter__, &unbound); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok: exception replaced below. |
||
| if (func == Py_None) { | ||
| Py_DECREF(func); | ||
| PyErr_Format(PyExc_TypeError, | ||
|
|
@@ -6457,7 +6415,7 @@ slot_tp_iter(PyObject *self) | |
| } | ||
|
|
||
| PyErr_Clear(); | ||
| func = lookup_method(self, &PyId___getitem__, &unbound); | ||
| func = lookup_maybe_method(self, &PyId___getitem__, &unbound); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok: exception replaced below. |
||
| if (func == NULL) { | ||
| PyErr_Format(PyExc_TypeError, | ||
| "'%.200s' object is not iterable", | ||
|
|
@@ -6597,7 +6555,7 @@ slot_am_await(PyObject *self) | |
| PyObject *func, *res; | ||
| _Py_IDENTIFIER(__await__); | ||
|
|
||
| func = lookup_method(self, &PyId___await__, &unbound); | ||
| func = lookup_maybe_method(self, &PyId___await__, &unbound); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok: exception replaced below. |
||
| if (func != NULL) { | ||
| res = call_unbound_noarg(unbound, func, self); | ||
| Py_DECREF(func); | ||
|
|
@@ -6616,7 +6574,7 @@ slot_am_aiter(PyObject *self) | |
| PyObject *func, *res; | ||
| _Py_IDENTIFIER(__aiter__); | ||
|
|
||
| func = lookup_method(self, &PyId___aiter__, &unbound); | ||
| func = lookup_maybe_method(self, &PyId___aiter__, &unbound); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok: exception replaced below. |
||
| if (func != NULL) { | ||
| res = call_unbound_noarg(unbound, func, self); | ||
| Py_DECREF(func); | ||
|
|
@@ -6635,7 +6593,7 @@ slot_am_anext(PyObject *self) | |
| PyObject *func, *res; | ||
| _Py_IDENTIFIER(__anext__); | ||
|
|
||
| func = lookup_method(self, &PyId___anext__, &unbound); | ||
| func = lookup_maybe_method(self, &PyId___anext__, &unbound); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok: exception replaced below. |
||
| if (func != NULL) { | ||
| res = call_unbound_noarg(unbound, func, self); | ||
| Py_DECREF(func); | ||
|
|
@@ -7182,7 +7140,7 @@ set_names(PyTypeObject *type) | |
| return -1; | ||
|
|
||
| while (PyDict_Next(names_to_set, &i, &key, &value)) { | ||
| set_name = lookup_maybe(value, &PyId___set_name__); | ||
| set_name = _PyObject_LookupSpecial(value, &PyId___set_name__); | ||
| if (set_name != NULL) { | ||
| tmp = PyObject_CallFunctionObjArgs(set_name, type, key, NULL); | ||
| Py_DECREF(set_name); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok: exception ignored using PyErr_Clear().