17db96d56Sopenharmony_ci#include "Python.h"
27db96d56Sopenharmony_ci#include "pycore_object.h"        // _PyObject_GET_WEAKREFS_LISTPTR()
37db96d56Sopenharmony_ci#include "structmember.h"         // PyMemberDef
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ci#define GET_WEAKREFS_LISTPTR(o) \
77db96d56Sopenharmony_ci        ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o))
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ciPy_ssize_t
117db96d56Sopenharmony_ci_PyWeakref_GetWeakrefCount(PyWeakReference *head)
127db96d56Sopenharmony_ci{
137db96d56Sopenharmony_ci    Py_ssize_t count = 0;
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci    while (head != NULL) {
167db96d56Sopenharmony_ci        ++count;
177db96d56Sopenharmony_ci        head = head->wr_next;
187db96d56Sopenharmony_ci    }
197db96d56Sopenharmony_ci    return count;
207db96d56Sopenharmony_ci}
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_cistatic PyObject *weakref_vectorcall(PyWeakReference *self, PyObject *const *args, size_t nargsf, PyObject *kwnames);
237db96d56Sopenharmony_ci
247db96d56Sopenharmony_cistatic void
257db96d56Sopenharmony_ciinit_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
267db96d56Sopenharmony_ci{
277db96d56Sopenharmony_ci    self->hash = -1;
287db96d56Sopenharmony_ci    self->wr_object = ob;
297db96d56Sopenharmony_ci    self->wr_prev = NULL;
307db96d56Sopenharmony_ci    self->wr_next = NULL;
317db96d56Sopenharmony_ci    self->wr_callback = Py_XNewRef(callback);
327db96d56Sopenharmony_ci    self->vectorcall = (vectorcallfunc)weakref_vectorcall;
337db96d56Sopenharmony_ci}
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_cistatic PyWeakReference *
367db96d56Sopenharmony_cinew_weakref(PyObject *ob, PyObject *callback)
377db96d56Sopenharmony_ci{
387db96d56Sopenharmony_ci    PyWeakReference *result;
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ci    result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
417db96d56Sopenharmony_ci    if (result) {
427db96d56Sopenharmony_ci        init_weakref(result, ob, callback);
437db96d56Sopenharmony_ci        PyObject_GC_Track(result);
447db96d56Sopenharmony_ci    }
457db96d56Sopenharmony_ci    return result;
467db96d56Sopenharmony_ci}
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci/* This function clears the passed-in reference and removes it from the
507db96d56Sopenharmony_ci * list of weak references for the referent.  This is the only code that
517db96d56Sopenharmony_ci * removes an item from the doubly-linked list of weak references for an
527db96d56Sopenharmony_ci * object; it is also responsible for clearing the callback slot.
537db96d56Sopenharmony_ci */
547db96d56Sopenharmony_cistatic void
557db96d56Sopenharmony_ciclear_weakref(PyWeakReference *self)
567db96d56Sopenharmony_ci{
577db96d56Sopenharmony_ci    PyObject *callback = self->wr_callback;
587db96d56Sopenharmony_ci
597db96d56Sopenharmony_ci    if (self->wr_object != Py_None) {
607db96d56Sopenharmony_ci        PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci        if (*list == self)
637db96d56Sopenharmony_ci            /* If 'self' is the end of the list (and thus self->wr_next == NULL)
647db96d56Sopenharmony_ci               then the weakref list itself (and thus the value of *list) will
657db96d56Sopenharmony_ci               end up being set to NULL. */
667db96d56Sopenharmony_ci            *list = self->wr_next;
677db96d56Sopenharmony_ci        self->wr_object = Py_None;
687db96d56Sopenharmony_ci        if (self->wr_prev != NULL)
697db96d56Sopenharmony_ci            self->wr_prev->wr_next = self->wr_next;
707db96d56Sopenharmony_ci        if (self->wr_next != NULL)
717db96d56Sopenharmony_ci            self->wr_next->wr_prev = self->wr_prev;
727db96d56Sopenharmony_ci        self->wr_prev = NULL;
737db96d56Sopenharmony_ci        self->wr_next = NULL;
747db96d56Sopenharmony_ci    }
757db96d56Sopenharmony_ci    if (callback != NULL) {
767db96d56Sopenharmony_ci        Py_DECREF(callback);
777db96d56Sopenharmony_ci        self->wr_callback = NULL;
787db96d56Sopenharmony_ci    }
797db96d56Sopenharmony_ci}
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
827db96d56Sopenharmony_ci * the callback intact and uncalled.  It must be possible to call self's
837db96d56Sopenharmony_ci * tp_dealloc() after calling this, so self has to be left in a sane enough
847db96d56Sopenharmony_ci * state for that to work.  We expect tp_dealloc to decref the callback
857db96d56Sopenharmony_ci * then.  The reason for not letting clear_weakref() decref the callback
867db96d56Sopenharmony_ci * right now is that if the callback goes away, that may in turn trigger
877db96d56Sopenharmony_ci * another callback (if a weak reference to the callback exists) -- running
887db96d56Sopenharmony_ci * arbitrary Python code in the middle of gc is a disaster.  The convolution
897db96d56Sopenharmony_ci * here allows gc to delay triggering such callbacks until the world is in
907db96d56Sopenharmony_ci * a sane state again.
917db96d56Sopenharmony_ci */
927db96d56Sopenharmony_civoid
937db96d56Sopenharmony_ci_PyWeakref_ClearRef(PyWeakReference *self)
947db96d56Sopenharmony_ci{
957db96d56Sopenharmony_ci    PyObject *callback;
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ci    assert(self != NULL);
987db96d56Sopenharmony_ci    assert(PyWeakref_Check(self));
997db96d56Sopenharmony_ci    /* Preserve and restore the callback around clear_weakref. */
1007db96d56Sopenharmony_ci    callback = self->wr_callback;
1017db96d56Sopenharmony_ci    self->wr_callback = NULL;
1027db96d56Sopenharmony_ci    clear_weakref(self);
1037db96d56Sopenharmony_ci    self->wr_callback = callback;
1047db96d56Sopenharmony_ci}
1057db96d56Sopenharmony_ci
1067db96d56Sopenharmony_cistatic void
1077db96d56Sopenharmony_ciweakref_dealloc(PyObject *self)
1087db96d56Sopenharmony_ci{
1097db96d56Sopenharmony_ci    PyObject_GC_UnTrack(self);
1107db96d56Sopenharmony_ci    clear_weakref((PyWeakReference *) self);
1117db96d56Sopenharmony_ci    Py_TYPE(self)->tp_free(self);
1127db96d56Sopenharmony_ci}
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_cistatic int
1167db96d56Sopenharmony_cigc_traverse(PyWeakReference *self, visitproc visit, void *arg)
1177db96d56Sopenharmony_ci{
1187db96d56Sopenharmony_ci    Py_VISIT(self->wr_callback);
1197db96d56Sopenharmony_ci    return 0;
1207db96d56Sopenharmony_ci}
1217db96d56Sopenharmony_ci
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_cistatic int
1247db96d56Sopenharmony_cigc_clear(PyWeakReference *self)
1257db96d56Sopenharmony_ci{
1267db96d56Sopenharmony_ci    clear_weakref(self);
1277db96d56Sopenharmony_ci    return 0;
1287db96d56Sopenharmony_ci}
1297db96d56Sopenharmony_ci
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_cistatic PyObject *
1327db96d56Sopenharmony_ciweakref_vectorcall(PyWeakReference *self, PyObject *const *args,
1337db96d56Sopenharmony_ci                   size_t nargsf, PyObject *kwnames)
1347db96d56Sopenharmony_ci{
1357db96d56Sopenharmony_ci    if (!_PyArg_NoKwnames("weakref", kwnames)) {
1367db96d56Sopenharmony_ci        return NULL;
1377db96d56Sopenharmony_ci    }
1387db96d56Sopenharmony_ci    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1397db96d56Sopenharmony_ci    if (!_PyArg_CheckPositional("weakref", nargs, 0, 0)) {
1407db96d56Sopenharmony_ci        return NULL;
1417db96d56Sopenharmony_ci    }
1427db96d56Sopenharmony_ci    return Py_NewRef(PyWeakref_GET_OBJECT(self));
1437db96d56Sopenharmony_ci}
1447db96d56Sopenharmony_ci
1457db96d56Sopenharmony_cistatic Py_hash_t
1467db96d56Sopenharmony_ciweakref_hash(PyWeakReference *self)
1477db96d56Sopenharmony_ci{
1487db96d56Sopenharmony_ci    if (self->hash != -1)
1497db96d56Sopenharmony_ci        return self->hash;
1507db96d56Sopenharmony_ci    PyObject* obj = PyWeakref_GET_OBJECT(self);
1517db96d56Sopenharmony_ci    if (obj == Py_None) {
1527db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError, "weak object has gone away");
1537db96d56Sopenharmony_ci        return -1;
1547db96d56Sopenharmony_ci    }
1557db96d56Sopenharmony_ci    Py_INCREF(obj);
1567db96d56Sopenharmony_ci    self->hash = PyObject_Hash(obj);
1577db96d56Sopenharmony_ci    Py_DECREF(obj);
1587db96d56Sopenharmony_ci    return self->hash;
1597db96d56Sopenharmony_ci}
1607db96d56Sopenharmony_ci
1617db96d56Sopenharmony_ci
1627db96d56Sopenharmony_cistatic PyObject *
1637db96d56Sopenharmony_ciweakref_repr(PyWeakReference *self)
1647db96d56Sopenharmony_ci{
1657db96d56Sopenharmony_ci    PyObject *name, *repr;
1667db96d56Sopenharmony_ci    PyObject* obj = PyWeakref_GET_OBJECT(self);
1677db96d56Sopenharmony_ci
1687db96d56Sopenharmony_ci    if (obj == Py_None) {
1697db96d56Sopenharmony_ci        return PyUnicode_FromFormat("<weakref at %p; dead>", self);
1707db96d56Sopenharmony_ci    }
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_ci    Py_INCREF(obj);
1737db96d56Sopenharmony_ci    name = _PyObject_LookupSpecial(obj, &_Py_ID(__name__));
1747db96d56Sopenharmony_ci    if (name == NULL || !PyUnicode_Check(name)) {
1757db96d56Sopenharmony_ci        repr = PyUnicode_FromFormat(
1767db96d56Sopenharmony_ci            "<weakref at %p; to '%s' at %p>",
1777db96d56Sopenharmony_ci            self,
1787db96d56Sopenharmony_ci            Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
1797db96d56Sopenharmony_ci            obj);
1807db96d56Sopenharmony_ci    }
1817db96d56Sopenharmony_ci    else {
1827db96d56Sopenharmony_ci        repr = PyUnicode_FromFormat(
1837db96d56Sopenharmony_ci            "<weakref at %p; to '%s' at %p (%U)>",
1847db96d56Sopenharmony_ci            self,
1857db96d56Sopenharmony_ci            Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
1867db96d56Sopenharmony_ci            obj,
1877db96d56Sopenharmony_ci            name);
1887db96d56Sopenharmony_ci    }
1897db96d56Sopenharmony_ci    Py_DECREF(obj);
1907db96d56Sopenharmony_ci    Py_XDECREF(name);
1917db96d56Sopenharmony_ci    return repr;
1927db96d56Sopenharmony_ci}
1937db96d56Sopenharmony_ci
1947db96d56Sopenharmony_ci/* Weak references only support equality, not ordering. Two weak references
1957db96d56Sopenharmony_ci   are equal if the underlying objects are equal. If the underlying object has
1967db96d56Sopenharmony_ci   gone away, they are equal if they are identical. */
1977db96d56Sopenharmony_ci
1987db96d56Sopenharmony_cistatic PyObject *
1997db96d56Sopenharmony_ciweakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
2007db96d56Sopenharmony_ci{
2017db96d56Sopenharmony_ci    if ((op != Py_EQ && op != Py_NE) ||
2027db96d56Sopenharmony_ci        !PyWeakref_Check(self) ||
2037db96d56Sopenharmony_ci        !PyWeakref_Check(other)) {
2047db96d56Sopenharmony_ci        Py_RETURN_NOTIMPLEMENTED;
2057db96d56Sopenharmony_ci    }
2067db96d56Sopenharmony_ci    if (PyWeakref_GET_OBJECT(self) == Py_None
2077db96d56Sopenharmony_ci        || PyWeakref_GET_OBJECT(other) == Py_None) {
2087db96d56Sopenharmony_ci        int res = (self == other);
2097db96d56Sopenharmony_ci        if (op == Py_NE)
2107db96d56Sopenharmony_ci            res = !res;
2117db96d56Sopenharmony_ci        if (res)
2127db96d56Sopenharmony_ci            Py_RETURN_TRUE;
2137db96d56Sopenharmony_ci        else
2147db96d56Sopenharmony_ci            Py_RETURN_FALSE;
2157db96d56Sopenharmony_ci    }
2167db96d56Sopenharmony_ci    PyObject* obj = PyWeakref_GET_OBJECT(self);
2177db96d56Sopenharmony_ci    PyObject* other_obj = PyWeakref_GET_OBJECT(other);
2187db96d56Sopenharmony_ci    Py_INCREF(obj);
2197db96d56Sopenharmony_ci    Py_INCREF(other_obj);
2207db96d56Sopenharmony_ci    PyObject* res = PyObject_RichCompare(obj, other_obj, op);
2217db96d56Sopenharmony_ci    Py_DECREF(obj);
2227db96d56Sopenharmony_ci    Py_DECREF(other_obj);
2237db96d56Sopenharmony_ci    return res;
2247db96d56Sopenharmony_ci}
2257db96d56Sopenharmony_ci
2267db96d56Sopenharmony_ci/* Given the head of an object's list of weak references, extract the
2277db96d56Sopenharmony_ci * two callback-less refs (ref and proxy).  Used to determine if the
2287db96d56Sopenharmony_ci * shared references exist and to determine the back link for newly
2297db96d56Sopenharmony_ci * inserted references.
2307db96d56Sopenharmony_ci */
2317db96d56Sopenharmony_cistatic void
2327db96d56Sopenharmony_ciget_basic_refs(PyWeakReference *head,
2337db96d56Sopenharmony_ci               PyWeakReference **refp, PyWeakReference **proxyp)
2347db96d56Sopenharmony_ci{
2357db96d56Sopenharmony_ci    *refp = NULL;
2367db96d56Sopenharmony_ci    *proxyp = NULL;
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci    if (head != NULL && head->wr_callback == NULL) {
2397db96d56Sopenharmony_ci        /* We need to be careful that the "basic refs" aren't
2407db96d56Sopenharmony_ci           subclasses of the main types.  That complicates this a
2417db96d56Sopenharmony_ci           little. */
2427db96d56Sopenharmony_ci        if (PyWeakref_CheckRefExact(head)) {
2437db96d56Sopenharmony_ci            *refp = head;
2447db96d56Sopenharmony_ci            head = head->wr_next;
2457db96d56Sopenharmony_ci        }
2467db96d56Sopenharmony_ci        if (head != NULL
2477db96d56Sopenharmony_ci            && head->wr_callback == NULL
2487db96d56Sopenharmony_ci            && PyWeakref_CheckProxy(head)) {
2497db96d56Sopenharmony_ci            *proxyp = head;
2507db96d56Sopenharmony_ci            /* head = head->wr_next; */
2517db96d56Sopenharmony_ci        }
2527db96d56Sopenharmony_ci    }
2537db96d56Sopenharmony_ci}
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci/* Insert 'newref' in the list after 'prev'.  Both must be non-NULL. */
2567db96d56Sopenharmony_cistatic void
2577db96d56Sopenharmony_ciinsert_after(PyWeakReference *newref, PyWeakReference *prev)
2587db96d56Sopenharmony_ci{
2597db96d56Sopenharmony_ci    newref->wr_prev = prev;
2607db96d56Sopenharmony_ci    newref->wr_next = prev->wr_next;
2617db96d56Sopenharmony_ci    if (prev->wr_next != NULL)
2627db96d56Sopenharmony_ci        prev->wr_next->wr_prev = newref;
2637db96d56Sopenharmony_ci    prev->wr_next = newref;
2647db96d56Sopenharmony_ci}
2657db96d56Sopenharmony_ci
2667db96d56Sopenharmony_ci/* Insert 'newref' at the head of the list; 'list' points to the variable
2677db96d56Sopenharmony_ci * that stores the head.
2687db96d56Sopenharmony_ci */
2697db96d56Sopenharmony_cistatic void
2707db96d56Sopenharmony_ciinsert_head(PyWeakReference *newref, PyWeakReference **list)
2717db96d56Sopenharmony_ci{
2727db96d56Sopenharmony_ci    PyWeakReference *next = *list;
2737db96d56Sopenharmony_ci
2747db96d56Sopenharmony_ci    newref->wr_prev = NULL;
2757db96d56Sopenharmony_ci    newref->wr_next = next;
2767db96d56Sopenharmony_ci    if (next != NULL)
2777db96d56Sopenharmony_ci        next->wr_prev = newref;
2787db96d56Sopenharmony_ci    *list = newref;
2797db96d56Sopenharmony_ci}
2807db96d56Sopenharmony_ci
2817db96d56Sopenharmony_cistatic int
2827db96d56Sopenharmony_ciparse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,
2837db96d56Sopenharmony_ci                        PyObject **obp, PyObject **callbackp)
2847db96d56Sopenharmony_ci{
2857db96d56Sopenharmony_ci    return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
2867db96d56Sopenharmony_ci}
2877db96d56Sopenharmony_ci
2887db96d56Sopenharmony_cistatic PyObject *
2897db96d56Sopenharmony_ciweakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2907db96d56Sopenharmony_ci{
2917db96d56Sopenharmony_ci    PyWeakReference *self = NULL;
2927db96d56Sopenharmony_ci    PyObject *ob, *callback = NULL;
2937db96d56Sopenharmony_ci
2947db96d56Sopenharmony_ci    if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
2957db96d56Sopenharmony_ci        PyWeakReference *ref, *proxy;
2967db96d56Sopenharmony_ci        PyWeakReference **list;
2977db96d56Sopenharmony_ci
2987db96d56Sopenharmony_ci        if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
2997db96d56Sopenharmony_ci            PyErr_Format(PyExc_TypeError,
3007db96d56Sopenharmony_ci                         "cannot create weak reference to '%s' object",
3017db96d56Sopenharmony_ci                         Py_TYPE(ob)->tp_name);
3027db96d56Sopenharmony_ci            return NULL;
3037db96d56Sopenharmony_ci        }
3047db96d56Sopenharmony_ci        if (callback == Py_None)
3057db96d56Sopenharmony_ci            callback = NULL;
3067db96d56Sopenharmony_ci        list = GET_WEAKREFS_LISTPTR(ob);
3077db96d56Sopenharmony_ci        get_basic_refs(*list, &ref, &proxy);
3087db96d56Sopenharmony_ci        if (callback == NULL && type == &_PyWeakref_RefType) {
3097db96d56Sopenharmony_ci            if (ref != NULL) {
3107db96d56Sopenharmony_ci                /* We can re-use an existing reference. */
3117db96d56Sopenharmony_ci                Py_INCREF(ref);
3127db96d56Sopenharmony_ci                return (PyObject *)ref;
3137db96d56Sopenharmony_ci            }
3147db96d56Sopenharmony_ci        }
3157db96d56Sopenharmony_ci        /* We have to create a new reference. */
3167db96d56Sopenharmony_ci        /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
3177db96d56Sopenharmony_ci           list on ob can be mutated.  This means that the ref and
3187db96d56Sopenharmony_ci           proxy pointers we got back earlier may have been collected,
3197db96d56Sopenharmony_ci           so we need to compute these values again before we use
3207db96d56Sopenharmony_ci           them. */
3217db96d56Sopenharmony_ci        self = (PyWeakReference *) (type->tp_alloc(type, 0));
3227db96d56Sopenharmony_ci        if (self != NULL) {
3237db96d56Sopenharmony_ci            init_weakref(self, ob, callback);
3247db96d56Sopenharmony_ci            if (callback == NULL && type == &_PyWeakref_RefType) {
3257db96d56Sopenharmony_ci                insert_head(self, list);
3267db96d56Sopenharmony_ci            }
3277db96d56Sopenharmony_ci            else {
3287db96d56Sopenharmony_ci                PyWeakReference *prev;
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ci                get_basic_refs(*list, &ref, &proxy);
3317db96d56Sopenharmony_ci                prev = (proxy == NULL) ? ref : proxy;
3327db96d56Sopenharmony_ci                if (prev == NULL)
3337db96d56Sopenharmony_ci                    insert_head(self, list);
3347db96d56Sopenharmony_ci                else
3357db96d56Sopenharmony_ci                    insert_after(self, prev);
3367db96d56Sopenharmony_ci            }
3377db96d56Sopenharmony_ci        }
3387db96d56Sopenharmony_ci    }
3397db96d56Sopenharmony_ci    return (PyObject *)self;
3407db96d56Sopenharmony_ci}
3417db96d56Sopenharmony_ci
3427db96d56Sopenharmony_cistatic int
3437db96d56Sopenharmony_ciweakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
3447db96d56Sopenharmony_ci{
3457db96d56Sopenharmony_ci    PyObject *tmp;
3467db96d56Sopenharmony_ci
3477db96d56Sopenharmony_ci    if (!_PyArg_NoKeywords("ref", kwargs))
3487db96d56Sopenharmony_ci        return -1;
3497db96d56Sopenharmony_ci
3507db96d56Sopenharmony_ci    if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
3517db96d56Sopenharmony_ci        return 0;
3527db96d56Sopenharmony_ci    else
3537db96d56Sopenharmony_ci        return -1;
3547db96d56Sopenharmony_ci}
3557db96d56Sopenharmony_ci
3567db96d56Sopenharmony_ci
3577db96d56Sopenharmony_cistatic PyMemberDef weakref_members[] = {
3587db96d56Sopenharmony_ci    {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY},
3597db96d56Sopenharmony_ci    {NULL} /* Sentinel */
3607db96d56Sopenharmony_ci};
3617db96d56Sopenharmony_ci
3627db96d56Sopenharmony_cistatic PyMethodDef weakref_methods[] = {
3637db96d56Sopenharmony_ci    {"__class_getitem__",    Py_GenericAlias,
3647db96d56Sopenharmony_ci    METH_O|METH_CLASS,       PyDoc_STR("See PEP 585")},
3657db96d56Sopenharmony_ci    {NULL} /* Sentinel */
3667db96d56Sopenharmony_ci};
3677db96d56Sopenharmony_ci
3687db96d56Sopenharmony_ciPyTypeObject
3697db96d56Sopenharmony_ci_PyWeakref_RefType = {
3707db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
3717db96d56Sopenharmony_ci    .tp_name = "weakref.ReferenceType",
3727db96d56Sopenharmony_ci    .tp_basicsize = sizeof(PyWeakReference),
3737db96d56Sopenharmony_ci    .tp_dealloc = weakref_dealloc,
3747db96d56Sopenharmony_ci    .tp_vectorcall_offset = offsetof(PyWeakReference, vectorcall),
3757db96d56Sopenharmony_ci    .tp_call = PyVectorcall_Call,
3767db96d56Sopenharmony_ci    .tp_repr = (reprfunc)weakref_repr,
3777db96d56Sopenharmony_ci    .tp_hash = (hashfunc)weakref_hash,
3787db96d56Sopenharmony_ci    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
3797db96d56Sopenharmony_ci                Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_BASETYPE,
3807db96d56Sopenharmony_ci    .tp_traverse = (traverseproc)gc_traverse,
3817db96d56Sopenharmony_ci    .tp_clear = (inquiry)gc_clear,
3827db96d56Sopenharmony_ci    .tp_richcompare = (richcmpfunc)weakref_richcompare,
3837db96d56Sopenharmony_ci    .tp_methods = weakref_methods,
3847db96d56Sopenharmony_ci    .tp_members = weakref_members,
3857db96d56Sopenharmony_ci    .tp_init = weakref___init__,
3867db96d56Sopenharmony_ci    .tp_alloc = PyType_GenericAlloc,
3877db96d56Sopenharmony_ci    .tp_new = weakref___new__,
3887db96d56Sopenharmony_ci    .tp_free = PyObject_GC_Del,
3897db96d56Sopenharmony_ci};
3907db96d56Sopenharmony_ci
3917db96d56Sopenharmony_ci
3927db96d56Sopenharmony_cistatic int
3937db96d56Sopenharmony_ciproxy_checkref(PyWeakReference *proxy)
3947db96d56Sopenharmony_ci{
3957db96d56Sopenharmony_ci    if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
3967db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ReferenceError,
3977db96d56Sopenharmony_ci                        "weakly-referenced object no longer exists");
3987db96d56Sopenharmony_ci        return 0;
3997db96d56Sopenharmony_ci    }
4007db96d56Sopenharmony_ci    return 1;
4017db96d56Sopenharmony_ci}
4027db96d56Sopenharmony_ci
4037db96d56Sopenharmony_ci
4047db96d56Sopenharmony_ci/* If a parameter is a proxy, check that it is still "live" and wrap it,
4057db96d56Sopenharmony_ci * replacing the original value with the raw object.  Raises ReferenceError
4067db96d56Sopenharmony_ci * if the param is a dead proxy.
4077db96d56Sopenharmony_ci */
4087db96d56Sopenharmony_ci#define UNWRAP(o) \
4097db96d56Sopenharmony_ci        if (PyWeakref_CheckProxy(o)) { \
4107db96d56Sopenharmony_ci            if (!proxy_checkref((PyWeakReference *)o)) \
4117db96d56Sopenharmony_ci                return NULL; \
4127db96d56Sopenharmony_ci            o = PyWeakref_GET_OBJECT(o); \
4137db96d56Sopenharmony_ci        }
4147db96d56Sopenharmony_ci
4157db96d56Sopenharmony_ci#define WRAP_UNARY(method, generic) \
4167db96d56Sopenharmony_ci    static PyObject * \
4177db96d56Sopenharmony_ci    method(PyObject *proxy) { \
4187db96d56Sopenharmony_ci        UNWRAP(proxy); \
4197db96d56Sopenharmony_ci        Py_INCREF(proxy); \
4207db96d56Sopenharmony_ci        PyObject* res = generic(proxy); \
4217db96d56Sopenharmony_ci        Py_DECREF(proxy); \
4227db96d56Sopenharmony_ci        return res; \
4237db96d56Sopenharmony_ci    }
4247db96d56Sopenharmony_ci
4257db96d56Sopenharmony_ci#define WRAP_BINARY(method, generic) \
4267db96d56Sopenharmony_ci    static PyObject * \
4277db96d56Sopenharmony_ci    method(PyObject *x, PyObject *y) { \
4287db96d56Sopenharmony_ci        UNWRAP(x); \
4297db96d56Sopenharmony_ci        UNWRAP(y); \
4307db96d56Sopenharmony_ci        Py_INCREF(x); \
4317db96d56Sopenharmony_ci        Py_INCREF(y); \
4327db96d56Sopenharmony_ci        PyObject* res = generic(x, y); \
4337db96d56Sopenharmony_ci        Py_DECREF(x); \
4347db96d56Sopenharmony_ci        Py_DECREF(y); \
4357db96d56Sopenharmony_ci        return res; \
4367db96d56Sopenharmony_ci    }
4377db96d56Sopenharmony_ci
4387db96d56Sopenharmony_ci/* Note that the third arg needs to be checked for NULL since the tp_call
4397db96d56Sopenharmony_ci * slot can receive NULL for this arg.
4407db96d56Sopenharmony_ci */
4417db96d56Sopenharmony_ci#define WRAP_TERNARY(method, generic) \
4427db96d56Sopenharmony_ci    static PyObject * \
4437db96d56Sopenharmony_ci    method(PyObject *proxy, PyObject *v, PyObject *w) { \
4447db96d56Sopenharmony_ci        UNWRAP(proxy); \
4457db96d56Sopenharmony_ci        UNWRAP(v); \
4467db96d56Sopenharmony_ci        if (w != NULL) \
4477db96d56Sopenharmony_ci            UNWRAP(w); \
4487db96d56Sopenharmony_ci        Py_INCREF(proxy); \
4497db96d56Sopenharmony_ci        Py_INCREF(v); \
4507db96d56Sopenharmony_ci        Py_XINCREF(w); \
4517db96d56Sopenharmony_ci        PyObject* res = generic(proxy, v, w); \
4527db96d56Sopenharmony_ci        Py_DECREF(proxy); \
4537db96d56Sopenharmony_ci        Py_DECREF(v); \
4547db96d56Sopenharmony_ci        Py_XDECREF(w); \
4557db96d56Sopenharmony_ci        return res; \
4567db96d56Sopenharmony_ci    }
4577db96d56Sopenharmony_ci
4587db96d56Sopenharmony_ci#define WRAP_METHOD(method, SPECIAL) \
4597db96d56Sopenharmony_ci    static PyObject * \
4607db96d56Sopenharmony_ci    method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
4617db96d56Sopenharmony_ci            UNWRAP(proxy); \
4627db96d56Sopenharmony_ci            Py_INCREF(proxy); \
4637db96d56Sopenharmony_ci            PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
4647db96d56Sopenharmony_ci            Py_DECREF(proxy); \
4657db96d56Sopenharmony_ci            return res; \
4667db96d56Sopenharmony_ci        }
4677db96d56Sopenharmony_ci
4687db96d56Sopenharmony_ci
4697db96d56Sopenharmony_ci/* direct slots */
4707db96d56Sopenharmony_ci
4717db96d56Sopenharmony_ciWRAP_BINARY(proxy_getattr, PyObject_GetAttr)
4727db96d56Sopenharmony_ciWRAP_UNARY(proxy_str, PyObject_Str)
4737db96d56Sopenharmony_ciWRAP_TERNARY(proxy_call, PyObject_Call)
4747db96d56Sopenharmony_ci
4757db96d56Sopenharmony_cistatic PyObject *
4767db96d56Sopenharmony_ciproxy_repr(PyWeakReference *proxy)
4777db96d56Sopenharmony_ci{
4787db96d56Sopenharmony_ci    return PyUnicode_FromFormat(
4797db96d56Sopenharmony_ci        "<weakproxy at %p to %s at %p>",
4807db96d56Sopenharmony_ci        proxy,
4817db96d56Sopenharmony_ci        Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
4827db96d56Sopenharmony_ci        PyWeakref_GET_OBJECT(proxy));
4837db96d56Sopenharmony_ci}
4847db96d56Sopenharmony_ci
4857db96d56Sopenharmony_ci
4867db96d56Sopenharmony_cistatic int
4877db96d56Sopenharmony_ciproxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
4887db96d56Sopenharmony_ci{
4897db96d56Sopenharmony_ci    if (!proxy_checkref(proxy))
4907db96d56Sopenharmony_ci        return -1;
4917db96d56Sopenharmony_ci    PyObject *obj = PyWeakref_GET_OBJECT(proxy);
4927db96d56Sopenharmony_ci    Py_INCREF(obj);
4937db96d56Sopenharmony_ci    int res = PyObject_SetAttr(obj, name, value);
4947db96d56Sopenharmony_ci    Py_DECREF(obj);
4957db96d56Sopenharmony_ci    return res;
4967db96d56Sopenharmony_ci}
4977db96d56Sopenharmony_ci
4987db96d56Sopenharmony_cistatic PyObject *
4997db96d56Sopenharmony_ciproxy_richcompare(PyObject *proxy, PyObject *v, int op)
5007db96d56Sopenharmony_ci{
5017db96d56Sopenharmony_ci    UNWRAP(proxy);
5027db96d56Sopenharmony_ci    UNWRAP(v);
5037db96d56Sopenharmony_ci    return PyObject_RichCompare(proxy, v, op);
5047db96d56Sopenharmony_ci}
5057db96d56Sopenharmony_ci
5067db96d56Sopenharmony_ci/* number slots */
5077db96d56Sopenharmony_ciWRAP_BINARY(proxy_add, PyNumber_Add)
5087db96d56Sopenharmony_ciWRAP_BINARY(proxy_sub, PyNumber_Subtract)
5097db96d56Sopenharmony_ciWRAP_BINARY(proxy_mul, PyNumber_Multiply)
5107db96d56Sopenharmony_ciWRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
5117db96d56Sopenharmony_ciWRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
5127db96d56Sopenharmony_ciWRAP_BINARY(proxy_mod, PyNumber_Remainder)
5137db96d56Sopenharmony_ciWRAP_BINARY(proxy_divmod, PyNumber_Divmod)
5147db96d56Sopenharmony_ciWRAP_TERNARY(proxy_pow, PyNumber_Power)
5157db96d56Sopenharmony_ciWRAP_UNARY(proxy_neg, PyNumber_Negative)
5167db96d56Sopenharmony_ciWRAP_UNARY(proxy_pos, PyNumber_Positive)
5177db96d56Sopenharmony_ciWRAP_UNARY(proxy_abs, PyNumber_Absolute)
5187db96d56Sopenharmony_ciWRAP_UNARY(proxy_invert, PyNumber_Invert)
5197db96d56Sopenharmony_ciWRAP_BINARY(proxy_lshift, PyNumber_Lshift)
5207db96d56Sopenharmony_ciWRAP_BINARY(proxy_rshift, PyNumber_Rshift)
5217db96d56Sopenharmony_ciWRAP_BINARY(proxy_and, PyNumber_And)
5227db96d56Sopenharmony_ciWRAP_BINARY(proxy_xor, PyNumber_Xor)
5237db96d56Sopenharmony_ciWRAP_BINARY(proxy_or, PyNumber_Or)
5247db96d56Sopenharmony_ciWRAP_UNARY(proxy_int, PyNumber_Long)
5257db96d56Sopenharmony_ciWRAP_UNARY(proxy_float, PyNumber_Float)
5267db96d56Sopenharmony_ciWRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
5277db96d56Sopenharmony_ciWRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
5287db96d56Sopenharmony_ciWRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
5297db96d56Sopenharmony_ciWRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
5307db96d56Sopenharmony_ciWRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
5317db96d56Sopenharmony_ciWRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
5327db96d56Sopenharmony_ciWRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
5337db96d56Sopenharmony_ciWRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
5347db96d56Sopenharmony_ciWRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
5357db96d56Sopenharmony_ciWRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
5367db96d56Sopenharmony_ciWRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
5377db96d56Sopenharmony_ciWRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
5387db96d56Sopenharmony_ciWRAP_UNARY(proxy_index, PyNumber_Index)
5397db96d56Sopenharmony_ciWRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply)
5407db96d56Sopenharmony_ciWRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply)
5417db96d56Sopenharmony_ci
5427db96d56Sopenharmony_cistatic int
5437db96d56Sopenharmony_ciproxy_bool(PyWeakReference *proxy)
5447db96d56Sopenharmony_ci{
5457db96d56Sopenharmony_ci    PyObject *o = PyWeakref_GET_OBJECT(proxy);
5467db96d56Sopenharmony_ci    if (!proxy_checkref(proxy)) {
5477db96d56Sopenharmony_ci        return -1;
5487db96d56Sopenharmony_ci    }
5497db96d56Sopenharmony_ci    Py_INCREF(o);
5507db96d56Sopenharmony_ci    int res = PyObject_IsTrue(o);
5517db96d56Sopenharmony_ci    Py_DECREF(o);
5527db96d56Sopenharmony_ci    return res;
5537db96d56Sopenharmony_ci}
5547db96d56Sopenharmony_ci
5557db96d56Sopenharmony_cistatic void
5567db96d56Sopenharmony_ciproxy_dealloc(PyWeakReference *self)
5577db96d56Sopenharmony_ci{
5587db96d56Sopenharmony_ci    PyObject_GC_UnTrack(self);
5597db96d56Sopenharmony_ci    if (self->wr_callback != NULL)
5607db96d56Sopenharmony_ci        PyObject_GC_UnTrack((PyObject *)self);
5617db96d56Sopenharmony_ci    clear_weakref(self);
5627db96d56Sopenharmony_ci    PyObject_GC_Del(self);
5637db96d56Sopenharmony_ci}
5647db96d56Sopenharmony_ci
5657db96d56Sopenharmony_ci/* sequence slots */
5667db96d56Sopenharmony_ci
5677db96d56Sopenharmony_cistatic int
5687db96d56Sopenharmony_ciproxy_contains(PyWeakReference *proxy, PyObject *value)
5697db96d56Sopenharmony_ci{
5707db96d56Sopenharmony_ci    if (!proxy_checkref(proxy))
5717db96d56Sopenharmony_ci        return -1;
5727db96d56Sopenharmony_ci
5737db96d56Sopenharmony_ci    PyObject *obj = PyWeakref_GET_OBJECT(proxy);
5747db96d56Sopenharmony_ci    Py_INCREF(obj);
5757db96d56Sopenharmony_ci    int res = PySequence_Contains(obj, value);
5767db96d56Sopenharmony_ci    Py_DECREF(obj);
5777db96d56Sopenharmony_ci    return res;
5787db96d56Sopenharmony_ci}
5797db96d56Sopenharmony_ci
5807db96d56Sopenharmony_ci/* mapping slots */
5817db96d56Sopenharmony_ci
5827db96d56Sopenharmony_cistatic Py_ssize_t
5837db96d56Sopenharmony_ciproxy_length(PyWeakReference *proxy)
5847db96d56Sopenharmony_ci{
5857db96d56Sopenharmony_ci    if (!proxy_checkref(proxy))
5867db96d56Sopenharmony_ci        return -1;
5877db96d56Sopenharmony_ci
5887db96d56Sopenharmony_ci    PyObject *obj = PyWeakref_GET_OBJECT(proxy);
5897db96d56Sopenharmony_ci    Py_INCREF(obj);
5907db96d56Sopenharmony_ci    Py_ssize_t res = PyObject_Length(obj);
5917db96d56Sopenharmony_ci    Py_DECREF(obj);
5927db96d56Sopenharmony_ci    return res;
5937db96d56Sopenharmony_ci}
5947db96d56Sopenharmony_ci
5957db96d56Sopenharmony_ciWRAP_BINARY(proxy_getitem, PyObject_GetItem)
5967db96d56Sopenharmony_ci
5977db96d56Sopenharmony_cistatic int
5987db96d56Sopenharmony_ciproxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
5997db96d56Sopenharmony_ci{
6007db96d56Sopenharmony_ci    if (!proxy_checkref(proxy))
6017db96d56Sopenharmony_ci        return -1;
6027db96d56Sopenharmony_ci
6037db96d56Sopenharmony_ci    PyObject *obj = PyWeakref_GET_OBJECT(proxy);
6047db96d56Sopenharmony_ci    Py_INCREF(obj);
6057db96d56Sopenharmony_ci    int res;
6067db96d56Sopenharmony_ci    if (value == NULL) {
6077db96d56Sopenharmony_ci        res = PyObject_DelItem(obj, key);
6087db96d56Sopenharmony_ci    } else {
6097db96d56Sopenharmony_ci        res = PyObject_SetItem(obj, key, value);
6107db96d56Sopenharmony_ci    }
6117db96d56Sopenharmony_ci    Py_DECREF(obj);
6127db96d56Sopenharmony_ci    return res;
6137db96d56Sopenharmony_ci}
6147db96d56Sopenharmony_ci
6157db96d56Sopenharmony_ci/* iterator slots */
6167db96d56Sopenharmony_ci
6177db96d56Sopenharmony_cistatic PyObject *
6187db96d56Sopenharmony_ciproxy_iter(PyWeakReference *proxy)
6197db96d56Sopenharmony_ci{
6207db96d56Sopenharmony_ci    if (!proxy_checkref(proxy))
6217db96d56Sopenharmony_ci        return NULL;
6227db96d56Sopenharmony_ci    PyObject *obj = PyWeakref_GET_OBJECT(proxy);
6237db96d56Sopenharmony_ci    Py_INCREF(obj);
6247db96d56Sopenharmony_ci    PyObject* res = PyObject_GetIter(obj);
6257db96d56Sopenharmony_ci    Py_DECREF(obj);
6267db96d56Sopenharmony_ci    return res;
6277db96d56Sopenharmony_ci}
6287db96d56Sopenharmony_ci
6297db96d56Sopenharmony_cistatic PyObject *
6307db96d56Sopenharmony_ciproxy_iternext(PyWeakReference *proxy)
6317db96d56Sopenharmony_ci{
6327db96d56Sopenharmony_ci    if (!proxy_checkref(proxy))
6337db96d56Sopenharmony_ci        return NULL;
6347db96d56Sopenharmony_ci
6357db96d56Sopenharmony_ci    PyObject *obj = PyWeakref_GET_OBJECT(proxy);
6367db96d56Sopenharmony_ci    if (!PyIter_Check(obj)) {
6377db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
6387db96d56Sopenharmony_ci            "Weakref proxy referenced a non-iterator '%.200s' object",
6397db96d56Sopenharmony_ci            Py_TYPE(obj)->tp_name);
6407db96d56Sopenharmony_ci        return NULL;
6417db96d56Sopenharmony_ci    }
6427db96d56Sopenharmony_ci    Py_INCREF(obj);
6437db96d56Sopenharmony_ci    PyObject* res = PyIter_Next(obj);
6447db96d56Sopenharmony_ci    Py_DECREF(obj);
6457db96d56Sopenharmony_ci    return res;
6467db96d56Sopenharmony_ci}
6477db96d56Sopenharmony_ci
6487db96d56Sopenharmony_ci
6497db96d56Sopenharmony_ciWRAP_METHOD(proxy_bytes, __bytes__)
6507db96d56Sopenharmony_ciWRAP_METHOD(proxy_reversed, __reversed__)
6517db96d56Sopenharmony_ci
6527db96d56Sopenharmony_ci
6537db96d56Sopenharmony_cistatic PyMethodDef proxy_methods[] = {
6547db96d56Sopenharmony_ci        {"__bytes__", proxy_bytes, METH_NOARGS},
6557db96d56Sopenharmony_ci        {"__reversed__", proxy_reversed, METH_NOARGS},
6567db96d56Sopenharmony_ci        {NULL, NULL}
6577db96d56Sopenharmony_ci};
6587db96d56Sopenharmony_ci
6597db96d56Sopenharmony_ci
6607db96d56Sopenharmony_cistatic PyNumberMethods proxy_as_number = {
6617db96d56Sopenharmony_ci    proxy_add,              /*nb_add*/
6627db96d56Sopenharmony_ci    proxy_sub,              /*nb_subtract*/
6637db96d56Sopenharmony_ci    proxy_mul,              /*nb_multiply*/
6647db96d56Sopenharmony_ci    proxy_mod,              /*nb_remainder*/
6657db96d56Sopenharmony_ci    proxy_divmod,           /*nb_divmod*/
6667db96d56Sopenharmony_ci    proxy_pow,              /*nb_power*/
6677db96d56Sopenharmony_ci    proxy_neg,              /*nb_negative*/
6687db96d56Sopenharmony_ci    proxy_pos,              /*nb_positive*/
6697db96d56Sopenharmony_ci    proxy_abs,              /*nb_absolute*/
6707db96d56Sopenharmony_ci    (inquiry)proxy_bool,    /*nb_bool*/
6717db96d56Sopenharmony_ci    proxy_invert,           /*nb_invert*/
6727db96d56Sopenharmony_ci    proxy_lshift,           /*nb_lshift*/
6737db96d56Sopenharmony_ci    proxy_rshift,           /*nb_rshift*/
6747db96d56Sopenharmony_ci    proxy_and,              /*nb_and*/
6757db96d56Sopenharmony_ci    proxy_xor,              /*nb_xor*/
6767db96d56Sopenharmony_ci    proxy_or,               /*nb_or*/
6777db96d56Sopenharmony_ci    proxy_int,              /*nb_int*/
6787db96d56Sopenharmony_ci    0,                      /*nb_reserved*/
6797db96d56Sopenharmony_ci    proxy_float,            /*nb_float*/
6807db96d56Sopenharmony_ci    proxy_iadd,             /*nb_inplace_add*/
6817db96d56Sopenharmony_ci    proxy_isub,             /*nb_inplace_subtract*/
6827db96d56Sopenharmony_ci    proxy_imul,             /*nb_inplace_multiply*/
6837db96d56Sopenharmony_ci    proxy_imod,             /*nb_inplace_remainder*/
6847db96d56Sopenharmony_ci    proxy_ipow,             /*nb_inplace_power*/
6857db96d56Sopenharmony_ci    proxy_ilshift,          /*nb_inplace_lshift*/
6867db96d56Sopenharmony_ci    proxy_irshift,          /*nb_inplace_rshift*/
6877db96d56Sopenharmony_ci    proxy_iand,             /*nb_inplace_and*/
6887db96d56Sopenharmony_ci    proxy_ixor,             /*nb_inplace_xor*/
6897db96d56Sopenharmony_ci    proxy_ior,              /*nb_inplace_or*/
6907db96d56Sopenharmony_ci    proxy_floor_div,        /*nb_floor_divide*/
6917db96d56Sopenharmony_ci    proxy_true_div,         /*nb_true_divide*/
6927db96d56Sopenharmony_ci    proxy_ifloor_div,       /*nb_inplace_floor_divide*/
6937db96d56Sopenharmony_ci    proxy_itrue_div,        /*nb_inplace_true_divide*/
6947db96d56Sopenharmony_ci    proxy_index,            /*nb_index*/
6957db96d56Sopenharmony_ci    proxy_matmul,           /*nb_matrix_multiply*/
6967db96d56Sopenharmony_ci    proxy_imatmul,          /*nb_inplace_matrix_multiply*/
6977db96d56Sopenharmony_ci};
6987db96d56Sopenharmony_ci
6997db96d56Sopenharmony_cistatic PySequenceMethods proxy_as_sequence = {
7007db96d56Sopenharmony_ci    (lenfunc)proxy_length,      /*sq_length*/
7017db96d56Sopenharmony_ci    0,                          /*sq_concat*/
7027db96d56Sopenharmony_ci    0,                          /*sq_repeat*/
7037db96d56Sopenharmony_ci    0,                          /*sq_item*/
7047db96d56Sopenharmony_ci    0,                          /*sq_slice*/
7057db96d56Sopenharmony_ci    0,                          /*sq_ass_item*/
7067db96d56Sopenharmony_ci    0,                           /*sq_ass_slice*/
7077db96d56Sopenharmony_ci    (objobjproc)proxy_contains, /* sq_contains */
7087db96d56Sopenharmony_ci};
7097db96d56Sopenharmony_ci
7107db96d56Sopenharmony_cistatic PyMappingMethods proxy_as_mapping = {
7117db96d56Sopenharmony_ci    (lenfunc)proxy_length,        /*mp_length*/
7127db96d56Sopenharmony_ci    proxy_getitem,                /*mp_subscript*/
7137db96d56Sopenharmony_ci    (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
7147db96d56Sopenharmony_ci};
7157db96d56Sopenharmony_ci
7167db96d56Sopenharmony_ci
7177db96d56Sopenharmony_ciPyTypeObject
7187db96d56Sopenharmony_ci_PyWeakref_ProxyType = {
7197db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
7207db96d56Sopenharmony_ci    "weakref.ProxyType",
7217db96d56Sopenharmony_ci    sizeof(PyWeakReference),
7227db96d56Sopenharmony_ci    0,
7237db96d56Sopenharmony_ci    /* methods */
7247db96d56Sopenharmony_ci    (destructor)proxy_dealloc,          /* tp_dealloc */
7257db96d56Sopenharmony_ci    0,                                  /* tp_vectorcall_offset */
7267db96d56Sopenharmony_ci    0,                                  /* tp_getattr */
7277db96d56Sopenharmony_ci    0,                                  /* tp_setattr */
7287db96d56Sopenharmony_ci    0,                                  /* tp_as_async */
7297db96d56Sopenharmony_ci    (reprfunc)proxy_repr,               /* tp_repr */
7307db96d56Sopenharmony_ci    &proxy_as_number,                   /* tp_as_number */
7317db96d56Sopenharmony_ci    &proxy_as_sequence,                 /* tp_as_sequence */
7327db96d56Sopenharmony_ci    &proxy_as_mapping,                  /* tp_as_mapping */
7337db96d56Sopenharmony_ci// Notice that tp_hash is intentionally omitted as proxies are "mutable" (when the reference dies).
7347db96d56Sopenharmony_ci    0,                                  /* tp_hash */
7357db96d56Sopenharmony_ci    0,                                  /* tp_call */
7367db96d56Sopenharmony_ci    proxy_str,                          /* tp_str */
7377db96d56Sopenharmony_ci    proxy_getattr,                      /* tp_getattro */
7387db96d56Sopenharmony_ci    (setattrofunc)proxy_setattr,        /* tp_setattro */
7397db96d56Sopenharmony_ci    0,                                  /* tp_as_buffer */
7407db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
7417db96d56Sopenharmony_ci    0,                                  /* tp_doc */
7427db96d56Sopenharmony_ci    (traverseproc)gc_traverse,          /* tp_traverse */
7437db96d56Sopenharmony_ci    (inquiry)gc_clear,                  /* tp_clear */
7447db96d56Sopenharmony_ci    proxy_richcompare,                  /* tp_richcompare */
7457db96d56Sopenharmony_ci    0,                                  /* tp_weaklistoffset */
7467db96d56Sopenharmony_ci    (getiterfunc)proxy_iter,            /* tp_iter */
7477db96d56Sopenharmony_ci    (iternextfunc)proxy_iternext,       /* tp_iternext */
7487db96d56Sopenharmony_ci        proxy_methods,                      /* tp_methods */
7497db96d56Sopenharmony_ci};
7507db96d56Sopenharmony_ci
7517db96d56Sopenharmony_ci
7527db96d56Sopenharmony_ciPyTypeObject
7537db96d56Sopenharmony_ci_PyWeakref_CallableProxyType = {
7547db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
7557db96d56Sopenharmony_ci    "weakref.CallableProxyType",
7567db96d56Sopenharmony_ci    sizeof(PyWeakReference),
7577db96d56Sopenharmony_ci    0,
7587db96d56Sopenharmony_ci    /* methods */
7597db96d56Sopenharmony_ci    (destructor)proxy_dealloc,          /* tp_dealloc */
7607db96d56Sopenharmony_ci    0,                                  /* tp_vectorcall_offset */
7617db96d56Sopenharmony_ci    0,                                  /* tp_getattr */
7627db96d56Sopenharmony_ci    0,                                  /* tp_setattr */
7637db96d56Sopenharmony_ci    0,                                  /* tp_as_async */
7647db96d56Sopenharmony_ci    (unaryfunc)proxy_repr,              /* tp_repr */
7657db96d56Sopenharmony_ci    &proxy_as_number,                   /* tp_as_number */
7667db96d56Sopenharmony_ci    &proxy_as_sequence,                 /* tp_as_sequence */
7677db96d56Sopenharmony_ci    &proxy_as_mapping,                  /* tp_as_mapping */
7687db96d56Sopenharmony_ci    0,                                  /* tp_hash */
7697db96d56Sopenharmony_ci    proxy_call,                         /* tp_call */
7707db96d56Sopenharmony_ci    proxy_str,                          /* tp_str */
7717db96d56Sopenharmony_ci    proxy_getattr,                      /* tp_getattro */
7727db96d56Sopenharmony_ci    (setattrofunc)proxy_setattr,        /* tp_setattro */
7737db96d56Sopenharmony_ci    0,                                  /* tp_as_buffer */
7747db96d56Sopenharmony_ci    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
7757db96d56Sopenharmony_ci    0,                                  /* tp_doc */
7767db96d56Sopenharmony_ci    (traverseproc)gc_traverse,          /* tp_traverse */
7777db96d56Sopenharmony_ci    (inquiry)gc_clear,                  /* tp_clear */
7787db96d56Sopenharmony_ci    proxy_richcompare,                  /* tp_richcompare */
7797db96d56Sopenharmony_ci    0,                                  /* tp_weaklistoffset */
7807db96d56Sopenharmony_ci    (getiterfunc)proxy_iter,            /* tp_iter */
7817db96d56Sopenharmony_ci    (iternextfunc)proxy_iternext,       /* tp_iternext */
7827db96d56Sopenharmony_ci};
7837db96d56Sopenharmony_ci
7847db96d56Sopenharmony_ci
7857db96d56Sopenharmony_ci
7867db96d56Sopenharmony_ciPyObject *
7877db96d56Sopenharmony_ciPyWeakref_NewRef(PyObject *ob, PyObject *callback)
7887db96d56Sopenharmony_ci{
7897db96d56Sopenharmony_ci    PyWeakReference *result = NULL;
7907db96d56Sopenharmony_ci    PyWeakReference **list;
7917db96d56Sopenharmony_ci    PyWeakReference *ref, *proxy;
7927db96d56Sopenharmony_ci
7937db96d56Sopenharmony_ci    if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
7947db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
7957db96d56Sopenharmony_ci                     "cannot create weak reference to '%s' object",
7967db96d56Sopenharmony_ci                     Py_TYPE(ob)->tp_name);
7977db96d56Sopenharmony_ci        return NULL;
7987db96d56Sopenharmony_ci    }
7997db96d56Sopenharmony_ci    list = GET_WEAKREFS_LISTPTR(ob);
8007db96d56Sopenharmony_ci    get_basic_refs(*list, &ref, &proxy);
8017db96d56Sopenharmony_ci    if (callback == Py_None)
8027db96d56Sopenharmony_ci        callback = NULL;
8037db96d56Sopenharmony_ci    if (callback == NULL)
8047db96d56Sopenharmony_ci        /* return existing weak reference if it exists */
8057db96d56Sopenharmony_ci        result = ref;
8067db96d56Sopenharmony_ci    if (result != NULL)
8077db96d56Sopenharmony_ci        Py_INCREF(result);
8087db96d56Sopenharmony_ci    else {
8097db96d56Sopenharmony_ci        /* Note: new_weakref() can trigger cyclic GC, so the weakref
8107db96d56Sopenharmony_ci           list on ob can be mutated.  This means that the ref and
8117db96d56Sopenharmony_ci           proxy pointers we got back earlier may have been collected,
8127db96d56Sopenharmony_ci           so we need to compute these values again before we use
8137db96d56Sopenharmony_ci           them. */
8147db96d56Sopenharmony_ci        result = new_weakref(ob, callback);
8157db96d56Sopenharmony_ci        if (result != NULL) {
8167db96d56Sopenharmony_ci            get_basic_refs(*list, &ref, &proxy);
8177db96d56Sopenharmony_ci            if (callback == NULL) {
8187db96d56Sopenharmony_ci                if (ref == NULL)
8197db96d56Sopenharmony_ci                    insert_head(result, list);
8207db96d56Sopenharmony_ci                else {
8217db96d56Sopenharmony_ci                    /* Someone else added a ref without a callback
8227db96d56Sopenharmony_ci                       during GC.  Return that one instead of this one
8237db96d56Sopenharmony_ci                       to avoid violating the invariants of the list
8247db96d56Sopenharmony_ci                       of weakrefs for ob. */
8257db96d56Sopenharmony_ci                    Py_DECREF(result);
8267db96d56Sopenharmony_ci                    Py_INCREF(ref);
8277db96d56Sopenharmony_ci                    result = ref;
8287db96d56Sopenharmony_ci                }
8297db96d56Sopenharmony_ci            }
8307db96d56Sopenharmony_ci            else {
8317db96d56Sopenharmony_ci                PyWeakReference *prev;
8327db96d56Sopenharmony_ci
8337db96d56Sopenharmony_ci                prev = (proxy == NULL) ? ref : proxy;
8347db96d56Sopenharmony_ci                if (prev == NULL)
8357db96d56Sopenharmony_ci                    insert_head(result, list);
8367db96d56Sopenharmony_ci                else
8377db96d56Sopenharmony_ci                    insert_after(result, prev);
8387db96d56Sopenharmony_ci            }
8397db96d56Sopenharmony_ci        }
8407db96d56Sopenharmony_ci    }
8417db96d56Sopenharmony_ci    return (PyObject *) result;
8427db96d56Sopenharmony_ci}
8437db96d56Sopenharmony_ci
8447db96d56Sopenharmony_ci
8457db96d56Sopenharmony_ciPyObject *
8467db96d56Sopenharmony_ciPyWeakref_NewProxy(PyObject *ob, PyObject *callback)
8477db96d56Sopenharmony_ci{
8487db96d56Sopenharmony_ci    PyWeakReference *result = NULL;
8497db96d56Sopenharmony_ci    PyWeakReference **list;
8507db96d56Sopenharmony_ci    PyWeakReference *ref, *proxy;
8517db96d56Sopenharmony_ci
8527db96d56Sopenharmony_ci    if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
8537db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
8547db96d56Sopenharmony_ci                     "cannot create weak reference to '%s' object",
8557db96d56Sopenharmony_ci                     Py_TYPE(ob)->tp_name);
8567db96d56Sopenharmony_ci        return NULL;
8577db96d56Sopenharmony_ci    }
8587db96d56Sopenharmony_ci    list = GET_WEAKREFS_LISTPTR(ob);
8597db96d56Sopenharmony_ci    get_basic_refs(*list, &ref, &proxy);
8607db96d56Sopenharmony_ci    if (callback == Py_None)
8617db96d56Sopenharmony_ci        callback = NULL;
8627db96d56Sopenharmony_ci    if (callback == NULL)
8637db96d56Sopenharmony_ci        /* attempt to return an existing weak reference if it exists */
8647db96d56Sopenharmony_ci        result = proxy;
8657db96d56Sopenharmony_ci    if (result != NULL)
8667db96d56Sopenharmony_ci        Py_INCREF(result);
8677db96d56Sopenharmony_ci    else {
8687db96d56Sopenharmony_ci        /* Note: new_weakref() can trigger cyclic GC, so the weakref
8697db96d56Sopenharmony_ci           list on ob can be mutated.  This means that the ref and
8707db96d56Sopenharmony_ci           proxy pointers we got back earlier may have been collected,
8717db96d56Sopenharmony_ci           so we need to compute these values again before we use
8727db96d56Sopenharmony_ci           them. */
8737db96d56Sopenharmony_ci        result = new_weakref(ob, callback);
8747db96d56Sopenharmony_ci        if (result != NULL) {
8757db96d56Sopenharmony_ci            PyWeakReference *prev;
8767db96d56Sopenharmony_ci
8777db96d56Sopenharmony_ci            if (PyCallable_Check(ob)) {
8787db96d56Sopenharmony_ci                Py_SET_TYPE(result, &_PyWeakref_CallableProxyType);
8797db96d56Sopenharmony_ci            }
8807db96d56Sopenharmony_ci            else {
8817db96d56Sopenharmony_ci                Py_SET_TYPE(result, &_PyWeakref_ProxyType);
8827db96d56Sopenharmony_ci            }
8837db96d56Sopenharmony_ci            get_basic_refs(*list, &ref, &proxy);
8847db96d56Sopenharmony_ci            if (callback == NULL) {
8857db96d56Sopenharmony_ci                if (proxy != NULL) {
8867db96d56Sopenharmony_ci                    /* Someone else added a proxy without a callback
8877db96d56Sopenharmony_ci                       during GC.  Return that one instead of this one
8887db96d56Sopenharmony_ci                       to avoid violating the invariants of the list
8897db96d56Sopenharmony_ci                       of weakrefs for ob. */
8907db96d56Sopenharmony_ci                    Py_DECREF(result);
8917db96d56Sopenharmony_ci                    result = proxy;
8927db96d56Sopenharmony_ci                    Py_INCREF(result);
8937db96d56Sopenharmony_ci                    goto skip_insert;
8947db96d56Sopenharmony_ci                }
8957db96d56Sopenharmony_ci                prev = ref;
8967db96d56Sopenharmony_ci            }
8977db96d56Sopenharmony_ci            else
8987db96d56Sopenharmony_ci                prev = (proxy == NULL) ? ref : proxy;
8997db96d56Sopenharmony_ci
9007db96d56Sopenharmony_ci            if (prev == NULL)
9017db96d56Sopenharmony_ci                insert_head(result, list);
9027db96d56Sopenharmony_ci            else
9037db96d56Sopenharmony_ci                insert_after(result, prev);
9047db96d56Sopenharmony_ci        skip_insert:
9057db96d56Sopenharmony_ci            ;
9067db96d56Sopenharmony_ci        }
9077db96d56Sopenharmony_ci    }
9087db96d56Sopenharmony_ci    return (PyObject *) result;
9097db96d56Sopenharmony_ci}
9107db96d56Sopenharmony_ci
9117db96d56Sopenharmony_ci
9127db96d56Sopenharmony_ciPyObject *
9137db96d56Sopenharmony_ciPyWeakref_GetObject(PyObject *ref)
9147db96d56Sopenharmony_ci{
9157db96d56Sopenharmony_ci    if (ref == NULL || !PyWeakref_Check(ref)) {
9167db96d56Sopenharmony_ci        PyErr_BadInternalCall();
9177db96d56Sopenharmony_ci        return NULL;
9187db96d56Sopenharmony_ci    }
9197db96d56Sopenharmony_ci    return PyWeakref_GET_OBJECT(ref);
9207db96d56Sopenharmony_ci}
9217db96d56Sopenharmony_ci
9227db96d56Sopenharmony_ci/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
9237db96d56Sopenharmony_ci * handle_weakrefs().
9247db96d56Sopenharmony_ci */
9257db96d56Sopenharmony_cistatic void
9267db96d56Sopenharmony_cihandle_callback(PyWeakReference *ref, PyObject *callback)
9277db96d56Sopenharmony_ci{
9287db96d56Sopenharmony_ci    PyObject *cbresult = PyObject_CallOneArg(callback, (PyObject *)ref);
9297db96d56Sopenharmony_ci
9307db96d56Sopenharmony_ci    if (cbresult == NULL)
9317db96d56Sopenharmony_ci        PyErr_WriteUnraisable(callback);
9327db96d56Sopenharmony_ci    else
9337db96d56Sopenharmony_ci        Py_DECREF(cbresult);
9347db96d56Sopenharmony_ci}
9357db96d56Sopenharmony_ci
9367db96d56Sopenharmony_ci/* This function is called by the tp_dealloc handler to clear weak references.
9377db96d56Sopenharmony_ci *
9387db96d56Sopenharmony_ci * This iterates through the weak references for 'object' and calls callbacks
9397db96d56Sopenharmony_ci * for those references which have one.  It returns when all callbacks have
9407db96d56Sopenharmony_ci * been attempted.
9417db96d56Sopenharmony_ci */
9427db96d56Sopenharmony_civoid
9437db96d56Sopenharmony_ciPyObject_ClearWeakRefs(PyObject *object)
9447db96d56Sopenharmony_ci{
9457db96d56Sopenharmony_ci    PyWeakReference **list;
9467db96d56Sopenharmony_ci
9477db96d56Sopenharmony_ci    if (object == NULL
9487db96d56Sopenharmony_ci        || !_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
9497db96d56Sopenharmony_ci        || Py_REFCNT(object) != 0)
9507db96d56Sopenharmony_ci    {
9517db96d56Sopenharmony_ci        PyErr_BadInternalCall();
9527db96d56Sopenharmony_ci        return;
9537db96d56Sopenharmony_ci    }
9547db96d56Sopenharmony_ci    list = GET_WEAKREFS_LISTPTR(object);
9557db96d56Sopenharmony_ci    /* Remove the callback-less basic and proxy references */
9567db96d56Sopenharmony_ci    if (*list != NULL && (*list)->wr_callback == NULL) {
9577db96d56Sopenharmony_ci        clear_weakref(*list);
9587db96d56Sopenharmony_ci        if (*list != NULL && (*list)->wr_callback == NULL)
9597db96d56Sopenharmony_ci            clear_weakref(*list);
9607db96d56Sopenharmony_ci    }
9617db96d56Sopenharmony_ci    if (*list != NULL) {
9627db96d56Sopenharmony_ci        PyWeakReference *current = *list;
9637db96d56Sopenharmony_ci        Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
9647db96d56Sopenharmony_ci        PyObject *err_type, *err_value, *err_tb;
9657db96d56Sopenharmony_ci
9667db96d56Sopenharmony_ci        PyErr_Fetch(&err_type, &err_value, &err_tb);
9677db96d56Sopenharmony_ci        if (count == 1) {
9687db96d56Sopenharmony_ci            PyObject *callback = current->wr_callback;
9697db96d56Sopenharmony_ci
9707db96d56Sopenharmony_ci            current->wr_callback = NULL;
9717db96d56Sopenharmony_ci            clear_weakref(current);
9727db96d56Sopenharmony_ci            if (callback != NULL) {
9737db96d56Sopenharmony_ci                if (Py_REFCNT((PyObject *)current) > 0) {
9747db96d56Sopenharmony_ci                    handle_callback(current, callback);
9757db96d56Sopenharmony_ci                }
9767db96d56Sopenharmony_ci                Py_DECREF(callback);
9777db96d56Sopenharmony_ci            }
9787db96d56Sopenharmony_ci        }
9797db96d56Sopenharmony_ci        else {
9807db96d56Sopenharmony_ci            PyObject *tuple;
9817db96d56Sopenharmony_ci            Py_ssize_t i = 0;
9827db96d56Sopenharmony_ci
9837db96d56Sopenharmony_ci            tuple = PyTuple_New(count * 2);
9847db96d56Sopenharmony_ci            if (tuple == NULL) {
9857db96d56Sopenharmony_ci                _PyErr_ChainExceptions(err_type, err_value, err_tb);
9867db96d56Sopenharmony_ci                return;
9877db96d56Sopenharmony_ci            }
9887db96d56Sopenharmony_ci
9897db96d56Sopenharmony_ci            for (i = 0; i < count; ++i) {
9907db96d56Sopenharmony_ci                PyWeakReference *next = current->wr_next;
9917db96d56Sopenharmony_ci
9927db96d56Sopenharmony_ci                if (Py_REFCNT((PyObject *)current) > 0) {
9937db96d56Sopenharmony_ci                    Py_INCREF(current);
9947db96d56Sopenharmony_ci                    PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
9957db96d56Sopenharmony_ci                    PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
9967db96d56Sopenharmony_ci                }
9977db96d56Sopenharmony_ci                else {
9987db96d56Sopenharmony_ci                    Py_DECREF(current->wr_callback);
9997db96d56Sopenharmony_ci                }
10007db96d56Sopenharmony_ci                current->wr_callback = NULL;
10017db96d56Sopenharmony_ci                clear_weakref(current);
10027db96d56Sopenharmony_ci                current = next;
10037db96d56Sopenharmony_ci            }
10047db96d56Sopenharmony_ci            for (i = 0; i < count; ++i) {
10057db96d56Sopenharmony_ci                PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
10067db96d56Sopenharmony_ci
10077db96d56Sopenharmony_ci                /* The tuple may have slots left to NULL */
10087db96d56Sopenharmony_ci                if (callback != NULL) {
10097db96d56Sopenharmony_ci                    PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
10107db96d56Sopenharmony_ci                    handle_callback((PyWeakReference *)item, callback);
10117db96d56Sopenharmony_ci                }
10127db96d56Sopenharmony_ci            }
10137db96d56Sopenharmony_ci            Py_DECREF(tuple);
10147db96d56Sopenharmony_ci        }
10157db96d56Sopenharmony_ci        assert(!PyErr_Occurred());
10167db96d56Sopenharmony_ci        PyErr_Restore(err_type, err_value, err_tb);
10177db96d56Sopenharmony_ci    }
10187db96d56Sopenharmony_ci}
1019