]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-109627: duplicated small exit blocks need to be assigned jump target labels...
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Fri, 22 Sep 2023 13:27:29 +0000 (14:27 +0100)
committerGitHub <noreply@github.com>
Fri, 22 Sep 2023 13:27:29 +0000 (15:27 +0200)
gh-109627: duplicated smalll exit blocks need to be assigned jump target labels (#109630)

(cherry picked from commit 9ccf0545efd5bc5af5aa51774030c471d49a972b)

Lib/test/test_compile.py
Misc/NEWS.d/next/Core and Builtins/2023-09-20-23-04-15.gh-issue-109627.xxe7De.rst [new file with mode: 0644]
Python/flowgraph.c

index fde52d40097f406e64201a83a71fc66266bdede3..00fb61988505ee0cce53708e741993235ffa454a 100644 (file)
@@ -1216,6 +1216,15 @@ class TestSpecifics(unittest.TestCase):
             return a
         self.assertEqual(f("x", "y", "z"), "y")
 
+    def test_duplicated_small_exit_block(self):
+        # See gh-109627
+        def f():
+            while element and something:
+                try:
+                    return something
+                except:
+                    pass
+
 
 @requires_debug_ranges()
 class TestSourcePositions(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-09-20-23-04-15.gh-issue-109627.xxe7De.rst b/Misc/NEWS.d/next/Core and Builtins/2023-09-20-23-04-15.gh-issue-109627.xxe7De.rst
new file mode 100644 (file)
index 0000000..397d76e
--- /dev/null
@@ -0,0 +1,2 @@
+Fix bug where the compiler does not assign a new jump target label to a
+duplicated small exit block.
index 4fe581beb5fc6344a0a2d5944bef48cb7fd3a0be..0ea32345f9f9be1b5fd5648402e2ff2ac05da337 100644 (file)
@@ -562,16 +562,23 @@ check_cfg(cfg_builder *g) {
     return SUCCESS;
 }
 
-/* Calculate the actual jump target from the target_label */
 static int
-translate_jump_labels_to_targets(basicblock *entryblock)
+get_max_label(basicblock *entryblock)
 {
-    int max_label = -1;
+    int lbl = -1;
     for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
-        if (b->b_label.id > max_label) {
-            max_label = b->b_label.id;
+        if (b->b_label.id > lbl) {
+            lbl = b->b_label.id;
         }
     }
+    return lbl;
+}
+
+/* Calculate the actual jump target from the target_label */
+static int
+translate_jump_labels_to_targets(basicblock *entryblock)
+{
+    int max_label = get_max_label(entryblock);
     size_t mapsize = sizeof(basicblock *) * (max_label + 1);
     basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);
     if (!label2block) {
@@ -2035,6 +2042,7 @@ is_exit_without_lineno(basicblock *b) {
     return true;
 }
 
+
 /* PEP 626 mandates that the f_lineno of a frame is correct
  * after a frame terminates. It would be prohibitively expensive
  * to continuously update the f_lineno field at runtime,
@@ -2048,6 +2056,9 @@ static int
 duplicate_exits_without_lineno(cfg_builder *g)
 {
     assert(no_empty_basic_blocks(g));
+
+    int next_lbl = get_max_label(g->g_entryblock) + 1;
+
     /* Copy all exit blocks without line number that are targets of a jump.
      */
     basicblock *entryblock = g->g_entryblock;
@@ -2066,6 +2077,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
                 target->b_predecessors--;
                 new_target->b_predecessors = 1;
                 new_target->b_next = target->b_next;
+                new_target->b_label.id = next_lbl++;
                 target->b_next = new_target;
             }
         }