mirror of
https://github.com/python/cpython.git
synced 2026-02-22 07:00:51 +00:00
gh-144549: Fix tail calling interpreter on Windows for FT (GH-144550)
This commit is contained in:
parent
28fb13cb33
commit
895e83727d
8 changed files with 62 additions and 86 deletions
|
|
@ -2364,31 +2364,9 @@ dummy_func(
|
|||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
|
||||
if (oparg & 1) {
|
||||
/* Designed to work in tandem with CALL, pushes two values. */
|
||||
_PyCStackRef method;
|
||||
_PyThreadState_PushCStackRef(tstate, &method);
|
||||
int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref);
|
||||
if (is_meth) {
|
||||
/* We can bypass temporary bound method object.
|
||||
meth is unbound method and obj is self.
|
||||
meth | self | arg1 | ... | argN
|
||||
*/
|
||||
assert(!PyStackRef_IsNull(method.ref)); // No errors on this branch
|
||||
self_or_null[0] = owner; // Transfer ownership
|
||||
DEAD(owner);
|
||||
attr = _PyThreadState_PopCStackRefSteal(tstate, &method);
|
||||
}
|
||||
else {
|
||||
/* meth is not an unbound method (but a regular attr, or
|
||||
something was returned by a descriptor protocol). Set
|
||||
the second element of the stack to NULL, to signal
|
||||
CALL that it's not a method call.
|
||||
meth | NULL | arg1 | ... | argN
|
||||
*/
|
||||
PyStackRef_CLOSE(owner);
|
||||
self_or_null[0] = PyStackRef_NULL;
|
||||
attr = _PyThreadState_PopCStackRefSteal(tstate, &method);
|
||||
ERROR_IF(PyStackRef_IsNull(attr));
|
||||
}
|
||||
attr = _Py_LoadAttr_StackRefSteal(tstate, owner, name, self_or_null);
|
||||
DEAD(owner);
|
||||
ERROR_IF(PyStackRef_IsNull(attr));
|
||||
}
|
||||
else {
|
||||
/* Classic, pushes one value. */
|
||||
|
|
|
|||
|
|
@ -1007,6 +1007,34 @@ _Py_BuildMap_StackRefSteal(
|
|||
return res;
|
||||
}
|
||||
|
||||
_PyStackRef
|
||||
_Py_LoadAttr_StackRefSteal(
|
||||
PyThreadState *tstate, _PyStackRef owner,
|
||||
PyObject *name, _PyStackRef *self_or_null)
|
||||
{
|
||||
_PyCStackRef method;
|
||||
_PyThreadState_PushCStackRef(tstate, &method);
|
||||
int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref);
|
||||
if (is_meth) {
|
||||
/* We can bypass temporary bound method object.
|
||||
meth is unbound method and obj is self.
|
||||
meth | self | arg1 | ... | argN
|
||||
*/
|
||||
assert(!PyStackRef_IsNull(method.ref)); // No errors on this branch
|
||||
self_or_null[0] = owner; // Transfer ownership
|
||||
return _PyThreadState_PopCStackRefSteal(tstate, &method);
|
||||
}
|
||||
/* meth is not an unbound method (but a regular attr, or
|
||||
something was returned by a descriptor protocol). Set
|
||||
the second element of the stack to NULL, to signal
|
||||
CALL that it's not a method call.
|
||||
meth | NULL | arg1 | ... | argN
|
||||
*/
|
||||
PyStackRef_CLOSE(owner);
|
||||
self_or_null[0] = PyStackRef_NULL;
|
||||
return _PyThreadState_PopCStackRefSteal(tstate, &method);
|
||||
}
|
||||
|
||||
#ifdef Py_DEBUG
|
||||
void
|
||||
_Py_assert_within_stack_bounds(
|
||||
|
|
|
|||
26
Python/executor_cases.c.h
generated
26
Python/executor_cases.c.h
generated
|
|
@ -8670,32 +8670,18 @@
|
|||
self_or_null = &stack_pointer[1];
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
|
||||
if (oparg & 1) {
|
||||
_PyCStackRef method;
|
||||
stack_pointer[0] = owner;
|
||||
stack_pointer += 1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyThreadState_PushCStackRef(tstate, &method);
|
||||
int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref);
|
||||
attr = _Py_LoadAttr_StackRefSteal(tstate, owner, name, self_or_null);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (is_meth) {
|
||||
assert(!PyStackRef_IsNull(method.ref));
|
||||
self_or_null[0] = owner;
|
||||
attr = _PyThreadState_PopCStackRefSteal(tstate, &method);
|
||||
}
|
||||
else {
|
||||
stack_pointer += -1;
|
||||
if (PyStackRef_IsNull(attr)) {
|
||||
stack_pointer[-1] = attr;
|
||||
stack_pointer += (oparg&1);
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(owner);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
self_or_null[0] = PyStackRef_NULL;
|
||||
attr = _PyThreadState_PopCStackRefSteal(tstate, &method);
|
||||
if (PyStackRef_IsNull(attr)) {
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
stack_pointer += 1;
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
23
Python/generated_cases.c.h
generated
23
Python/generated_cases.c.h
generated
|
|
@ -7898,28 +7898,11 @@
|
|||
self_or_null = &stack_pointer[0];
|
||||
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
|
||||
if (oparg & 1) {
|
||||
_PyCStackRef method;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyThreadState_PushCStackRef(tstate, &method);
|
||||
int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref);
|
||||
attr = _Py_LoadAttr_StackRefSteal(tstate, owner, name, self_or_null);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (is_meth) {
|
||||
assert(!PyStackRef_IsNull(method.ref));
|
||||
self_or_null[0] = owner;
|
||||
attr = _PyThreadState_PopCStackRefSteal(tstate, &method);
|
||||
}
|
||||
else {
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(owner);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
self_or_null[0] = PyStackRef_NULL;
|
||||
attr = _PyThreadState_PopCStackRefSteal(tstate, &method);
|
||||
if (PyStackRef_IsNull(attr)) {
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
stack_pointer += 1;
|
||||
if (PyStackRef_IsNull(attr)) {
|
||||
JUMP_TO_LABEL(pop_1_error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue