Skip to content

Commit 497fb9f

Browse files
committed
Reduce overhead of stackrefs a tiny bit for mortal objects
1 parent 3a12d18 commit 497fb9f

File tree

6 files changed

+65
-72
lines changed

6 files changed

+65
-72
lines changed

Include/internal/pycore_stackref.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ PyStackRef_IsNone(_PyStackRef ref)
261261

262262
#endif
263263

264+
/* Does this ref have an embedded refcount */
264265
static inline int
265266
PyStackRef_HasCount(_PyStackRef ref)
266267
{
@@ -298,9 +299,6 @@ PyStackRef_AsPyObjectSteal(_PyStackRef ref)
298299
}
299300
}
300301

301-
/* We will want to extend this to a larger set of objects in the future */
302-
#define _Py_IsDeferrable _Py_IsImmortal
303-
304302
static inline _PyStackRef
305303
PyStackRef_FromPyObjectSteal(PyObject *obj)
306304
{
@@ -311,6 +309,16 @@ PyStackRef_FromPyObjectSteal(PyObject *obj)
311309
return ref;
312310
}
313311

312+
static inline _PyStackRef
313+
PyStackRef_FromPyObjectStealMortal(PyObject *obj)
314+
{
315+
assert(obj != NULL);
316+
assert(!_Py_IsImmortal(obj));
317+
_PyStackRef ref = ((_PyStackRef){.bits = ((uintptr_t)(obj)) });
318+
PyStackRef_CheckValid(ref);
319+
return ref;
320+
}
321+
314322
// Check if a stackref is exactly the same as another stackref, including the
315323
// the deferred bit. This can only be used safely if you know that the deferred
316324
// bits of `a` and `b` match.
@@ -320,6 +328,7 @@ PyStackRef_FromPyObjectSteal(PyObject *obj)
320328
static inline _PyStackRef
321329
_PyStackRef_FromPyObjectNew(PyObject *obj)
322330
{
331+
assert(obj != NULL);
323332
if (_Py_IsImmortal(obj)) {
324333
return (_PyStackRef){ .bits = ((uintptr_t)obj) | Py_TAG_IMMORTAL};
325334
}

Python/bytecodes.c

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ dummy_func(
837837
PyStackRef_CLOSE_SPECIALIZED(sub_st, (destructor)PyObject_Free);
838838
DEAD(sub_st);
839839
PyStackRef_CLOSE(str_st);
840-
res = PyStackRef_FromPyObjectSteal(res_o);
840+
res = PyStackRef_FromPyObjectImmortal(res_o);
841841
}
842842

843843
inst(BINARY_SUBSCR_TUPLE_INT, (unused/1, tuple_st, sub_st -- res)) {
@@ -1662,8 +1662,7 @@ dummy_func(
16621662
int increfed = _Py_TryIncrefCompareStackRef(&entries[index].me_value, res_o, &res);
16631663
DEOPT_IF(!increfed);
16641664
#else
1665-
Py_INCREF(res_o);
1666-
res = PyStackRef_FromPyObjectSteal(res_o);
1665+
res = PyStackRef_FromPyObjectNew(res_o);
16671666
#endif
16681667
STAT_INC(LOAD_GLOBAL, hit);
16691668
null = PyStackRef_NULL;
@@ -1679,8 +1678,7 @@ dummy_func(
16791678
int increfed = _Py_TryIncrefCompareStackRef(&entries[index].me_value, res_o, &res);
16801679
DEOPT_IF(!increfed);
16811680
#else
1682-
Py_INCREF(res_o);
1683-
res = PyStackRef_FromPyObjectSteal(res_o);
1681+
res = PyStackRef_FromPyObjectNew(res_o);
16841682
#endif
16851683
STAT_INC(LOAD_GLOBAL, hit);
16861684
null = PyStackRef_NULL;
@@ -1718,7 +1716,7 @@ dummy_func(
17181716
if (cell == NULL) {
17191717
ERROR_NO_POP();
17201718
}
1721-
SETLOCAL(oparg, PyStackRef_FromPyObjectSteal(cell));
1719+
SETLOCAL(oparg, PyStackRef_FromPyObjectStealMortal(cell));
17221720
}
17231721

17241722
inst(DELETE_DEREF, (--)) {
@@ -1800,17 +1798,18 @@ dummy_func(
18001798
}
18011799

18021800
inst(BUILD_TUPLE, (values[oparg] -- tup)) {
1801+
assert(oparg != 0);
18031802
PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg);
18041803
INPUTS_DEAD();
18051804
ERROR_IF(tup_o == NULL, error);
1806-
tup = PyStackRef_FromPyObjectSteal(tup_o);
1805+
tup = PyStackRef_FromPyObjectStealMortal(tup_o);
18071806
}
18081807

18091808
inst(BUILD_LIST, (values[oparg] -- list)) {
18101809
PyObject *list_o = _PyList_FromStackRefSteal(values, oparg);
18111810
INPUTS_DEAD();
18121811
ERROR_IF(list_o == NULL, error);
1813-
list = PyStackRef_FromPyObjectSteal(list_o);
1812+
list = PyStackRef_FromPyObjectStealMortal(list_o);
18141813
}
18151814

18161815
inst(LIST_EXTEND, (list_st, unused[oparg-1], iterable_st -- list_st, unused[oparg-1])) {
@@ -1860,7 +1859,7 @@ dummy_func(
18601859
Py_DECREF(set_o);
18611860
ERROR_IF(true, error);
18621861
}
1863-
set = PyStackRef_FromPyObjectSteal(set_o);
1862+
set = PyStackRef_FromPyObjectStealMortal(set_o);
18641863
}
18651864

18661865
inst(BUILD_MAP, (values[oparg*2] -- map)) {
@@ -1876,7 +1875,7 @@ dummy_func(
18761875
STACKREFS_TO_PYOBJECTS_CLEANUP(values_o);
18771876
DECREF_INPUTS();
18781877
ERROR_IF(map_o == NULL, error);
1879-
map = PyStackRef_FromPyObjectSteal(map_o);
1878+
map = PyStackRef_FromPyObjectStealMortal(map_o);
18801879
}
18811880

18821881
inst(SETUP_ANNOTATIONS, (--)) {
@@ -2158,9 +2157,8 @@ dummy_func(
21582157
PyObject *attr_o = *value_ptr;
21592158
DEOPT_IF(attr_o == NULL);
21602159
STAT_INC(LOAD_ATTR, hit);
2161-
Py_INCREF(attr_o);
21622160
null = PyStackRef_NULL;
2163-
attr = PyStackRef_FromPyObjectSteal(attr_o);
2161+
attr = PyStackRef_FromPyObjectNew(attr_o);
21642162
DECREF_INPUTS();
21652163
}
21662164

@@ -2188,8 +2186,7 @@ dummy_func(
21882186
PyObject *attr_o = ep->me_value;
21892187
DEOPT_IF(attr_o == NULL);
21902188
STAT_INC(LOAD_ATTR, hit);
2191-
Py_INCREF(attr_o);
2192-
attr = PyStackRef_FromPyObjectSteal(attr_o);
2189+
attr = PyStackRef_FromPyObjectNew(attr_o);
21932190
null = PyStackRef_NULL;
21942191
DECREF_INPUTS();
21952192
}
@@ -2222,8 +2219,7 @@ dummy_func(
22222219
attr_o = ep->me_value;
22232220
DEOPT_IF(attr_o == NULL);
22242221
STAT_INC(LOAD_ATTR, hit);
2225-
Py_INCREF(attr_o);
2226-
attr = PyStackRef_FromPyObjectSteal(attr_o);
2222+
attr = PyStackRef_FromPyObjectNew(attr_o);
22272223
null = PyStackRef_NULL;
22282224
DECREF_INPUTS();
22292225
}
@@ -3681,7 +3677,7 @@ dummy_func(
36813677
DEOPT_IF(callable_o != (PyObject *)&PyType_Type);
36823678
DEAD(callable);
36833679
STAT_INC(CALL, hit);
3684-
res = PyStackRef_FromPyObjectSteal(Py_NewRef(Py_TYPE(arg_o)));
3680+
res = PyStackRef_FromPyObjectNew(Py_TYPE(arg_o));
36853681
PyStackRef_CLOSE(arg);
36863682
}
36873683

@@ -4596,7 +4592,7 @@ dummy_func(
45964592
frame = tstate->current_frame = prev;
45974593
LOAD_IP(frame->return_offset);
45984594
RELOAD_STACK();
4599-
res = PyStackRef_FromPyObjectSteal((PyObject *)gen);
4595+
res = PyStackRef_FromPyObjectStealMortal((PyObject *)gen);
46004596
LLTRACE_RESUME_FRAME();
46014597
}
46024598

@@ -4608,7 +4604,7 @@ dummy_func(
46084604
PyObject *slice_o = PySlice_New(start_o, stop_o, step_o);
46094605
DECREF_INPUTS();
46104606
ERROR_IF(slice_o == NULL, error);
4611-
slice = PyStackRef_FromPyObjectSteal(slice_o);
4607+
slice = PyStackRef_FromPyObjectStealMortal(slice_o);
46124608
}
46134609

46144610
inst(CONVERT_VALUE, (value -- result)) {
@@ -4955,8 +4951,7 @@ dummy_func(
49554951
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
49564952
PyObject *res_o = entries[index].me_value;
49574953
DEOPT_IF(res_o == NULL);
4958-
Py_INCREF(res_o);
4959-
res = PyStackRef_FromPyObjectSteal(res_o);
4954+
res = PyStackRef_FromPyObjectNew(res_o);
49604955
null = PyStackRef_NULL;
49614956
}
49624957

@@ -4965,8 +4960,7 @@ dummy_func(
49654960
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
49664961
PyObject *res_o = entries[index].me_value;
49674962
DEOPT_IF(res_o == NULL);
4968-
Py_INCREF(res_o);
4969-
res = PyStackRef_FromPyObjectSteal(res_o);
4963+
res = PyStackRef_FromPyObjectNew(res_o);
49704964
null = PyStackRef_NULL;
49714965
}
49724966

Python/executor_cases.c.h

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

0 commit comments

Comments
 (0)