summaryrefslogtreecommitdiffstats
path: root/Python/executor.c
blob: 88c039da8539e2d59bfd6d5f7bee7b8c1d87ef07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "Python.h"

#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"
#include "pycore_setobject.h"     // _PySet_Update()
#include "pycore_sliceobject.h"
#include "pycore_uops.h"

#include "ceval_macros.h"


#undef ASSERT_KWNAMES_IS_NULL
#define ASSERT_KWNAMES_IS_NULL() (void)0

#undef DEOPT_IF
#define DEOPT_IF(COND, INSTNAME) \
    if ((COND)) {                \
        goto deoptimize;         \
    }

#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, ...) \
        if (lltrace >= (level)) { printf(__VA_ARGS__); }
#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();

    OBJECT_STAT_INC(optimization_traces_executed);
    _Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
    int pc = 0;
    int opcode;
    int oparg;
    uint64_t operand;

    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++;
        OBJECT_STAT_INC(optimization_uops_executed);
        switch (opcode) {

#define TIER_TWO 2
#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:
pop_1_exit_unwind:
    STACK_SHRINK(1);
error:
    // On ERROR_IF we return NULL as the frame.
    // The caller recovers the frame from tstate->current_frame.
    DPRINTF(2, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand);
    _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);
    frame->prev_instr--;  // Back up to just before destination
    _PyFrame_SetStackPointer(frame, stack_pointer);
    Py_DECREF(self);
    return frame;
}