Skip to content

Commit c88bcbc

Browse files
committed
Avoid INCREF + Steal pairs by using New or return stack ref directly
1 parent 0c20416 commit c88bcbc

File tree

7 files changed

+92
-76
lines changed

7 files changed

+92
-76
lines changed

Include/internal/pycore_ceval.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ _Py_eval_breaker_bit_is_set(PyThreadState *tstate, uintptr_t bit)
325325
void _Py_set_eval_breaker_bit_all(PyInterpreterState *interp, uintptr_t bit);
326326
void _Py_unset_eval_breaker_bit_all(PyInterpreterState *interp, uintptr_t bit);
327327

328-
PyAPI_FUNC(PyObject *) _PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, double value);
328+
PyAPI_FUNC(_PyStackRef) _PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, double value);
329329

330330

331331
#ifdef __cplusplus

Include/internal/pycore_long.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ PyAPI_DATA(PyObject*) _PyLong_Rshift(PyObject *, int64_t);
109109
// Export for 'math' shared extension
110110
PyAPI_DATA(PyObject*) _PyLong_Lshift(PyObject *, int64_t);
111111

112-
PyAPI_FUNC(PyObject*) _PyLong_Add(PyLongObject *left, PyLongObject *right);
112+
PyAPI_FUNC(_PyStackRef) _PyLong_Add(PyLongObject *left, PyLongObject *right);
113113
PyAPI_FUNC(PyObject*) _PyLong_Multiply(PyLongObject *left, PyLongObject *right);
114114
PyAPI_FUNC(PyObject*) _PyLong_Subtract(PyLongObject *left, PyLongObject *right);
115115

Objects/floatobject.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -136,34 +136,37 @@ PyFloat_FromDouble(double fval)
136136

137137
#ifdef Py_GIL_DISABLED
138138

139-
PyObject *_PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, double value)
139+
_PyStackRef _PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, double value)
140140
{
141141
PyStackRef_CLOSE(left);
142142
PyStackRef_CLOSE(right);
143-
return PyFloat_FromDouble(value);
143+
return PyStackRef_FromPyObjectSteal(PyFloat_FromDouble(value));
144144
}
145145

146146
#else // Py_GIL_DISABLED
147147

148-
PyObject *_PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, double value)
148+
_PyStackRef _PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef right, double value)
149149
{
150-
PyObject *left_o = PyStackRef_AsPyObjectSteal(left);
151-
PyObject *right_o = PyStackRef_AsPyObjectSteal(right);
150+
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
151+
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
152152
if (Py_REFCNT(left_o) == 1) {
153153
((PyFloatObject *)left_o)->ob_fval = value;
154-
_Py_DECREF_SPECIALIZED(right_o, _PyFloat_ExactDealloc);
155-
return left_o;
154+
PyStackRef_CLOSE(right);
155+
return left;
156156
}
157157
else if (Py_REFCNT(right_o) == 1) {
158158
((PyFloatObject *)right_o)->ob_fval = value;
159-
_Py_DECREF_NO_DEALLOC(left_o);
160-
return right_o;
159+
PyStackRef_CLOSE(left);
160+
return right;
161161
}
162162
else {
163163
PyObject *result = PyFloat_FromDouble(value);
164-
_Py_DECREF_NO_DEALLOC(left_o);
165-
_Py_DECREF_NO_DEALLOC(right_o);
166-
return result;
164+
PyStackRef_CLOSE(left);
165+
PyStackRef_CLOSE(right);
166+
if (result == NULL) {
167+
return PyStackRef_NULL;
168+
}
169+
return PyStackRef_FromPyObjectStealMortal(result);
167170
}
168171
}
169172

Objects/longobject.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,27 @@ _PyLong_FromSTwoDigits(stwodigits x)
286286
return (PyLongObject*)_PyLong_FromLarge(x);
287287
}
288288

289+
/* Create a new int object from a C word-sized int, return a stackref */
290+
static inline _PyStackRef
291+
_PyLongRef_FromSTwoDigitsRef(stwodigits x)
292+
{
293+
if (IS_SMALL_INT(x)) {
294+
return PyStackRef_FromPyObjectImmortal(get_small_int((sdigit)x));
295+
}
296+
assert(x != 0);
297+
PyObject *res;
298+
if (is_medium_int(x)) {
299+
res = _PyLong_FromMedium((sdigit)x);
300+
}
301+
else {
302+
res = _PyLong_FromLarge(x);
303+
}
304+
if (res == NULL) {
305+
return PyStackRef_NULL;
306+
}
307+
return PyStackRef_FromPyObjectStealMortal(res);
308+
}
309+
289310
/* If a freshly-allocated int is already shared, it must
290311
be a small integer, so negating it must go to PyLong_FromLong */
291312
Py_LOCAL_INLINE(void)
@@ -3812,10 +3833,14 @@ long_add(PyLongObject *a, PyLongObject *b)
38123833
return z;
38133834
}
38143835

3815-
PyObject *
3836+
_PyStackRef
38163837
_PyLong_Add(PyLongObject *a, PyLongObject *b)
38173838
{
3818-
return (PyObject*)long_add(a, b);
3839+
if (_PyLong_BothAreCompact(a, b)) {
3840+
stwodigits z = medium_value(a) + medium_value(b);
3841+
return _PyLongRef_FromSTwoDigitsRef(z);
3842+
}
3843+
return PyStackRef_FromPyObjectSteal((PyObject*)long_add(a, b));
38193844
}
38203845

