2023-07-20 17:37:19 -03:00
|
|
|
#include "Python.h"
|
|
|
|
|
2023-08-23 14:39:00 -03:00
|
|
|
#include "opcode.h"
|
|
|
|
|
2023-10-04 18:52:28 -03:00
|
|
|
#include "pycore_bitutils.h"
|
2023-07-20 17:37:19 -03: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 12:04:34 -03:00
|
|
|
#include "pycore_setobject.h" // _PySet_Update()
|
2023-07-20 17:37:19 -03:00
|
|
|
#include "pycore_sliceobject.h"
|
|
|
|
#include "pycore_uops.h"
|
|
|
|
|
2023-08-31 07:34:52 -03:00
|
|
|
#define TIER_TWO 2
|
2023-07-20 17:37:19 -03:00
|
|
|
#include "ceval_macros.h"
|
|
|
|
|
|
|
|
|
|
|
|
#undef DEOPT_IF
|
|
|
|
#define DEOPT_IF(COND, INSTNAME) \
|
|
|
|
if ((COND)) { \
|
|
|
|
goto deoptimize; \
|
|
|
|
}
|
|
|
|
|
2023-10-04 18:52:28 -03: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 17:37:19 -03: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-08 01:36:25 -03:00
|
|
|
if (lltrace >= (level)) { printf(__VA_ARGS__); }
|
2023-07-20 17:37:19 -03: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,
|
|
|
|
2 * (long)(frame->prev_instr + 1 -
|
|
|
|
(_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive));
|
|
|
|
|
|
|
|
PyThreadState *tstate = _PyThreadState_GET();
|
|
|
|
_PyUOpExecutorObject *self = (_PyUOpExecutorObject *)executor;
|
|
|
|
|
|
|
|
CHECK_EVAL_BREAKER();
|
|
|
|
|
2023-10-04 18:52:28 -03:00
|
|
|
OPT_STAT_INC(traces_executed);
|
2023-07-20 17:37:19 -03: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 18:52:28 -03:00
|
|
|
#ifdef Py_STATS
|
|
|
|
uint64_t trace_uop_execution_counter = 0;
|
|
|
|
#endif
|
2023-07-20 17:37:19 -03: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 18:52:28 -03:00
|
|
|
OPT_STAT_INC(uops_executed);
|
|
|
|
UOP_EXE_INC(opcode);
|
|
|
|
#ifdef Py_STATS
|
|
|
|
trace_uop_execution_counter++;
|
|
|
|
#endif
|
|
|
|
|
2023-07-20 17:37:19 -03: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 07:16:03 -03:00
|
|
|
// The caller recovers the frame from tstate->current_frame.
|
2023-07-20 17:37:19 -03:00
|
|
|
DPRINTF(2, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
|
2023-10-04 18:52:28 -03:00
|
|
|
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
|
2023-07-20 17:37:19 -03: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 18:52:28 -03:00
|
|
|
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
|
2023-07-20 17:37:19 -03:00
|
|
|
frame->prev_instr--; // Back up to just before destination
|
|
|
|
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
|
|
Py_DECREF(self);
|
|
|
|
return frame;
|
|
|
|
}
|