(root)/
Python-3.12.0/
Objects/
weakrefobject.c
       1  #include "Python.h"
       2  #include "pycore_object.h"        // _PyObject_GET_WEAKREFS_LISTPTR()
       3  #include "structmember.h"         // PyMemberDef
       4  
       5  
       6  #define GET_WEAKREFS_LISTPTR(o) \
       7          ((PyWeakReference **) _PyObject_GET_WEAKREFS_LISTPTR(o))
       8  
       9  
      10  Py_ssize_t
      11  _PyWeakref_GetWeakrefCount(PyWeakReference *head)
      12  {
      13      Py_ssize_t count = 0;
      14  
      15      while (head != NULL) {
      16          ++count;
      17          head = head->wr_next;
      18      }
      19      return count;
      20  }
      21  
      22  static PyObject *weakref_vectorcall(PyWeakReference *self, PyObject *const *args, size_t nargsf, PyObject *kwnames);
      23  
      24  static void
      25  init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
      26  {
      27      self->hash = -1;
      28      self->wr_object = ob;
      29      self->wr_prev = NULL;
      30      self->wr_next = NULL;
      31      self->wr_callback = Py_XNewRef(callback);
      32      self->vectorcall = (vectorcallfunc)weakref_vectorcall;
      33  }
      34  
      35  static PyWeakReference *
      36  new_weakref(PyObject *ob, PyObject *callback)
      37  {
      38      PyWeakReference *result;
      39  
      40      result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
      41      if (result) {
      42          init_weakref(result, ob, callback);
      43          PyObject_GC_Track(result);
      44      }
      45      return result;
      46  }
      47  
      48  
      49  /* This function clears the passed-in reference and removes it from the
      50   * list of weak references for the referent.  This is the only code that
      51   * removes an item from the doubly-linked list of weak references for an
      52   * object; it is also responsible for clearing the callback slot.
      53   */
      54  static void
      55  clear_weakref(PyWeakReference *self)
      56  {
      57      PyObject *callback = self->wr_callback;
      58  
      59      if (self->wr_object != Py_None) {
      60          PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
      61  
      62          if (*list == self)
      63              /* If 'self' is the end of the list (and thus self->wr_next == NULL)
      64                 then the weakref list itself (and thus the value of *list) will
      65                 end up being set to NULL. */
      66              *list = self->wr_next;
      67          self->wr_object = Py_None;
      68          if (self->wr_prev != NULL)
      69              self->wr_prev->wr_next = self->wr_next;
      70          if (self->wr_next != NULL)
      71              self->wr_next->wr_prev = self->wr_prev;
      72          self->wr_prev = NULL;
      73          self->wr_next = NULL;
      74      }
      75      if (callback != NULL) {
      76          Py_DECREF(callback);
      77          self->wr_callback = NULL;
      78      }
      79  }
      80  
      81  /* Cyclic gc uses this to *just* clear the passed-in reference, leaving
      82   * the callback intact and uncalled.  It must be possible to call self's
      83   * tp_dealloc() after calling this, so self has to be left in a sane enough
      84   * state for that to work.  We expect tp_dealloc to decref the callback
      85   * then.  The reason for not letting clear_weakref() decref the callback
      86   * right now is that if the callback goes away, that may in turn trigger
      87   * another callback (if a weak reference to the callback exists) -- running
      88   * arbitrary Python code in the middle of gc is a disaster.  The convolution
      89   * here allows gc to delay triggering such callbacks until the world is in
      90   * a sane state again.
      91   */
      92  void
      93  _PyWeakref_ClearRef(PyWeakReference *self)
      94  {
      95      PyObject *callback;
      96  
      97      assert(self != NULL);
      98      assert(PyWeakref_Check(self));
      99      /* Preserve and restore the callback around clear_weakref. */
     100      callback = self->wr_callback;
     101      self->wr_callback = NULL;
     102      clear_weakref(self);
     103      self->wr_callback = callback;
     104  }
     105  
     106  static void
     107  weakref_dealloc(PyObject *self)
     108  {
     109      PyObject_GC_UnTrack(self);
     110      clear_weakref((PyWeakReference *) self);
     111      Py_TYPE(self)->tp_free(self);
     112  }
     113  
     114  
     115  static int
     116  gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
     117  {
     118      Py_VISIT(self->wr_callback);
     119      return 0;
     120  }
     121  
     122  
     123  static int
     124  gc_clear(PyWeakReference *self)
     125  {
     126      clear_weakref(self);
     127      return 0;
     128  }
     129  
     130  
     131  static PyObject *
     132  weakref_vectorcall(PyWeakReference *self, PyObject *const *args,
     133                     size_t nargsf, PyObject *kwnames)
     134  {
     135      if (!_PyArg_NoKwnames("weakref", kwnames)) {
     136          return NULL;
     137      }
     138      Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
     139      if (!_PyArg_CheckPositional("weakref", nargs, 0, 0)) {
     140          return NULL;
     141      }
     142      return Py_NewRef(PyWeakref_GET_OBJECT(self));
     143  }
     144  
     145  static Py_hash_t
     146  weakref_hash(PyWeakReference *self)
     147  {
     148      if (self->hash != -1)
     149          return self->hash;
     150      PyObject* obj = PyWeakref_GET_OBJECT(self);
     151      if (obj == Py_None) {
     152          PyErr_SetString(PyExc_TypeError, "weak object has gone away");
     153          return -1;
     154      }
     155      Py_INCREF(obj);
     156      self->hash = PyObject_Hash(obj);
     157      Py_DECREF(obj);
     158      return self->hash;
     159  }
     160  
     161  
     162  static PyObject *
     163  weakref_repr(PyWeakReference *self)
     164  {
     165      PyObject *name, *repr;
     166      PyObject* obj = PyWeakref_GET_OBJECT(self);
     167  
     168      if (obj == Py_None) {
     169          return PyUnicode_FromFormat("<weakref at %p; dead>", self);
     170      }
     171  
     172      Py_INCREF(obj);
     173      name = _PyObject_LookupSpecial(obj, &_Py_ID(__name__));
     174      if (name == NULL || !PyUnicode_Check(name)) {
     175          repr = PyUnicode_FromFormat(
     176              "<weakref at %p; to '%s' at %p>",
     177              self,
     178              Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
     179              obj);
     180      }
     181      else {
     182          repr = PyUnicode_FromFormat(
     183              "<weakref at %p; to '%s' at %p (%U)>",
     184              self,
     185              Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
     186              obj,
     187              name);
     188      }
     189      Py_DECREF(obj);
     190      Py_XDECREF(name);
     191      return repr;
     192  }
     193  
     194  /* Weak references only support equality, not ordering. Two weak references
     195     are equal if the underlying objects are equal. If the underlying object has
     196     gone away, they are equal if they are identical. */
     197  
     198  static PyObject *
     199  weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
     200  {
     201      if ((op != Py_EQ && op != Py_NE) ||
     202          !PyWeakref_Check(self) ||
     203          !PyWeakref_Check(other)) {
     204          Py_RETURN_NOTIMPLEMENTED;
     205      }
     206      if (PyWeakref_GET_OBJECT(self) == Py_None
     207          || PyWeakref_GET_OBJECT(other) == Py_None) {
     208          int res = (self == other);
     209          if (op == Py_NE)
     210              res = !res;
     211          if (res)
     212              Py_RETURN_TRUE;
     213          else
     214              Py_RETURN_FALSE;
     215      }
     216      PyObject* obj = PyWeakref_GET_OBJECT(self);
     217      PyObject* other_obj = PyWeakref_GET_OBJECT(other);
     218      Py_INCREF(obj);
     219      Py_INCREF(other_obj);
     220      PyObject* res = PyObject_RichCompare(obj, other_obj, op);
     221      Py_DECREF(obj);
     222      Py_DECREF(other_obj);
     223      return res;
     224  }
     225  
     226  /* Given the head of an object's list of weak references, extract the
     227   * two callback-less refs (ref and proxy).  Used to determine if the
     228   * shared references exist and to determine the back link for newly
     229   * inserted references.
     230   */
     231  static void
     232  get_basic_refs(PyWeakReference *head,
     233                 PyWeakReference **refp, PyWeakReference **proxyp)
     234  {
     235      *refp = NULL;
     236      *proxyp = NULL;
     237  
     238      if (head != NULL && head->wr_callback == NULL) {
     239          /* We need to be careful that the "basic refs" aren't
     240             subclasses of the main types.  That complicates this a
     241             little. */
     242          if (PyWeakref_CheckRefExact(head)) {
     243              *refp = head;
     244              head = head->wr_next;
     245          }
     246          if (head != NULL
     247              && head->wr_callback == NULL
     248              && PyWeakref_CheckProxy(head)) {
     249              *proxyp = head;
     250              /* head = head->wr_next; */
     251          }
     252      }
     253  }
     254  
     255  /* Insert 'newref' in the list after 'prev'.  Both must be non-NULL. */
     256  static void
     257  insert_after(PyWeakReference *newref, PyWeakReference *prev)
     258  {
     259      newref->wr_prev = prev;
     260      newref->wr_next = prev->wr_next;
     261      if (prev->wr_next != NULL)
     262          prev->wr_next->wr_prev = newref;
     263      prev->wr_next = newref;
     264  }
     265  
     266  /* Insert 'newref' at the head of the list; 'list' points to the variable
     267   * that stores the head.
     268   */
     269  static void
     270  insert_head(PyWeakReference *newref, PyWeakReference **list)
     271  {
     272      PyWeakReference *next = *list;
     273  
     274      newref->wr_prev = NULL;
     275      newref->wr_next = next;
     276      if (next != NULL)
     277          next->wr_prev = newref;
     278      *list = newref;
     279  }
     280  
     281  static int
     282  parse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,
     283                          PyObject **obp, PyObject **callbackp)
     284  {
     285      return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
     286  }
     287  
     288  static PyObject *
     289  weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     290  {
     291      PyWeakReference *self = NULL;
     292      PyObject *ob, *callback = NULL;
     293  
     294      if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
     295          PyWeakReference *ref, *proxy;
     296          PyWeakReference **list;
     297  
     298          if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
     299              PyErr_Format(PyExc_TypeError,
     300                           "cannot create weak reference to '%s' object",
     301                           Py_TYPE(ob)->tp_name);
     302              return NULL;
     303          }
     304          if (callback == Py_None)
     305              callback = NULL;
     306          list = GET_WEAKREFS_LISTPTR(ob);
     307          get_basic_refs(*list, &ref, &proxy);
     308          if (callback == NULL && type == &_PyWeakref_RefType) {
     309              if (ref != NULL) {
     310                  /* We can re-use an existing reference. */
     311                  return Py_NewRef(ref);
     312              }
     313          }
     314          /* We have to create a new reference. */
     315          /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
     316             list on ob can be mutated.  This means that the ref and
     317             proxy pointers we got back earlier may have been collected,
     318             so we need to compute these values again before we use
     319             them. */
     320          self = (PyWeakReference *) (type->tp_alloc(type, 0));
     321          if (self != NULL) {
     322              init_weakref(self, ob, callback);
     323              if (callback == NULL && type == &_PyWeakref_RefType) {
     324                  insert_head(self, list);
     325              }
     326              else {
     327                  PyWeakReference *prev;
     328  
     329                  get_basic_refs(*list, &ref, &proxy);
     330                  prev = (proxy == NULL) ? ref : proxy;
     331                  if (prev == NULL)
     332                      insert_head(self, list);
     333                  else
     334                      insert_after(self, prev);
     335              }
     336          }
     337      }
     338      return (PyObject *)self;
     339  }
     340  
     341  static int
     342  weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
     343  {
     344      PyObject *tmp;
     345  
     346      if (!_PyArg_NoKeywords("ref", kwargs))
     347          return -1;
     348  
     349      if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
     350          return 0;
     351      else
     352          return -1;
     353  }
     354  
     355  
     356  static PyMemberDef weakref_members[] = {
     357      {"__callback__", T_OBJECT, offsetof(PyWeakReference, wr_callback), READONLY},
     358      {NULL} /* Sentinel */
     359  };
     360  
     361  static PyMethodDef weakref_methods[] = {
     362      {"__class_getitem__",    Py_GenericAlias,
     363      METH_O|METH_CLASS,       PyDoc_STR("See PEP 585")},
     364      {NULL} /* Sentinel */
     365  };
     366  
     367  PyTypeObject
     368  _PyWeakref_RefType = {
     369      PyVarObject_HEAD_INIT(&PyType_Type, 0)
     370      .tp_name = "weakref.ReferenceType",
     371      .tp_basicsize = sizeof(PyWeakReference),
     372      .tp_dealloc = weakref_dealloc,
     373      .tp_vectorcall_offset = offsetof(PyWeakReference, vectorcall),
     374      .tp_call = PyVectorcall_Call,
     375      .tp_repr = (reprfunc)weakref_repr,
     376      .tp_hash = (hashfunc)weakref_hash,
     377      .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
     378                  Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_BASETYPE,
     379      .tp_traverse = (traverseproc)gc_traverse,
     380      .tp_clear = (inquiry)gc_clear,
     381      .tp_richcompare = (richcmpfunc)weakref_richcompare,
     382      .tp_methods = weakref_methods,
     383      .tp_members = weakref_members,
     384      .tp_init = weakref___init__,
     385      .tp_alloc = PyType_GenericAlloc,
     386      .tp_new = weakref___new__,
     387      .tp_free = PyObject_GC_Del,
     388  };
     389  
     390  
     391  static int
     392  proxy_checkref(PyWeakReference *proxy)
     393  {
     394      if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
     395          PyErr_SetString(PyExc_ReferenceError,
     396                          "weakly-referenced object no longer exists");
     397          return 0;
     398      }
     399      return 1;
     400  }
     401  
     402  
     403  /* If a parameter is a proxy, check that it is still "live" and wrap it,
     404   * replacing the original value with the raw object.  Raises ReferenceError
     405   * if the param is a dead proxy.
     406   */
     407  #define UNWRAP(o) \
     408          if (PyWeakref_CheckProxy(o)) { \
     409              if (!proxy_checkref((PyWeakReference *)o)) \
     410                  return NULL; \
     411              o = PyWeakref_GET_OBJECT(o); \
     412          }
     413  
     414  #define WRAP_UNARY(method, generic) \
     415      static PyObject * \
     416      method(PyObject *proxy) { \
     417          UNWRAP(proxy); \
     418          Py_INCREF(proxy); \
     419          PyObject* res = generic(proxy); \
     420          Py_DECREF(proxy); \
     421          return res; \
     422      }
     423  
     424  #define WRAP_BINARY(method, generic) \
     425      static PyObject * \
     426      method(PyObject *x, PyObject *y) { \
     427          UNWRAP(x); \
     428          UNWRAP(y); \
     429          Py_INCREF(x); \
     430          Py_INCREF(y); \
     431          PyObject* res = generic(x, y); \
     432          Py_DECREF(x); \
     433          Py_DECREF(y); \
     434          return res; \
     435      }
     436  
     437  /* Note that the third arg needs to be checked for NULL since the tp_call
     438   * slot can receive NULL for this arg.
     439   */
     440  #define WRAP_TERNARY(method, generic) \
     441      static PyObject * \
     442      method(PyObject *proxy, PyObject *v, PyObject *w) { \
     443          UNWRAP(proxy); \
     444          UNWRAP(v); \
     445          if (w != NULL) \
     446              UNWRAP(w); \
     447          Py_INCREF(proxy); \
     448          Py_INCREF(v); \
     449          Py_XINCREF(w); \
     450          PyObject* res = generic(proxy, v, w); \
     451          Py_DECREF(proxy); \
     452          Py_DECREF(v); \
     453          Py_XDECREF(w); \
     454          return res; \
     455      }
     456  
     457  #define WRAP_METHOD(method, SPECIAL) \
     458      static PyObject * \
     459      method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
     460              UNWRAP(proxy); \
     461              Py_INCREF(proxy); \
     462              PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
     463              Py_DECREF(proxy); \
     464              return res; \
     465          }
     466  
     467  
     468  /* direct slots */
     469  
     470  WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
     471  WRAP_UNARY(proxy_str, PyObject_Str)
     472  WRAP_TERNARY(proxy_call, PyObject_Call)
     473  
     474  static PyObject *
     475  proxy_repr(PyWeakReference *proxy)
     476  {
     477      return PyUnicode_FromFormat(
     478          "<weakproxy at %p to %s at %p>",
     479          proxy,
     480          Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
     481          PyWeakref_GET_OBJECT(proxy));
     482  }
     483  
     484  
     485  static int
     486  proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
     487  {
     488      if (!proxy_checkref(proxy))
     489          return -1;
     490      PyObject *obj = PyWeakref_GET_OBJECT(proxy);
     491      Py_INCREF(obj);
     492      int res = PyObject_SetAttr(obj, name, value);
     493      Py_DECREF(obj);
     494      return res;
     495  }
     496  
     497  static PyObject *
     498  proxy_richcompare(PyObject *proxy, PyObject *v, int op)
     499  {
     500      UNWRAP(proxy);
     501      UNWRAP(v);
     502      return PyObject_RichCompare(proxy, v, op);
     503  }
     504  
     505  /* number slots */
     506  WRAP_BINARY(proxy_add, PyNumber_Add)
     507  WRAP_BINARY(proxy_sub, PyNumber_Subtract)
     508  WRAP_BINARY(proxy_mul, PyNumber_Multiply)
     509  WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
     510  WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
     511  WRAP_BINARY(proxy_mod, PyNumber_Remainder)
     512  WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
     513  WRAP_TERNARY(proxy_pow, PyNumber_Power)
     514  WRAP_UNARY(proxy_neg, PyNumber_Negative)
     515  WRAP_UNARY(proxy_pos, PyNumber_Positive)
     516  WRAP_UNARY(proxy_abs, PyNumber_Absolute)
     517  WRAP_UNARY(proxy_invert, PyNumber_Invert)
     518  WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
     519  WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
     520  WRAP_BINARY(proxy_and, PyNumber_And)
     521  WRAP_BINARY(proxy_xor, PyNumber_Xor)
     522  WRAP_BINARY(proxy_or, PyNumber_Or)
     523  WRAP_UNARY(proxy_int, PyNumber_Long)
     524  WRAP_UNARY(proxy_float, PyNumber_Float)
     525  WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
     526  WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
     527  WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
     528  WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
     529  WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
     530  WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
     531  WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
     532  WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
     533  WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
     534  WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
     535  WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
     536  WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
     537  WRAP_UNARY(proxy_index, PyNumber_Index)
     538  WRAP_BINARY(proxy_matmul, PyNumber_MatrixMultiply)
     539  WRAP_BINARY(proxy_imatmul, PyNumber_InPlaceMatrixMultiply)
     540  
     541  static int
     542  proxy_bool(PyWeakReference *proxy)
     543  {
     544      PyObject *o = PyWeakref_GET_OBJECT(proxy);
     545      if (!proxy_checkref(proxy)) {
     546          return -1;
     547      }
     548      Py_INCREF(o);
     549      int res = PyObject_IsTrue(o);
     550      Py_DECREF(o);
     551      return res;
     552  }
     553  
     554  static void
     555  proxy_dealloc(PyWeakReference *self)
     556  {
     557      PyObject_GC_UnTrack(self);
     558      if (self->wr_callback != NULL)
     559          PyObject_GC_UnTrack((PyObject *)self);
     560      clear_weakref(self);
     561      PyObject_GC_Del(self);
     562  }
     563  
     564  /* sequence slots */
     565  
     566  static int
     567  proxy_contains(PyWeakReference *proxy, PyObject *value)
     568  {
     569      if (!proxy_checkref(proxy))
     570          return -1;
     571  
     572      PyObject *obj = PyWeakref_GET_OBJECT(proxy);
     573      Py_INCREF(obj);
     574      int res = PySequence_Contains(obj, value);
     575      Py_DECREF(obj);
     576      return res;
     577  }
     578  
     579  /* mapping slots */
     580  
     581  static Py_ssize_t
     582  proxy_length(PyWeakReference *proxy)
     583  {
     584      if (!proxy_checkref(proxy))
     585          return -1;
     586  
     587      PyObject *obj = PyWeakref_GET_OBJECT(proxy);
     588      Py_INCREF(obj);
     589      Py_ssize_t res = PyObject_Length(obj);
     590      Py_DECREF(obj);
     591      return res;
     592  }
     593  
     594  WRAP_BINARY(proxy_getitem, PyObject_GetItem)
     595  
     596  static int
     597  proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
     598  {
     599      if (!proxy_checkref(proxy))
     600          return -1;
     601  
     602      PyObject *obj = PyWeakref_GET_OBJECT(proxy);
     603      Py_INCREF(obj);
     604      int res;
     605      if (value == NULL) {
     606          res = PyObject_DelItem(obj, key);
     607      } else {
     608          res = PyObject_SetItem(obj, key, value);
     609      }
     610      Py_DECREF(obj);
     611      return res;
     612  }
     613  
     614  /* iterator slots */
     615  
     616  static PyObject *
     617  proxy_iter(PyWeakReference *proxy)
     618  {
     619      if (!proxy_checkref(proxy))
     620          return NULL;
     621      PyObject *obj = PyWeakref_GET_OBJECT(proxy);
     622      Py_INCREF(obj);
     623      PyObject* res = PyObject_GetIter(obj);
     624      Py_DECREF(obj);
     625      return res;
     626  }
     627  
     628  static PyObject *
     629  proxy_iternext(PyWeakReference *proxy)
     630  {
     631      if (!proxy_checkref(proxy))
     632          return NULL;
     633  
     634      PyObject *obj = PyWeakref_GET_OBJECT(proxy);
     635      if (!PyIter_Check(obj)) {
     636          PyErr_Format(PyExc_TypeError,
     637              "Weakref proxy referenced a non-iterator '%.200s' object",
     638              Py_TYPE(obj)->tp_name);
     639          return NULL;
     640      }
     641      Py_INCREF(obj);
     642      PyObject* res = PyIter_Next(obj);
     643      Py_DECREF(obj);
     644      return res;
     645  }
     646  
     647  
     648  WRAP_METHOD(proxy_bytes, __bytes__)
     649  WRAP_METHOD(proxy_reversed, __reversed__)
     650  
     651  
     652  static PyMethodDef proxy_methods[] = {
     653          {"__bytes__", proxy_bytes, METH_NOARGS},
     654          {"__reversed__", proxy_reversed, METH_NOARGS},
     655          {NULL, NULL}
     656  };
     657  
     658  
     659  static PyNumberMethods proxy_as_number = {
     660      proxy_add,              /*nb_add*/
     661      proxy_sub,              /*nb_subtract*/
     662      proxy_mul,              /*nb_multiply*/
     663      proxy_mod,              /*nb_remainder*/
     664      proxy_divmod,           /*nb_divmod*/
     665      proxy_pow,              /*nb_power*/
     666      proxy_neg,              /*nb_negative*/
     667      proxy_pos,              /*nb_positive*/
     668      proxy_abs,              /*nb_absolute*/
     669      (inquiry)proxy_bool,    /*nb_bool*/
     670      proxy_invert,           /*nb_invert*/
     671      proxy_lshift,           /*nb_lshift*/
     672      proxy_rshift,           /*nb_rshift*/
     673      proxy_and,              /*nb_and*/
     674      proxy_xor,              /*nb_xor*/
     675      proxy_or,               /*nb_or*/
     676      proxy_int,              /*nb_int*/
     677      0,                      /*nb_reserved*/
     678      proxy_float,            /*nb_float*/
     679      proxy_iadd,             /*nb_inplace_add*/
     680      proxy_isub,             /*nb_inplace_subtract*/
     681      proxy_imul,             /*nb_inplace_multiply*/
     682      proxy_imod,             /*nb_inplace_remainder*/
     683      proxy_ipow,             /*nb_inplace_power*/
     684      proxy_ilshift,          /*nb_inplace_lshift*/
     685      proxy_irshift,          /*nb_inplace_rshift*/
     686      proxy_iand,             /*nb_inplace_and*/
     687      proxy_ixor,             /*nb_inplace_xor*/
     688      proxy_ior,              /*nb_inplace_or*/
     689      proxy_floor_div,        /*nb_floor_divide*/
     690      proxy_true_div,         /*nb_true_divide*/
     691      proxy_ifloor_div,       /*nb_inplace_floor_divide*/
     692      proxy_itrue_div,        /*nb_inplace_true_divide*/
     693      proxy_index,            /*nb_index*/
     694      proxy_matmul,           /*nb_matrix_multiply*/
     695      proxy_imatmul,          /*nb_inplace_matrix_multiply*/
     696  };
     697  
     698  static PySequenceMethods proxy_as_sequence = {
     699      (lenfunc)proxy_length,      /*sq_length*/
     700      0,                          /*sq_concat*/
     701      0,                          /*sq_repeat*/
     702      0,                          /*sq_item*/
     703      0,                          /*sq_slice*/
     704      0,                          /*sq_ass_item*/
     705      0,                           /*sq_ass_slice*/
     706      (objobjproc)proxy_contains, /* sq_contains */
     707  };
     708  
     709  static PyMappingMethods proxy_as_mapping = {
     710      (lenfunc)proxy_length,        /*mp_length*/
     711      proxy_getitem,                /*mp_subscript*/
     712      (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
     713  };
     714  
     715  
     716  PyTypeObject
     717  _PyWeakref_ProxyType = {
     718      PyVarObject_HEAD_INIT(&PyType_Type, 0)
     719      "weakref.ProxyType",
     720      sizeof(PyWeakReference),
     721      0,
     722      /* methods */
     723      (destructor)proxy_dealloc,          /* tp_dealloc */
     724      0,                                  /* tp_vectorcall_offset */
     725      0,                                  /* tp_getattr */
     726      0,                                  /* tp_setattr */
     727      0,                                  /* tp_as_async */
     728      (reprfunc)proxy_repr,               /* tp_repr */
     729      &proxy_as_number,                   /* tp_as_number */
     730      &proxy_as_sequence,                 /* tp_as_sequence */
     731      &proxy_as_mapping,                  /* tp_as_mapping */
     732  // Notice that tp_hash is intentionally omitted as proxies are "mutable" (when the reference dies).
     733      0,                                  /* tp_hash */
     734      0,                                  /* tp_call */
     735      proxy_str,                          /* tp_str */
     736      proxy_getattr,                      /* tp_getattro */
     737      (setattrofunc)proxy_setattr,        /* tp_setattro */
     738      0,                                  /* tp_as_buffer */
     739      Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
     740      0,                                  /* tp_doc */
     741      (traverseproc)gc_traverse,          /* tp_traverse */
     742      (inquiry)gc_clear,                  /* tp_clear */
     743      proxy_richcompare,                  /* tp_richcompare */
     744      0,                                  /* tp_weaklistoffset */
     745      (getiterfunc)proxy_iter,            /* tp_iter */
     746      (iternextfunc)proxy_iternext,       /* tp_iternext */
     747          proxy_methods,                      /* tp_methods */
     748  };
     749  
     750  
     751  PyTypeObject
     752  _PyWeakref_CallableProxyType = {
     753      PyVarObject_HEAD_INIT(&PyType_Type, 0)
     754      "weakref.CallableProxyType",
     755      sizeof(PyWeakReference),
     756      0,
     757      /* methods */
     758      (destructor)proxy_dealloc,          /* tp_dealloc */
     759      0,                                  /* tp_vectorcall_offset */
     760      0,                                  /* tp_getattr */
     761      0,                                  /* tp_setattr */
     762      0,                                  /* tp_as_async */
     763      (unaryfunc)proxy_repr,              /* tp_repr */
     764      &proxy_as_number,                   /* tp_as_number */
     765      &proxy_as_sequence,                 /* tp_as_sequence */
     766      &proxy_as_mapping,                  /* tp_as_mapping */
     767      0,                                  /* tp_hash */
     768      proxy_call,                         /* tp_call */
     769      proxy_str,                          /* tp_str */
     770      proxy_getattr,                      /* tp_getattro */
     771      (setattrofunc)proxy_setattr,        /* tp_setattro */
     772      0,                                  /* tp_as_buffer */
     773      Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
     774      0,                                  /* tp_doc */
     775      (traverseproc)gc_traverse,          /* tp_traverse */
     776      (inquiry)gc_clear,                  /* tp_clear */
     777      proxy_richcompare,                  /* tp_richcompare */
     778      0,                                  /* tp_weaklistoffset */
     779      (getiterfunc)proxy_iter,            /* tp_iter */
     780      (iternextfunc)proxy_iternext,       /* tp_iternext */
     781  };
     782  
     783  
     784  
     785  PyObject *
     786  PyWeakref_NewRef(PyObject *ob, PyObject *callback)
     787  {
     788      PyWeakReference *result = NULL;
     789      PyWeakReference **list;
     790      PyWeakReference *ref, *proxy;
     791  
     792      if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
     793          PyErr_Format(PyExc_TypeError,
     794                       "cannot create weak reference to '%s' object",
     795                       Py_TYPE(ob)->tp_name);
     796          return NULL;
     797      }
     798      list = GET_WEAKREFS_LISTPTR(ob);
     799      get_basic_refs(*list, &ref, &proxy);
     800      if (callback == Py_None)
     801          callback = NULL;
     802      if (callback == NULL)
     803          /* return existing weak reference if it exists */
     804          result = ref;
     805      if (result != NULL)
     806          Py_INCREF(result);
     807      else {
     808          /* Note: new_weakref() can trigger cyclic GC, so the weakref
     809             list on ob can be mutated.  This means that the ref and
     810             proxy pointers we got back earlier may have been collected,
     811             so we need to compute these values again before we use
     812             them. */
     813          result = new_weakref(ob, callback);
     814          if (result != NULL) {
     815              get_basic_refs(*list, &ref, &proxy);
     816              if (callback == NULL) {
     817                  if (ref == NULL)
     818                      insert_head(result, list);
     819                  else {
     820                      /* Someone else added a ref without a callback
     821                         during GC.  Return that one instead of this one
     822                         to avoid violating the invariants of the list
     823                         of weakrefs for ob. */
     824                      Py_SETREF(result, (PyWeakReference*)Py_NewRef(ref));
     825                  }
     826              }
     827              else {
     828                  PyWeakReference *prev;
     829  
     830                  prev = (proxy == NULL) ? ref : proxy;
     831                  if (prev == NULL)
     832                      insert_head(result, list);
     833                  else
     834                      insert_after(result, prev);
     835              }
     836          }
     837      }
     838      return (PyObject *) result;
     839  }
     840  
     841  
     842  PyObject *
     843  PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
     844  {
     845      PyWeakReference *result = NULL;
     846      PyWeakReference **list;
     847      PyWeakReference *ref, *proxy;
     848  
     849      if (!_PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
     850          PyErr_Format(PyExc_TypeError,
     851                       "cannot create weak reference to '%s' object",
     852                       Py_TYPE(ob)->tp_name);
     853          return NULL;
     854      }
     855      list = GET_WEAKREFS_LISTPTR(ob);
     856      get_basic_refs(*list, &ref, &proxy);
     857      if (callback == Py_None)
     858          callback = NULL;
     859      if (callback == NULL)
     860          /* attempt to return an existing weak reference if it exists */
     861          result = proxy;
     862      if (result != NULL)
     863          Py_INCREF(result);
     864      else {
     865          /* Note: new_weakref() can trigger cyclic GC, so the weakref
     866             list on ob can be mutated.  This means that the ref and
     867             proxy pointers we got back earlier may have been collected,
     868             so we need to compute these values again before we use
     869             them. */
     870          result = new_weakref(ob, callback);
     871          if (result != NULL) {
     872              PyWeakReference *prev;
     873  
     874              if (PyCallable_Check(ob)) {
     875                  Py_SET_TYPE(result, &_PyWeakref_CallableProxyType);
     876              }
     877              else {
     878                  Py_SET_TYPE(result, &_PyWeakref_ProxyType);
     879              }
     880              get_basic_refs(*list, &ref, &proxy);
     881              if (callback == NULL) {
     882                  if (proxy != NULL) {
     883                      /* Someone else added a proxy without a callback
     884                         during GC.  Return that one instead of this one
     885                         to avoid violating the invariants of the list
     886                         of weakrefs for ob. */
     887                      Py_SETREF(result, (PyWeakReference*)Py_NewRef(proxy));
     888                      goto skip_insert;
     889                  }
     890                  prev = ref;
     891              }
     892              else
     893                  prev = (proxy == NULL) ? ref : proxy;
     894  
     895              if (prev == NULL)
     896                  insert_head(result, list);
     897              else
     898                  insert_after(result, prev);
     899          skip_insert:
     900              ;
     901          }
     902      }
     903      return (PyObject *) result;
     904  }
     905  
     906  
     907  PyObject *
     908  PyWeakref_GetObject(PyObject *ref)
     909  {
     910      if (ref == NULL || !PyWeakref_Check(ref)) {
     911          PyErr_BadInternalCall();
     912          return NULL;
     913      }
     914      return PyWeakref_GET_OBJECT(ref);
     915  }
     916  
     917  /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
     918   * handle_weakrefs().
     919   */
     920  static void
     921  handle_callback(PyWeakReference *ref, PyObject *callback)
     922  {
     923      PyObject *cbresult = PyObject_CallOneArg(callback, (PyObject *)ref);
     924  
     925      if (cbresult == NULL)
     926          PyErr_WriteUnraisable(callback);
     927      else
     928          Py_DECREF(cbresult);
     929  }
     930  
     931  /* This function is called by the tp_dealloc handler to clear weak references.
     932   *
     933   * This iterates through the weak references for 'object' and calls callbacks
     934   * for those references which have one.  It returns when all callbacks have
     935   * been attempted.
     936   */
     937  void
     938  PyObject_ClearWeakRefs(PyObject *object)
     939  {
     940      PyWeakReference **list;
     941  
     942      if (object == NULL
     943          || !_PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
     944          || Py_REFCNT(object) != 0)
     945      {
     946          PyErr_BadInternalCall();
     947          return;
     948      }
     949      list = GET_WEAKREFS_LISTPTR(object);
     950      /* Remove the callback-less basic and proxy references */
     951      if (*list != NULL && (*list)->wr_callback == NULL) {
     952          clear_weakref(*list);
     953          if (*list != NULL && (*list)->wr_callback == NULL)
     954              clear_weakref(*list);
     955      }
     956      if (*list != NULL) {
     957          PyWeakReference *current = *list;
     958          Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
     959          PyObject *exc = PyErr_GetRaisedException();
     960  
     961          if (count == 1) {
     962              PyObject *callback = current->wr_callback;
     963  
     964              current->wr_callback = NULL;
     965              clear_weakref(current);
     966              if (callback != NULL) {
     967                  if (Py_REFCNT((PyObject *)current) > 0) {
     968                      handle_callback(current, callback);
     969                  }
     970                  Py_DECREF(callback);
     971              }
     972          }
     973          else {
     974              PyObject *tuple;
     975              Py_ssize_t i = 0;
     976  
     977              tuple = PyTuple_New(count * 2);
     978              if (tuple == NULL) {
     979                  _PyErr_ChainExceptions1(exc);
     980                  return;
     981              }
     982  
     983              for (i = 0; i < count; ++i) {
     984                  PyWeakReference *next = current->wr_next;
     985  
     986                  if (Py_REFCNT((PyObject *)current) > 0) {
     987                      PyTuple_SET_ITEM(tuple, i * 2, Py_NewRef(current));
     988                      PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
     989                  }
     990                  else {
     991                      Py_DECREF(current->wr_callback);
     992                  }
     993                  current->wr_callback = NULL;
     994                  clear_weakref(current);
     995                  current = next;
     996              }
     997              for (i = 0; i < count; ++i) {
     998                  PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
     999  
    1000                  /* The tuple may have slots left to NULL */
    1001                  if (callback != NULL) {
    1002                      PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
    1003                      handle_callback((PyWeakReference *)item, callback);
    1004                  }
    1005              }
    1006              Py_DECREF(tuple);
    1007          }
    1008          assert(!PyErr_Occurred());
    1009          PyErr_SetRaisedException(exc);
    1010      }
    1011  }
    1012  
    1013  /* This function is called by _PyStaticType_Dealloc() to clear weak references.
    1014   *
    1015   * This is called at the end of runtime finalization, so we can just
    1016   * wipe out the type's weaklist.  We don't bother with callbacks
    1017   * or anything else.
    1018   */
    1019  void
    1020  _PyStaticType_ClearWeakRefs(PyInterpreterState *interp, PyTypeObject *type)
    1021  {
    1022      static_builtin_state *state = _PyStaticType_GetState(interp, type);
    1023      PyObject **list = _PyStaticType_GET_WEAKREFS_LISTPTR(state);
    1024      while (*list != NULL) {
    1025          /* Note that clear_weakref() pops the first ref off the type's
    1026             weaklist before clearing its wr_object and wr_callback.
    1027             That is how we're able to loop over the list. */
    1028          clear_weakref((PyWeakReference *)*list);
    1029      }
    1030  }