38213846
static PyObject *

Python/bytecodes.c

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -542,12 +542,11 @@ dummy_func(
542542
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
543543

544544
STAT_INC(BINARY_OP, hit);
545-
PyObject *res_o = _PyLong_Add((PyLongObject *)left_o, (PyLongObject *)right_o);
545+
res = _PyLong_Add((PyLongObject *)left_o, (PyLongObject *)right_o);
546546
PyStackRef_CLOSE_SPECIALIZED(right, (destructor)PyObject_Free);
547547
PyStackRef_CLOSE_SPECIALIZED(left, (destructor)PyObject_Free);
548548
INPUTS_DEAD();
549-
ERROR_IF(res_o == NULL, error);
550-
res = PyStackRef_FromPyObjectSteal(res_o);
549+
ERROR_IF(PyStackRef_IsNull(res), error);
551550
}
552551

553552
pure op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) {
@@ -595,10 +594,9 @@ dummy_func(
595594
double dres =
596595
((PyFloatObject *)left_o)->ob_fval *
597596
((PyFloatObject *)right_o)->ob_fval;
598-
PyObject *res_o = _PyFloat_FromDouble_ConsumeInputs(left, right, dres);
597+
res = _PyFloat_FromDouble_ConsumeInputs(left, right, dres);
599598
INPUTS_DEAD();
600-
ERROR_IF(res_o == NULL, error);
601-
res = PyStackRef_FromPyObjectSteal(res_o);
599+
ERROR_IF(PyStackRef_IsNull(res), error);
602600
}
603601

604602
pure op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) {
@@ -609,10 +607,9 @@ dummy_func(
609607
double dres =
610608
((PyFloatObject *)left_o)->ob_fval +
611609
((PyFloatObject *)right_o)->ob_fval;
612-
PyObject *res_o = _PyFloat_FromDouble_ConsumeInputs(left, right, dres);
610+
res = _PyFloat_FromDouble_ConsumeInputs(left, right, dres);
613611
INPUTS_DEAD();
614-
ERROR_IF(res_o == NULL, error);
615-
res = PyStackRef_FromPyObjectSteal(res_o);
612+
ERROR_IF(PyStackRef_IsNull(res), error);
616613
}
617614

618615
pure op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res)) {
@@ -623,10 +620,9 @@ dummy_func(
623620
double dres =
624621
((PyFloatObject *)left_o)->ob_fval -
625622
((PyFloatObject *)right_o)->ob_fval;
626-
PyObject *res_o = _PyFloat_FromDouble_ConsumeInputs(left, right, dres);
623+
res = _PyFloat_FromDouble_ConsumeInputs(left, right, dres);
627624
INPUTS_DEAD();
628-
ERROR_IF(res_o == NULL, error);
629-
res = PyStackRef_FromPyObjectSteal(res_o);
625+
ERROR_IF(PyStackRef_IsNull(res), error);
630626
}
631627

632628
macro(BINARY_OP_MULTIPLY_FLOAT) =
@@ -807,17 +803,18 @@ dummy_func(
807803
PyObject *res_o = _PyList_GetItemRef((PyListObject*)list, index);
808804
DEOPT_IF(res_o == NULL);
809805
STAT_INC(BINARY_SUBSCR, hit);
806+
PyStackRef_CLOSE_SPECIALIZED(sub_st, (destructor)PyObject_Free);
807+
DEAD(sub_st);
808+
PyStackRef_CLOSE(list_st);
809+
res = PyStackRef_FromPyObjectSteal(res_o);
810810
#else
811811
DEOPT_IF(index >= PyList_GET_SIZE(list));
812812
STAT_INC(BINARY_SUBSCR, hit);
813813
PyObject *res_o = PyList_GET_ITEM(list, index);
814814
assert(res_o != NULL);
815-
Py_INCREF(res_o);
815+
res = PyStackRef_FromPyObjectNew(res_o);
816+
DECREF_INPUTS();
816817
#endif
817-
PyStackRef_CLOSE_SPECIALIZED(sub_st, (destructor)PyObject_Free);
818-
DEAD(sub_st);
819-
PyStackRef_CLOSE(list_st);
820-
res = PyStackRef_FromPyObjectSteal(res_o);
821818
}
822819

823820
inst(BINARY_SUBSCR_STR_INT, (unused/1, str_st, sub_st -- res)) {
@@ -854,11 +851,8 @@ dummy_func(
854851
STAT_INC(BINARY_SUBSCR, hit);
855852
PyObject *res_o = PyTuple_GET_ITEM(tuple, index);
856853
assert(res_o != NULL);
857-
Py_INCREF(res_o);
858-
PyStackRef_CLOSE_SPECIALIZED(sub_st, (destructor)PyObject_Free);
859-
DEAD(sub_st);
860-
PyStackRef_CLOSE(tuple_st);
861-
res = PyStackRef_FromPyObjectSteal(res_o);
854+
res = PyStackRef_FromPyObjectNew(res_o);
855+
DECREF_INPUTS();
862856
}
863857

864858
inst(BINARY_SUBSCR_DICT, (unused/1, dict_st, sub_st -- res)) {

Python/executor_cases.c.h

Lines changed: 16 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 16 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)