[IMPORT_FROM] = { .nuops = 1, .uops = { { _IMPORT_FROM, OPARG_SIMPLE, 0 } } },
[IMPORT_NAME] = { .nuops = 1, .uops = { { _IMPORT_NAME, OPARG_SIMPLE, 0 } } },
[IS_OP] = { .nuops = 1, .uops = { { _IS_OP, OPARG_SIMPLE, 0 } } },
- [JUMP_BACKWARD_NO_INTERRUPT] = { .nuops = 1, .uops = { { _JUMP_BACKWARD_NO_INTERRUPT, OPARG_SIMPLE, 0 } } },
- [JUMP_BACKWARD_NO_JIT] = { .nuops = 2, .uops = { { _CHECK_PERIODIC, OPARG_SIMPLE, 1 }, { _JUMP_BACKWARD_NO_INTERRUPT, OPARG_SIMPLE, 1 } } },
+ [JUMP_BACKWARD_NO_INTERRUPT] = { .nuops = 1, .uops = { { _JUMP_BACKWARD_NO_INTERRUPT, OPARG_REPLACED, 0 } } },
+ [JUMP_BACKWARD_NO_JIT] = { .nuops = 2, .uops = { { _CHECK_PERIODIC, OPARG_SIMPLE, 1 }, { _JUMP_BACKWARD_NO_INTERRUPT, OPARG_REPLACED, 1 } } },
[LIST_APPEND] = { .nuops = 1, .uops = { { _LIST_APPEND, OPARG_SIMPLE, 0 } } },
[LIST_EXTEND] = { .nuops = 1, .uops = { { _LIST_EXTEND, OPARG_SIMPLE, 0 } } },
[LOAD_ATTR] = { .nuops = 1, .uops = { { _LOAD_ATTR, OPARG_SIMPLE, 8 } } },
[_IMPORT_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_IMPORT_FROM] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_IS_NONE] = HAS_ESCAPES_FLAG,
- [_JUMP_BACKWARD_NO_INTERRUPT] = HAS_ARG_FLAG | HAS_JUMP_FLAG,
[_GET_LEN] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_MATCH_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_MATCH_MAPPING] = 0,
[_ITER_NEXT_LIST_TIER_TWO] = "_ITER_NEXT_LIST_TIER_TWO",
[_ITER_NEXT_RANGE] = "_ITER_NEXT_RANGE",
[_ITER_NEXT_TUPLE] = "_ITER_NEXT_TUPLE",
- [_JUMP_BACKWARD_NO_INTERRUPT] = "_JUMP_BACKWARD_NO_INTERRUPT",
[_JUMP_TO_TOP] = "_JUMP_TO_TOP",
[_LIST_APPEND] = "_LIST_APPEND",
[_LIST_EXTEND] = "_LIST_EXTEND",
return 0;
case _IS_NONE:
return 1;
- case _JUMP_BACKWARD_NO_INTERRUPT:
- return 0;
case _GET_LEN:
return 0;
case _MATCH_CLASS:
#include "frameobject.h" // PyFrameLocalsProxyObject
#include "opcode.h" // EXTENDED_ARG
#include "../Include/pytypedefs.h"
-#include "../Include/internal/pycore_optimizer.h"
+#include "pycore_optimizer.h"
#include "clinic/frameobject.c.h"
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
RELOAD_STACK();
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
-#if TIER_TWO
- frame->instr_ptr += frame->return_offset;
-#endif
+ #endif
+ #if TIER_TWO
+ TIER2_STORE_IP(frame->return_offset);
+ #endif
res = temp;
LLTRACE_RESUME_FRAME();
}
_PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR);
#endif
RELOAD_STACK();
+ #if TIER_ONE
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
-#if TIER_TWO
- frame->instr_ptr += (1 + INLINE_CACHE_ENTRIES_SEND);
-#endif
+ #endif
+ #if TIER_TWO
+ TIER2_STORE_IP(1 + INLINE_CACHE_ENTRIES_SEND);
+ #endif
value = PyStackRef_MakeHeapSafe(temp);
LLTRACE_RESUME_FRAME();
}
macro(POP_JUMP_IF_NOT_NONE) = unused/1 + _IS_NONE + _POP_JUMP_IF_FALSE;
- inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) {
+ replaced inst(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.
* (see bpo-30039).
*/
-#if TIER_ONE
assert(oparg <= INSTR_OFFSET());
-#endif
JUMPBY(-oparg);
}
}
op(_FOR_ITER_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) {
- TIER2_JUMPBY(1 + INLINE_CACHE_ENTRIES_FOR_ITER);
+ TIER2_STORE_IP(1 + INLINE_CACHE_ENTRIES_FOR_ITER);
_PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index);
if (!PyStackRef_IsValid(item)) {
if (PyStackRef_IsError(item)) {
ERROR_NO_POP();
}
/* iterator ended normally */
- // Jump forward by oparg and skip the following END_FOR
- TIER2_JUMPBY(oparg + 1);
+ /* This just sets the IP to what it expects */
+ TIER2_STORE_IP(oparg + 1);
EXIT_IF(true);
}
next = item;
_PyInterpreterFrame *prev = frame->previous;
_PyThreadState_PopFrame(tstate, frame);
frame = tstate->current_frame = prev;
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
-#if TIER_TWO
+ #endif
+ #if TIER_TWO
frame->instr_ptr += (frame->return_offset);
-#endif
+ #endif
RELOAD_STACK();
res = PyStackRef_FromPyObjectStealMortal((PyObject *)gen);
LLTRACE_RESUME_FRAME();
for (;;) {
uopcode = next_uop->opcode;
#ifdef Py_DEBUG
- if (frame->lltrace >= 2) {
+ if (frame->lltrace >= 4) {
if (next_uop->opcode != _YIELD_VALUE &&
next_uop->opcode != _FOR_ITER_GEN_FRAME &&
next_uop->opcode != _PUSH_FRAME &&
next_uop->opcode != _PY_FRAME_KW &&
next_uop->opcode != _SAVE_RETURN_OFFSET &&
next_uop->opcode != _SAVE_RETURN_OFFSET) {
- // if (next_uop->opcode != _START_EXECUTOR) {
- // if (next_uop->format == UOP_FORMAT_TARGET) {
- // _Py_CODEUNIT *aim = _PyFrame_GetBytecode(frame) + next_uop->target;
- // printf(" aim=[%s]\n", _PyOpcode_OpName[aim->op.code]);
- // }
- // else if (next_uop->format == UOP_FORMAT_JUMP) {
- // _PyUOpInstruction *aim_uop = current_executor->trace + next_uop->jump_target;
- // if (aim_uop->format == UOP_FORMAT_TARGET) {
- // _Py_CODEUNIT *aim = _PyFrame_GetBytecode(frame) + aim_uop->target;
- // printf(" aim=[%s]\n", _PyOpcode_OpName[aim->op.code]);
- // }
- // }
- // }
+ if (next_uop->opcode != _START_EXECUTOR) {
+ if (next_uop->format == UOP_FORMAT_TARGET) {
+ _Py_CODEUNIT *aim = _PyFrame_GetBytecode(frame) + next_uop->target;
+ printf(" aim=[%s]\n", _PyOpcode_OpName[aim->op.code]);
+ }
+ else if (next_uop->format == UOP_FORMAT_JUMP) {
+ _PyUOpInstruction *aim_uop = current_executor->trace + next_uop->jump_target;
+ if (aim_uop->format == UOP_FORMAT_TARGET) {
+ _Py_CODEUNIT *aim = _PyFrame_GetBytecode(frame) + aim_uop->target;
+ printf(" aim=[%s]\n", _PyOpcode_OpName[aim->op.code]);
+ }
+ }
+ }
dump_stack(frame, stack_pointer);
}
if (next_uop->opcode == _START_EXECUTOR) {
# define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, instruction_funcptr_table, oparg
#endif
-
#if _Py_TAIL_CALL_INTERP
// Note: [[clang::musttail]] works for GCC 15, but not __attribute__((musttail)) at the moment.
# define Py_MUSTTAIL [[clang::musttail]]
* and skipped instructions.
*/
#define JUMPBY(x) (next_instr += (x))
-#define TIER2_JUMPBY(x) (frame->instr_ptr += (x))
+#define TIER2_STORE_IP(x) (frame->instr_ptr += (x))
#define SKIP_OVER(x) (next_instr += (x))
#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame)))
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
+ #endif
#if TIER_TWO
- frame->instr_ptr += frame->return_offset;
+ TIER2_STORE_IP(frame->return_offset);
#endif
res = temp;
LLTRACE_RESUME_FRAME();
_PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR);
#endif
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
+ #endif
#if TIER_TWO
- frame->instr_ptr += (1 + INLINE_CACHE_ENTRIES_SEND);
+ TIER2_STORE_IP(1 + INLINE_CACHE_ENTRIES_SEND);
#endif
value = PyStackRef_MakeHeapSafe(temp);
LLTRACE_RESUME_FRAME();
break;
}
- case _JUMP_BACKWARD_NO_INTERRUPT: {
- oparg = CURRENT_OPARG();
- #if TIER_ONE
- assert(oparg <= INSTR_OFFSET());
- #endif
- TIER2_JUMPBY(-oparg);
- break;
- }
+ /* _JUMP_BACKWARD_NO_INTERRUPT is not a viable micro-op for tier 2 because it is replaced */
case _GET_LEN: {
_PyStackRef obj;
oparg = CURRENT_OPARG();
null_or_index = stack_pointer[-1];
iter = stack_pointer[-2];
- TIER2_JUMPBY(1 + INLINE_CACHE_ENTRIES_FOR_ITER);
+ TIER2_STORE_IP(1 + INLINE_CACHE_ENTRIES_FOR_ITER);
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (PyStackRef_IsError(item)) {
JUMP_TO_ERROR();
}
- TIER2_JUMPBY(oparg + 1);
+ TIER2_STORE_IP(oparg + 1);
if (true) {
UOP_STAT_INC(uopcode, miss);
JUMP_TO_JUMP_TARGET();
_PyInterpreterFrame *prev = frame->previous;
_PyThreadState_PopFrame(tstate, frame);
frame = tstate->current_frame = prev;
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
+ #endif
#if TIER_TWO
frame->instr_ptr += (frame->return_offset);
#endif
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
+ #endif
#if TIER_TWO
- frame->instr_ptr += frame->return_offset;
+ TIER2_STORE_IP(frame->return_offset);
#endif
res = temp;
LLTRACE_RESUME_FRAME();
_PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR);
#endif
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
+ #endif
#if TIER_TWO
- frame->instr_ptr += (1 + INLINE_CACHE_ENTRIES_SEND);
+ TIER2_STORE_IP(1 + INLINE_CACHE_ENTRIES_SEND);
#endif
value = PyStackRef_MakeHeapSafe(temp);
LLTRACE_RESUME_FRAME();
}
// _JUMP_BACKWARD_NO_INTERRUPT
{
- #if TIER_ONE
assert(oparg <= INSTR_OFFSET());
- #endif
JUMPBY(-oparg);
}
DISPATCH();
}
// _JUMP_BACKWARD_NO_INTERRUPT
{
- #if TIER_ONE
assert(oparg <= INSTR_OFFSET());
- #endif
JUMPBY(-oparg);
}
// _JIT
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(JUMP_BACKWARD_NO_INTERRUPT);
- #if TIER_ONE
assert(oparg <= INSTR_OFFSET());
- #endif
JUMPBY(-oparg);
DISPATCH();
}
}
// _JUMP_BACKWARD_NO_INTERRUPT
{
- #if TIER_ONE
assert(oparg <= INSTR_OFFSET());
- #endif
JUMPBY(-oparg);
}
DISPATCH();
_PyInterpreterFrame *prev = frame->previous;
_PyThreadState_PopFrame(tstate, frame);
frame = tstate->current_frame = prev;
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
+ #endif
#if TIER_TWO
frame->instr_ptr += (frame->return_offset);
#endif
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
+ #endif
#if TIER_TWO
- frame->instr_ptr += frame->return_offset;
+ TIER2_STORE_IP(frame->return_offset);
#endif
res = temp;
LLTRACE_RESUME_FRAME();
_PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR);
#endif
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
+ #endif
#if TIER_TWO
- frame->instr_ptr += (1 + INLINE_CACHE_ENTRIES_SEND);
+ TIER2_STORE_IP(1 + INLINE_CACHE_ENTRIES_SEND);
#endif
value = PyStackRef_MakeHeapSafe(temp);
LLTRACE_RESUME_FRAME();
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
+ #endif
#if TIER_TWO
- frame->instr_ptr += frame->return_offset;
+ TIER2_STORE_IP(frame->return_offset);
#endif
res = temp;
LLTRACE_RESUME_FRAME();
_PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR);
#endif
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
+ #endif
#if TIER_TWO
- frame->instr_ptr += (1 + INLINE_CACHE_ENTRIES_SEND);
+ TIER2_STORE_IP(1 + INLINE_CACHE_ENTRIES_SEND);
#endif
value = PyStackRef_MakeHeapSafe(temp);
LLTRACE_RESUME_FRAME();
}
// _JUMP_BACKWARD_NO_INTERRUPT
{
- #if TIER_ONE
assert(oparg <= INSTR_OFFSET());
- #endif
JUMPBY(-oparg);
}
TRACING_DISPATCH();
}
// _JUMP_BACKWARD_NO_INTERRUPT
{
- #if TIER_ONE
assert(oparg <= INSTR_OFFSET());
- #endif
JUMPBY(-oparg);
}
// _JIT
(void)old_func;
int _jump_taken = false;
(void)_jump_taken;
- #if TIER_ONE
assert(oparg <= INSTR_OFFSET());
- #endif
JUMPBY(-oparg);
TRACING_DISPATCH();
}
}
// _JUMP_BACKWARD_NO_INTERRUPT
{
- #if TIER_ONE
assert(oparg <= INSTR_OFFSET());
- #endif
JUMPBY(-oparg);
}
TRACING_DISPATCH();
_PyInterpreterFrame *prev = frame->previous;
_PyThreadState_PopFrame(tstate, frame);
frame = tstate->current_frame = prev;
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
+ #endif
#if TIER_TWO
frame->instr_ptr += (frame->return_offset);
#endif
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(frame->return_offset);
+ #endif
#if TIER_TWO
- frame->instr_ptr += frame->return_offset;
+ TIER2_STORE_IP(frame->return_offset);
#endif
res = temp;
LLTRACE_RESUME_FRAME();
_PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR);
#endif
stack_pointer = _PyFrame_GetStackPointer(frame);
+ #if TIER_ONE
LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
+ #endif
#if TIER_TWO
- frame->instr_ptr += (1 + INLINE_CACHE_ENTRIES_SEND);
+ TIER2_STORE_IP(1 + INLINE_CACHE_ENTRIES_SEND);
#endif
value = PyStackRef_MakeHeapSafe(temp);
LLTRACE_RESUME_FRAME();
#include "pycore_tuple.h" // _PyTuple_FromArraySteal()
#include "opcode_ids.h"
-#include "../Include/internal/pycore_optimizer.h"
+#include "pycore_optimizer.h"
/* Uncomment this to dump debugging output when assertions fail */
break;
}
case JUMP_BACKWARD_JIT:
+ // This is possible as the JIT might have re-activated after it was disabled. // if (next_uop->opcode != _START_EXECUTOR) {
+ // if (next_uop->format == UOP_FORMAT_TARGET) {
+ // _Py_CODEUNIT *aim = _PyFrame_GetBytecode(frame) + next_uop->target;
+ // printf(" aim=[%s]\n", _PyOpcode_OpName[aim->op.code]);
+ // }
+ // else if (next_uop->format == UOP_FORMAT_JUMP) {
+ // _PyUOpInstruction *aim_uop = current_executor->trace + next_uop->jump_target;
+ // if (aim_uop->format == UOP_FORMAT_TARGET) {
+ // _Py_CODEUNIT *aim = _PyFrame_GetBytecode(frame) + aim_uop->target;
+ // printf(" aim=[%s]\n", _PyOpcode_OpName[aim->op.code]);
+ // }
+ // }
+ // }
+ case JUMP_BACKWARD_NO_JIT:
case JUMP_BACKWARD:
ADD_TO_TRACE(_CHECK_PERIODIC, 0, 0, target);
_Py_FALLTHROUGH;
break;
}
- case _JUMP_BACKWARD_NO_INTERRUPT: {
- break;
- }
+ /* _JUMP_BACKWARD_NO_INTERRUPT is not a viable micro-op for tier 2 */
case _GET_LEN: {
JitOptRef obj;
if storage.spilled:
raise analysis_error("stack_pointer needs reloading before dispatch", tkn)
storage.stack.flush(self.out)
- self.emit("TIER2_JUMPBY")
+ self.emit("TIER2_STORE_IP")
emit_to(self.out, tkn_iter, "SEMI")
self.emit(";\n")
return True