@@ -146,6 +146,38 @@ dummy_func(
146
146
RESUME_CHECK ,
147
147
};
148
148
149
+ tier1 op (_UPDATE_INSTRUMENTATION , (-- )) {
150
+ assert (frame == tstate -> current_frame );
151
+ if (tstate -> tracing == 0 ) {
152
+ uintptr_t global_version =
153
+ _Py_atomic_load_uintptr_relaxed (& tstate -> eval_breaker ) &
154
+ ~_PY_EVAL_EVENTS_MASK ;
155
+ PyCodeObject * code = _PyFrame_GetCode (frame );
156
+ uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE (code -> _co_instrumentation_version );
157
+ assert ((code_version & 255 ) == 0 );
158
+ if (code_version != global_version ) {
159
+ int err = _Py_Instrument (_PyFrame_GetCode (frame ), tstate -> interp );
160
+ ERROR_IF (err , error );
161
+ next_instr = this_instr ;
162
+ DISPATCH ();
163
+ }
164
+ }
165
+ }
166
+
167
+ tier1 op (_SWAP_TO_RESUME_CHECK ) {
168
+ if (tstate -> tracing == 0 ) {
169
+ assert (this_instr -> op .code == RESUME ||
170
+ this_instr -> op .code == RESUME_CHECK ||
171
+ this_instr -> op .code == INSTRUMENTED_RESUME ||
172
+ this_instr -> op .code == ENTER_EXECUTOR );
173
+ if (this_instr -> op .code == RESUME ) {
174
+ #if ENABLE_SPECIALIZATION
175
+ FT_ATOMIC_STORE_UINT8_RELAXED (this_instr -> op .code , RESUME_CHECK );
176
+ #endif /* ENABLE_SPECIALIZATION */
177
+ }
178
+ }
179
+ }
180
+
149
181
tier1 inst (RESUME , (-- )) {
150
182
assert (frame == tstate -> current_frame );
151
183
if (tstate -> tracing == 0 ) {
@@ -936,48 +968,25 @@ dummy_func(
936
968
LLTRACE_RESUME_FRAME ();
937
969
}
938
970
939
- inst ( INSTRUMENTED_RETURN_VALUE , (retval -- )) {
971
+ tier1 op ( _RETURN_VALUE_EVENT , (val -- val )) {
940
972
int err = _Py_call_instrumentation_arg (
941
973
tstate , PY_MONITORING_EVENT_PY_RETURN ,
942
- frame , this_instr , PyStackRef_AsPyObjectBorrow (retval ));
974
+ frame , this_instr , PyStackRef_AsPyObjectBorrow (val ));
943
975
if (err ) ERROR_NO_POP ();
944
- STACK_SHRINK (1 );
945
- assert (EMPTY ());
946
- _PyFrame_SetStackPointer (frame , stack_pointer );
947
- _Py_LeaveRecursiveCallPy (tstate );
948
- assert (frame != & entry_frame );
949
- // GH-99729: We need to unlink the frame *before* clearing it:
950
- _PyInterpreterFrame * dying = frame ;
951
- frame = tstate -> current_frame = dying -> previous ;
952
- _PyEval_FrameClearAndPop (tstate , dying );
953
- _PyFrame_StackPush (frame , retval );
954
- LOAD_IP (frame -> return_offset );
955
- goto resume_frame ;
956
976
}
957
977
978
+ macro (INSTRUMENTED_RETURN_VALUE ) =
979
+ _RETURN_VALUE_EVENT +
980
+ RETURN_VALUE ;
981
+
958
982
macro (RETURN_CONST ) =
959
983
LOAD_CONST +
960
984
RETURN_VALUE ;
961
985
962
- inst (INSTRUMENTED_RETURN_CONST , (-- )) {
963
- PyObject * retval = GETITEM (FRAME_CO_CONSTS , oparg );
964
- int err = _Py_call_instrumentation_arg (
965
- tstate , PY_MONITORING_EVENT_PY_RETURN ,
966
- frame , this_instr , retval );
967
- if (err ) ERROR_NO_POP ();
968
- Py_INCREF (retval );
969
- assert (EMPTY ());
970
- _PyFrame_SetStackPointer (frame , stack_pointer );
971
- _Py_LeaveRecursiveCallPy (tstate );
972
- assert (frame != & entry_frame );
973
- // GH-99729: We need to unlink the frame *before* clearing it:
974
- _PyInterpreterFrame * dying = frame ;
975
- frame = tstate -> current_frame = dying -> previous ;
976
- _PyEval_FrameClearAndPop (tstate , dying );
977
- _PyFrame_StackPush (frame , PyStackRef_FromPyObjectSteal (retval ));
978
- LOAD_IP (frame -> return_offset );
979
- goto resume_frame ;
980
- }
986
+ macro (INSTRUMENTED_RETURN_CONST ) =
987
+ LOAD_CONST +
988
+ _RETURN_VALUE_EVENT +
989
+ RETURN_VALUE ;
981
990
982
991
inst (GET_AITER , (obj -- iter )) {
983
992
unaryfunc getter = NULL ;
@@ -1171,31 +1180,6 @@ dummy_func(
1171
1180
DISPATCH_INLINED (gen_frame );
1172
1181
}
1173
1182
1174
- inst (INSTRUMENTED_YIELD_VALUE , (retval -- unused )) {
1175
- assert (frame != & entry_frame );
1176
- frame -> instr_ptr = next_instr ;
1177
- PyGenObject * gen = _PyGen_GetGeneratorFromFrame (frame );
1178
- assert (FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1 );
1179
- assert (oparg == 0 || oparg == 1 );
1180
- gen -> gi_frame_state = FRAME_SUSPENDED + oparg ;
1181
- _PyFrame_SetStackPointer (frame , stack_pointer - 1 );
1182
- int err = _Py_call_instrumentation_arg (
1183
- tstate , PY_MONITORING_EVENT_PY_YIELD ,
1184
- frame , this_instr , PyStackRef_AsPyObjectBorrow (retval ));
1185
- if (err ) ERROR_NO_POP ();
1186
- tstate -> exc_info = gen -> gi_exc_state .previous_item ;
1187
- gen -> gi_exc_state .previous_item = NULL ;
1188
- _Py_LeaveRecursiveCallPy (tstate );
1189
- _PyInterpreterFrame * gen_frame = frame ;
1190
- frame = tstate -> current_frame = frame -> previous ;
1191
- gen_frame -> previous = NULL ;
1192
- _PyFrame_StackPush (frame , retval );
1193
- /* We don't know which of these is relevant here, so keep them equal */
1194
- assert (INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER );
1195
- LOAD_IP (1 + INLINE_CACHE_ENTRIES_SEND );
1196
- goto resume_frame ;
1197
- }
1198
-
1199
1183
inst (YIELD_VALUE , (retval -- value )) {
1200
1184
// NOTE: It's important that YIELD_VALUE never raises an exception!
1201
1185
// The compiler treats any exception raised here as a failed close()
@@ -1232,6 +1216,23 @@ dummy_func(
1232
1216
LLTRACE_RESUME_FRAME ();
1233
1217
}
1234
1218
1219
+ tier1 op (_YIELD_VALUE_EVENT , (val -- val )) {
1220
+ SAVE_SP ();
1221
+ int err = _Py_call_instrumentation_arg (
1222
+ tstate , PY_MONITORING_EVENT_PY_YIELD ,
1223
+ frame , this_instr , PyStackRef_AsPyObjectBorrow (val ));
1224
+ LOAD_SP ();
1225
+ if (err ) ERROR_NO_POP ();
1226
+ if (frame -> instr_ptr != this_instr ) {
1227
+ next_instr = frame -> instr_ptr ;
1228
+ DISPATCH ();
1229
+ }
1230
+ }
1231
+
1232
+ macro (INSTRUMENTED_YIELD_VALUE ) =
1233
+ _YIELD_VALUE_EVENT +
1234
+ YIELD_VALUE ;
1235
+
1235
1236
inst (POP_EXCEPT , (exc_value -- )) {
1236
1237
_PyErr_StackItem * exc_info = tstate -> exc_info ;
1237
1238
Py_XSETREF (exc_info -> exc_value ,
@@ -4470,6 +4471,36 @@ dummy_func(
4470
4471
assert (oparg >= 2 );
4471
4472
}
4472
4473
4474
+ inst (INSTRUMENTED_LINE , ( -- )) {
4475
+ int original_opcode = 0 ;
4476
+ if (tstate -> tracing ) {
4477
+ PyCodeObject * code = _PyFrame_GetCode (frame );
4478
+ original_opcode = code -> _co_monitoring -> lines [(int )(this_instr - _PyCode_CODE (code ))].original_opcode ;
4479
+ next_instr = this_instr ;
4480
+ } else {
4481
+ _PyFrame_SetStackPointer (frame , stack_pointer );
4482
+ original_opcode = _Py_call_instrumentation_line (
4483
+ tstate , frame , this_instr , prev_instr );
4484
+ stack_pointer = _PyFrame_GetStackPointer (frame );
4485
+ if (original_opcode < 0 ) {
4486
+ next_instr = this_instr + 1 ;
4487
+ goto error ;
4488
+ }
4489
+ next_instr = frame -> instr_ptr ;
4490
+ if (next_instr != this_instr ) {
4491
+ DISPATCH ();
4492
+ }
4493
+ }
4494
+ if (_PyOpcode_Caches [original_opcode ]) {
4495
+ _PyBinaryOpCache * cache = (_PyBinaryOpCache * )(next_instr + 1 );
4496
+ /* Prevent the underlying instruction from specializing
4497
+ * and overwriting the instrumentation. */
4498
+ PAUSE_ADAPTIVE_COUNTER (cache -> counter );
4499
+ }
4500
+ opcode = original_opcode ;
4501
+ DISPATCH_GOTO ();
4502
+ }
4503
+
4473
4504
inst (INSTRUMENTED_INSTRUCTION , ( -- )) {
4474
4505
int next_opcode = _Py_call_instrumentation_instruction (
4475
4506
tstate , frame , this_instr );
0 commit comments