aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects/object.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/object.c')
-rw-r--r--Objects/object.c135
1 files changed, 111 insertions, 24 deletions
diff --git a/Objects/object.c b/Objects/object.c
index 723b0427e69..9fe61ba7f15 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1664,6 +1664,116 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
return 0;
}
+int
+_PyObject_GetMethodStackRef(PyThreadState *ts, PyObject *obj,
+ PyObject *name, _PyStackRef *method)
+{
+ int meth_found = 0;
+
+ assert(PyStackRef_IsNull(*method));
+
+ PyTypeObject *tp = Py_TYPE(obj);
+ if (!_PyType_IsReady(tp)) {
+ if (PyType_Ready(tp) < 0) {
+ return 0;
+ }
+ }
+
+ if (tp->tp_getattro != PyObject_GenericGetAttr || !PyUnicode_CheckExact(name)) {
+ PyObject *res = PyObject_GetAttr(obj, name);
+ if (res != NULL) {
+ *method = PyStackRef_FromPyObjectSteal(res);
+ }
+ return 0;
+ }
+
+ _PyType_LookupStackRefAndVersion(tp, name, method);
+ PyObject *descr = PyStackRef_AsPyObjectBorrow(*method);
+ descrgetfunc f = NULL;
+ if (descr != NULL) {
+ if (_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
+ meth_found = 1;
+ }
+ else {
+ f = Py_TYPE(descr)->tp_descr_get;
+ if (f != NULL && PyDescr_IsData(descr)) {
+ PyObject *value = f(descr, obj, (PyObject *)Py_TYPE(obj));
+ PyStackRef_CLEAR(*method);
+ if (value != NULL) {
+ *method = PyStackRef_FromPyObjectSteal(value);
+ }
+ return 0;
+ }
+ }
+ }
+ PyObject *dict, *attr;
+ if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) &&
+ _PyObject_TryGetInstanceAttribute(obj, name, &attr)) {
+ if (attr != NULL) {
+ PyStackRef_CLEAR(*method);
+ *method = PyStackRef_FromPyObjectSteal(attr);
+ return 0;
+ }
+ dict = NULL;
+ }
+ else if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) {
+ dict = (PyObject *)_PyObject_GetManagedDict(obj);
+ }
+ else {
+ PyObject **dictptr = _PyObject_ComputedDictPointer(obj);
+ if (dictptr != NULL) {
+ dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*dictptr);
+ }
+ else {
+ dict = NULL;
+ }
+ }
+ if (dict != NULL) {
+ // TODO: use _Py_dict_lookup_threadsafe_stackref
+ Py_INCREF(dict);
+ PyObject *value;
+ if (PyDict_GetItemRef(dict, name, &value) != 0) {
+ // found or error
+ Py_DECREF(dict);
+ PyStackRef_CLEAR(*method);
+ if (value != NULL) {
+ *method = PyStackRef_FromPyObjectSteal(value);
+ }
+ return 0;
+ }
+ // not found
+ Py_DECREF(dict);
+ }
+
+ if (meth_found) {
+ assert(!PyStackRef_IsNull(*method));
+ return 1;
+ }
+
+ if (f != NULL) {
+ PyObject *value = f(descr, obj, (PyObject *)Py_TYPE(obj));
+ PyStackRef_CLEAR(*method);
+ if (value) {
+ *method = PyStackRef_FromPyObjectSteal(value);
+ }
+ return 0;
+ }
+
+ if (descr != NULL) {
+ assert(!PyStackRef_IsNull(*method));
+ return 0;
+ }
+
+ PyErr_Format(PyExc_AttributeError,
+ "'%.100s' object has no attribute '%U'",
+ tp->tp_name, name);
+
+ _PyObject_SetAttributeErrorContext(obj, name);
+ assert(PyStackRef_IsNull(*method));
+ return 0;
+}
+
+
/* Generic GetAttr functions - put these in your tp_[gs]etattro slot. */
PyObject *
@@ -1906,34 +2016,11 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
int
PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)
{
- PyObject **dictptr = _PyObject_GetDictPtr(obj);
- if (dictptr == NULL) {
- if (_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_INLINE_VALUES) &&
- _PyObject_GetManagedDict(obj) == NULL
- ) {
- /* Was unable to convert to dict */
- PyErr_NoMemory();
- }
- else {
- PyErr_SetString(PyExc_AttributeError,
- "This object has no __dict__");
- }
- return -1;
- }
if (value == NULL) {
PyErr_SetString(PyExc_TypeError, "cannot delete __dict__");
return -1;
}
- if (!PyDict_Check(value)) {
- PyErr_Format(PyExc_TypeError,
- "__dict__ must be set to a dictionary, "
- "not a '%.200s'", Py_TYPE(value)->tp_name);
- return -1;
- }
- Py_BEGIN_CRITICAL_SECTION(obj);
- Py_XSETREF(*dictptr, Py_NewRef(value));
- Py_END_CRITICAL_SECTION();
- return 0;
+ return _PyObject_SetDict(obj, value);
}