Skip to content

Commit 03eea79

Browse files
Move _LOAD_ATTR body into external function
1 parent 25e99b3 commit 03eea79

6 files changed

Lines changed: 48 additions & 85 deletions

File tree

Include/internal/pycore_ceval.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,11 @@ _Py_assert_within_stack_bounds(
474474
_PyInterpreterFrame *frame, _PyStackRef *stack_pointer,
475475
const char *filename, int lineno);
476476

477+
PyAPI_FUNC(_PyStackRef)
478+
_Py_LoadAttr_StackRefSteal(
479+
PyThreadState *tstate, _PyStackRef owner,
480+
PyObject *name, _PyStackRef *self_or_null);
481+
477482
// Like PyMapping_GetOptionalItem, but returns the PyObject* instead of taking
478483
// it as an out parameter. This helps MSVC's escape analysis when used with
479484
// tail calling.

Modules/_testinternalcapi/test_cases.c.h

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

Python/bytecodes.c

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,31 +2364,9 @@ dummy_func(
23642364
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
23652365
if (oparg & 1) {
23662366
/* Designed to work in tandem with CALL, pushes two values. */
2367-
_PyCStackRef method;
2368-
_PyThreadState_PushCStackRef(tstate, &method);
2369-
int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref);
2370-
if (is_meth) {
2371-
/* We can bypass temporary bound method object.
2372-
meth is unbound method and obj is self.
2373-
meth | self | arg1 | ... | argN
2374-
*/
2375-
assert(!PyStackRef_IsNull(method.ref)); // No errors on this branch
2376-
self_or_null[0] = owner; // Transfer ownership
2377-
DEAD(owner);
2378-
attr = _PyThreadState_PopCStackRefSteal(tstate, &method);
2379-
}
2380-
else {
2381-
/* meth is not an unbound method (but a regular attr, or
2382-
something was returned by a descriptor protocol). Set
2383-
the second element of the stack to NULL, to signal
2384-
CALL that it's not a method call.
2385-
meth | NULL | arg1 | ... | argN
2386-
*/
2387-
PyStackRef_CLOSE(owner);
2388-
self_or_null[0] = PyStackRef_NULL;
2389-
attr = _PyThreadState_PopCStackRefSteal(tstate, &method);
2390-
ERROR_IF(PyStackRef_IsNull(attr));
2391-
}
2367+
attr = _Py_LoadAttr_StackRefSteal(tstate, owner, name, self_or_null);
2368+
DEAD(owner);
2369+
ERROR_IF(PyStackRef_IsNull(attr));
23922370
}
23932371
else {
23942372
/* Classic, pushes one value. */

Python/ceval.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,34 @@ _Py_BuildMap_StackRefSteal(
10071007
return res;
10081008
}
10091009

1010+
_PyStackRef
1011+
_Py_LoadAttr_StackRefSteal(
1012+
PyThreadState *tstate, _PyStackRef owner,
1013+
PyObject *name, _PyStackRef *self_or_null)
1014+
{
1015+
_PyCStackRef method;
1016+
_PyThreadState_PushCStackRef(tstate, &method);
1017+
int is_meth = _PyObject_GetMethodStackRef(tstate, PyStackRef_AsPyObjectBorrow(owner), name, &method.ref);
1018+
if (is_meth) {
1019+
/* We can bypass temporary bound method object.
1020+
meth is unbound method and obj is self.
1021+
meth | self | arg1 | ... | argN
1022+
*/
1023+
assert(!PyStackRef_IsNull(method.ref)); // No errors on this branch
1024+
self_or_null[0] = owner; // Transfer ownership
1025+
return _PyThreadState_PopCStackRefSteal(tstate, &method);
1026+
}
1027+
/* meth is not an unbound method (but a regular attr, or
1028+
something was returned by a descriptor protocol). Set
1029+
the second element of the stack to NULL, to signal
1030+
CALL that it's not a method call.
1031+
meth | NULL | arg1 | ... | argN
1032+
*/
1033+
PyStackRef_CLOSE(owner);
1034+
self_or_null[0] = PyStackRef_NULL;
1035+
return _PyThreadState_PopCStackRefSteal(tstate, &method);
1036+
}
1037+
10101038
#ifdef Py_DEBUG
10111039
void
10121040
_Py_assert_within_stack_bounds(

Python/executor_cases.c.h

Lines changed: 6 additions & 20 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: 3 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)