struct callable_cache callable_cache;
PyObject *common_consts[NUM_COMMON_CONSTANTS];
// JIT tracing state
+ bool jit_is_tracing;
int jit_tracer_code_max_size;
int jit_tracer_code_curr_size;
_PyBloomFilter jit_tracer_dependencies;
[FORMAT_WITH_SPEC] = { .nuops = 1, .uops = { { _FORMAT_WITH_SPEC, OPARG_SIMPLE, 0 } } },
[FOR_ITER] = { .nuops = 1, .uops = { { _FOR_ITER, OPARG_REPLACED, 0 } } },
[FOR_ITER_GEN] = { .nuops = 3, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _FOR_ITER_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } },
- [FOR_ITER_LIST] = { .nuops = 3, .uops = { { _ITER_CHECK_LIST, OPARG_SIMPLE, 1 }, { _ITER_JUMP_LIST, OPARG_REPLACED, 1 }, { _ITER_NEXT_LIST, OPARG_SIMPLE, 1 } } },
+ [FOR_ITER_LIST] = { .nuops = 3, .uops = { { _ITER_CHECK_LIST, OPARG_SIMPLE, 1 }, { _ITER_JUMP_LIST, OPARG_REPLACED, 1 }, { _ITER_NEXT_LIST, OPARG_REPLACED, 1 } } },
[FOR_ITER_RANGE] = { .nuops = 3, .uops = { { _ITER_CHECK_RANGE, OPARG_SIMPLE, 1 }, { _ITER_JUMP_RANGE, OPARG_REPLACED, 1 }, { _ITER_NEXT_RANGE, OPARG_SIMPLE, 1 } } },
[FOR_ITER_TUPLE] = { .nuops = 3, .uops = { { _ITER_CHECK_TUPLE, OPARG_SIMPLE, 1 }, { _ITER_JUMP_TUPLE, OPARG_REPLACED, 1 }, { _ITER_NEXT_TUPLE, OPARG_SIMPLE, 1 } } },
[GET_AITER] = { .nuops = 1, .uops = { { _GET_AITER, OPARG_SIMPLE, 0 } } },
[_FOR_ITER_TIER_TWO] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
[_ITER_CHECK_LIST] = HAS_EXIT_FLAG,
[_GUARD_NOT_EXHAUSTED_LIST] = HAS_EXIT_FLAG,
- [_ITER_NEXT_LIST] = HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG,
[_ITER_NEXT_LIST_TIER_TWO] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG,
[_ITER_CHECK_TUPLE] = HAS_EXIT_FLAG,
[_GUARD_NOT_EXHAUSTED_TUPLE] = HAS_EXIT_FLAG,
[_ITER_CHECK_LIST] = "_ITER_CHECK_LIST",
[_ITER_CHECK_RANGE] = "_ITER_CHECK_RANGE",
[_ITER_CHECK_TUPLE] = "_ITER_CHECK_TUPLE",
- [_ITER_NEXT_LIST] = "_ITER_NEXT_LIST",
[_ITER_NEXT_LIST_TIER_TWO] = "_ITER_NEXT_LIST_TIER_TWO",
[_ITER_NEXT_RANGE] = "_ITER_NEXT_RANGE",
[_ITER_NEXT_TUPLE] = "_ITER_NEXT_TUPLE",
return 0;
case _GUARD_NOT_EXHAUSTED_LIST:
return 0;
- case _ITER_NEXT_LIST:
- return 0;
case _ITER_NEXT_LIST_TIER_TWO:
return 0;
case _ITER_CHECK_TUPLE:
#endif
}
- op(_ITER_NEXT_LIST, (iter, null_or_index -- iter, null_or_index, next)) {
+ replaced op(_ITER_NEXT_LIST, (iter, null_or_index -- iter, null_or_index, next)) {
PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
assert(PyList_CheckExact(list_o));
#ifdef Py_GIL_DISABLED
JUMP_TO_LABEL(label);
#if _Py_TAIL_CALL_INTERP || USE_COMPUTED_GOTOS
-# define IS_JIT_TRACING() (DISPATCH_TABLE_VAR == TRACING_DISPATCH_TABLE)
-# define ENTER_TRACING() DISPATCH_TABLE_VAR = TRACING_DISPATCH_TABLE;
-# define LEAVE_TRACING() DISPATCH_TABLE_VAR = DISPATCH_TABLE;
+# define IS_JIT_TRACING() (tstate->interp->jit_is_tracing)
+# define ENTER_TRACING() \
+ assert(!IS_JIT_TRACING()); \
+ DISPATCH_TABLE_VAR = TRACING_DISPATCH_TABLE; \
+ tstate->interp->jit_is_tracing = true;
+# define LEAVE_TRACING() \
+ assert(IS_JIT_TRACING()); \
+ DISPATCH_TABLE_VAR = DISPATCH_TABLE; \
+ tstate->interp->jit_is_tracing = false;
# define BAIL_TRACING_NO_DISPATCH() \
LEAVE_TRACING(); \
_PyFrame_SetStackPointer(frame, stack_pointer); \
if (_err < 0) { \
JUMP_TO_LABEL(error); \
}
-# define BAIL_TRACING() \
- BAIL_TRACING_NO_DISPATCH() \
- DISPATCH();
-# define RECORD_TRACE() do { \
- if (add_to_code_trace(tstate, frame, old_code, old_func, this_instr, next_instr, opcode, oparg, _jump_taken)) { \
- BAIL_TRACING(); \
- } \
- } while (0);
# define RECORD_TRACE_NO_DISPATCH() do { \
if (add_to_code_trace(tstate, frame, old_code, old_func, this_instr, next_instr, opcode, oparg, _jump_taken)) { \
BAIL_TRACING_NO_DISPATCH(); \
#define TRACING_DISPATCH() \
{ \
assert(frame->stackpointer == NULL); \
- RECORD_TRACE(); \
+ RECORD_TRACE_NO_DISPATCH(); \
NEXTOPARG(); \
PRE_DISPATCH_GOTO(); \
DISPATCH_GOTO(); \
#define TIER1_TO_TIER2(EXECUTOR) \
do { \
- LEAVE_TRACING(); \
OPT_STAT_INC(traces_executed); \
next_instr = _Py_jit_entry((EXECUTOR), frame, stack_pointer, tstate); \
frame = tstate->current_frame; \
break;
}
- case _ITER_NEXT_LIST: {
- _PyStackRef null_or_index;
- _PyStackRef iter;
- _PyStackRef next;
- oparg = CURRENT_OPARG();
- null_or_index = stack_pointer[-1];
- iter = stack_pointer[-2];
- PyObject *list_o = PyStackRef_AsPyObjectBorrow(iter);
- assert(PyList_CheckExact(list_o));
- #ifdef Py_GIL_DISABLED
- assert(_Py_IsOwnedByCurrentThread(list_o) ||
- _PyObject_GC_IS_SHARED(list_o));
- STAT_INC(FOR_ITER, hit);
- _PyFrame_SetStackPointer(frame, stack_pointer);
- int result = _PyList_GetItemRefNoLock((PyListObject *)list_o, PyStackRef_UntagInt(null_or_index), &next);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- if (result < 0) {
- UOP_STAT_INC(uopcode, miss);
- JUMP_TO_JUMP_TARGET();
- }
- if (result == 0) {
- null_or_index = PyStackRef_TagInt(-1);
- stack_pointer[-1] = null_or_index;
- TIER2_JUMPBY(oparg + 1);
- break;
- }
- #else
- next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(list_o, PyStackRef_UntagInt(null_or_index)));
- #endif
- null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index);
- stack_pointer[-1] = null_or_index;
- stack_pointer[0] = next;
- stack_pointer += 1;
- assert(WITHIN_STACK_BOUNDS());
- break;
- }
+ /* _ITER_NEXT_LIST is not a viable micro-op for tier 2 because it is replaced */
case _ITER_NEXT_LIST_TIER_TWO: {
_PyStackRef null_or_index;
LABEL(error)
{
- assert(!IS_JIT_TRACING());
#ifdef NDEBUG
if (!_PyErr_Occurred(tstate)) {
_PyFrame_SetStackPointer(frame, stack_pointer);
LABEL(exception_unwind)
{
- assert(!IS_JIT_TRACING());
int offset = INSTR_OFFSET()-1;
int level, handler, lasti;
int handled = get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti);
break;
}
- case _ITER_NEXT_LIST: {
- JitOptRef next;
- next = sym_new_not_null(ctx);
- stack_pointer[0] = next;
- stack_pointer += 1;
- assert(WITHIN_STACK_BOUNDS());
- break;
- }
+ /* _ITER_NEXT_LIST is not a viable micro-op for tier 2 */
case _ITER_NEXT_LIST_TIER_TWO: {
JitOptRef next;