https://github.com/python/cpython/commit/c5f925c8c948736bd64652918b4e0186b91abbb5
commit: c5f925c8c948736bd64652918b4e0186b91abbb5
branch: main
author: Tian Gao <[email protected]>
committer: markshannon <[email protected]>
date: 2025-02-25T15:43:49Z
summary:
gh-122029: Move monitoring after method expand for CALL_KW (GH-130488)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2025-02-23-20-48-31.gh-issue-122029.iW8GvA.rst
M Lib/test/test_sys_setprofile.py
M Python/bytecodes.c
M Python/generated_cases.c.h
diff --git a/Lib/test/test_sys_setprofile.py b/Lib/test/test_sys_setprofile.py
index 311a4d2cafe88d..0753a9d8b8e0ee 100644
--- a/Lib/test/test_sys_setprofile.py
+++ b/Lib/test/test_sys_setprofile.py
@@ -493,6 +493,24 @@ class A:
# The last c_call is the call to sys.setprofile
self.assertEqual(events, ['c_call', 'c_return', 'c_call'])
+ class B:
+ f = classmethod(max)
+ events = []
+ sys.setprofile(lambda frame, event, args: events.append(event))
+ # Not important, we only want to trigger INSTRUMENTED_CALL_KW
+ B().f(1, key=lambda x: 0)
+ sys.setprofile(None)
+ # The last c_call is the call to sys.setprofile
+ self.assertEqual(
+ events,
+ ['c_call',
+ 'call', 'return',
+ 'call', 'return',
+ 'c_return',
+ 'c_call'
+ ]
+ )
+
if __name__ == "__main__":
unittest.main()
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-23-20-48-31.gh-issue-122029.iW8GvA.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-23-20-48-31.gh-issue-122029.iW8GvA.rst
new file mode 100644
index 00000000000000..ec7d774a16fdb0
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-23-20-48-31.gh-issue-122029.iW8GvA.rst
@@ -0,0 +1 @@
+``INSTRUMENTED_CALL_KW`` will expand the method before monitoring to reflect
the actual behavior more accurately.
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 3c5cb07709d66c..6f91b10b8b8a9b 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -4509,8 +4509,8 @@ dummy_func(
macro(INSTRUMENTED_CALL_KW) =
counter/1 +
unused/2 +
- _MONITOR_CALL_KW +
_MAYBE_EXPAND_METHOD_KW +
+ _MONITOR_CALL_KW +
_DO_CALL_KW;
op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable[1], unused[1],
unused[oparg], kwnames -- callable[1], unused[1], unused[oparg], kwnames)) {
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 268e8836994bc4..377be6fb6d6390 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -6413,14 +6413,37 @@
_PyStackRef *callable;
_PyStackRef *self_or_null;
_PyStackRef *args;
- _PyStackRef kwnames;
_PyStackRef kwnames_in;
_PyStackRef *func;
_PyStackRef *maybe_self;
_PyStackRef kwnames_out;
+ _PyStackRef kwnames;
_PyStackRef res;
/* Skip 1 cache entry */
/* Skip 2 cache entries */
+ // _MAYBE_EXPAND_METHOD_KW
+ {
+ kwnames_in = stack_pointer[-1];
+ args = &stack_pointer[-1 - oparg];
+ self_or_null = &stack_pointer[-2 - oparg];
+ callable = &stack_pointer[-3 - oparg];
+ func = &stack_pointer[-3 - oparg];
+ maybe_self = &stack_pointer[-2 - oparg];
+ args = &stack_pointer[-1 - oparg];
+ (void)args;
+ if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type &&
PyStackRef_IsNull(self_or_null[0])) {
+ PyObject *callable_o =
PyStackRef_AsPyObjectBorrow(callable[0]);
+ PyObject *self = ((PyMethodObject *)callable_o)->im_self;
+ maybe_self[0] = PyStackRef_FromPyObjectNew(self);
+ PyObject *method = ((PyMethodObject *)callable_o)->im_func;
+ _PyStackRef temp = callable[0];
+ func[0] = PyStackRef_FromPyObjectNew(method);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_CLOSE(temp);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ }
+ kwnames_out = kwnames_in;
+ }
// _MONITOR_CALL_KW
{
args = &stack_pointer[-1 - oparg];
@@ -6440,6 +6463,7 @@
}
}
PyObject *function = PyStackRef_AsPyObjectBorrow(callable[0]);
+ stack_pointer[-1] = kwnames_out;
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
@@ -6449,32 +6473,9 @@
JUMP_TO_LABEL(error);
}
}
- // _MAYBE_EXPAND_METHOD_KW
- {
- kwnames_in = stack_pointer[-1];
- func = &stack_pointer[-3 - oparg];
- maybe_self = &stack_pointer[-2 - oparg];
- args = &stack_pointer[-1 - oparg];
- (void)args;
- if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type &&
PyStackRef_IsNull(self_or_null[0])) {
- PyObject *callable_o =
PyStackRef_AsPyObjectBorrow(callable[0]);
- PyObject *self = ((PyMethodObject *)callable_o)->im_self;
- maybe_self[0] = PyStackRef_FromPyObjectNew(self);
- PyObject *method = ((PyMethodObject *)callable_o)->im_func;
- _PyStackRef temp = callable[0];
- func[0] = PyStackRef_FromPyObjectNew(method);
- _PyFrame_SetStackPointer(frame, stack_pointer);
- PyStackRef_CLOSE(temp);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- }
- kwnames_out = kwnames_in;
- }
// _DO_CALL_KW
{
kwnames = kwnames_out;
- args = &stack_pointer[-1 - oparg];
- self_or_null = &stack_pointer[-2 - oparg];
- callable = &stack_pointer[-3 - oparg];
PyObject *callable_o =
PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames);
// oparg counts all of the args, but *not* self:
@@ -6492,7 +6493,6 @@
{
int code_flags =
((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL :
Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
- stack_pointer[-1] = kwnames;
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, callable[0], locals,
@@ -6519,7 +6519,6 @@
/* Callable is not a normal Python function */
STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o);
if (CONVERSION_FAILED(args_o)) {
- stack_pointer[-1] = kwnames;
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyStackRef tmp = kwnames;
kwnames = PyStackRef_NULL;
@@ -6541,7 +6540,6 @@
assert(WITHIN_STACK_BOUNDS());
JUMP_TO_LABEL(error);
}
- stack_pointer[-1] = kwnames;
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *res_o = PyObject_Vectorcall(
callable_o, args_o,
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]