Skip to content

Commit 681778c

Browse files
authored
GH-113710: Improve _SET_IP and _CHECK_VALIDITY (GH-115248)
1 parent de07941 commit 681778c

7 files changed

+79
-35
lines changed

Include/internal/pycore_uop_ids.h

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

Include/internal/pycore_uop_metadata.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
198198
[_GUARD_IS_NONE_POP] = HAS_DEOPT_FLAG,
199199
[_GUARD_IS_NOT_NONE_POP] = HAS_DEOPT_FLAG,
200200
[_JUMP_TO_TOP] = HAS_EVAL_BREAK_FLAG,
201-
[_SET_IP] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG,
201+
[_SET_IP] = 0,
202202
[_SAVE_RETURN_OFFSET] = HAS_ARG_FLAG,
203203
[_EXIT_TRACE] = HAS_DEOPT_FLAG,
204204
[_CHECK_VALIDITY] = HAS_DEOPT_FLAG,
@@ -209,6 +209,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
209209
[_CHECK_GLOBALS] = HAS_DEOPT_FLAG,
210210
[_CHECK_BUILTINS] = HAS_DEOPT_FLAG,
211211
[_INTERNAL_INCREMENT_OPT_COUNTER] = 0,
212+
[_CHECK_VALIDITY_AND_SET_IP] = HAS_DEOPT_FLAG,
212213
};
213214

214215
const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
@@ -264,6 +265,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
264265
[_CHECK_PEP_523] = "_CHECK_PEP_523",
265266
[_CHECK_STACK_SPACE] = "_CHECK_STACK_SPACE",
266267
[_CHECK_VALIDITY] = "_CHECK_VALIDITY",
268+
[_CHECK_VALIDITY_AND_SET_IP] = "_CHECK_VALIDITY_AND_SET_IP",
267269
[_COMPARE_OP] = "_COMPARE_OP",
268270
[_COMPARE_OP_FLOAT] = "_COMPARE_OP_FLOAT",
269271
[_COMPARE_OP_INT] = "_COMPARE_OP_INT",

Python/bytecodes.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4037,10 +4037,9 @@ dummy_func(
40374037
CHECK_EVAL_BREAKER();
40384038
}
40394039

4040-
op(_SET_IP, (--)) {
4040+
op(_SET_IP, (instr_ptr/4 --)) {
40414041
TIER_TWO_ONLY
4042-
// TODO: Put the code pointer in `operand` to avoid indirection via `frame`
4043-
frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)) + oparg;
4042+
frame->instr_ptr = (_Py_CODEUNIT *)instr_ptr;
40444043
}
40454044

