| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-23 18:39:00 +01:00
										 |  |  | #include "opcode.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-04 17:52:28 -04:00
										 |  |  | #include "pycore_bitutils.h"
 | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  | #include "pycore_call.h"
 | 
					
						
							|  |  |  | #include "pycore_ceval.h"
 | 
					
						
							|  |  |  | #include "pycore_dict.h"
 | 
					
						
							|  |  |  | #include "pycore_emscripten_signal.h"
 | 
					
						
							|  |  |  | #include "pycore_intrinsics.h"
 | 
					
						
							|  |  |  | #include "pycore_long.h"
 | 
					
						
							|  |  |  | #include "pycore_object.h"
 | 
					
						
							|  |  |  | #include "pycore_opcode_metadata.h"
 | 
					
						
							|  |  |  | #include "pycore_opcode_utils.h"
 | 
					
						
							|  |  |  | #include "pycore_pyerrors.h"
 | 
					
						
							|  |  |  | #include "pycore_range.h"
 | 
					
						
							| 
									
										
										
										
											2023-07-22 17:04:34 +02:00
										 |  |  | #include "pycore_setobject.h"     // _PySet_Update()
 | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  | #include "pycore_sliceobject.h"
 | 
					
						
							|  |  |  | #include "pycore_uops.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-31 11:34:52 +01:00
										 |  |  | #define TIER_TWO 2
 | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  | #include "ceval_macros.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef DEOPT_IF
 | 
					
						
							|  |  |  | #define DEOPT_IF(COND, INSTNAME) \
 | 
					
						
							|  |  |  |     if ((COND)) {                \ | 
					
						
							| 
									
										
										
										
											2023-10-30 20:02:45 -04:00
										 |  |  |         UOP_STAT_INC(INSTNAME, miss); \ | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  |         goto deoptimize;         \ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-04 17:52:28 -04:00
										 |  |  | #ifdef Py_STATS
 | 
					
						
							|  |  |  | // Disable these macros that apply to Tier 1 stats when we are in Tier 2
 | 
					
						
							|  |  |  | #undef STAT_INC
 | 
					
						
							|  |  |  | #define STAT_INC(opname, name) ((void)0)
 | 
					
						
							|  |  |  | #undef STAT_DEC
 | 
					
						
							|  |  |  | #define STAT_DEC(opname, name) ((void)0)
 | 
					
						
							|  |  |  | #undef CALL_STAT_INC
 | 
					
						
							|  |  |  | #define CALL_STAT_INC(name) ((void)0)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  | #undef ENABLE_SPECIALIZATION
 | 
					
						
							|  |  |  | #define ENABLE_SPECIALIZATION 0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _PyInterpreterFrame * | 
					
						
							|  |  |  | _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  |     char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG"); | 
					
						
							|  |  |  |     int lltrace = 0; | 
					
						
							|  |  |  |     if (uop_debug != NULL && *uop_debug >= '0') { | 
					
						
							|  |  |  |         lltrace = *uop_debug - '0';  // TODO: Parse an int and all that
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     #define DPRINTF(level, ...) \
 | 
					
						
							| 
									
										
										
										
											2023-08-07 21:36:25 -07:00
										 |  |  |         if (lltrace >= (level)) { printf(__VA_ARGS__); } | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     #define DPRINTF(level, ...)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DPRINTF(3, | 
					
						
							|  |  |  |             "Entering _PyUopExecute for %s (%s:%d) at byte offset %ld\n", | 
					
						
							|  |  |  |             PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_qualname), | 
					
						
							|  |  |  |             PyUnicode_AsUTF8(_PyFrame_GetCode(frame)->co_filename), | 
					
						
							|  |  |  |             _PyFrame_GetCode(frame)->co_firstlineno, | 
					
						
							| 
									
										
										
										
											2023-10-26 14:43:10 +01:00
										 |  |  |             2 * (long)(frame->instr_ptr - | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  |                    (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyThreadState *tstate = _PyThreadState_GET(); | 
					
						
							|  |  |  |     _PyUOpExecutorObject *self = (_PyUOpExecutorObject *)executor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     CHECK_EVAL_BREAKER(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-04 17:52:28 -04:00
										 |  |  |     OPT_STAT_INC(traces_executed); | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  |     _Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive; | 
					
						
							|  |  |  |     int pc = 0; | 
					
						
							|  |  |  |     int opcode; | 
					
						
							|  |  |  |     int oparg; | 
					
						
							|  |  |  |     uint64_t operand; | 
					
						
							| 
									
										
										
										
											2023-10-04 17:52:28 -04:00
										 |  |  | #ifdef Py_STATS
 | 
					
						
							|  |  |  |     uint64_t trace_uop_execution_counter = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (;;) { | 
					
						
							|  |  |  |         opcode = self->trace[pc].opcode; | 
					
						
							|  |  |  |         oparg = self->trace[pc].oparg; | 
					
						
							|  |  |  |         operand = self->trace[pc].operand; | 
					
						
							|  |  |  |         DPRINTF(3, | 
					
						
							|  |  |  |                 "%4d: uop %s, oparg %d, operand %" PRIu64 ", stack_level %d\n", | 
					
						
							|  |  |  |                 pc, | 
					
						
							|  |  |  |                 opcode < 256 ? _PyOpcode_OpName[opcode] : _PyOpcode_uop_name[opcode], | 
					
						
							|  |  |  |                 oparg, | 
					
						
							|  |  |  |                 operand, | 
					
						
							|  |  |  |                 (int)(stack_pointer - _PyFrame_Stackbase(frame))); | 
					
						
							|  |  |  |         pc++; | 
					
						
							| 
									
										
										
										
											2023-10-04 17:52:28 -04:00
										 |  |  |         OPT_STAT_INC(uops_executed); | 
					
						
							| 
									
										
										
										
											2023-10-30 20:02:45 -04:00
										 |  |  |         UOP_STAT_INC(opcode, execution_count); | 
					
						
							| 
									
										
										
										
											2023-10-04 17:52:28 -04:00
										 |  |  | #ifdef Py_STATS
 | 
					
						
							|  |  |  |         trace_uop_execution_counter++; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  |         switch (opcode) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "executor_cases.c.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 fprintf(stderr, "Unknown uop %d, operand %" PRIu64 "\n", opcode, operand); | 
					
						
							|  |  |  |                 Py_FatalError("Unknown uop"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unbound_local_error: | 
					
						
							|  |  |  |     _PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError, | 
					
						
							|  |  |  |         UNBOUNDLOCAL_ERROR_MSG, | 
					
						
							|  |  |  |         PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |     goto error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pop_4_error: | 
					
						
							|  |  |  |     STACK_SHRINK(1); | 
					
						
							|  |  |  | pop_3_error: | 
					
						
							|  |  |  |     STACK_SHRINK(1); | 
					
						
							|  |  |  | pop_2_error: | 
					
						
							|  |  |  |     STACK_SHRINK(1); | 
					
						
							|  |  |  | pop_1_error: | 
					
						
							|  |  |  |     STACK_SHRINK(1); | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |     // On ERROR_IF we return NULL as the frame.
 | 
					
						
							| 
									
										
										
										
											2023-08-17 11:16:03 +01:00
										 |  |  |     // The caller recovers the frame from tstate->current_frame.
 | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  |     DPRINTF(2, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); | 
					
						
							| 
									
										
										
										
											2023-10-04 17:52:28 -04:00
										 |  |  |     OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); | 
					
						
							| 
									
										
										
										
											2023-10-26 14:43:10 +01:00
										 |  |  |     frame->return_offset = 0;  // Don't leave this random
 | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  |     _PyFrame_SetStackPointer(frame, stack_pointer); | 
					
						
							|  |  |  |     Py_DECREF(self); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | deoptimize: | 
					
						
							|  |  |  |     // On DEOPT_IF we just repeat the last instruction.
 | 
					
						
							|  |  |  |     // This presumes nothing was popped from the stack (nor pushed).
 | 
					
						
							|  |  |  |     DPRINTF(2, "DEOPT: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); | 
					
						
							| 
									
										
										
										
											2023-10-04 17:52:28 -04:00
										 |  |  |     OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); | 
					
						
							| 
									
										
										
										
											2023-10-26 14:43:10 +01:00
										 |  |  |     frame->return_offset = 0;  // Dispatch to frame->instr_ptr
 | 
					
						
							| 
									
										
										
										
											2023-07-20 13:37:19 -07:00
										 |  |  |     _PyFrame_SetStackPointer(frame, stack_pointer); | 
					
						
							|  |  |  |     Py_DECREF(self); | 
					
						
							|  |  |  |     return frame; | 
					
						
							|  |  |  | } |