|
29 | 29 |
|
30 | 30 | #define MAX_EXECUTORS_SIZE 256 |
31 | 31 |
|
| 32 | +// Trace too short, no progress: |
| 33 | +// _START_EXECUTOR |
| 34 | +// _MAKE_WARM |
| 35 | +// _CHECK_VALIDITY |
| 36 | +// _SET_IP |
| 37 | +// is 4-5 instructions. |
| 38 | +#define CODE_SIZE_NO_PROGRESS 5 |
| 39 | +// We start with _START_EXECUTOR, _MAKE_WARM |
| 40 | +#define CODE_SIZE_EMPTY 2 |
| 41 | + |
32 | 42 | #define _PyExecutorObject_CAST(op) ((_PyExecutorObject *)(op)) |
33 | 43 |
|
34 | 44 | static bool |
@@ -489,6 +499,14 @@ BRANCH_TO_GUARD[4][2] = { |
489 | 499 | [POP_JUMP_IF_NOT_NONE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_NOT_NONE_POP, |
490 | 500 | }; |
491 | 501 |
|
| 502 | +static const uint16_t |
| 503 | +guard_ip_uop[MAX_UOP_ID + 1] = { |
| 504 | + [_PUSH_FRAME] = _GUARD_IP__PUSH_FRAME, |
| 505 | + [_RETURN_GENERATOR] = _GUARD_IP_RETURN_GENERATOR, |
| 506 | + [_RETURN_VALUE] = _GUARD_IP_RETURN_VALUE, |
| 507 | + [_YIELD_VALUE] = _GUARD_IP_YIELD_VALUE, |
| 508 | +}; |
| 509 | + |
492 | 510 |
|
493 | 511 | #define CONFIDENCE_RANGE 1000 |
494 | 512 | #define CONFIDENCE_CUTOFF 333 |
@@ -601,7 +619,7 @@ _PyJit_translate_single_bytecode_to_trace( |
601 | 619 |
|
602 | 620 | /* Special case the first instruction, |
603 | 621 | * so that we can guarantee forward progress */ |
604 | | - if (progress_needed && _tstate->jit_tracer_state.prev_state.code_curr_size <= 3) { |
| 622 | + if (progress_needed && _tstate->jit_tracer_state.prev_state.code_curr_size <= CODE_SIZE_NO_PROGRESS) { |
605 | 623 | if (OPCODE_HAS_EXIT(opcode) || OPCODE_HAS_DEOPT(opcode)) { |
606 | 624 | opcode = _PyOpcode_Deopt[opcode]; |
607 | 625 | } |
@@ -750,7 +768,7 @@ _PyJit_translate_single_bytecode_to_trace( |
750 | 768 | { |
751 | 769 | if ((next_instr != _tstate->jit_tracer_state.initial_state.close_loop_instr) && |
752 | 770 | (next_instr != _tstate->jit_tracer_state.initial_state.start_instr) && |
753 | | - _tstate->jit_tracer_state.prev_state.code_curr_size > 5 && |
| 771 | + _tstate->jit_tracer_state.prev_state.code_curr_size > CODE_SIZE_NO_PROGRESS && |
754 | 772 | // For side exits, we don't want to terminate them early. |
755 | 773 | _tstate->jit_tracer_state.initial_state.exit == NULL && |
756 | 774 | // These are coroutines, and we want to unroll those usually. |
@@ -898,28 +916,17 @@ _PyJit_translate_single_bytecode_to_trace( |
898 | 916 | } // End switch (opcode) |
899 | 917 |
|
900 | 918 | if (needs_guard_ip) { |
901 | | - switch (trace[trace_length-1].opcode) { |
902 | | - case _PUSH_FRAME: |
903 | | - ADD_TO_TRACE(_GUARD_IP__PUSH_FRAME, 0, (uintptr_t)next_instr, 0); |
904 | | - break; |
905 | | - case _RETURN_GENERATOR: |
906 | | - ADD_TO_TRACE(_GUARD_IP_RETURN_GENERATOR, 0, (uintptr_t)next_instr, 0); |
907 | | - break; |
908 | | - case _RETURN_VALUE: |
909 | | - ADD_TO_TRACE(_GUARD_IP_RETURN_VALUE, 0, (uintptr_t)next_instr, 0); |
910 | | - break; |
911 | | - case _YIELD_VALUE: |
912 | | - ADD_TO_TRACE(_GUARD_IP_YIELD_VALUE, 0, (uintptr_t)next_instr, 0); |
913 | | - break; |
914 | | - default: |
915 | | - DPRINTF(1, "Unknown uop needing guard ip %s\n", _PyOpcode_uop_name[trace[trace_length-1].opcode]); |
916 | | - Py_UNREACHABLE(); |
| 919 | + uint16_t guard_ip = guard_ip_uop[trace[trace_length-1].opcode]; |
| 920 | + if (guard_ip == 0) { |
| 921 | + DPRINTF(1, "Unknown uop needing guard ip %s\n", _PyOpcode_uop_name[trace[trace_length-1].opcode]); |
| 922 | + Py_UNREACHABLE(); |
917 | 923 | } |
| 924 | + ADD_TO_TRACE(guard_ip, 0, (uintptr_t)next_instr, 0); |
918 | 925 | } |
919 | 926 | // Loop back to the start |
920 | 927 | int is_first_instr = _tstate->jit_tracer_state.initial_state.close_loop_instr == next_instr || |
921 | 928 | _tstate->jit_tracer_state.initial_state.start_instr == next_instr; |
922 | | - if (is_first_instr && _tstate->jit_tracer_state.prev_state.code_curr_size > 5) { |
| 929 | + if (is_first_instr && _tstate->jit_tracer_state.prev_state.code_curr_size > CODE_SIZE_NO_PROGRESS) { |
923 | 930 | if (needs_guard_ip) { |
924 | 931 | ADD_TO_TRACE(_SET_IP, 0, (uintptr_t)next_instr, 0); |
925 | 932 | } |
@@ -961,7 +968,7 @@ _PyJit_TryInitializeTracing( |
961 | 968 | _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; |
962 | 969 | // A recursive trace. |
963 | 970 | // Don't trace into the inner call because it will stomp on the previous trace, causing endless retraces. |
964 | | - if (_tstate->jit_tracer_state.prev_state.code_curr_size > 2) { |
| 971 | + if (_tstate->jit_tracer_state.prev_state.code_curr_size > CODE_SIZE_NO_PROGRESS) { |
965 | 972 | return 0; |
966 | 973 | } |
967 | 974 | if (oparg > 0xFFFF) { |
@@ -996,7 +1003,7 @@ _PyJit_TryInitializeTracing( |
996 | 1003 |
|
997 | 1004 | add_to_trace(_tstate->jit_tracer_state.code_buffer, 0, _START_EXECUTOR, 0, (uintptr_t)start_instr, INSTR_IP(start_instr, code)); |
998 | 1005 | add_to_trace(_tstate->jit_tracer_state.code_buffer, 1, _MAKE_WARM, 0, 0, 0); |
999 | | - _tstate->jit_tracer_state.prev_state.code_curr_size = 2; |
| 1006 | + _tstate->jit_tracer_state.prev_state.code_curr_size = CODE_SIZE_EMPTY; |
1000 | 1007 |
|
1001 | 1008 | _tstate->jit_tracer_state.prev_state.code_max_size = UOP_MAX_TRACE_LENGTH; |
1002 | 1009 | _tstate->jit_tracer_state.initial_state.start_instr = start_instr; |
@@ -1031,7 +1038,7 @@ _PyJit_FinalizeTracing(PyThreadState *tstate) |
1031 | 1038 | Py_CLEAR(_tstate->jit_tracer_state.initial_state.code); |
1032 | 1039 | Py_CLEAR(_tstate->jit_tracer_state.initial_state.func); |
1033 | 1040 | Py_CLEAR(_tstate->jit_tracer_state.prev_state.instr_code); |
1034 | | - _tstate->jit_tracer_state.prev_state.code_curr_size = 2; |
| 1041 | + _tstate->jit_tracer_state.prev_state.code_curr_size = CODE_SIZE_EMPTY; |
1035 | 1042 | _tstate->jit_tracer_state.prev_state.code_max_size = UOP_MAX_TRACE_LENGTH - 1; |
1036 | 1043 | } |
1037 | 1044 |
|
@@ -1112,18 +1119,16 @@ prepare_for_execution(_PyUOpInstruction *buffer, int length) |
1112 | 1119 | exit_op = _HANDLE_PENDING_AND_DEOPT; |
1113 | 1120 | } |
1114 | 1121 | int32_t jump_target = target; |
1115 | | - bool unique_target = false; |
1116 | 1122 | if ( |
1117 | 1123 | opcode == _GUARD_IP__PUSH_FRAME || |
1118 | 1124 | opcode == _GUARD_IP_RETURN_VALUE || |
1119 | 1125 | opcode == _GUARD_IP_YIELD_VALUE || |
1120 | 1126 | opcode == _GUARD_IP_RETURN_GENERATOR |
1121 | 1127 | ) { |
1122 | 1128 | exit_op = _DYNAMIC_EXIT; |
1123 | | - unique_target = true; |
1124 | 1129 | } |
1125 | 1130 | bool is_control_flow = (opcode == _GUARD_IS_FALSE_POP || opcode == _GUARD_IS_TRUE_POP || is_for_iter_test[opcode]); |
1126 | | - if (unique_target || jump_target != current_jump_target || current_exit_op != exit_op) { |
| 1131 | + if (jump_target != current_jump_target || current_exit_op != exit_op) { |
1127 | 1132 | make_exit(&buffer[next_spare], exit_op, jump_target, is_control_flow); |
1128 | 1133 | current_exit_op = exit_op; |
1129 | 1134 | current_jump_target = jump_target; |
@@ -1363,8 +1368,7 @@ uop_optimize( |
1363 | 1368 | } |
1364 | 1369 | int curr_stackentries = _tstate->jit_tracer_state.initial_state.stack_depth; |
1365 | 1370 | int length = _tstate->jit_tracer_state.prev_state.code_curr_size; |
1366 | | - // Trace too short, don't bother. |
1367 | | - if (length <= 5) { |
| 1371 | + if (length <= CODE_SIZE_NO_PROGRESS) { |
1368 | 1372 | return 0; |
1369 | 1373 | } |
1370 | 1374 | assert(length > 0); |
|
0 commit comments