Skip to content

Commit 6fde7b0

Browse files
committed
Rename _PyStackRef_StealIfUnborrowed
1 parent 6568fd9 commit 6fde7b0

File tree

7 files changed

+37
-49
lines changed

7 files changed

+37
-49
lines changed

Include/internal/pycore_frame.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,23 +152,21 @@ _PyFrame_NumSlotsForCodeObject(PyCodeObject *code)
152152
return code->co_framesize - FRAME_SPECIALS_SIZE;
153153
}
154154

155-
static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
155+
static inline void
156+
_PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
156157
{
157158
*dest = *src;
158159
assert(src->stackpointer != NULL);
159160
int stacktop = (int)(src->stackpointer - src->localsplus);
160161
assert(stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
161162
dest->stackpointer = dest->localsplus + stacktop;
163+
// The generator may outlive any references that were providing "support"
164+
// for borrowed references in the frame. Convert them to strong references.
162165
for (int i = 0; i < stacktop; i++) {
163-
dest->localsplus[i] = _PyStackRef_StealIfUnborrowed(src->localsplus[i]);
164-
}
165-
// XXX - More efficient version of this?
166-
if (_PyStackRef_IsBorrowed(dest->f_executable)) {
167-
dest->f_executable = PyStackRef_FromPyObjectNew(PyStackRef_AsPyObjectBorrow(dest->f_executable));
168-
}
169-
if (_PyStackRef_IsBorrowed(dest->f_funcobj)) {
170-
dest->f_funcobj = PyStackRef_FromPyObjectNew(PyStackRef_AsPyObjectBorrow(dest->f_funcobj));
166+
dest->localsplus[i] = _PyStackRef_NewIfBorrowedOrSteal(src->localsplus[i]);
171167
}
168+
dest->f_executable = _PyStackRef_NewIfBorrowedOrSteal(dest->f_executable);
169+
dest->f_funcobj = _PyStackRef_NewIfBorrowedOrSteal(dest->f_funcobj);
172170
// Don't leave a dangling pointer to the old frame when creating generators
173171
// and coroutines:
174172
dest->previous = NULL;

Include/internal/pycore_stackref.h

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -213,24 +213,6 @@ _PyStackRef_FromPyObjectSteal(PyObject *obj)
213213
}
214214
# define PyStackRef_FromPyObjectSteal(obj) _PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj))
215215

216-
static inline _PyStackRef
217-
_PyStackRef_StealIfUnborrowed(_PyStackRef stackref)
218-
{
219-
if (PyStackRef_IsNull(stackref)) {
220-
return stackref;
221-
}
222-
if (PyStackRef_IsDeferred(stackref)) {
223-
PyObject *obj = PyStackRef_AsPyObjectBorrow(stackref);
224-
if (_Py_IsImmortal(obj) || _PyObject_HasDeferredRefcount(obj)) {
225-
return stackref;
226-
}
227-
else {
228-
return (_PyStackRef){ .bits = (uintptr_t)(Py_NewRef(obj)) | Py_TAG_PTR };
229-
}
230-
}
231-
return stackref;
232-
}
233-
234216
static inline bool
235217
_PyStackRef_IsBorrowed(_PyStackRef stackref)
236218
{
@@ -241,6 +223,17 @@ _PyStackRef_IsBorrowed(_PyStackRef stackref)
241223
return !(_Py_IsImmortal(obj) || _PyObject_HasDeferredRefcount(obj));
242224
}
243225

226+
227+
static inline _PyStackRef
228+
_PyStackRef_NewIfBorrowedOrSteal(_PyStackRef stackref)
229+
{
230+
if (_PyStackRef_IsBorrowed(stackref)) {
231+
PyObject *obj = PyStackRef_AsPyObjectBorrow(stackref);
232+
return (_PyStackRef){ .bits = (uintptr_t)(Py_NewRef(obj)) | Py_TAG_PTR };
233+
}
234+
return stackref;
235+
}
236+
244237
static inline _PyStackRef
245238
PyStackRef_FromPyObjectNew(PyObject *obj)
246239
{

Python/bytecodes.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,7 @@ dummy_func(
11031103
// is pushed to a different frame, the callers' frame.
11041104
inst(RETURN_VALUE, (retval -- res)) {
11051105
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
1106-
_PyStackRef temp = _PyStackRef_StealIfUnborrowed(retval);
1106+
_PyStackRef temp = _PyStackRef_NewIfBorrowedOrSteal(retval);
11071107
DEAD(retval);
11081108
SAVE_STACK();
11091109
assert(EMPTY());
@@ -1201,7 +1201,7 @@ dummy_func(
12011201

12021202
PyObject *retval_o;
12031203
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
1204-
_PyStackRef tmp = _PyStackRef_StealIfUnborrowed(v);
1204+
_PyStackRef tmp = _PyStackRef_NewIfBorrowedOrSteal(v);
12051205
DEAD(v);
12061206
if ((tstate->interp->eval_frame == NULL) &&
12071207
(Py_TYPE(receiver_o) == &PyGen_Type || Py_TYPE(receiver_o) == &PyCoro_Type) &&
@@ -1255,7 +1255,7 @@ dummy_func(
12551255
DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING);
12561256
STAT_INC(SEND, hit);
12571257
gen_frame = &gen->gi_iframe;
1258-
_PyFrame_StackPush(gen_frame, _PyStackRef_StealIfUnborrowed(v));
1258+
_PyFrame_StackPush(gen_frame, _PyStackRef_NewIfBorrowedOrSteal(v));
12591259
DEAD(v);
12601260
gen->gi_frame_state = FRAME_EXECUTING;
12611261
gen->gi_exc_state.previous_item = tstate->exc_info;
@@ -1302,7 +1302,7 @@ dummy_func(
13021302
#endif
13031303
RELOAD_STACK();
13041304
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
1305-
value = _PyStackRef_StealIfUnborrowed(temp);
1305+
value = _PyStackRef_NewIfBorrowedOrSteal(temp);
13061306
LLTRACE_RESUME_FRAME();
13071307
}
13081308

Python/executor_cases.c.h

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

Python/frame.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,12 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
5757
frame->f_executable = PyStackRef_DUP(frame->f_executable);
5858
int stacktop = (int)(frame->stackpointer - frame->localsplus);
5959
assert(stacktop >= _PyFrame_GetCode(frame)->co_nlocalsplus);
60-
// XXX - Maybe more optimal sequence to do here
61-
if (_PyStackRef_IsBorrowed(frame->f_executable)) {
62-
frame->f_executable = PyStackRef_FromPyObjectNew(PyStackRef_AsPyObjectBorrow(frame->f_executable));
63-
}
64-
if (_PyStackRef_IsBorrowed(frame->f_funcobj)) {
65-
frame->f_funcobj = PyStackRef_FromPyObjectNew(PyStackRef_AsPyObjectBorrow(frame->f_funcobj));
66-
}
60+
// The frame object may outlive any references that were providing "support"
61+
// for borrowed references in the frame. Convert them to strong references.
62+
frame->f_executable = _PyStackRef_NewIfBorrowedOrSteal(frame->f_executable);
63+
frame->f_funcobj = _PyStackRef_NewIfBorrowedOrSteal(frame->f_funcobj);
6764
for (int i = 0; i < stacktop; i++) {
68-
frame->localsplus[i] = _PyStackRef_StealIfUnborrowed(frame->localsplus[i]);
65+
frame->localsplus[i] = _PyStackRef_NewIfBorrowedOrSteal(frame->localsplus[i]);
6966
}
7067
f->f_frame = frame;
7168
frame->owner = FRAME_OWNED_BY_FRAME_OBJECT;

Python/generated_cases.c.h

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

Tools/cases_generator/analyzer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,6 @@ def has_error_without_pop(op: parser.CodeDef) -> bool:
591591
"PyStackRef_CLEAR",
592592
"PyStackRef_CLOSE_SPECIALIZED",
593593
"PyStackRef_DUP",
594-
"_PyStackRef_StealIfUnborrowed",
595594
"PyStackRef_False",
596595
"PyStackRef_FromPyObjectImmortal",
597596
"PyStackRef_FromPyObjectNew",
@@ -649,6 +648,7 @@ def has_error_without_pop(op: parser.CodeDef) -> bool:
649648
"_PyObject_GetManagedDict",
650649
"_PyObject_InlineValues",
651650
"_PyObject_ManagedDictPointer",
651+
"_PyStackRef_NewIfBorrowedOrSteal",
652652
"_PyThreadState_HasStackSpace",
653653
"_PyTuple_FromStackRefStealOnSuccess",
654654
"_PyTuple_ITEMS",

0 commit comments

Comments
 (0)