From f038e7f472efd2918dcd68ade9104cd073740a60 Mon Sep 17 00:00:00 2001 From: Lauta Date: Fri, 9 May 2025 01:24:20 +0200 Subject: [PATCH 1/9] Allow LOAD_FAST to be optimized to LOAD_FAST_BORROW when the loaded reference is unconsumed at the end of a basic block, as long as it's otherwise safe to borrow (not killed and not stored as a local). --- Lib/test/test_peepholer.py | 35 ++++++++++++++++++++++++++--------- Python/flowgraph.c | 2 +- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 47f51f1979faab..475dd37e38747f 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -2430,14 +2430,14 @@ def test_optimized(self): ] self.check(insts, expected) - def test_unoptimized_if_unconsumed(self): + def test_optimize_unconsumed_when_is_safe(self): insts = [ ("LOAD_FAST", 0, 1), ("LOAD_FAST", 1, 2), ("POP_TOP", None, 3), ] expected = [ - ("LOAD_FAST", 0, 1), + ("LOAD_FAST_BORROW", 0, 1), ("LOAD_FAST_BORROW", 1, 2), ("POP_TOP", None, 3), ] @@ -2449,7 +2449,7 @@ def test_unoptimized_if_unconsumed(self): ("POP_TOP", None, 3), ] expected = [ - ("LOAD_FAST", 0, 1), + ("LOAD_FAST_BORROW", 0, 1), ("NOP", None, 2), ("NOP", None, 3), ] @@ -2509,7 +2509,12 @@ def test_consume_some_inputs_no_outputs(self): ("GET_LEN", None, 2), ("LIST_APPEND", 0, 3), ] - self.check(insts, insts) + expected = [ + ("LOAD_FAST_BORROW", 0, 1), + ("GET_LEN", None, 2), + ("LIST_APPEND", 0, 3), + ] + self.check(insts, expected) def test_check_exc_match(self): insts = [ @@ -2518,7 +2523,7 @@ def test_check_exc_match(self): ("CHECK_EXC_MATCH", None, 3) ] expected = [ - ("LOAD_FAST", 0, 1), + ("LOAD_FAST_BORROW", 0, 1), ("LOAD_FAST_BORROW", 1, 2), ("CHECK_EXC_MATCH", None, 3) ] @@ -2537,7 +2542,19 @@ def test_for_iter(self): ("LOAD_CONST", 0, 7), ("RETURN_VALUE", None, 8), ] - self.cfg_optimization_test(insts, insts, consts=[None]) + expected = [ + ("LOAD_FAST_BORROW", 0, 1), + top := self.Label(), + ("FOR_ITER", end := self.Label(), 2), + ("STORE_FAST", 2, 3), + ("JUMP", top, 4), + end, + ("END_FOR", None, 5), + ("POP_TOP", None, 6), + ("LOAD_CONST", 0, 7), + ("RETURN_VALUE", None, 8), + ] + self.cfg_optimization_test(insts, expected, consts=[None]) def test_load_attr(self): insts = [ @@ -2556,7 +2573,7 @@ def test_load_attr(self): ("LOAD_ATTR", 1, 2), ] expected = [ - ("LOAD_FAST", 0, 1), + ("LOAD_FAST_BORROW", 0, 1), ("LOAD_ATTR", 1, 2), ] self.check(insts, expected) @@ -2586,7 +2603,7 @@ def test_super_attr(self): expected = [ ("LOAD_FAST_BORROW", 0, 1), ("LOAD_FAST_BORROW", 1, 2), - ("LOAD_FAST", 2, 3), + ("LOAD_FAST_BORROW", 2, 3), ("LOAD_SUPER_ATTR", 1, 4), ] self.check(insts, expected) @@ -2603,7 +2620,7 @@ def test_send(self): ("RETURN_VALUE", None, 7) ] expected = [ - ("LOAD_FAST", 0, 1), + ("LOAD_FAST_BORROW", 0, 1), ("LOAD_FAST_BORROW", 1, 2), ("SEND", end := self.Label(), 3), ("LOAD_CONST", 0, 4), diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 78ef02a911a72b..80b30f8c702e23 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -2976,7 +2976,7 @@ optimize_load_fast(cfg_builder *g) // Optimize instructions for (int i = 0; i < block->b_iused; i++) { - if (!instr_flags[i]) { + if (!(instr_flags[i] & (SUPPORT_KILLED | STORED_AS_LOCAL))) { cfg_instr *instr = &block->b_instr[i]; switch (instr->i_opcode) { case LOAD_FAST: From 8f38622c2148e060f0191f5e3d971c2e7930005b Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 00:06:53 +0000 Subject: [PATCH 2/9] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-05-09-00-06-52.gh-issue-133672.y6QwwH.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-05-09-00-06-52.gh-issue-133672.y6QwwH.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-05-09-00-06-52.gh-issue-133672.y6QwwH.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-09-00-06-52.gh-issue-133672.y6QwwH.rst new file mode 100644 index 00000000000000..63d014e4329f8c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-09-00-06-52.gh-issue-133672.y6QwwH.rst @@ -0,0 +1 @@ +The peephole optimizer now converts LOAD_FAST to LOAD_FAST_BORROW more aggressively. This optimization is applied even if the loaded variable remains live on the stack at the end of a basic block, as long as the borrow is otherwise determined to be safe. This can reduce reference counting overhead in certain code patterns, such as with iterables in loops. From 2f0ffdda25a22b0d46a24224ac552392d80e2944 Mon Sep 17 00:00:00 2001 From: Lauta Date: Wed, 14 May 2025 14:56:02 +0200 Subject: [PATCH 3/9] Improve CFG optimization with new LOAD_FAST_BORROW safety checks. --- Python/flowgraph.c | 349 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 340 insertions(+), 9 deletions(-) diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 80b30f8c702e23..c795ebb454054b 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -71,6 +71,8 @@ typedef struct _PyCfgBasicblock { unsigned b_cold : 1; /* b_warm is used by the cold-detection algorithm to mark blocks which are definitely not cold */ unsigned b_warm : 1; + /* b_dfs_visited_gen is used by the borrow-safe analysis to mark whether a block has been visited */ + int b_dfs_visited_gen; } basicblock; @@ -95,6 +97,8 @@ typedef struct _PyCfgBuilder cfg_builder; #define LOCATION(LNO, END_LNO, COL, END_COL) \ ((const _Py_SourceLocation){(LNO), (END_LNO), (COL), (END_COL)}) +static int cfg_dfs_generation_counter = 0; + static inline int is_block_push(cfg_instr *i) { @@ -2701,6 +2705,267 @@ load_fast_push_block(basicblock ***sp, basicblock *target, } } +/* + * Recursively determine if a borrowed reference remains safe along all CFG paths. + * + * This function performs a Depth-First Search (DFS) starting from 'current_block'. + * It tracks a specific value that was notionally loaded by a LOAD_FAST_BORROW + * instruction and is currently at 'depth_of_value_on_entry' on the operand stack + * (0 being TOS, -1 if already known to be consumed). The 'original_local_idx' + * is the index of the local variable from which this value was borrowed. + * + * A borrow is considered UNSAFE if, along any execution path before the + * borrowed value is consumed from the stack: + * 1. The 'original_local_idx' (the backing store for the borrow) is overwritten + * (e.g., by STORE_FAST, DELETE_FAST on that local). + * 2. The borrowed value itself, when at the top of the stack (depth 0), is + * consumed by an instruction that stores it into any local variable + * (e.g., STORE_FAST). + * 3. The value is not consumed and the CFG path ends (e.g., end of function + * without consumption) or enters a cycle where it's not consumed. + * + * The function uses 'cfg_dfs_generation_counter' in conjunction with + * 'current_block->b_dfs_visited_gen' to detect cycles within the current + * specific DFS traversal, preventing infinite loops and deeming such cyclic + * paths unsafe if the value isn't consumed within the cycle. + * + * Stack depths are tracked by: + * - 'depth_of_value_on_entry': The depth of the tracked item upon entering 'current_block'. + * - 'current_target_depth': The depth of the item as instructions in 'current_block' are processed. + * - 'depth_before_jump_op_effect': When a jump instruction is encountered, this + * is calculated by simulating all prior instructions in 'current_block' to find + * the item's depth *just before* the jump instruction itself has any stack effect. + * This precise depth is then used to calculate the 'target_entry_depth' for the + * recursive call to the jump's target block. + * + * Args: + * current_block: The basic block to start analysis from for this recursive step. + * depth_of_value_on_entry: The depth of the tracked borrowed value from TOS + * (0 = TOS, -1 if already consumed). + * original_local_idx: The index of the local variable backing the borrow. + * g: The CFG builder. + * + * Returns: + * true if the borrow is safe along all paths from this point, false otherwise. + */ +static bool +is_borrow_safe( + basicblock *current_block, + Py_ssize_t depth_of_value_on_entry, + int original_local_idx, + cfg_builder *g) +{ + if (depth_of_value_on_entry == -1) { + return true; + } + + if (current_block->b_dfs_visited_gen == cfg_dfs_generation_counter) { + return false; + } + current_block->b_dfs_visited_gen = cfg_dfs_generation_counter; + + Py_ssize_t current_target_depth = depth_of_value_on_entry; + + for (int i = 0; i < current_block->b_iused; i++) { + cfg_instr *instr = ¤t_block->b_instr[i]; + int opcode = instr->i_opcode; + int oparg = instr->i_oparg; + + // 1. Check if the original local is killed before the value is consumed. + if ((opcode == STORE_FAST || opcode == DELETE_FAST || opcode == LOAD_FAST_AND_CLEAR) && + oparg == original_local_idx) { + return false; + } + + // 2. Simulate stack effect and check for consumption or unsafe store. + stack_effects effects_noj; + if (get_stack_effects(opcode, oparg, 0, &effects_noj) < 0) { + return false; // Error in stack effect calculation + } + int num_popped = _PyOpcode_num_popped(opcode, oparg); + int num_pushed = _PyOpcode_num_pushed(opcode, oparg); + + if (current_target_depth < num_popped) { + if (opcode == STORE_FAST && current_target_depth == 0) { + // Unsafe: borrowed value was at TOS and is being stored into a local. + return false; + } + return true; // Safely consumed by this instruction. + } + // Value not consumed, update its depth. + current_target_depth = current_target_depth - num_popped + num_pushed; + + // 3. Handle branches (jumps are always last in a basic block). + if (HAS_TARGET(opcode)) { + if (i != current_block->b_iused - 1) { + continue; // Skip jumps that are not the last instruction in the block. + } + bool safe_on_all_branches = true; + + // Calculate item's depth just before this jump instruction's own stack effect. + Py_ssize_t depth_before_jump_op_effect = depth_of_value_on_entry; + for(int k=0; k < i; ++k) { // Iterate instructions before the current jump + cfg_instr *prev_instr_in_block = ¤t_block->b_instr[k]; + // Kill check for intermediate instructions + if ((prev_instr_in_block->i_opcode == STORE_FAST || + prev_instr_in_block->i_opcode == DELETE_FAST || + prev_instr_in_block->i_opcode == LOAD_FAST_AND_CLEAR) && + prev_instr_in_block->i_oparg == original_local_idx) { + return false; + } + stack_effects prev_effects; + if (get_stack_effects(prev_instr_in_block->i_opcode, prev_instr_in_block->i_oparg, 0, &prev_effects) < 0) { + return false; + } + int prev_popped_val = _PyOpcode_num_popped(prev_instr_in_block->i_opcode, prev_instr_in_block->i_oparg); + if (depth_before_jump_op_effect < prev_popped_val) { // Consumed before jump + if (prev_instr_in_block->i_opcode == STORE_FAST && depth_before_jump_op_effect == 0) { + return false; // Stored into local + } + return true; // Safely consumed before the jump + } + depth_before_jump_op_effect = depth_before_jump_op_effect - prev_popped_val + + _PyOpcode_num_pushed(prev_instr_in_block->i_opcode, prev_instr_in_block->i_oparg); + } + + // Analyze jump target path + stack_effects effects_jump; + if (get_stack_effects(opcode, oparg, 1, &effects_jump) < 0) return false; + int jump_popped_val = _PyOpcode_num_popped(opcode, oparg); + Py_ssize_t target_entry_depth = depth_before_jump_op_effect; + + if (target_entry_depth < jump_popped_val) { // Consumed by the jump op itself + if (opcode == STORE_FAST && target_entry_depth == 0) { + safe_on_all_branches = false; + } + // else: safely consumed by jump operation. + } else { // Not consumed by jump op, recurse on target. + target_entry_depth = target_entry_depth - jump_popped_val + _PyOpcode_num_pushed(opcode, oparg); + if (!is_borrow_safe(instr->i_target, target_entry_depth, original_local_idx, g)) { + safe_on_all_branches = false; + } + } + + // Analyze fallthrough path for conditional jumps, if the jump path was safe. + if (safe_on_all_branches && IS_CONDITIONAL_JUMP_OPCODE(opcode) && current_block->b_next) { + // 'current_target_depth' already reflects the stack state if the jump is *not* taken. + if (!is_borrow_safe(current_block->b_next, current_target_depth, original_local_idx, g)) { + safe_on_all_branches = false; + } + } + return safe_on_all_branches; + } + } + + // When the instructions finish and the value isn't consumed, check fallthrough. + if (current_block->b_next && BB_HAS_FALLTHROUGH(current_block)) { + return is_borrow_safe(current_block->b_next, current_target_depth, original_local_idx, g); + } + + // No further path (or no fallthrough) and value is still on stack (current_target_depth is valid). + // This means it's unconsumed at the end of a CFG path. + return false; +} + + +/* + * Initiates a Control Flow Graph (CFG) wide safety check for a borrowed reference. + * + * This function is called when a LOAD_FAST instruction is a candidate for + * LOAD_FAST_BORROW, but its produced value ('REF_UNCONSUMED' flag is set) + * might live beyond the current basic block ('producer_block'). + * + * It determines the immediate successor(s) of the 'producer_block' and the + * stack depth at which the borrowed value (identified by 'original_local_idx' + * and initially at 'depth_of_value_at_producer_end' from TOS) would enter + * these successors. + * + * It then calls 'is_borrow_safe()' for each successor path. The borrow is + * considered globally safe only if 'is_borrow_safe()' returns true for ALL + * possible successor paths. + * + * A new DFS traversal is started by incrementing 'cfg_dfs_generation_counter' + * to ensure that 'is_borrow_safe()' uses a fresh set of visited markers + * ('b_dfs_visited_gen') for its analysis. + * + * Args: + * producer_block: The basic block containing the LOAD_FAST candidate. + * depth_of_value_at_producer_end: The depth of the candidate borrowed value + * from TOS at the end of 'producer_block'. + * (0 = TOS, -1 if already consumed - though + * this function expects a live value). + * original_local_idx: The index of the local variable backing the borrow. + * g: The CFG builder. + * + * Returns: + * true if the borrow is safe across all subsequent CFG paths, false otherwise. + */ +static bool +check_borrow_safety_globally( + basicblock *producer_block, + Py_ssize_t depth_of_value_at_producer_end, + int original_local_idx, + cfg_builder *g) +{ + cfg_dfs_generation_counter++; + bool overall_safety = true; + + cfg_instr *last_instr = basicblock_last_instr(producer_block); + + // If depth is -1, implies value was already consumed or is invalid for tracking. + if (depth_of_value_at_producer_end == -1) { + return false; + } + + if (last_instr && HAS_TARGET(last_instr->i_opcode)) { + stack_effects effects_jump; + if (get_stack_effects(last_instr->i_opcode, last_instr->i_oparg, 1, &effects_jump) < 0) return false; + int jump_popped = _PyOpcode_num_popped(last_instr->i_opcode, last_instr->i_oparg); + Py_ssize_t entry_depth_for_target = depth_of_value_at_producer_end; + + if (entry_depth_for_target < jump_popped) { // Consumed by the jump itself. + if (last_instr->i_opcode == STORE_FAST && entry_depth_for_target == 0) { + overall_safety = false; // Unsafe store of borrowed value. + } + // else: safely consumed. + } else { + entry_depth_for_target = entry_depth_for_target - jump_popped + + _PyOpcode_num_pushed(last_instr->i_opcode, last_instr->i_oparg); + if (!is_borrow_safe(last_instr->i_target, entry_depth_for_target, original_local_idx, g)) { + overall_safety = false; + } + } + + // Analyze fallthrough path for conditional jumps, if the jump path was safe. + if (overall_safety && IS_CONDITIONAL_JUMP_OPCODE(last_instr->i_opcode) && producer_block->b_next) { + stack_effects effects_fall; // Stack effect if jump is NOT taken. + if (get_stack_effects(last_instr->i_opcode, last_instr->i_oparg, 0, &effects_fall) < 0) return false; + int fall_popped = _PyOpcode_num_popped(last_instr->i_opcode, last_instr->i_oparg); + Py_ssize_t entry_depth_for_fallthrough = depth_of_value_at_producer_end; + + if (entry_depth_for_fallthrough < fall_popped) { // Consumed by not taking jump. + if (last_instr->i_opcode == STORE_FAST && entry_depth_for_fallthrough == 0) { + overall_safety = false; // Unsafe store. + } + // else: safely consumed. + } else { // Not consumed by not taking jump, recurse on fallthrough. + entry_depth_for_fallthrough = entry_depth_for_fallthrough - fall_popped + + _PyOpcode_num_pushed(last_instr->i_opcode, last_instr->i_oparg); + if (!is_borrow_safe(producer_block->b_next, entry_depth_for_fallthrough, original_local_idx, g)) { + overall_safety = false; + } + } + } + } else if (producer_block->b_next && BB_HAS_FALLTHROUGH(producer_block)) { // Standard fallthrough, no jump. + if (!is_borrow_safe(producer_block->b_next, depth_of_value_at_producer_end, original_local_idx, g)) { + overall_safety = false; + } + } else { // No successors (e.g., block ends in RETURN/RAISE) and value still on stack. + overall_safety = false; // Unconsumed at end of a CFG path. + } + return overall_safety; +} + /* * Strength reduce LOAD_FAST{_LOAD_FAST} instructions into faster variants that * load borrowed references onto the operand stack. @@ -2747,6 +3012,7 @@ optimize_load_fast(cfg_builder *g) basicblock *entryblock = g->g_entryblock; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { max_instrs = Py_MAX(max_instrs, b->b_iused); + b->b_dfs_visited_gen = 0; } size_t instr_flags_size = max_instrs * sizeof(uint8_t); uint8_t *instr_flags = PyMem_Malloc(instr_flags_size); @@ -2976,17 +3242,82 @@ optimize_load_fast(cfg_builder *g) // Optimize instructions for (int i = 0; i < block->b_iused; i++) { - if (!(instr_flags[i] & (SUPPORT_KILLED | STORED_AS_LOCAL))) { - cfg_instr *instr = &block->b_instr[i]; - switch (instr->i_opcode) { - case LOAD_FAST: + cfg_instr *instr = &block->b_instr[i]; + bool is_load_fast_type = (instr->i_opcode == LOAD_FAST || instr->i_opcode == LOAD_FAST_LOAD_FAST); + + if (is_load_fast_type) { + bool killed_or_stored_locally = (instr_flags[i] & (SUPPORT_KILLED | STORED_AS_LOCAL)); + if (killed_or_stored_locally) { + continue; // Definitely cannot borrow due to local block issues + } + + bool unconsumed_in_block = (instr_flags[i] & REF_UNCONSUMED); + bool can_borrow = false; + + if (!unconsumed_in_block) { + can_borrow = true; // Safe by local analysis, consumed in current block + } else { + if (instr->i_opcode == LOAD_FAST) { + int local_idx = instr->i_oparg; + Py_ssize_t depth_from_tos_at_block_end = -1; + // Find the specific item on the `refs` stack (at end of current block simulation) + for (Py_ssize_t k = 0; k < refs.size; k++) { + ref r = ref_stack_at(&refs, k); + if (r.instr == i && r.local == local_idx) { // Match instruction and local + depth_from_tos_at_block_end = refs.size - 1 - k; + break; + } + } + + if (depth_from_tos_at_block_end != -1) { + can_borrow = check_borrow_safety_globally(block, depth_from_tos_at_block_end, local_idx, g); + } else { + // If REF_UNCONSUMED is set but we couldn't find its depth, assume unsafe. + // This can happen if refs.size is 0, yet flag is set. + can_borrow = false; + } + + } else { // LOAD_FAST_LOAD_FAST + can_borrow = true; // Assume true, prove false if any part is unsafe + int local_idx1 = instr->i_oparg >> 4; + int local_idx2 = instr->i_oparg & 15; + Py_ssize_t depth1 = -1, depth2 = -1; + + // Find depths on `refs` stack for both products of this LFLF instruction `i` + for (Py_ssize_t k = 0; k < refs.size; k++) { + ref r = ref_stack_at(&refs, k); + if (r.instr == i) { + Py_ssize_t current_depth = refs.size - 1 - k; + if (r.local == local_idx1 && depth1 == -1) depth1 = current_depth; + else if (r.local == local_idx2 && depth2 == -1) depth2 = current_depth; + } + } + + bool found_any_on_stack = (depth1 != -1 || depth2 != -1); + + if (depth1 != -1) { + if (!check_borrow_safety_globally(block, depth1, local_idx1, g)) { + can_borrow = false; + } + } + if (can_borrow && depth2 != -1) { + if (!check_borrow_safety_globally(block, depth2, local_idx2, g)) { + can_borrow = false; + } + } + + if (unconsumed_in_block && !found_any_on_stack) { + can_borrow = false; + } + } + } + + if (can_borrow) { + if (instr->i_opcode == LOAD_FAST) { instr->i_opcode = LOAD_FAST_BORROW; - break; - case LOAD_FAST_LOAD_FAST: + } else if (instr->i_opcode == LOAD_FAST_LOAD_FAST) { instr->i_opcode = LOAD_FAST_BORROW_LOAD_FAST_BORROW; - break; - default: - break; + } } } } From 695a9283e091748c1928b68958e23497c4771cc8 Mon Sep 17 00:00:00 2001 From: Lauta Date: Wed, 14 May 2025 15:30:21 +0200 Subject: [PATCH 4/9] Update test_peepholer.py to reflect the new changes made to flowgraph.c --- Lib/test/test_peepholer.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 475dd37e38747f..8f2df397f00f34 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -2430,14 +2430,14 @@ def test_optimized(self): ] self.check(insts, expected) - def test_optimize_unconsumed_when_is_safe(self): + def test_unoptimized_if_unconsumed(self): insts = [ ("LOAD_FAST", 0, 1), ("LOAD_FAST", 1, 2), ("POP_TOP", None, 3), ] expected = [ - ("LOAD_FAST_BORROW", 0, 1), + ("LOAD_FAST", 0, 1), ("LOAD_FAST_BORROW", 1, 2), ("POP_TOP", None, 3), ] @@ -2449,7 +2449,7 @@ def test_optimize_unconsumed_when_is_safe(self): ("POP_TOP", None, 3), ] expected = [ - ("LOAD_FAST_BORROW", 0, 1), + ("LOAD_FAST", 0, 1), ("NOP", None, 2), ("NOP", None, 3), ] @@ -2509,12 +2509,7 @@ def test_consume_some_inputs_no_outputs(self): ("GET_LEN", None, 2), ("LIST_APPEND", 0, 3), ] - expected = [ - ("LOAD_FAST_BORROW", 0, 1), - ("GET_LEN", None, 2), - ("LIST_APPEND", 0, 3), - ] - self.check(insts, expected) + self.check(insts, insts) def test_check_exc_match(self): insts = [ @@ -2523,7 +2518,7 @@ def test_check_exc_match(self): ("CHECK_EXC_MATCH", None, 3) ] expected = [ - ("LOAD_FAST_BORROW", 0, 1), + ("LOAD_FAST", 0, 1), ("LOAD_FAST_BORROW", 1, 2), ("CHECK_EXC_MATCH", None, 3) ] @@ -2573,7 +2568,7 @@ def test_load_attr(self): ("LOAD_ATTR", 1, 2), ] expected = [ - ("LOAD_FAST_BORROW", 0, 1), + ("LOAD_FAST", 0, 1), ("LOAD_ATTR", 1, 2), ] self.check(insts, expected) @@ -2603,7 +2598,7 @@ def test_super_attr(self): expected = [ ("LOAD_FAST_BORROW", 0, 1), ("LOAD_FAST_BORROW", 1, 2), - ("LOAD_FAST_BORROW", 2, 3), + ("LOAD_FAST", 2, 3), ("LOAD_SUPER_ATTR", 1, 4), ] self.check(insts, expected) From a4300a5e6c21b6555cfba4ceb4c5803c49dd8294 Mon Sep 17 00:00:00 2001 From: Lauta Date: Wed, 14 May 2025 16:47:39 +0200 Subject: [PATCH 5/9] Fix linter issues. --- Python/flowgraph.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/flowgraph.c b/Python/flowgraph.c index c795ebb454054b..dd9fbe83962eed 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -3268,7 +3268,7 @@ optimize_load_fast(cfg_builder *g) break; } } - + if (depth_from_tos_at_block_end != -1) { can_borrow = check_borrow_safety_globally(block, depth_from_tos_at_block_end, local_idx, g); } else { @@ -3305,7 +3305,7 @@ optimize_load_fast(cfg_builder *g) can_borrow = false; } } - + if (unconsumed_in_block && !found_any_on_stack) { can_borrow = false; } From 8cba63a366d015156dcfeb7a78f490c92c0f0a0f Mon Sep 17 00:00:00 2001 From: Lauta Date: Wed, 14 May 2025 17:02:28 +0200 Subject: [PATCH 6/9] Improved documentation for is_borrow_safe and check_borrow_safety_globally --- Python/flowgraph.c | 78 +++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/Python/flowgraph.c b/Python/flowgraph.c index dd9fbe83962eed..5d827c6a90ed46 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -2708,7 +2708,7 @@ load_fast_push_block(basicblock ***sp, basicblock *target, /* * Recursively determine if a borrowed reference remains safe along all CFG paths. * - * This function performs a Depth-First Search (DFS) starting from 'current_block'. + * This function performs a DFS starting from 'current_block'. * It tracks a specific value that was notionally loaded by a LOAD_FAST_BORROW * instruction and is currently at 'depth_of_value_on_entry' on the operand stack * (0 being TOS, -1 if already known to be consumed). The 'original_local_idx' @@ -2733,20 +2733,11 @@ load_fast_push_block(basicblock ***sp, basicblock *target, * - 'depth_of_value_on_entry': The depth of the tracked item upon entering 'current_block'. * - 'current_target_depth': The depth of the item as instructions in 'current_block' are processed. * - 'depth_before_jump_op_effect': When a jump instruction is encountered, this - * is calculated by simulating all prior instructions in 'current_block' to find - * the item's depth *just before* the jump instruction itself has any stack effect. - * This precise depth is then used to calculate the 'target_entry_depth' for the - * recursive call to the jump's target block. + * is calculated by simulating all prior instructions in 'current_block' to find + * the item's depth *just before* the jump instruction itself has any stack effect. + * This precise depth is then used to calculate the 'target_entry_depth' for the + * recursive call to the jump's target block. * - * Args: - * current_block: The basic block to start analysis from for this recursive step. - * depth_of_value_on_entry: The depth of the tracked borrowed value from TOS - * (0 = TOS, -1 if already consumed). - * original_local_idx: The index of the local variable backing the borrow. - * g: The CFG builder. - * - * Returns: - * true if the borrow is safe along all paths from this point, false otherwise. */ static bool is_borrow_safe( @@ -2771,40 +2762,34 @@ is_borrow_safe( int opcode = instr->i_opcode; int oparg = instr->i_oparg; - // 1. Check if the original local is killed before the value is consumed. if ((opcode == STORE_FAST || opcode == DELETE_FAST || opcode == LOAD_FAST_AND_CLEAR) && oparg == original_local_idx) { return false; } - // 2. Simulate stack effect and check for consumption or unsafe store. stack_effects effects_noj; if (get_stack_effects(opcode, oparg, 0, &effects_noj) < 0) { - return false; // Error in stack effect calculation + return false; } int num_popped = _PyOpcode_num_popped(opcode, oparg); int num_pushed = _PyOpcode_num_pushed(opcode, oparg); if (current_target_depth < num_popped) { if (opcode == STORE_FAST && current_target_depth == 0) { - // Unsafe: borrowed value was at TOS and is being stored into a local. return false; } - return true; // Safely consumed by this instruction. + return true; } - // Value not consumed, update its depth. current_target_depth = current_target_depth - num_popped + num_pushed; - // 3. Handle branches (jumps are always last in a basic block). if (HAS_TARGET(opcode)) { if (i != current_block->b_iused - 1) { continue; // Skip jumps that are not the last instruction in the block. } bool safe_on_all_branches = true; - // Calculate item's depth just before this jump instruction's own stack effect. Py_ssize_t depth_before_jump_op_effect = depth_of_value_on_entry; - for(int k=0; k < i; ++k) { // Iterate instructions before the current jump + for(int k=0; k < i; ++k) { cfg_instr *prev_instr_in_block = ¤t_block->b_instr[k]; // Kill check for intermediate instructions if ((prev_instr_in_block->i_opcode == STORE_FAST || @@ -2818,11 +2803,11 @@ is_borrow_safe( return false; } int prev_popped_val = _PyOpcode_num_popped(prev_instr_in_block->i_opcode, prev_instr_in_block->i_oparg); - if (depth_before_jump_op_effect < prev_popped_val) { // Consumed before jump + if (depth_before_jump_op_effect < prev_popped_val) { if (prev_instr_in_block->i_opcode == STORE_FAST && depth_before_jump_op_effect == 0) { - return false; // Stored into local + return false; } - return true; // Safely consumed before the jump + return true; } depth_before_jump_op_effect = depth_before_jump_op_effect - prev_popped_val + _PyOpcode_num_pushed(prev_instr_in_block->i_opcode, prev_instr_in_block->i_oparg); @@ -2834,11 +2819,10 @@ is_borrow_safe( int jump_popped_val = _PyOpcode_num_popped(opcode, oparg); Py_ssize_t target_entry_depth = depth_before_jump_op_effect; - if (target_entry_depth < jump_popped_val) { // Consumed by the jump op itself + if (target_entry_depth < jump_popped_val) { if (opcode == STORE_FAST && target_entry_depth == 0) { safe_on_all_branches = false; } - // else: safely consumed by jump operation. } else { // Not consumed by jump op, recurse on target. target_entry_depth = target_entry_depth - jump_popped_val + _PyOpcode_num_pushed(opcode, oparg); if (!is_borrow_safe(instr->i_target, target_entry_depth, original_local_idx, g)) { @@ -2848,7 +2832,6 @@ is_borrow_safe( // Analyze fallthrough path for conditional jumps, if the jump path was safe. if (safe_on_all_branches && IS_CONDITIONAL_JUMP_OPCODE(opcode) && current_block->b_next) { - // 'current_target_depth' already reflects the stack state if the jump is *not* taken. if (!is_borrow_safe(current_block->b_next, current_target_depth, original_local_idx, g)) { safe_on_all_branches = false; } @@ -2862,14 +2845,16 @@ is_borrow_safe( return is_borrow_safe(current_block->b_next, current_target_depth, original_local_idx, g); } - // No further path (or no fallthrough) and value is still on stack (current_target_depth is valid). - // This means it's unconsumed at the end of a CFG path. + /* + No further path (or no fallthrough) and value is still on stack (current_target_depth is valid). + This means it's unconsumed at the end of a CFG path, so it's unsafe. + */ return false; } /* - * Initiates a Control Flow Graph (CFG) wide safety check for a borrowed reference. + * Initiates a CFG wide safety check for a borrowed reference. * * This function is called when a LOAD_FAST instruction is a candidate for * LOAD_FAST_BORROW, but its produced value ('REF_UNCONSUMED' flag is set) @@ -2888,17 +2873,6 @@ is_borrow_safe( * to ensure that 'is_borrow_safe()' uses a fresh set of visited markers * ('b_dfs_visited_gen') for its analysis. * - * Args: - * producer_block: The basic block containing the LOAD_FAST candidate. - * depth_of_value_at_producer_end: The depth of the candidate borrowed value - * from TOS at the end of 'producer_block'. - * (0 = TOS, -1 if already consumed - though - * this function expects a live value). - * original_local_idx: The index of the local variable backing the borrow. - * g: The CFG builder. - * - * Returns: - * true if the borrow is safe across all subsequent CFG paths, false otherwise. */ static bool check_borrow_safety_globally( @@ -2923,11 +2897,10 @@ check_borrow_safety_globally( int jump_popped = _PyOpcode_num_popped(last_instr->i_opcode, last_instr->i_oparg); Py_ssize_t entry_depth_for_target = depth_of_value_at_producer_end; - if (entry_depth_for_target < jump_popped) { // Consumed by the jump itself. + if (entry_depth_for_target < jump_popped) { if (last_instr->i_opcode == STORE_FAST && entry_depth_for_target == 0) { - overall_safety = false; // Unsafe store of borrowed value. + overall_safety = false; } - // else: safely consumed. } else { entry_depth_for_target = entry_depth_for_target - jump_popped + _PyOpcode_num_pushed(last_instr->i_opcode, last_instr->i_oparg); @@ -2938,17 +2911,16 @@ check_borrow_safety_globally( // Analyze fallthrough path for conditional jumps, if the jump path was safe. if (overall_safety && IS_CONDITIONAL_JUMP_OPCODE(last_instr->i_opcode) && producer_block->b_next) { - stack_effects effects_fall; // Stack effect if jump is NOT taken. + stack_effects effects_fall; if (get_stack_effects(last_instr->i_opcode, last_instr->i_oparg, 0, &effects_fall) < 0) return false; int fall_popped = _PyOpcode_num_popped(last_instr->i_opcode, last_instr->i_oparg); Py_ssize_t entry_depth_for_fallthrough = depth_of_value_at_producer_end; - if (entry_depth_for_fallthrough < fall_popped) { // Consumed by not taking jump. + if (entry_depth_for_fallthrough < fall_popped) { if (last_instr->i_opcode == STORE_FAST && entry_depth_for_fallthrough == 0) { - overall_safety = false; // Unsafe store. + overall_safety = false; } - // else: safely consumed. - } else { // Not consumed by not taking jump, recurse on fallthrough. + } else { // Recurse on fallthrough. entry_depth_for_fallthrough = entry_depth_for_fallthrough - fall_popped + _PyOpcode_num_pushed(last_instr->i_opcode, last_instr->i_oparg); if (!is_borrow_safe(producer_block->b_next, entry_depth_for_fallthrough, original_local_idx, g)) { @@ -2960,8 +2932,8 @@ check_borrow_safety_globally( if (!is_borrow_safe(producer_block->b_next, depth_of_value_at_producer_end, original_local_idx, g)) { overall_safety = false; } - } else { // No successors (e.g., block ends in RETURN/RAISE) and value still on stack. - overall_safety = false; // Unconsumed at end of a CFG path. + } else { + overall_safety = false; } return overall_safety; } From 71f72e5ee2f3f3e591f2f8078edf725afe139601 Mon Sep 17 00:00:00 2001 From: Lautaro Javier Fernandez Pricco Date: Sun, 12 Oct 2025 01:11:18 +0000 Subject: [PATCH 7/9] Update branch --- .github/workflows/posix-deps-apt.sh | 0 Android/android.py | 0 Doc/make.bat | 0 Lib/ctypes/macholib/fetch_macholib | 0 Lib/ctypes/macholib/fetch_macholib.bat | 0 Lib/encodings/rot_13.py | 0 Lib/idlelib/idle.bat | 0 Lib/idlelib/pyshell.py | 0 Lib/test/archivetestdata/exe_with_z64 | Bin Lib/test/archivetestdata/exe_with_zip | Bin Lib/test/archivetestdata/header.sh | 0 Lib/test/bisect_cmd.py | 0 Lib/test/crashers/recursive_call.py | 0 Lib/test/curses_tests.py | 0 Lib/test/re_tests.py | 0 Lib/test/regrtest.py | 0 Lib/test/support/smtpd.py | 0 Lib/test/test_array.py | 0 Lib/test/test_importlib/resources/zip.py | 0 Lib/test/test_uuid.py | 0 Lib/venv/scripts/nt/activate.bat | 0 Lib/venv/scripts/nt/deactivate.bat | 0 Mac/BuildScript/build-installer.py | 0 Mac/BuildScript/scripts/postflight.documentation | 0 Mac/BuildScript/scripts/postflight.ensurepip | 0 Mac/BuildScript/scripts/postflight.framework | 0 Mac/BuildScript/scripts/postflight.patch-profile | 0 Mac/IDLE/IDLE.app/Contents/MacOS/IDLE | 0 Mac/Tools/plistlib_generate_testdata.py | 0 Misc/mypy/_colorize.py | 1 - Misc/mypy/_pyrepl | 1 - Misc/mypy/make_symlinks.py | 0 Misc/mypy/token.py | 1 - Misc/mypy/tomllib | 1 - Modules/_decimal/tests/runall-memorydebugger.sh | 0 Modules/_hacl/refresh.sh | 0 Modules/expat/refresh.sh | 0 Modules/makesetup | 0 Modules/makexp_aix | 0 Objects/typeslots.py | 0 PC/python3dll.c | 0 PCbuild/blurb.bat | 0 PCbuild/build.bat | 0 PCbuild/build_env.bat | 0 PCbuild/clean.bat | 0 PCbuild/env.bat | 0 PCbuild/find_msbuild.bat | 0 PCbuild/find_python.bat | 0 PCbuild/fix_encoding.py | 0 PCbuild/get_external.py | 0 PCbuild/get_externals.bat | 0 PCbuild/idle.bat | 0 PCbuild/prepare_libffi.bat | 0 PCbuild/prepare_ssl.bat | 0 PCbuild/prepare_ssl.py | 0 PCbuild/prepare_tcltk.bat | 0 PCbuild/rt.bat | 0 Parser/asdl_c.py | 0 Tools/build/generate_re_casefix.py | 0 Tools/build/generate_sre_constants.py | 0 Tools/build/generate_token.py | 0 Tools/build/parse_html5_entities.py | 0 Tools/build/regen-configure.sh | 0 Tools/build/smelly.py | 0 Tools/build/verify_ensurepip_wheels.py | 0 Tools/buildbot/build.bat | 0 Tools/buildbot/buildmsi.bat | 0 Tools/buildbot/clean.bat | 0 Tools/buildbot/remoteDeploy.bat | 0 Tools/buildbot/remotePythonInfo.bat | 0 Tools/buildbot/test.bat | 0 Tools/c-analyzer/must-resolve.sh | 0 Tools/clinic/clinic.py | 0 Tools/freeze/freeze.py | 0 Tools/gdb/libpython.py | 0 Tools/i18n/makelocalealias.py | 0 Tools/i18n/msgfmt.py | 0 Tools/i18n/pygettext.py | 0 Tools/msi/build.bat | 0 Tools/msi/buildrelease.bat | 0 Tools/msi/get_externals.bat | 0 Tools/msi/testrelease.bat | 0 Tools/msi/uploadrelease.bat | 0 Tools/nuget/build.bat | 0 Tools/patchcheck/patchcheck.py | 0 Tools/patchcheck/reindent.py | 0 Tools/patchcheck/untabify.py | 0 Tools/peg_generator/pegen/__main__.py | 0 Tools/peg_generator/pegen/first_sets.py | 0 Tools/scripts/checkpip.py | 0 Tools/scripts/combinerefs.py | 0 Tools/scripts/idle3 | 0 Tools/scripts/pydoc3 | 0 Tools/ssl/make_ssl_data.py | 0 Tools/ssl/multissltests.py | 0 Tools/unicode/comparecodecs.py | 0 Tools/unicode/genwincodecs.bat | 0 Tools/unittestgui/unittestgui.py | 0 Tools/wasm/emscripten/make_libffi.sh | 0 Tools/wasm/emscripten/web_example/server.py | 0 Tools/wasm/emscripten/web_example/wasm_assets.py | 0 Tools/wasm/wasi-env | 0 config.guess | 0 config.sub | 0 configure | 0 iOS/Resources/bin/arm64-apple-ios-ar | 0 iOS/Resources/bin/arm64-apple-ios-clang | 0 iOS/Resources/bin/arm64-apple-ios-clang++ | 0 iOS/Resources/bin/arm64-apple-ios-cpp | 0 iOS/Resources/bin/arm64-apple-ios-simulator-ar | 0 iOS/Resources/bin/arm64-apple-ios-simulator-clang | 0 iOS/Resources/bin/arm64-apple-ios-simulator-clang++ | 0 iOS/Resources/bin/arm64-apple-ios-simulator-cpp | 0 iOS/Resources/bin/x86_64-apple-ios-simulator-ar | 0 iOS/Resources/bin/x86_64-apple-ios-simulator-clang | 0 .../bin/x86_64-apple-ios-simulator-clang++ | 0 iOS/Resources/bin/x86_64-apple-ios-simulator-cpp | 0 install-sh | 0 118 files changed, 4 deletions(-) mode change 100755 => 100644 .github/workflows/posix-deps-apt.sh mode change 100755 => 100644 Android/android.py mode change 100644 => 100755 Doc/make.bat mode change 100755 => 100644 Lib/ctypes/macholib/fetch_macholib mode change 100644 => 100755 Lib/ctypes/macholib/fetch_macholib.bat mode change 100755 => 100644 Lib/encodings/rot_13.py mode change 100644 => 100755 Lib/idlelib/idle.bat mode change 100755 => 100644 Lib/idlelib/pyshell.py mode change 100755 => 100644 Lib/test/archivetestdata/exe_with_z64 mode change 100755 => 100644 Lib/test/archivetestdata/exe_with_zip mode change 100755 => 100644 Lib/test/archivetestdata/header.sh mode change 100755 => 100644 Lib/test/bisect_cmd.py mode change 100755 => 100644 Lib/test/crashers/recursive_call.py mode change 100755 => 100644 Lib/test/curses_tests.py mode change 100755 => 100644 Lib/test/re_tests.py mode change 100755 => 100644 Lib/test/regrtest.py mode change 100755 => 100644 Lib/test/support/smtpd.py mode change 100755 => 100644 Lib/test/test_array.py mode change 100755 => 100644 Lib/test/test_importlib/resources/zip.py mode change 100755 => 100644 Lib/test/test_uuid.py mode change 100644 => 100755 Lib/venv/scripts/nt/activate.bat mode change 100644 => 100755 Lib/venv/scripts/nt/deactivate.bat mode change 100755 => 100644 Mac/BuildScript/build-installer.py mode change 100755 => 100644 Mac/BuildScript/scripts/postflight.documentation mode change 100755 => 100644 Mac/BuildScript/scripts/postflight.ensurepip mode change 100755 => 100644 Mac/BuildScript/scripts/postflight.framework mode change 100755 => 100644 Mac/BuildScript/scripts/postflight.patch-profile mode change 100755 => 100644 Mac/IDLE/IDLE.app/Contents/MacOS/IDLE mode change 100755 => 100644 Mac/Tools/plistlib_generate_testdata.py delete mode 120000 Misc/mypy/_colorize.py delete mode 120000 Misc/mypy/_pyrepl mode change 100755 => 100644 Misc/mypy/make_symlinks.py delete mode 120000 Misc/mypy/token.py delete mode 120000 Misc/mypy/tomllib mode change 100755 => 100644 Modules/_decimal/tests/runall-memorydebugger.sh mode change 100755 => 100644 Modules/_hacl/refresh.sh mode change 100755 => 100644 Modules/expat/refresh.sh mode change 100755 => 100644 Modules/makesetup mode change 100755 => 100644 Modules/makexp_aix mode change 100755 => 100644 Objects/typeslots.py mode change 100755 => 100644 PC/python3dll.c mode change 100644 => 100755 PCbuild/blurb.bat mode change 100644 => 100755 PCbuild/build.bat mode change 100644 => 100755 PCbuild/build_env.bat mode change 100644 => 100755 PCbuild/clean.bat mode change 100644 => 100755 PCbuild/env.bat mode change 100644 => 100755 PCbuild/find_msbuild.bat mode change 100644 => 100755 PCbuild/find_python.bat mode change 100755 => 100644 PCbuild/fix_encoding.py mode change 100755 => 100644 PCbuild/get_external.py mode change 100644 => 100755 PCbuild/get_externals.bat mode change 100644 => 100755 PCbuild/idle.bat mode change 100644 => 100755 PCbuild/prepare_libffi.bat mode change 100644 => 100755 PCbuild/prepare_ssl.bat mode change 100755 => 100644 PCbuild/prepare_ssl.py mode change 100644 => 100755 PCbuild/prepare_tcltk.bat mode change 100644 => 100755 PCbuild/rt.bat mode change 100755 => 100644 Parser/asdl_c.py mode change 100755 => 100644 Tools/build/generate_re_casefix.py mode change 100755 => 100644 Tools/build/generate_sre_constants.py mode change 100755 => 100644 Tools/build/generate_token.py mode change 100755 => 100644 Tools/build/parse_html5_entities.py mode change 100755 => 100644 Tools/build/regen-configure.sh mode change 100755 => 100644 Tools/build/smelly.py mode change 100755 => 100644 Tools/build/verify_ensurepip_wheels.py mode change 100644 => 100755 Tools/buildbot/build.bat mode change 100644 => 100755 Tools/buildbot/buildmsi.bat mode change 100644 => 100755 Tools/buildbot/clean.bat mode change 100644 => 100755 Tools/buildbot/remoteDeploy.bat mode change 100644 => 100755 Tools/buildbot/remotePythonInfo.bat mode change 100644 => 100755 Tools/buildbot/test.bat mode change 100755 => 100644 Tools/c-analyzer/must-resolve.sh mode change 100755 => 100644 Tools/clinic/clinic.py mode change 100755 => 100644 Tools/freeze/freeze.py mode change 100755 => 100644 Tools/gdb/libpython.py mode change 100755 => 100644 Tools/i18n/makelocalealias.py mode change 100755 => 100644 Tools/i18n/msgfmt.py mode change 100755 => 100644 Tools/i18n/pygettext.py mode change 100644 => 100755 Tools/msi/build.bat mode change 100644 => 100755 Tools/msi/buildrelease.bat mode change 100644 => 100755 Tools/msi/get_externals.bat mode change 100644 => 100755 Tools/msi/testrelease.bat mode change 100644 => 100755 Tools/msi/uploadrelease.bat mode change 100644 => 100755 Tools/nuget/build.bat mode change 100755 => 100644 Tools/patchcheck/patchcheck.py mode change 100755 => 100644 Tools/patchcheck/reindent.py mode change 100755 => 100644 Tools/patchcheck/untabify.py mode change 100755 => 100644 Tools/peg_generator/pegen/__main__.py mode change 100755 => 100644 Tools/peg_generator/pegen/first_sets.py mode change 100755 => 100644 Tools/scripts/checkpip.py mode change 100755 => 100644 Tools/scripts/combinerefs.py mode change 100755 => 100644 Tools/scripts/idle3 mode change 100755 => 100644 Tools/scripts/pydoc3 mode change 100755 => 100644 Tools/ssl/make_ssl_data.py mode change 100755 => 100644 Tools/ssl/multissltests.py mode change 100755 => 100644 Tools/unicode/comparecodecs.py mode change 100644 => 100755 Tools/unicode/genwincodecs.bat mode change 100755 => 100644 Tools/unittestgui/unittestgui.py mode change 100755 => 100644 Tools/wasm/emscripten/make_libffi.sh mode change 100755 => 100644 Tools/wasm/emscripten/web_example/server.py mode change 100755 => 100644 Tools/wasm/emscripten/web_example/wasm_assets.py mode change 100755 => 100644 Tools/wasm/wasi-env mode change 100755 => 100644 config.guess mode change 100755 => 100644 config.sub mode change 100755 => 100644 configure mode change 100755 => 100644 iOS/Resources/bin/arm64-apple-ios-ar mode change 100755 => 100644 iOS/Resources/bin/arm64-apple-ios-clang mode change 100755 => 100644 iOS/Resources/bin/arm64-apple-ios-clang++ mode change 100755 => 100644 iOS/Resources/bin/arm64-apple-ios-cpp mode change 100755 => 100644 iOS/Resources/bin/arm64-apple-ios-simulator-ar mode change 100755 => 100644 iOS/Resources/bin/arm64-apple-ios-simulator-clang mode change 100755 => 100644 iOS/Resources/bin/arm64-apple-ios-simulator-clang++ mode change 100755 => 100644 iOS/Resources/bin/arm64-apple-ios-simulator-cpp mode change 100755 => 100644 iOS/Resources/bin/x86_64-apple-ios-simulator-ar mode change 100755 => 100644 iOS/Resources/bin/x86_64-apple-ios-simulator-clang mode change 100755 => 100644 iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ mode change 100755 => 100644 iOS/Resources/bin/x86_64-apple-ios-simulator-cpp mode change 100755 => 100644 install-sh diff --git a/.github/workflows/posix-deps-apt.sh b/.github/workflows/posix-deps-apt.sh old mode 100755 new mode 100644 diff --git a/Android/android.py b/Android/android.py old mode 100755 new mode 100644 diff --git a/Doc/make.bat b/Doc/make.bat old mode 100644 new mode 100755 diff --git a/Lib/ctypes/macholib/fetch_macholib b/Lib/ctypes/macholib/fetch_macholib old mode 100755 new mode 100644 diff --git a/Lib/ctypes/macholib/fetch_macholib.bat b/Lib/ctypes/macholib/fetch_macholib.bat old mode 100644 new mode 100755 diff --git a/Lib/encodings/rot_13.py b/Lib/encodings/rot_13.py old mode 100755 new mode 100644 diff --git a/Lib/idlelib/idle.bat b/Lib/idlelib/idle.bat old mode 100644 new mode 100755 diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py old mode 100755 new mode 100644 diff --git a/Lib/test/archivetestdata/exe_with_z64 b/Lib/test/archivetestdata/exe_with_z64 old mode 100755 new mode 100644 diff --git a/Lib/test/archivetestdata/exe_with_zip b/Lib/test/archivetestdata/exe_with_zip old mode 100755 new mode 100644 diff --git a/Lib/test/archivetestdata/header.sh b/Lib/test/archivetestdata/header.sh old mode 100755 new mode 100644 diff --git a/Lib/test/bisect_cmd.py b/Lib/test/bisect_cmd.py old mode 100755 new mode 100644 diff --git a/Lib/test/crashers/recursive_call.py b/Lib/test/crashers/recursive_call.py old mode 100755 new mode 100644 diff --git a/Lib/test/curses_tests.py b/Lib/test/curses_tests.py old mode 100755 new mode 100644 diff --git a/Lib/test/re_tests.py b/Lib/test/re_tests.py old mode 100755 new mode 100644 diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py old mode 100755 new mode 100644 diff --git a/Lib/test/support/smtpd.py b/Lib/test/support/smtpd.py old mode 100755 new mode 100644 diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py old mode 100755 new mode 100644 diff --git a/Lib/test/test_importlib/resources/zip.py b/Lib/test/test_importlib/resources/zip.py old mode 100755 new mode 100644 diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py old mode 100755 new mode 100644 diff --git a/Lib/venv/scripts/nt/activate.bat b/Lib/venv/scripts/nt/activate.bat old mode 100644 new mode 100755 diff --git a/Lib/venv/scripts/nt/deactivate.bat b/Lib/venv/scripts/nt/deactivate.bat old mode 100644 new mode 100755 diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py old mode 100755 new mode 100644 diff --git a/Mac/BuildScript/scripts/postflight.documentation b/Mac/BuildScript/scripts/postflight.documentation old mode 100755 new mode 100644 diff --git a/Mac/BuildScript/scripts/postflight.ensurepip b/Mac/BuildScript/scripts/postflight.ensurepip old mode 100755 new mode 100644 diff --git a/Mac/BuildScript/scripts/postflight.framework b/Mac/BuildScript/scripts/postflight.framework old mode 100755 new mode 100644 diff --git a/Mac/BuildScript/scripts/postflight.patch-profile b/Mac/BuildScript/scripts/postflight.patch-profile old mode 100755 new mode 100644 diff --git a/Mac/IDLE/IDLE.app/Contents/MacOS/IDLE b/Mac/IDLE/IDLE.app/Contents/MacOS/IDLE old mode 100755 new mode 100644 diff --git a/Mac/Tools/plistlib_generate_testdata.py b/Mac/Tools/plistlib_generate_testdata.py old mode 100755 new mode 100644 diff --git a/Misc/mypy/_colorize.py b/Misc/mypy/_colorize.py deleted file mode 120000 index 9b7304769ec30b..00000000000000 --- a/Misc/mypy/_colorize.py +++ /dev/null @@ -1 +0,0 @@ -../../Lib/_colorize.py \ No newline at end of file diff --git a/Misc/mypy/_pyrepl b/Misc/mypy/_pyrepl deleted file mode 120000 index bd7b69909663b6..00000000000000 --- a/Misc/mypy/_pyrepl +++ /dev/null @@ -1 +0,0 @@ -../../Lib/_pyrepl \ No newline at end of file diff --git a/Misc/mypy/make_symlinks.py b/Misc/mypy/make_symlinks.py old mode 100755 new mode 100644 diff --git a/Misc/mypy/token.py b/Misc/mypy/token.py deleted file mode 120000 index 0a39f726dda1aa..00000000000000 --- a/Misc/mypy/token.py +++ /dev/null @@ -1 +0,0 @@ -../../Lib/token.py \ No newline at end of file diff --git a/Misc/mypy/tomllib b/Misc/mypy/tomllib deleted file mode 120000 index 20f34d49da0cd4..00000000000000 --- a/Misc/mypy/tomllib +++ /dev/null @@ -1 +0,0 @@ -../../Lib/tomllib \ No newline at end of file diff --git a/Modules/_decimal/tests/runall-memorydebugger.sh b/Modules/_decimal/tests/runall-memorydebugger.sh old mode 100755 new mode 100644 diff --git a/Modules/_hacl/refresh.sh b/Modules/_hacl/refresh.sh old mode 100755 new mode 100644 diff --git a/Modules/expat/refresh.sh b/Modules/expat/refresh.sh old mode 100755 new mode 100644 diff --git a/Modules/makesetup b/Modules/makesetup old mode 100755 new mode 100644 diff --git a/Modules/makexp_aix b/Modules/makexp_aix old mode 100755 new mode 100644 diff --git a/Objects/typeslots.py b/Objects/typeslots.py old mode 100755 new mode 100644 diff --git a/PC/python3dll.c b/PC/python3dll.c old mode 100755 new mode 100644 diff --git a/PCbuild/blurb.bat b/PCbuild/blurb.bat old mode 100644 new mode 100755 diff --git a/PCbuild/build.bat b/PCbuild/build.bat old mode 100644 new mode 100755 diff --git a/PCbuild/build_env.bat b/PCbuild/build_env.bat old mode 100644 new mode 100755 diff --git a/PCbuild/clean.bat b/PCbuild/clean.bat old mode 100644 new mode 100755 diff --git a/PCbuild/env.bat b/PCbuild/env.bat old mode 100644 new mode 100755 diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat old mode 100644 new mode 100755 diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat old mode 100644 new mode 100755 diff --git a/PCbuild/fix_encoding.py b/PCbuild/fix_encoding.py old mode 100755 new mode 100644 diff --git a/PCbuild/get_external.py b/PCbuild/get_external.py old mode 100755 new mode 100644 diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat old mode 100644 new mode 100755 diff --git a/PCbuild/idle.bat b/PCbuild/idle.bat old mode 100644 new mode 100755 diff --git a/PCbuild/prepare_libffi.bat b/PCbuild/prepare_libffi.bat old mode 100644 new mode 100755 diff --git a/PCbuild/prepare_ssl.bat b/PCbuild/prepare_ssl.bat old mode 100644 new mode 100755 diff --git a/PCbuild/prepare_ssl.py b/PCbuild/prepare_ssl.py old mode 100755 new mode 100644 diff --git a/PCbuild/prepare_tcltk.bat b/PCbuild/prepare_tcltk.bat old mode 100644 new mode 100755 diff --git a/PCbuild/rt.bat b/PCbuild/rt.bat old mode 100644 new mode 100755 diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py old mode 100755 new mode 100644 diff --git a/Tools/build/generate_re_casefix.py b/Tools/build/generate_re_casefix.py old mode 100755 new mode 100644 diff --git a/Tools/build/generate_sre_constants.py b/Tools/build/generate_sre_constants.py old mode 100755 new mode 100644 diff --git a/Tools/build/generate_token.py b/Tools/build/generate_token.py old mode 100755 new mode 100644 diff --git a/Tools/build/parse_html5_entities.py b/Tools/build/parse_html5_entities.py old mode 100755 new mode 100644 diff --git a/Tools/build/regen-configure.sh b/Tools/build/regen-configure.sh old mode 100755 new mode 100644 diff --git a/Tools/build/smelly.py b/Tools/build/smelly.py old mode 100755 new mode 100644 diff --git a/Tools/build/verify_ensurepip_wheels.py b/Tools/build/verify_ensurepip_wheels.py old mode 100755 new mode 100644 diff --git a/Tools/buildbot/build.bat b/Tools/buildbot/build.bat old mode 100644 new mode 100755 diff --git a/Tools/buildbot/buildmsi.bat b/Tools/buildbot/buildmsi.bat old mode 100644 new mode 100755 diff --git a/Tools/buildbot/clean.bat b/Tools/buildbot/clean.bat old mode 100644 new mode 100755 diff --git a/Tools/buildbot/remoteDeploy.bat b/Tools/buildbot/remoteDeploy.bat old mode 100644 new mode 100755 diff --git a/Tools/buildbot/remotePythonInfo.bat b/Tools/buildbot/remotePythonInfo.bat old mode 100644 new mode 100755 diff --git a/Tools/buildbot/test.bat b/Tools/buildbot/test.bat old mode 100644 new mode 100755 diff --git a/Tools/c-analyzer/must-resolve.sh b/Tools/c-analyzer/must-resolve.sh old mode 100755 new mode 100644 diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py old mode 100755 new mode 100644 diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py old mode 100755 new mode 100644 diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py old mode 100755 new mode 100644 diff --git a/Tools/i18n/makelocalealias.py b/Tools/i18n/makelocalealias.py old mode 100755 new mode 100644 diff --git a/Tools/i18n/msgfmt.py b/Tools/i18n/msgfmt.py old mode 100755 new mode 100644 diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py old mode 100755 new mode 100644 diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat old mode 100644 new mode 100755 diff --git a/Tools/msi/buildrelease.bat b/Tools/msi/buildrelease.bat old mode 100644 new mode 100755 diff --git a/Tools/msi/get_externals.bat b/Tools/msi/get_externals.bat old mode 100644 new mode 100755 diff --git a/Tools/msi/testrelease.bat b/Tools/msi/testrelease.bat old mode 100644 new mode 100755 diff --git a/Tools/msi/uploadrelease.bat b/Tools/msi/uploadrelease.bat old mode 100644 new mode 100755 diff --git a/Tools/nuget/build.bat b/Tools/nuget/build.bat old mode 100644 new mode 100755 diff --git a/Tools/patchcheck/patchcheck.py b/Tools/patchcheck/patchcheck.py old mode 100755 new mode 100644 diff --git a/Tools/patchcheck/reindent.py b/Tools/patchcheck/reindent.py old mode 100755 new mode 100644 diff --git a/Tools/patchcheck/untabify.py b/Tools/patchcheck/untabify.py old mode 100755 new mode 100644 diff --git a/Tools/peg_generator/pegen/__main__.py b/Tools/peg_generator/pegen/__main__.py old mode 100755 new mode 100644 diff --git a/Tools/peg_generator/pegen/first_sets.py b/Tools/peg_generator/pegen/first_sets.py old mode 100755 new mode 100644 diff --git a/Tools/scripts/checkpip.py b/Tools/scripts/checkpip.py old mode 100755 new mode 100644 diff --git a/Tools/scripts/combinerefs.py b/Tools/scripts/combinerefs.py old mode 100755 new mode 100644 diff --git a/Tools/scripts/idle3 b/Tools/scripts/idle3 old mode 100755 new mode 100644 diff --git a/Tools/scripts/pydoc3 b/Tools/scripts/pydoc3 old mode 100755 new mode 100644 diff --git a/Tools/ssl/make_ssl_data.py b/Tools/ssl/make_ssl_data.py old mode 100755 new mode 100644 diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py old mode 100755 new mode 100644 diff --git a/Tools/unicode/comparecodecs.py b/Tools/unicode/comparecodecs.py old mode 100755 new mode 100644 diff --git a/Tools/unicode/genwincodecs.bat b/Tools/unicode/genwincodecs.bat old mode 100644 new mode 100755 diff --git a/Tools/unittestgui/unittestgui.py b/Tools/unittestgui/unittestgui.py old mode 100755 new mode 100644 diff --git a/Tools/wasm/emscripten/make_libffi.sh b/Tools/wasm/emscripten/make_libffi.sh old mode 100755 new mode 100644 diff --git a/Tools/wasm/emscripten/web_example/server.py b/Tools/wasm/emscripten/web_example/server.py old mode 100755 new mode 100644 diff --git a/Tools/wasm/emscripten/web_example/wasm_assets.py b/Tools/wasm/emscripten/web_example/wasm_assets.py old mode 100755 new mode 100644 diff --git a/Tools/wasm/wasi-env b/Tools/wasm/wasi-env old mode 100755 new mode 100644 diff --git a/config.guess b/config.guess old mode 100755 new mode 100644 diff --git a/config.sub b/config.sub old mode 100755 new mode 100644 diff --git a/configure b/configure old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/arm64-apple-ios-ar b/iOS/Resources/bin/arm64-apple-ios-ar old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/arm64-apple-ios-clang b/iOS/Resources/bin/arm64-apple-ios-clang old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/arm64-apple-ios-clang++ b/iOS/Resources/bin/arm64-apple-ios-clang++ old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/arm64-apple-ios-cpp b/iOS/Resources/bin/arm64-apple-ios-cpp old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-ar b/iOS/Resources/bin/arm64-apple-ios-simulator-ar old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang b/iOS/Resources/bin/arm64-apple-ios-simulator-clang old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ b/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-cpp b/iOS/Resources/bin/arm64-apple-ios-simulator-cpp old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-ar b/iOS/Resources/bin/x86_64-apple-ios-simulator-ar old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ old mode 100755 new mode 100644 diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp b/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp old mode 100755 new mode 100644 diff --git a/install-sh b/install-sh old mode 100755 new mode 100644 From 0b2cb8d6e32bf1ef243a4cddeb0d24b25c677620 Mon Sep 17 00:00:00 2001 From: Lautaro Javier Fernandez Pricco Date: Sun, 12 Oct 2025 01:45:26 +0000 Subject: [PATCH 8/9] Restore executable permissions stripped by accident --- .github/workflows/posix-deps-apt.sh | 0 Android/android.py | 0 Doc/make.bat | 0 Lib/ctypes/macholib/fetch_macholib | 0 Lib/ctypes/macholib/fetch_macholib.bat | 0 Lib/encodings/rot_13.py | 0 Lib/idlelib/idle.bat | 0 Lib/idlelib/pyshell.py | 0 Lib/test/archivetestdata/exe_with_z64 | Bin Lib/test/archivetestdata/exe_with_zip | Bin Lib/test/archivetestdata/header.sh | 0 Lib/test/bisect_cmd.py | 0 Lib/test/crashers/recursive_call.py | 0 Lib/test/curses_tests.py | 0 Lib/test/re_tests.py | 0 Lib/test/regrtest.py | 0 Lib/test/support/smtpd.py | 0 Lib/test/test_array.py | 0 Lib/test/test_importlib/resources/zip.py | 0 Lib/test/test_uuid.py | 0 Lib/venv/scripts/nt/activate.bat | 0 Lib/venv/scripts/nt/deactivate.bat | 0 Mac/BuildScript/build-installer.py | 0 Mac/BuildScript/scripts/postflight.documentation | 0 Mac/BuildScript/scripts/postflight.ensurepip | 0 Mac/BuildScript/scripts/postflight.framework | 0 Mac/BuildScript/scripts/postflight.patch-profile | 0 Mac/IDLE/IDLE.app/Contents/MacOS/IDLE | 0 Mac/Tools/plistlib_generate_testdata.py | 0 Misc/mypy/make_symlinks.py | 0 Modules/_decimal/tests/runall-memorydebugger.sh | 0 Modules/_hacl/refresh.sh | 0 Modules/expat/refresh.sh | 0 Modules/makesetup | 0 Modules/makexp_aix | 0 Objects/typeslots.py | 0 PC/python3dll.c | 0 PCbuild/blurb.bat | 0 PCbuild/build.bat | 0 PCbuild/build_env.bat | 0 PCbuild/clean.bat | 0 PCbuild/env.bat | 0 PCbuild/find_msbuild.bat | 0 PCbuild/find_python.bat | 0 PCbuild/fix_encoding.py | 0 PCbuild/get_external.py | 0 PCbuild/get_externals.bat | 0 PCbuild/idle.bat | 0 PCbuild/prepare_libffi.bat | 0 PCbuild/prepare_ssl.bat | 0 PCbuild/prepare_ssl.py | 0 PCbuild/prepare_tcltk.bat | 0 PCbuild/rt.bat | 0 Parser/asdl_c.py | 0 Tools/build/generate_re_casefix.py | 0 Tools/build/generate_sre_constants.py | 0 Tools/build/generate_token.py | 0 Tools/build/parse_html5_entities.py | 0 Tools/build/regen-configure.sh | 0 Tools/build/smelly.py | 0 Tools/build/verify_ensurepip_wheels.py | 0 Tools/buildbot/build.bat | 0 Tools/buildbot/buildmsi.bat | 0 Tools/buildbot/clean.bat | 0 Tools/buildbot/remoteDeploy.bat | 0 Tools/buildbot/remotePythonInfo.bat | 0 Tools/buildbot/test.bat | 0 Tools/c-analyzer/must-resolve.sh | 0 Tools/clinic/clinic.py | 0 Tools/freeze/freeze.py | 0 Tools/gdb/libpython.py | 0 Tools/i18n/makelocalealias.py | 0 Tools/i18n/msgfmt.py | 0 Tools/i18n/pygettext.py | 0 Tools/msi/build.bat | 0 Tools/msi/buildrelease.bat | 0 Tools/msi/get_externals.bat | 0 Tools/msi/testrelease.bat | 0 Tools/msi/uploadrelease.bat | 0 Tools/nuget/build.bat | 0 Tools/patchcheck/patchcheck.py | 0 Tools/patchcheck/reindent.py | 0 Tools/patchcheck/untabify.py | 0 Tools/peg_generator/pegen/__main__.py | 0 Tools/peg_generator/pegen/first_sets.py | 0 Tools/scripts/checkpip.py | 0 Tools/scripts/combinerefs.py | 0 Tools/scripts/idle3 | 0 Tools/scripts/pydoc3 | 0 Tools/ssl/make_ssl_data.py | 0 Tools/ssl/multissltests.py | 0 Tools/unicode/comparecodecs.py | 0 Tools/unicode/genwincodecs.bat | 0 Tools/unittestgui/unittestgui.py | 0 Tools/wasm/emscripten/make_libffi.sh | 0 Tools/wasm/emscripten/wasm_assets.py | 0 Tools/wasm/emscripten/web_example/server.py | 0 Tools/wasm/wasi-env | 0 config.guess | 0 config.sub | 0 configure | 0 iOS/Resources/bin/arm64-apple-ios-ar | 0 iOS/Resources/bin/arm64-apple-ios-clang | 0 iOS/Resources/bin/arm64-apple-ios-clang++ | 0 iOS/Resources/bin/arm64-apple-ios-cpp | 0 iOS/Resources/bin/arm64-apple-ios-simulator-ar | 0 iOS/Resources/bin/arm64-apple-ios-simulator-clang | 0 iOS/Resources/bin/arm64-apple-ios-simulator-clang++ | 0 iOS/Resources/bin/arm64-apple-ios-simulator-cpp | 0 iOS/Resources/bin/x86_64-apple-ios-simulator-ar | 0 iOS/Resources/bin/x86_64-apple-ios-simulator-clang | 0 .../bin/x86_64-apple-ios-simulator-clang++ | 0 iOS/Resources/bin/x86_64-apple-ios-simulator-cpp | 0 install-sh | 0 114 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .github/workflows/posix-deps-apt.sh mode change 100644 => 100755 Android/android.py mode change 100755 => 100644 Doc/make.bat mode change 100644 => 100755 Lib/ctypes/macholib/fetch_macholib mode change 100755 => 100644 Lib/ctypes/macholib/fetch_macholib.bat mode change 100644 => 100755 Lib/encodings/rot_13.py mode change 100755 => 100644 Lib/idlelib/idle.bat mode change 100644 => 100755 Lib/idlelib/pyshell.py mode change 100644 => 100755 Lib/test/archivetestdata/exe_with_z64 mode change 100644 => 100755 Lib/test/archivetestdata/exe_with_zip mode change 100644 => 100755 Lib/test/archivetestdata/header.sh mode change 100644 => 100755 Lib/test/bisect_cmd.py mode change 100644 => 100755 Lib/test/crashers/recursive_call.py mode change 100644 => 100755 Lib/test/curses_tests.py mode change 100644 => 100755 Lib/test/re_tests.py mode change 100644 => 100755 Lib/test/regrtest.py mode change 100644 => 100755 Lib/test/support/smtpd.py mode change 100644 => 100755 Lib/test/test_array.py mode change 100644 => 100755 Lib/test/test_importlib/resources/zip.py mode change 100644 => 100755 Lib/test/test_uuid.py mode change 100755 => 100644 Lib/venv/scripts/nt/activate.bat mode change 100755 => 100644 Lib/venv/scripts/nt/deactivate.bat mode change 100644 => 100755 Mac/BuildScript/build-installer.py mode change 100644 => 100755 Mac/BuildScript/scripts/postflight.documentation mode change 100644 => 100755 Mac/BuildScript/scripts/postflight.ensurepip mode change 100644 => 100755 Mac/BuildScript/scripts/postflight.framework mode change 100644 => 100755 Mac/BuildScript/scripts/postflight.patch-profile mode change 100644 => 100755 Mac/IDLE/IDLE.app/Contents/MacOS/IDLE mode change 100644 => 100755 Mac/Tools/plistlib_generate_testdata.py mode change 100644 => 100755 Misc/mypy/make_symlinks.py mode change 100644 => 100755 Modules/_decimal/tests/runall-memorydebugger.sh mode change 100644 => 100755 Modules/_hacl/refresh.sh mode change 100644 => 100755 Modules/expat/refresh.sh mode change 100644 => 100755 Modules/makesetup mode change 100644 => 100755 Modules/makexp_aix mode change 100644 => 100755 Objects/typeslots.py mode change 100644 => 100755 PC/python3dll.c mode change 100755 => 100644 PCbuild/blurb.bat mode change 100755 => 100644 PCbuild/build.bat mode change 100755 => 100644 PCbuild/build_env.bat mode change 100755 => 100644 PCbuild/clean.bat mode change 100755 => 100644 PCbuild/env.bat mode change 100755 => 100644 PCbuild/find_msbuild.bat mode change 100755 => 100644 PCbuild/find_python.bat mode change 100644 => 100755 PCbuild/fix_encoding.py mode change 100644 => 100755 PCbuild/get_external.py mode change 100755 => 100644 PCbuild/get_externals.bat mode change 100755 => 100644 PCbuild/idle.bat mode change 100755 => 100644 PCbuild/prepare_libffi.bat mode change 100755 => 100644 PCbuild/prepare_ssl.bat mode change 100644 => 100755 PCbuild/prepare_ssl.py mode change 100755 => 100644 PCbuild/prepare_tcltk.bat mode change 100755 => 100644 PCbuild/rt.bat mode change 100644 => 100755 Parser/asdl_c.py mode change 100644 => 100755 Tools/build/generate_re_casefix.py mode change 100644 => 100755 Tools/build/generate_sre_constants.py mode change 100644 => 100755 Tools/build/generate_token.py mode change 100644 => 100755 Tools/build/parse_html5_entities.py mode change 100644 => 100755 Tools/build/regen-configure.sh mode change 100644 => 100755 Tools/build/smelly.py mode change 100644 => 100755 Tools/build/verify_ensurepip_wheels.py mode change 100755 => 100644 Tools/buildbot/build.bat mode change 100755 => 100644 Tools/buildbot/buildmsi.bat mode change 100755 => 100644 Tools/buildbot/clean.bat mode change 100755 => 100644 Tools/buildbot/remoteDeploy.bat mode change 100755 => 100644 Tools/buildbot/remotePythonInfo.bat mode change 100755 => 100644 Tools/buildbot/test.bat mode change 100644 => 100755 Tools/c-analyzer/must-resolve.sh mode change 100644 => 100755 Tools/clinic/clinic.py mode change 100644 => 100755 Tools/freeze/freeze.py mode change 100644 => 100755 Tools/gdb/libpython.py mode change 100644 => 100755 Tools/i18n/makelocalealias.py mode change 100644 => 100755 Tools/i18n/msgfmt.py mode change 100644 => 100755 Tools/i18n/pygettext.py mode change 100755 => 100644 Tools/msi/build.bat mode change 100755 => 100644 Tools/msi/buildrelease.bat mode change 100755 => 100644 Tools/msi/get_externals.bat mode change 100755 => 100644 Tools/msi/testrelease.bat mode change 100755 => 100644 Tools/msi/uploadrelease.bat mode change 100755 => 100644 Tools/nuget/build.bat mode change 100644 => 100755 Tools/patchcheck/patchcheck.py mode change 100644 => 100755 Tools/patchcheck/reindent.py mode change 100644 => 100755 Tools/patchcheck/untabify.py mode change 100644 => 100755 Tools/peg_generator/pegen/__main__.py mode change 100644 => 100755 Tools/peg_generator/pegen/first_sets.py mode change 100644 => 100755 Tools/scripts/checkpip.py mode change 100644 => 100755 Tools/scripts/combinerefs.py mode change 100644 => 100755 Tools/scripts/idle3 mode change 100644 => 100755 Tools/scripts/pydoc3 mode change 100644 => 100755 Tools/ssl/make_ssl_data.py mode change 100644 => 100755 Tools/ssl/multissltests.py mode change 100644 => 100755 Tools/unicode/comparecodecs.py mode change 100755 => 100644 Tools/unicode/genwincodecs.bat mode change 100644 => 100755 Tools/unittestgui/unittestgui.py mode change 100644 => 100755 Tools/wasm/emscripten/make_libffi.sh mode change 100644 => 100755 Tools/wasm/emscripten/wasm_assets.py mode change 100644 => 100755 Tools/wasm/emscripten/web_example/server.py mode change 100644 => 100755 Tools/wasm/wasi-env mode change 100644 => 100755 config.guess mode change 100644 => 100755 config.sub mode change 100644 => 100755 configure mode change 100644 => 100755 iOS/Resources/bin/arm64-apple-ios-ar mode change 100644 => 100755 iOS/Resources/bin/arm64-apple-ios-clang mode change 100644 => 100755 iOS/Resources/bin/arm64-apple-ios-clang++ mode change 100644 => 100755 iOS/Resources/bin/arm64-apple-ios-cpp mode change 100644 => 100755 iOS/Resources/bin/arm64-apple-ios-simulator-ar mode change 100644 => 100755 iOS/Resources/bin/arm64-apple-ios-simulator-clang mode change 100644 => 100755 iOS/Resources/bin/arm64-apple-ios-simulator-clang++ mode change 100644 => 100755 iOS/Resources/bin/arm64-apple-ios-simulator-cpp mode change 100644 => 100755 iOS/Resources/bin/x86_64-apple-ios-simulator-ar mode change 100644 => 100755 iOS/Resources/bin/x86_64-apple-ios-simulator-clang mode change 100644 => 100755 iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ mode change 100644 => 100755 iOS/Resources/bin/x86_64-apple-ios-simulator-cpp mode change 100644 => 100755 install-sh diff --git a/.github/workflows/posix-deps-apt.sh b/.github/workflows/posix-deps-apt.sh old mode 100644 new mode 100755 diff --git a/Android/android.py b/Android/android.py old mode 100644 new mode 100755 diff --git a/Doc/make.bat b/Doc/make.bat old mode 100755 new mode 100644 diff --git a/Lib/ctypes/macholib/fetch_macholib b/Lib/ctypes/macholib/fetch_macholib old mode 100644 new mode 100755 diff --git a/Lib/ctypes/macholib/fetch_macholib.bat b/Lib/ctypes/macholib/fetch_macholib.bat old mode 100755 new mode 100644 diff --git a/Lib/encodings/rot_13.py b/Lib/encodings/rot_13.py old mode 100644 new mode 100755 diff --git a/Lib/idlelib/idle.bat b/Lib/idlelib/idle.bat old mode 100755 new mode 100644 diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py old mode 100644 new mode 100755 diff --git a/Lib/test/archivetestdata/exe_with_z64 b/Lib/test/archivetestdata/exe_with_z64 old mode 100644 new mode 100755 diff --git a/Lib/test/archivetestdata/exe_with_zip b/Lib/test/archivetestdata/exe_with_zip old mode 100644 new mode 100755 diff --git a/Lib/test/archivetestdata/header.sh b/Lib/test/archivetestdata/header.sh old mode 100644 new mode 100755 diff --git a/Lib/test/bisect_cmd.py b/Lib/test/bisect_cmd.py old mode 100644 new mode 100755 diff --git a/Lib/test/crashers/recursive_call.py b/Lib/test/crashers/recursive_call.py old mode 100644 new mode 100755 diff --git a/Lib/test/curses_tests.py b/Lib/test/curses_tests.py old mode 100644 new mode 100755 diff --git a/Lib/test/re_tests.py b/Lib/test/re_tests.py old mode 100644 new mode 100755 diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py old mode 100644 new mode 100755 diff --git a/Lib/test/support/smtpd.py b/Lib/test/support/smtpd.py old mode 100644 new mode 100755 diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py old mode 100644 new mode 100755 diff --git a/Lib/test/test_importlib/resources/zip.py b/Lib/test/test_importlib/resources/zip.py old mode 100644 new mode 100755 diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py old mode 100644 new mode 100755 diff --git a/Lib/venv/scripts/nt/activate.bat b/Lib/venv/scripts/nt/activate.bat old mode 100755 new mode 100644 diff --git a/Lib/venv/scripts/nt/deactivate.bat b/Lib/venv/scripts/nt/deactivate.bat old mode 100755 new mode 100644 diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py old mode 100644 new mode 100755 diff --git a/Mac/BuildScript/scripts/postflight.documentation b/Mac/BuildScript/scripts/postflight.documentation old mode 100644 new mode 100755 diff --git a/Mac/BuildScript/scripts/postflight.ensurepip b/Mac/BuildScript/scripts/postflight.ensurepip old mode 100644 new mode 100755 diff --git a/Mac/BuildScript/scripts/postflight.framework b/Mac/BuildScript/scripts/postflight.framework old mode 100644 new mode 100755 diff --git a/Mac/BuildScript/scripts/postflight.patch-profile b/Mac/BuildScript/scripts/postflight.patch-profile old mode 100644 new mode 100755 diff --git a/Mac/IDLE/IDLE.app/Contents/MacOS/IDLE b/Mac/IDLE/IDLE.app/Contents/MacOS/IDLE old mode 100644 new mode 100755 diff --git a/Mac/Tools/plistlib_generate_testdata.py b/Mac/Tools/plistlib_generate_testdata.py old mode 100644 new mode 100755 diff --git a/Misc/mypy/make_symlinks.py b/Misc/mypy/make_symlinks.py old mode 100644 new mode 100755 diff --git a/Modules/_decimal/tests/runall-memorydebugger.sh b/Modules/_decimal/tests/runall-memorydebugger.sh old mode 100644 new mode 100755 diff --git a/Modules/_hacl/refresh.sh b/Modules/_hacl/refresh.sh old mode 100644 new mode 100755 diff --git a/Modules/expat/refresh.sh b/Modules/expat/refresh.sh old mode 100644 new mode 100755 diff --git a/Modules/makesetup b/Modules/makesetup old mode 100644 new mode 100755 diff --git a/Modules/makexp_aix b/Modules/makexp_aix old mode 100644 new mode 100755 diff --git a/Objects/typeslots.py b/Objects/typeslots.py old mode 100644 new mode 100755 diff --git a/PC/python3dll.c b/PC/python3dll.c old mode 100644 new mode 100755 diff --git a/PCbuild/blurb.bat b/PCbuild/blurb.bat old mode 100755 new mode 100644 diff --git a/PCbuild/build.bat b/PCbuild/build.bat old mode 100755 new mode 100644 diff --git a/PCbuild/build_env.bat b/PCbuild/build_env.bat old mode 100755 new mode 100644 diff --git a/PCbuild/clean.bat b/PCbuild/clean.bat old mode 100755 new mode 100644 diff --git a/PCbuild/env.bat b/PCbuild/env.bat old mode 100755 new mode 100644 diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat old mode 100755 new mode 100644 diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat old mode 100755 new mode 100644 diff --git a/PCbuild/fix_encoding.py b/PCbuild/fix_encoding.py old mode 100644 new mode 100755 diff --git a/PCbuild/get_external.py b/PCbuild/get_external.py old mode 100644 new mode 100755 diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat old mode 100755 new mode 100644 diff --git a/PCbuild/idle.bat b/PCbuild/idle.bat old mode 100755 new mode 100644 diff --git a/PCbuild/prepare_libffi.bat b/PCbuild/prepare_libffi.bat old mode 100755 new mode 100644 diff --git a/PCbuild/prepare_ssl.bat b/PCbuild/prepare_ssl.bat old mode 100755 new mode 100644 diff --git a/PCbuild/prepare_ssl.py b/PCbuild/prepare_ssl.py old mode 100644 new mode 100755 diff --git a/PCbuild/prepare_tcltk.bat b/PCbuild/prepare_tcltk.bat old mode 100755 new mode 100644 diff --git a/PCbuild/rt.bat b/PCbuild/rt.bat old mode 100755 new mode 100644 diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py old mode 100644 new mode 100755 diff --git a/Tools/build/generate_re_casefix.py b/Tools/build/generate_re_casefix.py old mode 100644 new mode 100755 diff --git a/Tools/build/generate_sre_constants.py b/Tools/build/generate_sre_constants.py old mode 100644 new mode 100755 diff --git a/Tools/build/generate_token.py b/Tools/build/generate_token.py old mode 100644 new mode 100755 diff --git a/Tools/build/parse_html5_entities.py b/Tools/build/parse_html5_entities.py old mode 100644 new mode 100755 diff --git a/Tools/build/regen-configure.sh b/Tools/build/regen-configure.sh old mode 100644 new mode 100755 diff --git a/Tools/build/smelly.py b/Tools/build/smelly.py old mode 100644 new mode 100755 diff --git a/Tools/build/verify_ensurepip_wheels.py b/Tools/build/verify_ensurepip_wheels.py old mode 100644 new mode 100755 diff --git a/Tools/buildbot/build.bat b/Tools/buildbot/build.bat old mode 100755 new mode 100644 diff --git a/Tools/buildbot/buildmsi.bat b/Tools/buildbot/buildmsi.bat old mode 100755 new mode 100644 diff --git a/Tools/buildbot/clean.bat b/Tools/buildbot/clean.bat old mode 100755 new mode 100644 diff --git a/Tools/buildbot/remoteDeploy.bat b/Tools/buildbot/remoteDeploy.bat old mode 100755 new mode 100644 diff --git a/Tools/buildbot/remotePythonInfo.bat b/Tools/buildbot/remotePythonInfo.bat old mode 100755 new mode 100644 diff --git a/Tools/buildbot/test.bat b/Tools/buildbot/test.bat old mode 100755 new mode 100644 diff --git a/Tools/c-analyzer/must-resolve.sh b/Tools/c-analyzer/must-resolve.sh old mode 100644 new mode 100755 diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py old mode 100644 new mode 100755 diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py old mode 100644 new mode 100755 diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py old mode 100644 new mode 100755 diff --git a/Tools/i18n/makelocalealias.py b/Tools/i18n/makelocalealias.py old mode 100644 new mode 100755 diff --git a/Tools/i18n/msgfmt.py b/Tools/i18n/msgfmt.py old mode 100644 new mode 100755 diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py old mode 100644 new mode 100755 diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat old mode 100755 new mode 100644 diff --git a/Tools/msi/buildrelease.bat b/Tools/msi/buildrelease.bat old mode 100755 new mode 100644 diff --git a/Tools/msi/get_externals.bat b/Tools/msi/get_externals.bat old mode 100755 new mode 100644 diff --git a/Tools/msi/testrelease.bat b/Tools/msi/testrelease.bat old mode 100755 new mode 100644 diff --git a/Tools/msi/uploadrelease.bat b/Tools/msi/uploadrelease.bat old mode 100755 new mode 100644 diff --git a/Tools/nuget/build.bat b/Tools/nuget/build.bat old mode 100755 new mode 100644 diff --git a/Tools/patchcheck/patchcheck.py b/Tools/patchcheck/patchcheck.py old mode 100644 new mode 100755 diff --git a/Tools/patchcheck/reindent.py b/Tools/patchcheck/reindent.py old mode 100644 new mode 100755 diff --git a/Tools/patchcheck/untabify.py b/Tools/patchcheck/untabify.py old mode 100644 new mode 100755 diff --git a/Tools/peg_generator/pegen/__main__.py b/Tools/peg_generator/pegen/__main__.py old mode 100644 new mode 100755 diff --git a/Tools/peg_generator/pegen/first_sets.py b/Tools/peg_generator/pegen/first_sets.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/checkpip.py b/Tools/scripts/checkpip.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/combinerefs.py b/Tools/scripts/combinerefs.py old mode 100644 new mode 100755 diff --git a/Tools/scripts/idle3 b/Tools/scripts/idle3 old mode 100644 new mode 100755 diff --git a/Tools/scripts/pydoc3 b/Tools/scripts/pydoc3 old mode 100644 new mode 100755 diff --git a/Tools/ssl/make_ssl_data.py b/Tools/ssl/make_ssl_data.py old mode 100644 new mode 100755 diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py old mode 100644 new mode 100755 diff --git a/Tools/unicode/comparecodecs.py b/Tools/unicode/comparecodecs.py old mode 100644 new mode 100755 diff --git a/Tools/unicode/genwincodecs.bat b/Tools/unicode/genwincodecs.bat old mode 100755 new mode 100644 diff --git a/Tools/unittestgui/unittestgui.py b/Tools/unittestgui/unittestgui.py old mode 100644 new mode 100755 diff --git a/Tools/wasm/emscripten/make_libffi.sh b/Tools/wasm/emscripten/make_libffi.sh old mode 100644 new mode 100755 diff --git a/Tools/wasm/emscripten/wasm_assets.py b/Tools/wasm/emscripten/wasm_assets.py old mode 100644 new mode 100755 diff --git a/Tools/wasm/emscripten/web_example/server.py b/Tools/wasm/emscripten/web_example/server.py old mode 100644 new mode 100755 diff --git a/Tools/wasm/wasi-env b/Tools/wasm/wasi-env old mode 100644 new mode 100755 diff --git a/config.guess b/config.guess old mode 100644 new mode 100755 diff --git a/config.sub b/config.sub old mode 100644 new mode 100755 diff --git a/configure b/configure old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/arm64-apple-ios-ar b/iOS/Resources/bin/arm64-apple-ios-ar old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/arm64-apple-ios-clang b/iOS/Resources/bin/arm64-apple-ios-clang old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/arm64-apple-ios-clang++ b/iOS/Resources/bin/arm64-apple-ios-clang++ old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/arm64-apple-ios-cpp b/iOS/Resources/bin/arm64-apple-ios-cpp old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-ar b/iOS/Resources/bin/arm64-apple-ios-simulator-ar old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang b/iOS/Resources/bin/arm64-apple-ios-simulator-clang old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ b/iOS/Resources/bin/arm64-apple-ios-simulator-clang++ old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/arm64-apple-ios-simulator-cpp b/iOS/Resources/bin/arm64-apple-ios-simulator-cpp old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-ar b/iOS/Resources/bin/x86_64-apple-ios-simulator-ar old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ b/iOS/Resources/bin/x86_64-apple-ios-simulator-clang++ old mode 100644 new mode 100755 diff --git a/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp b/iOS/Resources/bin/x86_64-apple-ios-simulator-cpp old mode 100644 new mode 100755 diff --git a/install-sh b/install-sh old mode 100644 new mode 100755 From c40721524789cc9226943e3f7740dd05cb5255cc Mon Sep 17 00:00:00 2001 From: Lautaro Javier Fernandez Pricco Date: Sun, 12 Oct 2025 02:04:12 +0000 Subject: [PATCH 9/9] Restore mypy symlinks --- Misc/mypy/_colorize.py | 1 + Misc/mypy/_pyrepl | 1 + Misc/mypy/token.py | 1 + Misc/mypy/tomllib | 1 + 4 files changed, 4 insertions(+) create mode 120000 Misc/mypy/_colorize.py create mode 120000 Misc/mypy/_pyrepl create mode 120000 Misc/mypy/token.py create mode 120000 Misc/mypy/tomllib diff --git a/Misc/mypy/_colorize.py b/Misc/mypy/_colorize.py new file mode 120000 index 00000000000000..9b7304769ec30b --- /dev/null +++ b/Misc/mypy/_colorize.py @@ -0,0 +1 @@ +../../Lib/_colorize.py \ No newline at end of file diff --git a/Misc/mypy/_pyrepl b/Misc/mypy/_pyrepl new file mode 120000 index 00000000000000..bd7b69909663b6 --- /dev/null +++ b/Misc/mypy/_pyrepl @@ -0,0 +1 @@ +../../Lib/_pyrepl \ No newline at end of file diff --git a/Misc/mypy/token.py b/Misc/mypy/token.py new file mode 120000 index 00000000000000..0a39f726dda1aa --- /dev/null +++ b/Misc/mypy/token.py @@ -0,0 +1 @@ +../../Lib/token.py \ No newline at end of file diff --git a/Misc/mypy/tomllib b/Misc/mypy/tomllib new file mode 120000 index 00000000000000..20f34d49da0cd4 --- /dev/null +++ b/Misc/mypy/tomllib @@ -0,0 +1 @@ +../../Lib/tomllib \ No newline at end of file