mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	GH-108614: Add RESUME_CHECK instruction (GH-108630)
				
					
				
			This commit is contained in:
		
							parent
							
								
									d485551c9d
								
							
						
					
					
						commit
						0858328ca2
					
				
					 16 changed files with 519 additions and 482 deletions
				
			
		
							
								
								
									
										2
									
								
								Python/abstract_interp_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Python/abstract_interp_cases.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -7,7 +7,7 @@ | |||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case RESUME: { | ||||
|         case RESUME_CHECK: { | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -132,24 +132,37 @@ dummy_func( | |||
|         inst(NOP, (--)) { | ||||
|         } | ||||
| 
 | ||||
|         family(RESUME, 0) = { | ||||
|             RESUME_CHECK, | ||||
|         }; | ||||
| 
 | ||||
|         inst(RESUME, (--)) { | ||||
|             TIER_ONE_ONLY | ||||
|             assert(frame == tstate->current_frame); | ||||
|             /* Possibly combine this with eval breaker */ | ||||
|             if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { | ||||
|                 int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); | ||||
|                 ERROR_IF(err, error); | ||||
|                 #if TIER_ONE | ||||
|                 next_instr--; | ||||
|                 #endif | ||||
|                 #if TIER_TWO | ||||
|                 goto deoptimize; | ||||
|                 #endif | ||||
|             } | ||||
|             else if (oparg < 2) { | ||||
|                 CHECK_EVAL_BREAKER(); | ||||
|             else { | ||||
|                 if (oparg < 2) { | ||||
|                     CHECK_EVAL_BREAKER(); | ||||
|                 } | ||||
|                 next_instr[-1].op.code = RESUME_CHECK; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         inst(RESUME_CHECK, (--)) { | ||||
| #if defined(__EMSCRIPTEN__) | ||||
|             DEOPT_IF(emscripten_signal_clock == 0, RESUME); | ||||
|             emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; | ||||
| #endif | ||||
|             /* Possibly combine these two checks */ | ||||
|             DEOPT_IF(_PyFrame_GetCode(frame)->_co_instrumentation_version | ||||
|                 != tstate->interp->monitoring_version, RESUME); | ||||
|             DEOPT_IF(_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker), RESUME); | ||||
|         } | ||||
| 
 | ||||
|         inst(INSTRUMENTED_RESUME, (--)) { | ||||
|             /* Possible performance enhancement:
 | ||||
|              *   We need to check the eval breaker anyway, can we | ||||
|  |  | |||
|  | @ -374,6 +374,8 @@ static inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate)  { | |||
|     tstate->py_recursion_remaining++; | ||||
| } | ||||
| 
 | ||||
| /* Marker to specify tier 1 only instructions */ | ||||
| #define TIER_ONE_ONLY | ||||
| 
 | ||||
| /* Implementation of "macros" that modify the instruction pointer,
 | ||||
|  * stack pointer, or frame pointer. | ||||
|  |  | |||
|  | @ -38,19 +38,17 @@ _Py_CheckEmscriptenSignals(void) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #define PY_EMSCRIPTEN_SIGNAL_INTERVAL 50 | ||||
| static int emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL; | ||||
| 
 | ||||
| void | ||||
| _Py_CheckEmscriptenSignalsPeriodically(void) | ||||
| { | ||||
|     if (!Py_EMSCRIPTEN_SIGNAL_HANDLING) { | ||||
|         return; | ||||
|     } | ||||
|     emscripten_signal_clock--; | ||||
|     if (emscripten_signal_clock == 0) { | ||||
|         emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL; | ||||
|         _Py_CheckEmscriptenSignals(); | ||||
|     } | ||||
|     else if (Py_EMSCRIPTEN_SIGNAL_HANDLING) { | ||||
|         emscripten_signal_clock--; | ||||
|     } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										25
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										25
									
								
								Python/executor_cases.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -7,22 +7,15 @@ | |||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case RESUME: { | ||||
|             assert(frame == tstate->current_frame); | ||||
|             /* Possibly combine this with eval breaker */ | ||||
|             if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { | ||||
|                 int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); | ||||
|                 if (err) goto error; | ||||
|                 #if TIER_ONE | ||||
|                 next_instr--; | ||||
|                 #endif | ||||
|                 #if TIER_TWO | ||||
|                 goto deoptimize; | ||||
|                 #endif | ||||
|             } | ||||
|             else if (oparg < 2) { | ||||
|                 CHECK_EVAL_BREAKER(); | ||||
|             } | ||||
|         case RESUME_CHECK: { | ||||
| #if defined(__EMSCRIPTEN__) | ||||
|             DEOPT_IF(emscripten_signal_clock == 0, RESUME); | ||||
|             emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; | ||||
| #endif | ||||
|             /* Possibly combine these two checks */ | ||||
|             DEOPT_IF(_PyFrame_GetCode(frame)->_co_instrumentation_version | ||||
|                 != tstate->interp->monitoring_version, RESUME); | ||||
|             DEOPT_IF(_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker), RESUME); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										28
									
								
								Python/generated_cases.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										28
									
								
								Python/generated_cases.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -8,24 +8,36 @@ | |||
|         } | ||||
| 
 | ||||
|         TARGET(RESUME) { | ||||
|             PREDICTED(RESUME); | ||||
|             static_assert(0 == 0, "incorrect cache size"); | ||||
|             TIER_ONE_ONLY | ||||
|             assert(frame == tstate->current_frame); | ||||
|             /* Possibly combine this with eval breaker */ | ||||
|             if (_PyFrame_GetCode(frame)->_co_instrumentation_version != tstate->interp->monitoring_version) { | ||||
|                 int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); | ||||
|                 if (err) goto error; | ||||
|                 #if TIER_ONE | ||||
|                 next_instr--; | ||||
|                 #endif | ||||
|                 #if TIER_TWO | ||||
|                 goto deoptimize; | ||||
|                 #endif | ||||
|             } | ||||
|             else if (oparg < 2) { | ||||
|                 CHECK_EVAL_BREAKER(); | ||||
|             else { | ||||
|                 if (oparg < 2) { | ||||
|                     CHECK_EVAL_BREAKER(); | ||||
|                 } | ||||
|                 next_instr[-1].op.code = RESUME_CHECK; | ||||
|             } | ||||
|             DISPATCH(); | ||||
|         } | ||||
| 
 | ||||
|         TARGET(RESUME_CHECK) { | ||||
| #if defined(__EMSCRIPTEN__) | ||||
|             DEOPT_IF(emscripten_signal_clock == 0, RESUME); | ||||
|             emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; | ||||
| #endif | ||||
|             /* Possibly combine these two checks */ | ||||
|             DEOPT_IF(_PyFrame_GetCode(frame)->_co_instrumentation_version | ||||
|                 != tstate->interp->monitoring_version, RESUME); | ||||
|             DEOPT_IF(_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker), RESUME); | ||||
|             DISPATCH(); | ||||
|         } | ||||
| 
 | ||||
|         TARGET(INSTRUMENTED_RESUME) { | ||||
|             /* Possible performance enhancement:
 | ||||
|              *   We need to check the eval breaker anyway, can we | ||||
|  |  | |||
							
								
								
									
										4
									
								
								Python/opcode_targets.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								Python/opcode_targets.h
									
										
									
										generated
									
									
									
								
							|  | @ -46,6 +46,7 @@ static void *opcode_targets[256] = { | |||
|     &&TARGET_POP_TOP, | ||||
|     &&TARGET_PUSH_EXC_INFO, | ||||
|     &&TARGET_PUSH_NULL, | ||||
|     &&TARGET_RESUME_CHECK, | ||||
|     &&TARGET_RETURN_GENERATOR, | ||||
|     &&TARGET_RETURN_VALUE, | ||||
|     &&TARGET_SETUP_ANNOTATIONS, | ||||
|  | @ -164,8 +165,8 @@ static void *opcode_targets[256] = { | |||
|     &&TARGET_POP_JUMP_IF_NOT_NONE, | ||||
|     &&TARGET_POP_JUMP_IF_TRUE, | ||||
|     &&TARGET_RAISE_VARARGS, | ||||
|     &&TARGET_RERAISE, | ||||
|     &&TARGET_RESUME, | ||||
|     &&TARGET_RERAISE, | ||||
|     &&TARGET_RETURN_CONST, | ||||
|     &&TARGET_SEND, | ||||
|     &&TARGET_SEND_GEN, | ||||
|  | @ -235,7 +236,6 @@ static void *opcode_targets[256] = { | |||
|     &&_unknown_opcode, | ||||
|     &&_unknown_opcode, | ||||
|     &&_unknown_opcode, | ||||
|     &&_unknown_opcode, | ||||
|     &&TARGET_INSTRUMENTED_RESUME, | ||||
|     &&TARGET_INSTRUMENTED_END_FOR, | ||||
|     &&TARGET_INSTRUMENTED_END_SEND, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Mark Shannon
						Mark Shannon