summaryrefslogtreecommitdiffstats
path: root/Python/bytecodes.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2024-07-26 13:35:57 (GMT)
committerGitHub <noreply@github.com>2024-07-26 13:35:57 (GMT)
commit95a73917cd5a204979a78c13ba912621f1eeb2e3 (patch)
treea2e37935e85955c44c096eacc9e55aed2eb7a36b /Python/bytecodes.c
parentafb0aa6ed20bd8e982ecb307f12923cf8dbccd8c (diff)
downloadcpython-95a73917cd5a204979a78c13ba912621f1eeb2e3.zip
cpython-95a73917cd5a204979a78c13ba912621f1eeb2e3.tar.gz
cpython-95a73917cd5a204979a78c13ba912621f1eeb2e3.tar.bz2
GH-122029: Break INSTRUMENTED_CALL into micro-ops, so that its behavior is consistent with CALL (GH-122177)
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r--Python/bytecodes.c71
1 files changed, 42 insertions, 29 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 971397c..871e2db 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -3241,20 +3241,6 @@ dummy_func(
unused/1 +
_LOAD_ATTR_METHOD_LAZY_DICT;
- inst(INSTRUMENTED_CALL, (unused/3 -- )) {
- int is_meth = PyStackRef_AsPyObjectBorrow(PEEK(oparg + 1)) != NULL;
- int total_args = oparg + is_meth;
- PyObject *function = PyStackRef_AsPyObjectBorrow(PEEK(oparg + 2));
- PyObject *arg = total_args == 0 ?
- &_PyInstrumentation_MISSING : PyStackRef_AsPyObjectBorrow(PEEK(total_args));
- int err = _Py_call_instrumentation_2args(
- tstate, PY_MONITORING_EVENT_CALL,
- frame, this_instr, function, arg);
- ERROR_IF(err, error);
- PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
- GO_TO_INSTRUCTION(CALL);
- }
-
// Cache layout: counter/1, func_version/2
// CALL_INTRINSIC_1/2, CALL_KW, and CALL_FUNCTION_EX aren't members!
family(CALL, INLINE_CACHE_ENTRIES_CALL) = {
@@ -3292,27 +3278,33 @@ dummy_func(
#endif /* ENABLE_SPECIALIZATION */
}
+ op(_MAYBE_EXPAND_METHOD, (callable, self_or_null, args[oparg] -- func, maybe_self, args[oparg])) {
+ if (PyStackRef_TYPE(callable) == &PyMethod_Type && PyStackRef_IsNull(self_or_null)) {
+ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
+ PyObject *self = ((PyMethodObject *)callable_o)->im_self;
+ maybe_self = PyStackRef_FromPyObjectNew(self);
+ PyObject *method = ((PyMethodObject *)callable_o)->im_func;
+ func = PyStackRef_FromPyObjectNew(method);
+ /* Make sure that callable and all args are in memory */
+ args[-2] = func;
+ args[-1] = maybe_self;
+ PyStackRef_CLOSE(callable);
+ }
+ else {
+ func = callable;
+ maybe_self = self_or_null;
+ }
+ }
+
// When calling Python, inline the call using DISPATCH_INLINED().
- op(_CALL, (callable, self_or_null, args[oparg] -- res)) {
+ op(_DO_CALL, (callable, self_or_null, args[oparg] -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
- PyObject *self_or_null_o = PyStackRef_AsPyObjectBorrow(self_or_null);
// oparg counts all of the args, but *not* self:
int total_args = oparg;
- if (self_or_null_o != NULL) {
- args--;
- total_args++;
- }
- else if (Py_TYPE(callable_o) == &PyMethod_Type) {
+ if (!PyStackRef_IsNull(self_or_null)) {
args--;
total_args++;
- PyObject *self = ((PyMethodObject *)callable_o)->im_self;
- args[0] = PyStackRef_FromPyObjectNew(self);
- PyObject *method = ((PyMethodObject *)callable_o)->im_func;
- args[-1] = PyStackRef_FromPyObjectNew(method);
- PyStackRef_CLOSE(callable);
- callable_o = method;
- callable = args[-1];
}
// Check if the call can be inlined or not
if (Py_TYPE(callable_o) == &PyFunction_Type &&
@@ -3376,7 +3368,28 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
- macro(CALL) = _SPECIALIZE_CALL + unused/2 + _CALL + _CHECK_PERIODIC;
+ op(_MONITOR_CALL, (func, maybe_self, args[oparg] -- func, maybe_self, args[oparg])) {
+ int is_meth = !PyStackRef_IsNull(maybe_self);
+ PyObject *function = PyStackRef_AsPyObjectBorrow(func);
+ PyObject *arg0;
+ if (is_meth) {
+ arg0 = PyStackRef_AsPyObjectBorrow(maybe_self);
+ }
+ else if (oparg) {
+ arg0 = PyStackRef_AsPyObjectBorrow(args[0]);
+ }
+ else {
+ arg0 = &_PyInstrumentation_MISSING;
+ }
+ int err = _Py_call_instrumentation_2args(
+ tstate, PY_MONITORING_EVENT_CALL,
+ frame, this_instr, function, arg0
+ );
+ ERROR_IF(err, error);
+ }
+
+ macro(CALL) = _SPECIALIZE_CALL + unused/2 + _MAYBE_EXPAND_METHOD + _DO_CALL + _CHECK_PERIODIC;
+ macro(INSTRUMENTED_CALL) = unused/3 + _MAYBE_EXPAND_METHOD + _MONITOR_CALL + _DO_CALL + _CHECK_PERIODIC;
op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _PyInterpreterFrame*)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);