mirror of
https://github.com/python/cpython.git
synced 2025-08-28 12:45:07 +00:00
[3.10] bpo-45773: Stop "optimizing" certain jump patterns (GH-29526)
This commit is contained in:
parent
c5bfb88eb6
commit
a89bbde83f
6 changed files with 60 additions and 81 deletions
|
@ -514,5 +514,12 @@ class TestBuglets(unittest.TestCase):
|
||||||
except Exception or Exception:
|
except Exception or Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def test_bpo_45773_pop_jump_if_true(self):
|
||||||
|
compile("while True or spam: pass", "<test>", "exec")
|
||||||
|
|
||||||
|
def test_bpo_45773_pop_jump_if_false(self):
|
||||||
|
compile("while True or not spam: pass", "<test>", "exec")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix a compiler hang when attempting to optimize certain jump patterns.
|
115
Python/compile.c
115
Python/compile.c
|
@ -21,6 +21,8 @@
|
||||||
* objects.
|
* objects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_ast.h" // _PyAST_GetDocString()
|
#include "pycore_ast.h" // _PyAST_GetDocString()
|
||||||
#include "pycore_compile.h" // _PyFuture_FromAST()
|
#include "pycore_compile.h" // _PyFuture_FromAST()
|
||||||
|
@ -7264,25 +7266,24 @@ fold_rotations(struct instr *inst, int n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt to eliminate jumps to jumps by updating inst to jump to
|
||||||
static int
|
// target->i_target using the provided opcode. Return whether or not the
|
||||||
eliminate_jump_to_jump(basicblock *bb, int opcode) {
|
// optimization was successful.
|
||||||
assert (bb->b_iused > 0);
|
static bool
|
||||||
struct instr *inst = &bb->b_instr[bb->b_iused-1];
|
jump_thread(struct instr *inst, struct instr *target, int opcode)
|
||||||
assert (is_jump(inst));
|
{
|
||||||
assert (inst->i_target->b_iused > 0);
|
assert(is_jump(inst));
|
||||||
struct instr *target = &inst->i_target->b_instr[0];
|
assert(is_jump(target));
|
||||||
if (inst->i_target == target->i_target) {
|
// bpo-45773: If inst->i_target == target->i_target, then nothing actually
|
||||||
/* Nothing to do */
|
// changes (and we fall into an infinite loop):
|
||||||
return 0;
|
if (inst->i_lineno == target->i_lineno &&
|
||||||
|
inst->i_target != target->i_target)
|
||||||
|
{
|
||||||
|
inst->i_target = target->i_target;
|
||||||
|
inst->i_opcode = opcode;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
int lineno = target->i_lineno;
|
return false;
|
||||||
if (add_jump_to_block(bb, opcode, lineno, target->i_target) == 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
assert (bb->b_iused >= 2);
|
|
||||||
bb->b_instr[bb->b_iused-2].i_opcode = NOP;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Maximum size of basic block that should be copied in optimizer */
|
/* Maximum size of basic block that should be copied in optimizer */
|
||||||
|
@ -7399,25 +7400,21 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
|
||||||
where y+1 is the instruction following the second test.
|
where y+1 is the instruction following the second test.
|
||||||
*/
|
*/
|
||||||
case JUMP_IF_FALSE_OR_POP:
|
case JUMP_IF_FALSE_OR_POP:
|
||||||
switch(target->i_opcode) {
|
switch (target->i_opcode) {
|
||||||
case POP_JUMP_IF_FALSE:
|
case POP_JUMP_IF_FALSE:
|
||||||
if (inst->i_lineno == target->i_lineno) {
|
i -= jump_thread(inst, target, POP_JUMP_IF_FALSE);
|
||||||
*inst = *target;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case JUMP_ABSOLUTE:
|
case JUMP_ABSOLUTE:
|
||||||
case JUMP_FORWARD:
|
case JUMP_FORWARD:
|
||||||
case JUMP_IF_FALSE_OR_POP:
|
case JUMP_IF_FALSE_OR_POP:
|
||||||
if (inst->i_lineno == target->i_lineno &&
|
i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP);
|
||||||
inst->i_target != target->i_target) {
|
|
||||||
inst->i_target = target->i_target;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case JUMP_IF_TRUE_OR_POP:
|
case JUMP_IF_TRUE_OR_POP:
|
||||||
assert (inst->i_target->b_iused == 1);
|
case POP_JUMP_IF_TRUE:
|
||||||
if (inst->i_lineno == target->i_lineno) {
|
if (inst->i_lineno == target->i_lineno) {
|
||||||
|
// We don't need to bother checking for loops here,
|
||||||
|
// since a block's b_next cannot point to itself:
|
||||||
|
assert(inst->i_target != inst->i_target->b_next);
|
||||||
inst->i_opcode = POP_JUMP_IF_FALSE;
|
inst->i_opcode = POP_JUMP_IF_FALSE;
|
||||||
inst->i_target = inst->i_target->b_next;
|
inst->i_target = inst->i_target->b_next;
|
||||||
--i;
|
--i;
|
||||||
|
@ -7425,27 +7422,22 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JUMP_IF_TRUE_OR_POP:
|
case JUMP_IF_TRUE_OR_POP:
|
||||||
switch(target->i_opcode) {
|
switch (target->i_opcode) {
|
||||||
case POP_JUMP_IF_TRUE:
|
case POP_JUMP_IF_TRUE:
|
||||||
if (inst->i_lineno == target->i_lineno) {
|
i -= jump_thread(inst, target, POP_JUMP_IF_TRUE);
|
||||||
*inst = *target;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case JUMP_ABSOLUTE:
|
case JUMP_ABSOLUTE:
|
||||||
case JUMP_FORWARD:
|
case JUMP_FORWARD:
|
||||||
case JUMP_IF_TRUE_OR_POP:
|
case JUMP_IF_TRUE_OR_POP:
|
||||||
if (inst->i_lineno == target->i_lineno &&
|
i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP);
|
||||||
inst->i_target != target->i_target) {
|
|
||||||
inst->i_target = target->i_target;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case JUMP_IF_FALSE_OR_POP:
|
case JUMP_IF_FALSE_OR_POP:
|
||||||
assert (inst->i_target->b_iused == 1);
|
case POP_JUMP_IF_FALSE:
|
||||||
if (inst->i_lineno == target->i_lineno) {
|
if (inst->i_lineno == target->i_lineno) {
|
||||||
|
// We don't need to bother checking for loops here,
|
||||||
|
// since a block's b_next cannot point to itself:
|
||||||
|
assert(inst->i_target != inst->i_target->b_next);
|
||||||
inst->i_opcode = POP_JUMP_IF_TRUE;
|
inst->i_opcode = POP_JUMP_IF_TRUE;
|
||||||
inst->i_target = inst->i_target->b_next;
|
inst->i_target = inst->i_target->b_next;
|
||||||
--i;
|
--i;
|
||||||
|
@ -7453,54 +7445,33 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case POP_JUMP_IF_FALSE:
|
case POP_JUMP_IF_FALSE:
|
||||||
switch(target->i_opcode) {
|
switch (target->i_opcode) {
|
||||||
case JUMP_ABSOLUTE:
|
case JUMP_ABSOLUTE:
|
||||||
case JUMP_FORWARD:
|
case JUMP_FORWARD:
|
||||||
if (inst->i_lineno == target->i_lineno) {
|
case JUMP_IF_FALSE_OR_POP:
|
||||||
inst->i_target = target->i_target;
|
i -= jump_thread(inst, target, POP_JUMP_IF_FALSE);
|
||||||
i--;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case POP_JUMP_IF_TRUE:
|
case POP_JUMP_IF_TRUE:
|
||||||
switch(target->i_opcode) {
|
switch (target->i_opcode) {
|
||||||
case JUMP_ABSOLUTE:
|
case JUMP_ABSOLUTE:
|
||||||
case JUMP_FORWARD:
|
case JUMP_FORWARD:
|
||||||
if (inst->i_lineno == target->i_lineno) {
|
case JUMP_IF_TRUE_OR_POP:
|
||||||
inst->i_target = target->i_target;
|
i -= jump_thread(inst, target, POP_JUMP_IF_TRUE);
|
||||||
i--;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JUMP_ABSOLUTE:
|
case JUMP_ABSOLUTE:
|
||||||
case JUMP_FORWARD:
|
case JUMP_FORWARD:
|
||||||
assert (i == bb->b_iused-1);
|
switch (target->i_opcode) {
|
||||||
switch(target->i_opcode) {
|
|
||||||
case JUMP_FORWARD:
|
|
||||||
if (eliminate_jump_to_jump(bb, inst->i_opcode)) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case JUMP_ABSOLUTE:
|
case JUMP_ABSOLUTE:
|
||||||
if (eliminate_jump_to_jump(bb, JUMP_ABSOLUTE)) {
|
case JUMP_FORWARD:
|
||||||
goto error;
|
i -= jump_thread(inst, target, JUMP_ABSOLUTE);
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FOR_ITER:
|
case FOR_ITER:
|
||||||
assert (i == bb->b_iused-1);
|
|
||||||
if (target->i_opcode == JUMP_FORWARD) {
|
if (target->i_opcode == JUMP_FORWARD) {
|
||||||
if (eliminate_jump_to_jump(bb, inst->i_opcode)) {
|
i -= jump_thread(inst, target, FOR_ITER);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ROT_N:
|
case ROT_N:
|
||||||
|
|
8
Python/importlib.h
generated
8
Python/importlib.h
generated
|
@ -782,8 +782,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
|
||||||
103,0,110,1,100,2,125,5,124,4,124,0,124,1,124,5,
|
103,0,110,1,100,2,125,5,124,4,124,0,124,1,124,5,
|
||||||
100,4,141,3,83,0,124,3,100,2,117,0,114,67,116,0,
|
100,4,141,3,83,0,124,3,100,2,117,0,114,67,116,0,
|
||||||
124,1,100,5,131,2,114,65,122,7,124,1,160,4,124,0,
|
124,1,100,5,131,2,114,65,122,7,124,1,160,4,124,0,
|
||||||
161,1,125,3,87,0,110,13,4,0,116,5,121,64,1,0,
|
161,1,125,3,87,0,113,67,4,0,116,5,121,64,1,0,
|
||||||
1,0,1,0,100,2,125,3,89,0,110,3,119,0,100,6,
|
1,0,1,0,100,2,125,3,89,0,113,67,119,0,100,6,
|
||||||
125,3,116,6,124,0,124,1,124,2,124,3,100,7,141,4,
|
125,3,116,6,124,0,124,1,124,2,124,3,100,7,141,4,
|
||||||
83,0,41,8,122,53,82,101,116,117,114,110,32,97,32,109,
|
83,0,41,8,122,53,82,101,116,117,114,110,32,97,32,109,
|
||||||
111,100,117,108,101,32,115,112,101,99,32,98,97,115,101,100,
|
111,100,117,108,101,32,115,112,101,99,32,98,97,115,101,100,
|
||||||
|
@ -812,9 +812,9 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
|
||||||
122,5,124,0,106,4,125,5,87,0,110,11,4,0,116,1,
|
122,5,124,0,106,4,125,5,87,0,110,11,4,0,116,1,
|
||||||
121,59,1,0,1,0,1,0,100,0,125,5,89,0,110,1,
|
121,59,1,0,1,0,1,0,100,0,125,5,89,0,110,1,
|
||||||
119,0,124,2,100,0,117,0,114,87,124,5,100,0,117,0,
|
119,0,124,2,100,0,117,0,114,87,124,5,100,0,117,0,
|
||||||
114,85,122,5,124,1,106,5,125,2,87,0,110,13,4,0,
|
114,85,122,5,124,1,106,5,125,2,87,0,113,87,4,0,
|
||||||
116,1,121,84,1,0,1,0,1,0,100,0,125,2,89,0,
|
116,1,121,84,1,0,1,0,1,0,100,0,125,2,89,0,
|
||||||
110,3,119,0,124,5,125,2,122,5,124,0,106,6,125,6,
|
113,87,119,0,124,5,125,2,122,5,124,0,106,6,125,6,
|
||||||
87,0,110,11,4,0,116,1,121,103,1,0,1,0,1,0,
|
87,0,110,11,4,0,116,1,121,103,1,0,1,0,1,0,
|
||||||
100,0,125,6,89,0,110,1,119,0,122,7,116,7,124,0,
|
100,0,125,6,89,0,110,1,119,0,122,7,116,7,124,0,
|
||||||
106,8,131,1,125,7,87,0,110,11,4,0,116,1,121,122,
|
106,8,131,1,125,7,87,0,110,11,4,0,116,1,121,122,
|
||||||
|
|
6
Python/importlib_external.h
generated
6
Python/importlib_external.h
generated
|
@ -977,8 +977,8 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = {
|
||||||
8,0,0,0,67,0,0,0,115,54,1,0,0,124,1,100,
|
8,0,0,0,67,0,0,0,115,54,1,0,0,124,1,100,
|
||||||
1,117,0,114,29,100,2,125,1,116,0,124,2,100,3,131,
|
1,117,0,114,29,100,2,125,1,116,0,124,2,100,3,131,
|
||||||
2,114,28,122,7,124,2,160,1,124,0,161,1,125,1,87,
|
2,114,28,122,7,124,2,160,1,124,0,161,1,125,1,87,
|
||||||
0,110,38,4,0,116,2,121,27,1,0,1,0,1,0,89,
|
0,113,57,4,0,116,2,121,27,1,0,1,0,1,0,89,
|
||||||
0,110,30,119,0,110,28,116,3,160,4,124,1,161,1,125,
|
0,113,57,119,0,110,28,116,3,160,4,124,1,161,1,125,
|
||||||
1,116,5,124,1,131,1,115,57,122,9,116,6,116,3,160,
|
1,116,5,124,1,131,1,115,57,122,9,116,6,116,3,160,
|
||||||
7,161,0,124,1,131,2,125,1,87,0,110,9,4,0,116,
|
7,161,0,124,1,131,2,125,1,87,0,110,9,4,0,116,
|
||||||
8,121,56,1,0,1,0,1,0,89,0,110,1,119,0,116,
|
8,121,56,1,0,1,0,1,0,89,0,110,1,119,0,116,
|
||||||
|
@ -990,7 +990,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = {
|
||||||
1,83,0,124,3,116,16,117,0,114,131,116,0,124,2,100,
|
1,83,0,124,3,116,16,117,0,114,131,116,0,124,2,100,
|
||||||
6,131,2,114,130,122,7,124,2,160,17,124,0,161,1,125,
|
6,131,2,114,130,122,7,124,2,160,17,124,0,161,1,125,
|
||||||
7,87,0,110,9,4,0,116,2,121,124,1,0,1,0,1,
|
7,87,0,110,9,4,0,116,2,121,124,1,0,1,0,1,
|
||||||
0,89,0,110,10,119,0,124,7,114,130,103,0,124,4,95,
|
0,89,0,113,134,119,0,124,7,114,130,103,0,124,4,95,
|
||||||
18,110,3,124,3,124,4,95,18,124,4,106,18,103,0,107,
|
18,110,3,124,3,124,4,95,18,124,4,106,18,103,0,107,
|
||||||
2,114,153,124,1,114,153,116,19,124,1,131,1,100,7,25,
|
2,114,153,124,1,114,153,116,19,124,1,131,1,100,7,25,
|
||||||
0,125,8,124,4,106,18,160,20,124,8,161,1,1,0,124,
|
0,125,8,124,4,106,18,160,20,124,8,161,1,1,0,124,
|
||||||
|
|
|
@ -1004,9 +1004,9 @@ const unsigned char _Py_M__zipimport[] = {
|
||||||
1,0,1,0,89,0,113,9,119,0,124,8,100,4,25,0,
|
1,0,1,0,89,0,113,9,119,0,124,8,100,4,25,0,
|
||||||
125,9,116,8,124,0,106,4,124,8,131,2,125,10,100,0,
|
125,9,116,8,124,0,106,4,124,8,131,2,125,10,100,0,
|
||||||
125,11,124,5,114,91,122,10,116,9,124,0,124,9,124,7,
|
125,11,124,5,114,91,122,10,116,9,124,0,124,9,124,7,
|
||||||
124,1,124,10,131,5,125,11,87,0,110,25,4,0,116,10,
|
124,1,124,10,131,5,125,11,87,0,113,96,4,0,116,10,
|
||||||
121,90,1,0,125,12,1,0,122,8,124,12,125,3,87,0,
|
121,90,1,0,125,12,1,0,122,8,124,12,125,3,87,0,
|
||||||
89,0,100,0,125,12,126,12,110,10,100,0,125,12,126,12,
|
89,0,100,0,125,12,126,12,113,96,100,0,125,12,126,12,
|
||||||
119,1,119,0,116,11,124,9,124,10,131,2,125,11,124,11,
|
119,1,119,0,116,11,124,9,124,10,131,2,125,11,124,11,
|
||||||
100,0,117,0,114,101,113,9,124,8,100,4,25,0,125,9,
|
100,0,117,0,114,101,113,9,124,8,100,4,25,0,125,9,
|
||||||
124,11,124,6,124,9,102,3,2,0,1,0,83,0,124,3,
|
124,11,124,6,124,9,102,3,2,0,1,0,83,0,124,3,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue