Skip to content

Commit 7192671

Browse files
Fully working bm_generators
1 parent fba9d2d commit 7192671

File tree

7 files changed

+33
-40
lines changed

7 files changed

+33
-40
lines changed

Python/bytecodes.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3033,7 +3033,7 @@ dummy_func(
30333033
/* If the eval breaker is set then stay in tier 1.
30343034
* This avoids any potentially infinite loops
30353035
* involving _RESUME_CHECK */
3036-
if (IS_JIT_TRACING() || _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
3036+
if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
30373037
opcode = executor->vm_data.opcode;
30383038
oparg = (oparg & ~255) | executor->vm_data.oparg;
30393039
next_instr = this_instr;
@@ -3236,6 +3236,7 @@ dummy_func(
32363236
}
32373237

32383238
op(_FOR_ITER_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) {
3239+
TIER2_JUMPBY(1 + INLINE_CACHE_ENTRIES_FOR_ITER);
32393240
_PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index);
32403241
if (!PyStackRef_IsValid(item)) {
32413242
if (PyStackRef_IsError(item)) {

Python/ceval.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,8 +1195,11 @@ _PyTier2Interpreter(
11951195
for (;;) {
11961196
uopcode = next_uop->opcode;
11971197
#ifdef Py_DEBUG
1198-
if (frame->lltrace >= 4 && next_uop->opcode != _YIELD_VALUE) {
1199-
// dump_stack(frame, stack_pointer);
1198+
if (frame->lltrace >= 4 &&
1199+
next_uop->opcode != _YIELD_VALUE &&
1200+
next_uop->opcode != _FOR_ITER_GEN_FRAME &&
1201+
next_uop->opcode != _PUSH_FRAME) {
1202+
dump_stack(frame, stack_pointer);
12001203
if (next_uop->opcode == _START_EXECUTOR) {
12011204
printf("%4d uop: ", 0);
12021205
}

Python/executor_cases.c.h

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer.c

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ _PyJIT_translate_single_bytecode_to_trace(
568568

569569
target = INSTR_IP(target_instr, old_code);
570570
// One for possible _DEOPT, one because _CHECK_VALIDITY itself might _DEOPT
571-
max_length-=2;
571+
max_length -= 2;
572572
if ((uint16_t)oparg != (uint64_t)oparg) {
573573
goto full;
574574
}
@@ -583,26 +583,27 @@ _PyJIT_translate_single_bytecode_to_trace(
583583
return 1;
584584
}
585585

586-
// Unsupported opcodes
587-
if (opcode == WITH_EXCEPT_START || opcode == RERAISE || opcode == CLEANUP_THROW) {
586+
if (opcode == ENTER_EXECUTOR) {
588587
goto full;
589588
}
590589

591-
RESERVE_RAW(1, "_CHECK_VALIDITY");
592-
ADD_TO_TRACE(_CHECK_VALIDITY, 0, 0, target);
593-
594-
if (!OPCODE_HAS_NO_SAVE_IP(opcode)) {
595-
RESERVE_RAW(2, "_SET_IP");
596-
ADD_TO_TRACE(_SET_IP, 0, (uintptr_t)target_instr, target);
590+
// Unsupported opcodes
591+
if (opcode == WITH_EXCEPT_START || opcode == RERAISE || opcode == CLEANUP_THROW) {
592+
goto full;
597593
}
598594

599595
bool needs_guard_ip = _PyOpcode_NeedsGuardIp[opcode] &&
600596
!(opcode == FOR_ITER_RANGE || opcode == FOR_ITER_LIST || opcode == FOR_ITER_TUPLE) &&
601597
!(opcode == JUMP_BACKWARD_NO_INTERRUPT || opcode == JUMP_BACKWARD || opcode == JUMP_BACKWARD_JIT) &&
602598
!(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_NONE || opcode == POP_JUMP_IF_NOT_NONE);
603599

604-
if (needs_guard_ip) {
605-
RESERVE_RAW(1, "_GUARD_IP");
600+
const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode];
601+
RESERVE_RAW(expansion->nuops + needs_guard_ip + 3, "uop and various checks");
602+
603+
ADD_TO_TRACE(_CHECK_VALIDITY, 0, 0, target);
604+
605+
if (!OPCODE_HAS_NO_SAVE_IP(opcode)) {
606+
ADD_TO_TRACE(_SET_IP, 0, (uintptr_t)target_instr, target);
606607
}
607608

608609
/* Special case the first instruction,
@@ -623,12 +624,10 @@ _PyJIT_translate_single_bytecode_to_trace(
623624

624625
if (OPCODE_HAS_EXIT(opcode)) {
625626
// Make space for side exit and final _EXIT_TRACE:
626-
RESERVE_RAW(2, "_EXIT_TRACE");
627627
max_length--;
628628
}
629629
if (OPCODE_HAS_ERROR(opcode)) {
630630
// Make space for error stub and final _EXIT_TRACE:
631-
RESERVE_RAW(2, "_ERROR_POP_N");
632631
max_length--;
633632
}
634633

@@ -643,7 +642,9 @@ _PyJIT_translate_single_bytecode_to_trace(
643642
int bitcount = counter & 1;
644643
int jump_likely = bitcount;
645644
uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_likely];
646-
ADD_TO_TRACE(uopcode, 0, 0, INSTR_IP(target_instr, old_code));
645+
_Py_CODEUNIT *next_instr = target_instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]];
646+
_Py_CODEUNIT *false_target = next_instr + oparg;
647+
ADD_TO_TRACE(uopcode, 0, 0, INSTR_IP(false_target, old_code));
647648
break;
648649
}
649650
case JUMP_BACKWARD_JIT:
@@ -704,13 +705,6 @@ _PyJIT_translate_single_bytecode_to_trace(
704705
if (uop == _TIER2_RESUME_CHECK) {
705706
target = next_inst;
706707
}
707-
#ifdef Py_DEBUG
708-
else {
709-
uint32_t jump_target = next_inst + oparg;
710-
assert(_Py_GetBaseCodeUnit(old_code, jump_target).op.code == END_FOR);
711-
assert(_Py_GetBaseCodeUnit(old_code, jump_target+1).op.code == POP_ITER);
712-
}
713-
#endif
714708
break;
715709
case OPERAND1_1:
716710
assert(trace[trace_length-1].opcode == uop);
@@ -772,6 +766,8 @@ _PyJIT_translate_single_bytecode_to_trace(
772766
if (!is_terminator(&tstate->interp->jit_tracer_code_buffer[trace_length-1])) {
773767
// Undo the last few instructions.
774768
trace_length = tstate->interp->jit_tracer_code_curr_size;
769+
// We previously reversed one.
770+
max_length += 1;
775771
ADD_TO_TRACE(_EXIT_TRACE, 0, 0, target);
776772
}
777773
tstate->interp->jit_tracer_code_curr_size = trace_length;
@@ -1121,10 +1117,14 @@ uop_optimize(
11211117
char *env_var = Py_GETENV("PYTHON_UOPS_OPTIMIZE");
11221118
bool is_noopt = true;
11231119
if (env_var == NULL || *env_var == '\0' || *env_var > '0') {
1124-
is_noopt = true;
1120+
is_noopt = false;
11251121
}
11261122
int curr_stackentries = tstate->interp->jit_tracer_initial_stack_depth;
11271123
int length = interp->jit_tracer_code_curr_size;
1124+
// Trace too short, don't bother.
1125+
if (length <= 8) {
1126+
return 0;
1127+
}
11281128
assert(length > 0);
11291129
assert(length < UOP_MAX_TRACE_LENGTH);
11301130
OPT_STAT_INC(traces_created);

Python/optimizer_analysis.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
493493
}
494494
/* _PUSH_FRAME doesn't escape or error, but it
495495
* does need the IP for the return address */
496-
bool needs_ip = opcode == _PUSH_FRAME;
496+
bool needs_ip = (opcode == _PUSH_FRAME || opcode == _YIELD_VALUE);
497497
if (_PyUop_Flags[opcode] & HAS_ESCAPES_FLAG) {
498498
needs_ip = true;
499499
may_have_escaped = true;

Tools/cases_generator/tier2_generator.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -226,16 +226,6 @@ def generate_tier2(
226226
)
227227
continue
228228
out.emit(f"case {uop.name}: {{\n")
229-
if uop.properties.jumps:
230-
containing_inst = None
231-
for inst in analysis.instructions.values():
232-
if uop in inst.parts:
233-
print(uop.name, inst.name)
234-
containing_inst = inst
235-
break
236-
assert containing_inst is not None, uop.name
237-
size = containing_inst.size
238-
out.emit(f"TIER2_JUMPBY({size});\n")
239229
declare_variables(uop, out)
240230
stack = Stack()
241231
stack = write_uop(uop, emitter, stack)

0 commit comments

Comments
 (0)