diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 224fe6199f..47bf6198b1 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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; @@ -1435,7 +1429,7 @@ lookup_maybe(PyObject *self, _Py_Identifier *attrid) return res; } -static PyObject * +Py_LOCAL_INLINE(PyObject *) lookup_maybe_method(PyObject *self, _Py_Identifier *attrid, int *unbound) { PyObject *res = _PyType_LookupId(Py_TYPE(self), attrid); @@ -1461,7 +1455,7 @@ lookup_maybe_method(PyObject *self, _Py_Identifier *attrid, int *unbound) return res; } -static PyObject * +Py_LOCAL_INLINE(PyObject *) lookup_method(PyObject *self, _Py_Identifier *attrid, int *unbound) { PyObject *res = lookup_maybe_method(self, attrid, unbound); @@ -1471,75 +1465,103 @@ 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) +Py_LOCAL_INLINE(PyObject *) +call_unbound_noarg(int unbound, PyObject *func, PyObject *self) { if (unbound) { - return _PyObject_FastCall_Prepend(func, self, args, nargs); + PyObject *args[1] = {self}; + return _PyObject_FastCall(func, args, 1); } else { - return _PyObject_FastCall(func, args, nargs); + return _PyObject_CallNoArg(func); } } -static PyObject* -call_unbound_noarg(int unbound, PyObject *func, PyObject *self) +Py_LOCAL_INLINE(PyObject *) +call_unbound_onearg(int unbound, PyObject *func, PyObject *self, PyObject *arg) { if (unbound) { - PyObject *args[1] = {self}; - return _PyObject_FastCall(func, args, 1); + PyObject *args[2] = {self, arg}; + return _PyObject_FastCall(func, args, 2); } else { - return _PyObject_CallNoArg(func); + PyObject *args[1] = {arg}; + return _PyObject_FastCall(func, args, 1); } } -/* 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. */ +/* Variations of PyObject_CallMethodObjArgs that uses lookup_maybe_method() + instead of PyObject_GetAttrString(). */ static PyObject * -call_method(PyObject *obj, _Py_Identifier *name, - PyObject **args, Py_ssize_t nargs) +call_method_noarg(PyObject *self, _Py_Identifier *name) { int unbound; PyObject *func, *retval; - func = lookup_maybe_method(obj, name, &unbound); - if (func == NULL) { - if (!PyErr_Occurred()) - PyErr_SetObject(PyExc_AttributeError, name->object); + func = lookup_method(self, name, &unbound); + if (func == NULL) + return NULL; + + retval = call_unbound_noarg(unbound, func, self); + Py_DECREF(func); + return retval; +} + +static PyObject * +call_method_onearg(PyObject *self, _Py_Identifier *name, PyObject *arg) +{ + int unbound; + PyObject *func, *retval; + + func = lookup_method(self, name, &unbound); + if (func == NULL) return NULL; - } - retval = call_unbound(unbound, func, obj, args, nargs); + retval = call_unbound_onearg(unbound, func, self, arg); Py_DECREF(func); return retval; } -/* Clone of call_method() that returns NotImplemented when the lookup fails. */ +static PyObject * +call_method_twoargs(PyObject *self, _Py_Identifier *name, PyObject *arg1, + PyObject *arg2) +{ + int unbound; + PyObject *func, *retval; + + func = lookup_method(self, name, &unbound); + if (func == NULL) + return NULL; + + if (unbound) { + PyObject *args[3] = {self, arg1, arg2}; + retval = _PyObject_FastCall(func, args, 3); + } + else { + PyObject *args[2] = {arg1, arg2}; + retval = _PyObject_FastCall(func, args, 2); + } + Py_DECREF(func); + return retval; +} + +/* Clone of call_method_onearg() that returns NotImplemented when the + lookup fails. */ static PyObject * -call_maybe(PyObject *obj, _Py_Identifier *name, - PyObject **args, Py_ssize_t nargs) +call_maybe(PyObject *self, _Py_Identifier *name, PyObject *arg) { int unbound; PyObject *func, *retval; - func = lookup_maybe_method(obj, name, &unbound); + func = lookup_maybe_method(self, name, &unbound); if (func == NULL) { if (!PyErr_Occurred()) Py_RETURN_NOTIMPLEMENTED; return NULL; } - retval = call_unbound(unbound, func, obj, args, nargs); + retval = call_unbound_onearg(unbound, func, self, arg); Py_DECREF(func); return retval; } @@ -1900,13 +1922,7 @@ mro_invoke(PyTypeObject *type) if (custom) { _Py_IDENTIFIER(mro); - int unbound; - PyObject *mro_meth = lookup_method((PyObject *)type, &PyId_mro, - &unbound); - if (mro_meth == NULL) - return NULL; - mro_result = call_unbound_noarg(unbound, mro_meth, (PyObject *)type); - Py_DECREF(mro_meth); + mro_result = call_method_noarg((PyObject *)type, &PyId_mro); } else { mro_result = mro_implementation(type); @@ -5846,16 +5862,15 @@ static PyObject * \ FUNCNAME(PyObject *self) \ { \ _Py_static_string(id, OPSTR); \ - return call_method(self, &id, NULL, 0); \ + return call_method_noarg(self, &id); \ } #define SLOT1(FUNCNAME, OPSTR, ARG1TYPE) \ static PyObject * \ FUNCNAME(PyObject *self, ARG1TYPE arg1) \ { \ - PyObject* stack[1] = {arg1}; \ _Py_static_string(id, OPSTR); \ - return call_method(self, &id, stack, 1); \ + return call_method_onearg(self, &id, arg1); \ } /* Boolean helper for SLOT1BINFULL(). @@ -5897,7 +5912,6 @@ method_is_overloaded(PyObject *left, PyObject *right, struct _Py_Identifier *nam static PyObject * \ FUNCNAME(PyObject *self, PyObject *other) \ { \ - PyObject* stack[1]; \ _Py_static_string(op_id, OPSTR); \ _Py_static_string(rop_id, ROPSTR); \ int do_other = Py_TYPE(self) != Py_TYPE(other) && \ @@ -5909,23 +5923,20 @@ FUNCNAME(PyObject *self, PyObject *other) \ if (do_other && \ PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self)) && \ method_is_overloaded(self, other, &rop_id)) { \ - stack[0] = self; \ - r = call_maybe(other, &rop_id, stack, 1); \ + r = call_maybe(other, &rop_id, self); \ if (r != Py_NotImplemented) \ return r; \ Py_DECREF(r); \ do_other = 0; \ } \ - stack[0] = other; \ - r = call_maybe(self, &op_id, stack, 1); \ + r = call_maybe(self, &op_id, other); \ if (r != Py_NotImplemented || \ Py_TYPE(other) == Py_TYPE(self)) \ return r; \ Py_DECREF(r); \ } \ if (do_other) { \ - stack[0] = self; \ - return call_maybe(other, &rop_id, stack, 1); \ + return call_maybe(other, &rop_id, self); \ } \ Py_RETURN_NOTIMPLEMENTED; \ } @@ -5936,7 +5947,7 @@ FUNCNAME(PyObject *self, PyObject *other) \ static Py_ssize_t slot_sq_length(PyObject *self) { - PyObject *res = call_method(self, &PyId___len__, NULL, 0); + PyObject *res = call_method_noarg(self, &PyId___len__); Py_ssize_t len; if (res == NULL) @@ -6004,7 +6015,6 @@ error: static int slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value) { - PyObject *stack[2]; PyObject *res; PyObject *index_obj; @@ -6013,13 +6023,11 @@ slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value) return -1; } - stack[0] = index_obj; if (value == NULL) { - res = call_method(self, &PyId___delitem__, stack, 1); + res = call_method_onearg(self, &PyId___delitem__, index_obj); } else { - stack[1] = value; - res = call_method(self, &PyId___setitem__, stack, 2); + res = call_method_twoargs(self, &PyId___setitem__, index_obj, value); } Py_DECREF(index_obj); @@ -6046,8 +6054,7 @@ slot_sq_contains(PyObject *self, PyObject *value) return -1; } if (func != NULL) { - PyObject *args[1] = {value}; - res = call_unbound(unbound, func, self, args, 1); + res = call_unbound_onearg(unbound, func, self, value); Py_DECREF(func); if (res != NULL) { result = PyObject_IsTrue(res); @@ -6069,16 +6076,13 @@ SLOT1(slot_mp_subscript, "__getitem__", PyObject *) static int slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value) { - PyObject *stack[2]; PyObject *res; - stack[0] = key; if (value == NULL) { - res = call_method(self, &PyId___delitem__, stack, 1); + res = call_method_onearg(self, &PyId___delitem__, key); } else { - stack[1] = value; - res = call_method(self, &PyId___setitem__, stack, 2); + res = call_method_twoargs(self, &PyId___setitem__, key, value); } if (res == NULL) @@ -6111,8 +6115,7 @@ slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus) slot_nb_power, so check before calling self.__pow__. */ if (Py_TYPE(self)->tp_as_number != NULL && Py_TYPE(self)->tp_as_number->nb_power == slot_nb_power) { - PyObject* stack[2] = {other, modulus}; - return call_method(self, &PyId___pow__, stack, 2); + return call_method_twoargs(self, &PyId___pow__, other, modulus); } Py_RETURN_NOTIMPLEMENTED; } @@ -6179,7 +6182,7 @@ static PyObject * slot_nb_index(PyObject *self) { _Py_IDENTIFIER(__index__); - return call_method(self, &PyId___index__, NULL, 0); + return call_method_noarg(self, &PyId___index__); } @@ -6201,9 +6204,8 @@ SLOT1(slot_nb_inplace_remainder, "__imod__", PyObject *) static PyObject * slot_nb_inplace_power(PyObject *self, PyObject * arg1, PyObject *arg2) { - PyObject *stack[1] = {arg1}; _Py_IDENTIFIER(__ipow__); - return call_method(self, &PyId___ipow__, stack, 1); + return call_method_onearg(self, &PyId___ipow__, arg1); } SLOT1(slot_nb_inplace_lshift, "__ilshift__", PyObject *) SLOT1(slot_nb_inplace_rshift, "__irshift__", PyObject *) @@ -6223,7 +6225,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 +6245,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); if (func == Py_None) { Py_DECREF(func); @@ -6251,6 +6253,7 @@ slot_tp_hash(PyObject *self) } if (func == NULL) { + PyErr_Clear(); return PyObject_HashNotImplemented(self); } @@ -6320,8 +6323,7 @@ slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds) static PyObject * slot_tp_getattro(PyObject *self, PyObject *name) { - PyObject *stack[1] = {name}; - return call_method(self, &PyId___getattribute__, stack, 1); + return call_method_onearg(self, &PyId___getattribute__, name); } static PyObject * @@ -6388,18 +6390,15 @@ slot_tp_getattr_hook(PyObject *self, PyObject *name) static int slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value) { - PyObject *stack[2]; PyObject *res; _Py_IDENTIFIER(__delattr__); _Py_IDENTIFIER(__setattr__); - stack[0] = name; if (value == NULL) { - res = call_method(self, &PyId___delattr__, stack, 1); + res = call_method_onearg(self, &PyId___delattr__, name); } else { - stack[1] = value; - res = call_method(self, &PyId___setattr__, stack, 2); + res = call_method_twoargs(self, &PyId___setattr__, name, value); } if (res == NULL) return -1; @@ -6422,14 +6421,13 @@ 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); if (func == NULL) { PyErr_Clear(); Py_RETURN_NOTIMPLEMENTED; } - PyObject *args[1] = {other}; - res = call_unbound(unbound, func, self, args, 1); + res = call_unbound_onearg(unbound, func, self, other); Py_DECREF(func); return res; } @@ -6441,7 +6439,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); if (func == Py_None) { Py_DECREF(func); PyErr_Format(PyExc_TypeError, @@ -6457,7 +6455,7 @@ slot_tp_iter(PyObject *self) } PyErr_Clear(); - func = lookup_method(self, &PyId___getitem__, &unbound); + func = lookup_maybe_method(self, &PyId___getitem__, &unbound); if (func == NULL) { PyErr_Format(PyExc_TypeError, "'%.200s' object is not iterable", @@ -6472,7 +6470,7 @@ static PyObject * slot_tp_iternext(PyObject *self) { _Py_IDENTIFIER(__next__); - return call_method(self, &PyId___next__, NULL, 0); + return call_method_noarg(self, &PyId___next__); } static PyObject * @@ -6500,18 +6498,15 @@ slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type) static int slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value) { - PyObject* stack[2]; PyObject *res; _Py_IDENTIFIER(__delete__); _Py_IDENTIFIER(__set__); - stack[0] = target; if (value == NULL) { - res = call_method(self, &PyId___delete__, stack, 1); + res = call_method_onearg(self, &PyId___delete__, target); } else { - stack[1] = value; - res = call_method(self, &PyId___set__, stack, 2); + res = call_method_twoargs(self, &PyId___set__, target, value); } if (res == NULL) return -1; @@ -6597,7 +6592,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); if (func != NULL) { res = call_unbound_noarg(unbound, func, self); Py_DECREF(func); @@ -6616,7 +6611,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); if (func != NULL) { res = call_unbound_noarg(unbound, func, self); Py_DECREF(func); @@ -6635,7 +6630,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); if (func != NULL) { res = call_unbound_noarg(unbound, func, self); Py_DECREF(func); @@ -7182,7 +7177,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);