8000 Address half of Mark's review · python/cpython@6c76fe3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6c76fe3

Browse files
Address half of Mark's review
1 parent d744c8a commit 6c76fe3

File tree

6 files changed

+126
-90
lines changed

6 files changed

+126
-90
lines changed

Include/internal/pycore_stackref.h

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,54 +20,88 @@ typedef union {
2020
#define Py_TAG_DEFERRED (1)
2121

2222
#define Py_TAG_PTR (0)
23-
#define Py_TAG (1)
23+
#define Py_TAG_BITS (1)
2424

2525
#ifdef Py_GIL_DISABLED
26-
static const _PyStackRef Py_STACKREF_NULL = { .bits = 0 | Py_TAG_DEFERRED};
27-
26+
static const _PyStackRef Py_STACKREF_NULL = { .bits = 0 | Py_TAG_DEFERRED};
2827
#else
29-
static const _PyStackRef Py_STACKREF_NULL = { .bits = 0 };
28+
static const _PyStackRef Py_STACKREF_NULL = { .bits = 0 };
3029
#endif
3130

3231
#define PyStackRef_IsNull(stackref) ((stackref).bits == Py_STACKREF_NULL.bits)
3332

34-
static inline int
35-
PyStackRef_IsTrue(_PyStackRef stackref) {
33+
static inline _PyStackRef
34+
PyStackRef_True(void)
35+
{
3636
#ifdef Py_GIL_DISABLED
37-
const _PyStackRef STACKREF_TRUE = {.bits = ((uintptr_t)Py_True | Py_TAG_DEFERRED)};
37+
const _PyStackRef STACKREF_TRUE = {.bits = ((uintptr_t)Py_True |
38+
Py_TAG_DEFERRED)};
3839
#else
3940
const _PyStackRef STACKREF_TRUE = {.bits = ((uintptr_t)Py_True)};
4041
#endif
41-
return stackref.bits == STACKREF_TRUE.bits;
42+
return STACKREF_TRUE;
4243
}
4344

44-
static inline int
45-
PyStackRef_IsFalse(_PyStackRef stackref) {
45+
static inline _PyStackRef
46+
PyStackRef_False(void)
47+
{
4648
#ifdef Py_GIL_DISABLED
47-
const _PyStackRef STACKREF_FALSE = {.bits = ((uintptr_t)Py_False | Py_TAG_DEFERRED)};
49+
const _PyStackRef STACKREF_FALSE = {.bits = ((uintptr_t)Py_False |
50+
Py_TAG_DEFERRED)};
4851
#else
4952
const _PyStackRef STACKREF_FALSE = {.bits = ((uintptr_t)Py_False)};
5053
#endif
51-
return stackref.bits == STACKREF_FALSE.bits;
54+
return STACKREF_FALSE;
5255
}
5356

57+
static inline _PyStackRef
58+
PyStackRef_None(void)
59+
{
60+
#ifdef Py_GIL_DISABLED
61+
const _PyStackRef STACKREF_NONE = {.bits = ((uintptr_t)Py_None |
62+
Py_TAG_DEFERRED)};
63+
#else
64+
const _PyStackRef STACKREF_NONE = {.bits = ((uintptr_t)Py_None)};
65+
#endif
66+
return STACKREF_NONE;
67+
}
68+
69+
static inline int
70+
PyStackRef_Is(_PyStackRef a, _PyStackRef b) {
71+
return a.bits == b.bits;
72+
}
73+
74+
static inline int
75+
PyStackRef_IsTrue(_PyStackRef stackref) {
76+
return PyStackRef_Is(stackref, PyStackRef_True());
77+
}
78+
79+
static inline int
80+
PyStackRef_IsFalse(_PyStackRef stackref) {
81+
return PyStackRef_Is(stackref, PyStackRef_False());
82+
}
83+
84+
static inline int
85+
PyStackRef_IsNone(_PyStackRef stackref) {
86+
return PyStackRef_Is(stackref, PyStackRef_None());
87+
}
5488

5589
static inline int
5690
PyStackRef_IsDeferred(_PyStackRef ref)
5791
{
58-
return ((ref.bits & Py_TAG) == Py_TAG_DEFERRED);
92+
return ((ref.bits & Py_TAG_BITS) == Py_TAG_DEFERRED);
5993
}
6094

6195
#ifdef Py_GIL_DISABLED
6296
// Gets a PyObject * from a _PyStackRef
6397
static inline PyObject *
6498
PyStackRef_AsPyObjectBorrow(_PyStackRef tagged)
6599
{
66-
PyObject *cleared = ((PyObject *)((tagged).bits & (~Py_TAG)));
100+
PyObject *cleared = ((PyObject *)((tagged).bits & (~Py_TAG_BITS)));
67101
return cleared;
68102
}
69103
#else
70-
// Need to define as macro because some platforms have very sensitive stack sizes.
104+
// Need to define as macro because WASI has very sensitive stack sizes.
71105
# define PyStackRef_AsPyObjectBorrow(tagged) ((PyObject *)(tagged).bits)
72106
#endif
73107

@@ -76,7 +110,7 @@ static inline _PyStackRef
76110
_PyStackRef_FromPyObjectSteal(PyObject *obj)
77111
{
78112
// Make sure we don't take an already tagged value.
79-
assert(((uintptr_t)obj & Py_TAG) == 0);
113+
assert(((uintptr_t)obj & Py_TAG_BITS) == 0);
80114
int tag = (obj == NULL || _Py_IsImmortal(obj)) ? (Py_TAG_DEFERRED) : Py_TAG_PTR;
81115
return ((_PyStackRef){.bits = ((uintptr_t)(obj)) | tag});
82116
}
@@ -93,7 +127,7 @@ static inline _PyStackRef
93127
PyStackRef_FromPyObjectNew(PyObject *obj)
94128
{
95129
// Make sure we don't take an already tagged value.
96-
assert(((uintptr_t)obj & Py_TAG) == 0);
130+
assert(((uintptr_t)obj & Py_TAG_BITS) == 0);
97131
assert(obj != NULL);
98132
// TODO (gh-117139): Add deferred objects later.
99133
if (_Py_IsImmortal(obj)) {
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
Convert the Python evaluation stack to use internal stack references. The
2-
purpose is to support tagged pointers.
2+
purpose is to support tagged pointers. In :pep:`703`, this will
3+
allow for its form of deferred reference counting, While for both
4+
the default and free-threaded builds, this sets up the infrastructure
5+
for unboxed integers in the future.

Python/bytecodes.c

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ dummy_func(
347347
int err = PyObject_IsTrue(PyStackRef_AsPyObjectBorrow(value));
348348
DECREF_INPUTS();
349349
ERROR_IF(err < 0, error);
350-
res = PyStackRef_FromPyObjectSteal(err ? Py_True : Py_False);
350+
res = err ? PyStackRef_True() : PyStackRef_False();
351351
}
352352

353353
macro(TO_BOOL) = _SPECIALIZE_TO_BOOL + unused/2 + _TO_BOOL;
@@ -363,27 +363,27 @@ dummy_func(
363363
STAT_INC(TO_BOOL, hit);
364364
if (_PyLong_IsZero((PyLongObject *)value_o)) {
365365
assert(_Py_IsImmortal(value_o));
366-
res = PyStackRef_FromPyObjectSteal(Py_False);
366+
res = PyStackRef_False();
367367
}
368368
else {
369369
DECREF_INPUTS();
370-
res = PyStackRef_FromPyObjectSteal(Py_True);
370+
res = PyStackRef_True();
371371
}
372372
}
373373

374374
inst(TO_BOOL_LIST, (unused/1, unused/2, value -- res)) {
375375
PyObject *value_o = PyStackRef_AsPyObjectBorrow(value);
376376
EXIT_IF(!PyList_CheckExact(value_o));
377377
STAT_INC(TO_BOOL, hit);
378-
res = PyStackRef_FromPyObjectSteal(Py_SIZE(value_o) ? Py_True : Py_False);
378+
res = Py_SIZE(value_o) ? PyStackRef_True() : PyStackRef_False();
379379
DECREF_INPUTS();
380380
}
381381

382382
inst(TO_BOOL_NONE, (unused/1, unused/2, value -- res)) {
383383
// This one is a bit weird, because we expect *some* failures:
384-
EXIT_IF(!Py_IsNone(PyStackRef_AsPyObjectBorrow(value)));
384+
EXIT_IF(!PyStackRef_IsNone(value));
385385
STAT_INC(TO_BOOL, hit);
386-
res = PyStackRef_FromPyObjectSteal(Py_False);
386+
res = PyStackRef_False();
387387
}
388388

389389
inst(TO_BOOL_STR, (unused/1, unused/2, value -- res)) {
@@ -392,18 +392,18 @@ dummy_func(
392392
STAT_INC(TO_BOOL, hit);
393393
if (value_o == &_Py_STR(empty)) {
394394
assert(_Py_IsImmortal(PyStackRef_AsPyObjectBorrow(value)));
395-
res = PyStackRef_FromPyObjectSteal(Py_False);
395+
res = PyStackRef_False();
396396
}
397397
else {
398398
assert(Py_SIZE(value_o));
399399
DECREF_INPUTS();
400-
res = PyStackRef_FromPyObjectSteal(Py_True);
400+
res = PyStackRef_True();
401401
}
402402
}
403403

404404
op(_REPLACE_WITH_TRUE, (value -- res)) {
405405
DECREF_INPUTS();
406-
res = PyStackRef_FromPyObjectSteal(Py_True);
406+
res = PyStackRef_True();
407407
}
408408

409409
macro(TO_BOOL_ALWAYS_TRUE) =
@@ -587,7 +587,7 @@ dummy_func(
587587

588588
assert(next_instr->op.code == STORE_FAST);
589589
_PyStackRef *target_local = &GETLOCAL(next_instr->op.arg);
590-
DEOPT_IF(PyStackRef_AsPyObjectBorrow(*target_local) != left_o);
590+
DEOPT_IF(!PyStackRef_Is(*target_local, left));
591591
STAT_INC(BINARY_OP, hit);
592592
/* Handle `left = left + right` or `left += right` for str.
593593
*
@@ -1131,7 +1131,7 @@ dummy_func(
11311131
frame->return_offset = (uint16_t)(next_instr - this_instr + oparg);
11321132
DISPATCH_INLINED(gen_frame);
11331133
}
1134-
if (Py_IsNone(v_o) && PyIter_Check(receiver_o)) {
1134+
if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) {
11351135
retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o);
11361136
}
11371137
else {
@@ -1287,9 +1287,9 @@ dummy_func(
12871287
assert(exc_value && PyExceptionInstance_Check(exc_value));
12881288

12891289
if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) {
1290-
value = PyStackRef_FromPyObjectSteal(Py_NewRef(((PyStopIterationObject *)exc_value)->value));
1290+
value = PyStackRef_FromPyObjectNew(((PyStopIterationObject *)exc_value)->value);
12911291
DECREF_INPUTS();
1292-
none = PyStackRef_FromPyObjectSteal(Py_None);
1292+
none = PyStackRef_None();
12931293
}
12941294
else {
12951295
_PyErr_SetRaisedException(tstate, Py_NewRef(exc_value));
@@ -2718,7 +2718,7 @@ dummy_func(
27182718

27192719
replaced op(_POP_JUMP_IF_FALSE, (cond -- )) {
27202720
assert(PyBool_Check(PyStackRef_AsPyObjectBorrow(cond)));
2721-
int flag = Py_IsFalse(PyStackRef_AsPyObjectBorrow(cond));
2721+
int flag = PyStackRef_IsFalse(cond);
27222722
#if ENABLE_SPECIALIZATION
27232723
this_instr[1].cache = (this_instr[1].cache << 1) | flag;
27242724
#endif
@@ -2735,11 +2735,11 @@ dummy_func(
27352735
}
27362736

27372737
op(_IS_NONE, (value -- b)) {
2738-
if (Py_IsNone(PyStackRef_AsPyObjectBorrow(value))) {
2739-
b = PyStackRef_FromPyObjectSteal(Py_True);
2738+
if (PyStackRef_IsNone(value)) {
2739+
b = PyStackRef_True();
27402740
}
27412741
else {
2742-
b = PyStackRef_FromPyObjectSteal(Py_False);
2742+
b = PyStackRef_False();
27432743
DECREF_INPUTS();
27442744
}
27452745
}
@@ -3091,7 +3091,7 @@ dummy_func(
30913091
DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING);
30923092
STAT_INC(FOR_ITER, hit);
30933093
_PyInterpreterFrame *gen_frame_o = (_PyInterpreterFrame *)(_PyInterpreterFrame *)gen->gi_iframe;
3094-
_PyFrame_StackPush(gen_frame_o, PyStackRef_FromPyObjectSteal(Py_None));
3094+
_PyFrame_StackPush(gen_frame_o, PyStackRef_None());
30953095
gen->gi_frame_state = FRAME_EXECUTING;
30963096
gen->gi_exc_state.previous_item = tstate->exc_info;
30973097
tstate->exc_info = &gen->gi_exc_state;
@@ -3248,7 +3248,7 @@ dummy_func(
32483248
prev_exc = PyStackRef_FromPyObjectSteal(exc_info->exc_value);
32493249
}
32503250
else {
3251-
prev_exc = PyStackRef_FromPyObjectSteal(Py_None);
3251+
prev_exc = PyStackRef_None();
32523252
}
32533253
assert(PyExceptionInstance_Check(PyStackRef_AsPyObjectBorrow(new_exc)));
32543254
exc_info->exc_value = Py_NewRef(PyStackRef_AsPyObjectBorrow(new_exc));
@@ -4582,8 +4582,7 @@ dummy_func(
45824582

45834583
inst(INSTRUMENTED_POP_JUMP_IF_NONE, (unused/1 -- )) {
45844584
_PyStackRef value_stackref = POP();
4585-
PyObject *value = PyStackRef_AsPyObjectBorrow(value_stackref);
4586-
int flag = Py_IsNone(value);
4585+
int flag = PyStackRef_IsNone(value_stackref);
45874586
int offset;
45884587
if (flag) {
45894588
offset = oparg;
@@ -4600,9 +4599,8 @@ dummy_func(
46004599

46014600
inst(INSTRUMENTED_POP_JUMP_IF_NOT_NONE, (unused/1 -- )) {
46024601
_PyStackRef value_stackref = POP();
4603-
PyObject *value = PyStackRef_AsPyObjectBorrow(value_stackref);
46044602
int offset;
4605-
int nflag = Py_IsNone(value);
4603+
int nflag = PyStackRef_IsNone(value_stackref);
46064604
if (nflag) {
46074605
offset = 0;
46084606
}
@@ -4653,20 +4651,18 @@ dummy_func(
46534651
}
46544652

46554653
op (_GUARD_IS_NONE_POP, (val -- )) {
4656-
PyObject *val_o = PyStackRef_AsPyObjectBorrow(val);
46574654

46584655
SYNC_SP();
4659-
if (!Py_IsNone(val_o)) {
4656+
if (!PyStackRef_IsNone(value)) {
46604657
PyStackRef_CLOSE(val);
46614658
EXIT_IF(1);
46624659
}
46634660
}
46644661

46654662
op (_GUARD_IS_NOT_NONE_POP, (val -- )) {
4666-
PyObject *val_o = PyStackRef_AsPyObjectBorrow(val);
46674663

46684664
SYNC_SP();
4669-
EXIT_IF(Py_IsNone(val_o));
4665+
EXIT_IF(PyStackRef_IsNone(val));
46704666
PyStackRef_CLOSE(val);
46714667
}
46724668

0 commit comments

Comments
 (0)
0