Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 46 additions & 33 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1357,22 +1357,35 @@ eval_frame_handle_pending(PyThreadState *tstate)
#endif

#ifdef Py_STATS
#define INSTRUCTION_START(op) \
#define RECORD_STATS(op) \
do { \
frame->prev_instr = next_instr++; \
OPCODE_EXE_INC(op); \
_py_stats.opcode_stats[lastopcode].pair_count[op]++; \
lastopcode = op; \
} while (0)
#else
#define INSTRUCTION_START(op) (frame->prev_instr = next_instr++)
#define RECORD_STATS(op) ((void)0)
#endif

#define INSTRUCTION_START(op) \
do { \
frame->prev_instr = next_instr++; \
RECORD_STATS(op); \
} while (0)

#define SAFE_INSTRUCTION_START(op) \
do { \
next_instr++;\
RECORD_STATS(op); \
} while (0)

#if USE_COMPUTED_GOTOS
#define TARGET(op) TARGET_##op: INSTRUCTION_START(op);
#define TARGET_SAFE(op) TARGET_##op: SAFE_INSTRUCTION_START(op);
#define DISPATCH_GOTO() goto *opcode_targets[opcode]
#else
#define TARGET(op) case op: INSTRUCTION_START(op);
#define TARGET_SAFE(op) case op: SAFE_INSTRUCTION_START(op);
#define DISPATCH_GOTO() goto dispatch_opcode
#endif

Expand Down Expand Up @@ -1831,16 +1844,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
It is essential that any operation that fails must goto error
and that all operation that succeed call DISPATCH() ! */