40464045
op(_SAVE_RETURN_OFFSET, (--)) {
@@ -4100,6 +4099,11 @@ dummy_func(
41004099
exe->count++;
41014100
}
41024101

4102+
op(_CHECK_VALIDITY_AND_SET_IP, (instr_ptr/4 --)) {
4103+
TIER_TWO_ONLY
4104+
DEOPT_IF(!current_executor->vm_data.valid);
4105+
frame->instr_ptr = (_Py_CODEUNIT *)instr_ptr;
4106+
}
41034107

41044108
// END BYTECODES //
41054109

Python/executor_cases.c.h

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

Python/optimizer.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,8 @@ translate_bytecode_to_trace(
432432
top: // Jump here after _PUSH_FRAME or likely branches
433433
for (;;) {
434434
target = INSTR_IP(instr, code);
435-
RESERVE_RAW(3, "epilogue"); // Always need space for _SET_IP, _CHECK_VALIDITY and _EXIT_TRACE
436-
ADD_TO_TRACE(_SET_IP, target, 0, target);
437-
ADD_TO_TRACE(_CHECK_VALIDITY, 0, 0, target);
435+
RESERVE_RAW(2, "epilogue"); // Always need space for _SET_IP, _CHECK_VALIDITY and _EXIT_TRACE
436+
ADD_TO_TRACE(_CHECK_VALIDITY_AND_SET_IP, 0, (uintptr_t)instr, target);
438437

439438
uint32_t opcode = instr->op.code;
440439
uint32_t oparg = instr->op.arg;

Python/optimizer_analysis.c

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -652,35 +652,62 @@ uop_redundancy_eliminator(
652652
static void
653653
remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
654654
{
655+
/* Remove _SET_IP and _CHECK_VALIDITY where possible.
656+
* _SET_IP is needed if the following instruction escapes or
657+
* could error. _CHECK_VALIDITY is needed if the previous
658+
* instruction could have escaped. */
655659
int last_set_ip = -1;
656-
bool maybe_invalid = false;
660+
bool may_have_escaped = false;
657661
for (int pc = 0; pc < buffer_size; pc++) {
658662
int opcode = buffer[pc].opcode;
659-
if (opcode == _SET_IP) {
660-
buffer[pc].opcode = NOP;
661-
last_set_ip = pc;
662-
}
663-
else if (opcode == _CHECK_VALIDITY) {
664-
if (maybe_invalid) {
665-
maybe_invalid = false;
666-
}
667-
else {
663+
switch (opcode) {
664+
case _SET_IP:
668665
buffer[pc].opcode = NOP;
669-
}
670-
}
671-
else if (op_is_end(opcode)) {
672-
break;
673-
}
674-
else {
675-
if (_PyUop_Flags[opcode] & HAS_ESCAPES_FLAG) {
676-
maybe_invalid = true;
677-
if (last_set_ip >= 0) {
678-
buffer[last_set_ip].opcode = _SET_IP;
666+
last_set_ip = pc;
667+
break;
668+
case _CHECK_VALIDITY:
669+
if (may_have_escaped) {
670+
may_have_escaped = false;
679671
}
680-
}
681-
if ((_PyUop_Flags[opcode] & HAS_ERROR_FLAG) || opcode == _PUSH_FRAME) {
682-
if (last_set_ip >= 0) {
683-
buffer[last_set_ip].opcode = _SET_IP;
672+
else {
673+
buffer[pc].opcode = NOP;
674+
}
675+
break;
676+
case _CHECK_VALIDITY_AND_SET_IP:
677+
if (may_have_escaped) {
678+
may_have_escaped = false;
679+
buffer[pc].opcode = _CHECK_VALIDITY;
680+
}
681+
else {
682+
buffer[pc].opcode = NOP;
683+
}
684+
last_set_ip = pc;
685+
break;
686+
case _JUMP_TO_TOP:
687+
case _EXIT_TRACE:
688+
return;
689+
default:
690+
{
691+
bool needs_ip = false;
692+
if (_PyUop_Flags[opcode] & HAS_ESCAPES_FLAG) {
693+
needs_ip = true;
694+
may_have_escaped = true;
695+
}
696+
if (_PyUop_Flags[opcode] & HAS_ERROR_FLAG) {
697+
needs_ip = true;
698+
}
699+
if (opcode == _PUSH_FRAME) {
700+
needs_ip = true;
701+
}
702+
if (needs_ip && last_set_ip >= 0) {
703+
if (buffer[last_set_ip].opcode == _CHECK_VALIDITY) {
704+
buffer[last_set_ip].opcode = _CHECK_VALIDITY_AND_SET_IP;
705+
}
706+
else {
707+
assert(buffer[last_set_ip].opcode == _NOP);
708+
buffer[last_set_ip].opcode = _SET_IP;
709+
}
710+
last_set_ip = -1;
684711
}
685712
}
686713
}

Python/tier2_redundancy_eliminator_cases.c.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,3 +1674,7 @@
16741674
break;
16751675
}
16761676

1677+
case _CHECK_VALIDITY_AND_SET_IP: {
1678+
break;
1679+
}
1680+

0 commit comments

Comments
 (0)