Skip to content

Commit f3c118a

Browse files
Revert "keep the old UNWRAP Macro and create a new MACRO UNWRAP_OR to cleam the"
This reverts commit a50b3a4.
1 parent e515fea commit f3c118a

File tree

1 file changed

+76
-56
lines changed

1 file changed

+76
-56
lines changed

Objects/weakrefobject.c

Lines changed: 76 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -530,42 +530,39 @@ proxy_check_ref(PyObject *obj)
530530
return true;
531531
}
532532

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.
537-
*/
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.
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).
552541
*/
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); \
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;
563550
}
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+
}
564559

565560
#define WRAP_UNARY(method, generic) \
566561
static PyObject * \
567562
method(PyObject *proxy) { \
568-
UNWRAP(proxy); \
563+
int proxy_incref = 0; \
564+
if (!_proxy_unwrap(&proxy, &proxy_incref)) \
565+
return NULL; \
569566
PyObject* res = generic(proxy); \
570567
Py_DECREF(proxy); \
571568
return res; \
@@ -574,12 +571,19 @@ proxy_check_ref(PyObject *obj)
574571
#define WRAP_BINARY(method, generic) \
575572
static PyObject * \
576573
method(PyObject *x, PyObject *y) { \
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; \
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; \
583587
}
584588

585589
/* Note that the third arg needs to be checked for NULL since the tp_call
@@ -588,27 +592,36 @@ proxy_check_ref(PyObject *obj)
588592
#define WRAP_TERNARY(method, generic) \
589593
static PyObject * \
590594
method(PyObject *proxy, PyObject *v, PyObject *w) { \
591-
UNWRAP(proxy); \
592-
UNWRAP_OR(v, Py_DECREF(proxy)); \
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; \
593598
if (w != NULL) { \
594-
UNWRAP_OR(w, Py_DECREF(proxy); Py_DECREF(v)); \
599+
if (!_proxy_unwrap(&w, &w_incref)) goto clean_up; \
595600
} \
596-
PyObject* res = generic(proxy, v, w); \
597-
Py_DECREF(proxy); \
598-
Py_DECREF(v); \
599-
Py_XDECREF(w); \
600-
return res; \
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; \
601613
}
602614

603615
#define WRAP_METHOD(method, SPECIAL) \
604616
static PyObject * \
605617
method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
606-
UNWRAP(proxy); \
607-
PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
608-
Py_DECREF(proxy); \
609-
return res; \
610-
}
611-
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+
}
612625

613626
/* direct slots */
614627

@@ -651,12 +664,19 @@ proxy_setattr(PyObject *proxy, PyObject *name, PyObject *value)
651664
static PyObject *
652665
proxy_richcompare(PyObject *proxy, PyObject *v, int op)
653666
{
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;
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;
660680
}
661681

662682
/* number slots */

0 commit comments

Comments
 (0)