TARGET(NOP) {
TARGET_SAFE(NOP) {
DISPATCH();
}

TARGET(RESUME) {
TARGET_SAFE(RESUME) {
_PyCode_Warmup(frame->f_code);
JUMP_TO_INSTRUCTION(RESUME_QUICK);
}

TARGET(RESUME_QUICK) {
TARGET_SAFE(RESUME_QUICK) {
PREDICTED(RESUME_QUICK);
assert(tstate->cframe == &cframe);
assert(frame == cframe.current_frame);
Expand All @@ -1861,7 +1874,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(LOAD_FAST) {
TARGET_SAFE(LOAD_FAST) {
PyObject *value = GETLOCAL(oparg);
if (value == NULL) {
goto unbound_local_error;
Expand All @@ -1871,7 +1884,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(LOAD_CONST) {
TARGET_SAFE(LOAD_CONST) {
PREDICTED(LOAD_CONST);
PyObject *value = GETITEM(consts, oparg);
Py_INCREF(value);
Expand All @@ -1886,7 +1899,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(LOAD_FAST__LOAD_FAST) {
TARGET_SAFE(LOAD_FAST__LOAD_FAST) {
PyObject *value = GETLOCAL(oparg);
if (value == NULL) {
goto unbound_local_error;
Expand All @@ -1904,7 +1917,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
NOTRACE_DISPATCH();
}

TARGET(LOAD_FAST__LOAD_CONST) {
TARGET_SAFE(LOAD_FAST__LOAD_CONST) {
PyObject *value = GETLOCAL(oparg);
if (value == NULL) {
goto unbound_local_error;
Expand Down Expand Up @@ -1943,7 +1956,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
NOTRACE_DISPATCH();
}

TARGET(LOAD_CONST__LOAD_FAST) {
TARGET_SAFE(LOAD_CONST__LOAD_FAST) {
PyObject *value = GETITEM(consts, oparg);
NEXTOPARG();
next_instr++;
Expand All @@ -1964,7 +1977,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(PUSH_NULL) {
TARGET_SAFE(PUSH_NULL) {
/* Use BASIC_PUSH as NULL is not a valid object pointer */
BASIC_PUSH(NULL);
DISPATCH();
Expand Down Expand Up @@ -2775,7 +2788,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
}

TARGET(LOAD_ASSERTION_ERROR) {
TARGET_SAFE(LOAD_ASSERTION_ERROR) {
PyObject *value = PyExc_AssertionError;
Py_INCREF(value);
PUSH(value);
Expand Down Expand Up @@ -3122,7 +3135,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
}

TARGET(LOAD_GLOBAL_MODULE) {
TARGET_SAFE(LOAD_GLOBAL_MODULE) {
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
PyDictObject *dict = (PyDictObject *)GLOBALS();
Expand All @@ -3143,7 +3156,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
NOTRACE_DISPATCH();
}

TARGET(LOAD_GLOBAL_BUILTIN) {
TARGET_SAFE(LOAD_GLOBAL_BUILTIN) {
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);
Expand Down Expand Up @@ -3258,7 +3271,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(COPY_FREE_VARS) {
TARGET_SAFE(COPY_FREE_VARS) {
/* Copy closure variables to free variables */
PyCodeObject *co = frame->f_code;
PyObject *closure = frame->f_func->func_closure;
Expand Down Expand Up @@ -4044,12 +4057,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(JUMP_FORWARD) {
TARGET_SAFE(JUMP_FORWARD) {
JUMPBY(oparg);
DISPATCH();
}

TARGET(JUMP_BACKWARD) {
TARGET_SAFE(JUMP_BACKWARD) {
_PyCode_Warmup(frame->f_code);
JUMP_TO_INSTRUCTION(JUMP_BACKWARD_QUICK);
}
Expand Down Expand Up @@ -4247,7 +4260,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(JUMP_BACKWARD_NO_INTERRUPT) {
TARGET_SAFE(JUMP_BACKWARD_NO_INTERRUPT) {
/* This bytecode is used in the `yield from` or `await` loop.
* If there is an interrupt, we want it handled in the innermost
* generator or coroutine, so we deliberately do not check it here.
Expand All @@ -4257,7 +4270,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(JUMP_BACKWARD_QUICK) {
TARGET_SAFE(JUMP_BACKWARD_QUICK) {
PREDICTED(JUMP_BACKWARD_QUICK);
assert(oparg < INSTR_OFFSET());
JUMPBY(-oparg);
Expand Down Expand Up @@ -4515,7 +4528,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(PUSH_EXC_INFO) {
TARGET_SAFE(PUSH_EXC_INFO) {
PyObject *value = TOP();

_PyErr_StackItem *exc_info = tstate->exc_info;
Expand Down Expand Up @@ -4593,7 +4606,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
}

TARGET(LOAD_METHOD_WITH_VALUES) {
TARGET_SAFE(LOAD_METHOD_WITH_VALUES) {
/* LOAD_METHOD, with cached method object */
assert(cframe.use_tracing == 0);
PyObject *self = TOP();
Expand All @@ -4619,7 +4632,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
NOTRACE_DISPATCH();
}

TARGET(LOAD_METHOD_WITH_DICT) {
TARGET_SAFE(LOAD_METHOD_WITH_DICT) {
/* LOAD_METHOD, with a dict
Can be either a managed dict, or a tp_dictoffset offset.*/
assert(cframe.use_tracing == 0);
Expand Down Expand Up @@ -4651,7 +4664,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
NOTRACE_DISPATCH();
}

TARGET(LOAD_METHOD_NO_DICT) {
TARGET_SAFE(LOAD_METHOD_NO_DICT) {
assert(cframe.use_tracing == 0);
PyObject *self = TOP();
PyTypeObject *self_cls = Py_TYPE(self);
Expand Down Expand Up @@ -4706,7 +4719,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
NOTRACE_DISPATCH();
}

TARGET(PRECALL) {
TARGET_SAFE(PRECALL) {
PREDICTED(PRECALL);
/* Designed to work in tamdem with LOAD_METHOD. */
/* `meth` is NULL when LOAD_METHOD thinks that it's not
Expand Down Expand Up @@ -4752,7 +4765,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(PRECALL_BOUND_METHOD) {
TARGET_SAFE(PRECALL_BOUND_METHOD) {
DEOPT_IF(is_method(stack_pointer, oparg), PRECALL);
PyObject *function = PEEK(oparg + 1);
DEOPT_IF(Py_TYPE(function) != &PyMethod_Type, PRECALL);
Expand All @@ -4768,7 +4781,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(PRECALL_PYFUNC) {
TARGET_SAFE(PRECALL_PYFUNC) {
int nargs = oparg + is_method(stack_pointer, oparg);
PyObject *function = PEEK(nargs + 1);
DEOPT_IF(Py_TYPE(function) != &PyFunction_Type, PRECALL);
Expand All @@ -4777,7 +4790,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(KW_NAMES) {
TARGET_SAFE(KW_NAMES) {
assert(call_shape.kwnames == NULL);
assert(oparg < PyTuple_GET_SIZE(consts));
call_shape.kwnames = GETITEM(consts, oparg);
Expand Down Expand Up @@ -5583,7 +5596,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}

TARGET(COPY) {
TARGET_SAFE(COPY) {
assert(oparg != 0);
PyObject *peek = PEEK(oparg);
Py_INCREF(peek);
Expand Down Expand Up @@ -5626,15 +5639,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
}

TARGET(SWAP) {
TARGET_SAFE(SWAP) {
assert(oparg != 0);
PyObject *top = TOP();
SET_TOP(PEEK(oparg));
PEEK(oparg) = top;
DISPATCH();
}

TARGET(EXTENDED_ARG) {
TARGET_SAFE(EXTENDED_ARG) {
assert(oparg);
oparg <<= 8;
oparg |= _Py_OPARG(*next_instr);
Expand All @@ -5643,14 +5656,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH_GOTO();
}

TARGET(EXTENDED_ARG_QUICK) {
TARGET_SAFE(EXTENDED_ARG_QUICK) {
assert(oparg);
oparg <<= 8;
oparg |= _Py_OPARG(*next_instr);
NOTRACE_DISPATCH_SAME_OPARG();
}

TARGET(CACHE) {
TARGET_SAFE(CACHE) {
Py_UNREACHABLE();
}

Expand Down