Skip to content

Commit 220f3bf

Browse files
add a cleanup using goto instead of returningh null
1 parent d3064d7 commit 220f3bf

File tree

1 file changed

+74
-61
lines changed

1 file changed

+74
-61
lines changed

Objects/weakrefobject.c

Lines changed: 74 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -530,24 +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.
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).
537541
*/
538-
#define UNWRAP(o) \
539-
if (PyWeakref_CheckProxy(o)) { \
540-
o = _PyWeakref_GET_REF(o); \
541-
proxy_check_ref(o); \
542-
} \
543-
else { \
544-
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;
545550
}
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+
}
546559

547560
#define WRAP_UNARY(method, generic) \
548561
static PyObject * \
549562
method(PyObject *proxy) { \
550-
UNWRAP(proxy); \
563+
int proxy_incref = 0; \
564+
if (!_proxy_unwrap(&proxy, &proxy_incref)) \
565+
return NULL; \
551566
PyObject* res = generic(proxy); \
552567
Py_DECREF(proxy); \
553568
return res; \
@@ -556,18 +571,19 @@ proxy_check_ref(PyObject *obj)
556571
#define WRAP_BINARY(method, generic) \
557572
static PyObject * \
558573
method(PyObject *x, PyObject *y) { \
559-
UNWRAP(x); \
560-
if (x == NULL) \
561-
return NULL; \
562-
UNWRAP(y); \
563-
if (y == NULL) { \
564-
Py_XDECREF(x); \
565-
return NULL; \
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; \
566582
} \
567-
PyObject* res = generic(x, y); \
568-
Py_DECREF(x); \
569-
Py_DECREF(y); \
570-
return res; \
583+
clean_up: \
584+
if (x_incref) Py_DECREF(x); \
585+
if (y_incref) Py_DECREF(y); \
586+
return NULL; \
571587
}
572588

573589
/* Note that the third arg needs to be checked for NULL since the tp_call
@@ -576,40 +592,36 @@ proxy_check_ref(PyObject *obj)
576592
#define WRAP_TERNARY(method, generic) \
577593
static PyObject * \
578594
method(PyObject *proxy, PyObject *v, PyObject *w) { \
579-
UNWRAP(proxy); \
580-
if (proxy == NULL) \
581-
return NULL; \
582-
UNWRAP(v); \
583-
if (v == NULL) { \
584-
Py_XDECREF(proxy); \
585-
return NULL; \
586-
} \
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; \
587598
if (w != NULL) { \
588-
UNWRAP(w); \
589-
if (w == NULL) { \
590-
Py_XDECREF(proxy); \
591-
Py_XDECREF(v); \
592-
return NULL; \
593-
} \
599+
if (!_proxy_unwrap(&w, &w_incref)) goto clean_up; \
594600
} \
595-
PyObject* res = generic(proxy, v, w); \
596-
Py_DECREF(proxy); \
597-
Py_DECREF(v); \
598-
Py_XDECREF(w); \
599-
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; \
600613
}
601614

602615
#define WRAP_METHOD(method, SPECIAL) \
603616
static PyObject * \
604617
method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
605-
UNWRAP(proxy); \
606-
if (proxy == NULL) \
607-
return NULL; \
608-
PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
609-
Py_DECREF(proxy); \
610-
return res; \
611-
}
612-
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+
}
613625

614626
/* direct slots */
615627

@@ -652,18 +664,19 @@ proxy_setattr(PyObject *proxy, PyObject *name, PyObject *value)
652664
static PyObject *
653665
proxy_richcompare(PyObject *proxy, PyObject *v, int op)
654666
{
655-
UNWRAP(proxy);
656-
if (proxy == NULL)
657-
return NULL;
658-
UNWRAP(v);
659-
if (v == NULL) {
660-
Py_XDECREF(proxy);
661-
return NULL;
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;
662675
}
663-
PyObject* res = PyObject_RichCompare(proxy, v, op);
664-
Py_DECREF(proxy);
665-
Py_DECREF(v);
666-
return res;
676+
clean_up:
677+
if (proxy_incref) Py_DECREF(proxy);
678+
if (v_incref) Py_DECREF(v);
679+
return NULL;
667680
}
668681

669682
/* number slots */

0 commit comments

Comments
 (0)