@@ -530,39 +530,42 @@ proxy_check_ref(PyObject *obj)
530530 return true;
531531}
532532
533- /*
534- * Unwrap a proxy into a strong reference.
535- * - If `o` is a live proxy: replaces `o` with the underlying object
536- * (already Py_INCREF'd by _PyWeakref_GET_REF), sets *did_incref = 1.
537- * - If `o` is a dead proxy: sets ReferenceError, sets `o` = NULL,
538- * sets *did_incref = 0.
539- * - If `o` is not a proxy: Py_INCREF's it, sets *did_incref = 1.
540- * Returns 1 on success, 0 on dead proxy (caller must goto error).
533+
534+ /* If a parameter is a proxy, check that it is still "live" and wrap it,
535+ * replacing the original value with the raw object. Raises ReferenceError
536+ * if the param is a dead proxy.
541537 */
542- static inline int
543- _proxy_unwrap (PyObject * * op , int * did_incref )
544- {
545- if (PyWeakref_CheckProxy (* op )) {
546- * op = _PyWeakref_GET_REF (* op );
547- if (!proxy_check_ref (* op )) {
548- * did_incref = 0 ;
549- return 0 ;
538+ #define UNWRAP (o ) \
539+ if (PyWeakref_CheckProxy(o)) { \
540+ o = _PyWeakref_GET_REF(o); \
541+ if (!proxy_check_ref(o)) { \
542+ return NULL; \
543+ } \
544+ } \
545+ else { \
546+ Py_INCREF(o); \
547+ }
548+
549+ /* Like UNWRAP, but executes `cleanup` before returning NULL.
550+ * Use when a prior UNWRAP has already incremented a refcount that
551+ * must be released if this unwrap fails.
552+ */
553+ #define UNWRAP_OR (o , cleanup ) \
554+ if (PyWeakref_CheckProxy(o)) { \
555+ o = _PyWeakref_GET_REF(o); \
556+ if (!proxy_check_ref(o)) { \
557+ cleanup; \
558+ return NULL; \
559+ } \
560+ } \
561+ else { \
562+ Py_INCREF(o); \
550563 }
551- /* _PyWeakref_GET_REF already returned a strong ref */
552- }
553- else {
554- Py_INCREF (* op );
555- }
556- * did_incref = 1 ;
557- return 1 ;
558- }
559564
560565#define WRAP_UNARY (method , generic ) \
561566 static PyObject * \
562567 method(PyObject *proxy) { \
563- int proxy_incref = 0; \
564- if (!_proxy_unwrap(&proxy, &proxy_incref)) \
565- return NULL; \
568+ UNWRAP(proxy); \
566569 PyObject* res = generic(proxy); \
567570 Py_DECREF(proxy); \
568571 return res; \
@@ -571,19 +574,12 @@ _proxy_unwrap(PyObject **op, int *did_incref)
571574#define WRAP_BINARY (method , generic ) \
572575 static PyObject * \
573576 method(PyObject *x, PyObject *y) { \
574- int x_incref = 0, y_incref = 0; \
575- if (!_proxy_unwrap(&x, &x_incref)) goto clean_up; \
576- if (!_proxy_unwrap(&y, &y_incref)) goto clean_up; \
577- { \
578- PyObject* res = generic(x, y); \
579- Py_DECREF(x); \
580- Py_DECREF(y); \
581- return res; \
582- } \
583- clean_up: \
584- if (x_incref) Py_DECREF(x); \
585- if (y_incref) Py_DECREF(y); \
586- return NULL; \
577+ UNWRAP(x); \
578+ UNWRAP_OR(y, Py_DECREF(x)); \
579+ PyObject* res = generic(x, y); \
580+ Py_DECREF(x); \
581+ Py_DECREF(y); \
582+ return res; \
587583 }
588584
589585/* Note that the third arg needs to be checked for NULL since the tp_call
@@ -592,36 +588,27 @@ _proxy_unwrap(PyObject **op, int *did_incref)
592588#define WRAP_TERNARY (method , generic ) \
593589 static PyObject * \
594590 method(PyObject *proxy, PyObject *v, PyObject *w) { \
595- int proxy_incref = 0, v_incref = 0, w_incref = 0; \
596- if (!_proxy_unwrap(&proxy, &proxy_incref)) goto clean_up; \
597- if (!_proxy_unwrap(&v, &v_incref)) goto clean_up; \
591+ UNWRAP(proxy); \
592+ UNWRAP_OR(v, Py_DECREF(proxy)); \
598593 if (w != NULL) { \
599- if (!_proxy_unwrap(& w, &w_incref)) goto clean_up ; \
594+ UNWRAP_OR( w, Py_DECREF(proxy); Py_DECREF(v)) ; \
600595 } \
601- { \
602- PyObject* res = generic(proxy, v, w); \
603- Py_DECREF(proxy); \
604- Py_DECREF(v); \
605- Py_XDECREF(w); \
606- return res; \
607- } \
608- clean_up: \
609- if (proxy_incref) Py_DECREF(proxy); \
610- if (v_incref) Py_DECREF(v); \
611- if (w_incref) Py_DECREF(w); \
612- return NULL; \
596+ PyObject* res = generic(proxy, v, w); \
597+ Py_DECREF(proxy); \
598+ Py_DECREF(v); \
599+ Py_XDECREF(w); \
600+ return res; \
613601 }
614602
615603#define WRAP_METHOD (method , SPECIAL ) \
616604 static PyObject * \
617605 method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
618- int proxy_incref = 0; \
619- if (!_proxy_unwrap(&proxy, &proxy_incref)) \
620- return NULL; \
621- PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
622- Py_DECREF(proxy); \
623- return res; \
624- }
606+ UNWRAP(proxy); \
607+ PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
608+ Py_DECREF(proxy); \
609+ return res; \
610+ }
611+
625612
626613/* direct slots */
627614
@@ -664,19 +651,12 @@ proxy_setattr(PyObject *proxy, PyObject *name, PyObject *value)
664651static PyObject *
665652proxy_richcompare (PyObject * proxy , PyObject * v , int op )
666653{
667- int proxy_incref = 0 , v_incref = 0 ;
668- if (!_proxy_unwrap (& proxy , & proxy_incref )) goto clean_up ;
669- if (!_proxy_unwrap (& v , & v_incref )) goto clean_up ;
670- {
671- PyObject * res = PyObject_RichCompare (proxy , v , op );
672- Py_DECREF (proxy );
673- Py_DECREF (v );
674- return res ;
675- }
676- clean_up :
677- if (proxy_incref ) Py_DECREF (proxy );
678- if (v_incref ) Py_DECREF (v );
679- return NULL ;
654+ UNWRAP (proxy );
655+ UNWRAP_OR (v , Py_DECREF (proxy ));
656+ PyObject * res = PyObject_RichCompare (proxy , v , op );
657+ Py_DECREF (proxy );
658+ Py_DECREF (v );
659+ return res ;
680660}
681661
682662/* number slots */
0 commit comments