diff options
author | Brandt Bucher <brandt@python.org> | 2021-11-11 21:52:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-11 21:52:43 (GMT) |
commit | a89bbde83fe7f8cc347341e7ec57cda3ba312530 (patch) | |
tree | 893064e56728e4531f5ac23f918618882c67b995 /Python | |
parent | c5bfb88eb6f82111bb1603ae9d78d0476b552d66 (diff) | |
download | cpython-a89bbde83fe7f8cc347341e7ec57cda3ba312530.zip cpython-a89bbde83fe7f8cc347341e7ec57cda3ba312530.tar.gz cpython-a89bbde83fe7f8cc347341e7ec57cda3ba312530.tar.bz2 |
[3.10] bpo-45773: Stop "optimizing" certain jump patterns (GH-29526)
Diffstat (limited to 'Python')
-rw-r--r-- | Python/compile.c | 115 | ||||
-rw-r--r-- | Python/importlib.h | 8 | ||||
-rw-r--r-- | Python/importlib_external.h | 6 | ||||
-rw-r--r-- | Python/importlib_zipimport.h | 4 |
4 files changed, 52 insertions, 81 deletions
diff --git a/Python/compile.c b/Python/compile.c index 9086103..3eb34d8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -21,6 +21,8 @@ * objects. */ +#include <stdbool.h> + #include "Python.h" #include "pycore_ast.h" // _PyAST_GetDocString() #include "pycore_compile.h" // _PyFuture_FromAST() @@ -7264,25 +7266,24 @@ fold_rotations(struct instr *inst, int n) } } - -static int -eliminate_jump_to_jump(basicblock *bb, int opcode) { - assert (bb->b_iused > 0); - struct instr *inst = &bb->b_instr[bb->b_iused-1]; - assert (is_jump(inst)); - assert (inst->i_target->b_iused > 0); - struct instr *target = &inst->i_target->b_instr[0]; - if (inst->i_target == target->i_target) { - /* Nothing to do */ - return 0; - } - int lineno = target->i_lineno; - if (add_jump_to_block(bb, opcode, lineno, target->i_target) == 0) { - return -1; +// Attempt to eliminate jumps to jumps by updating inst to jump to +// target->i_target using the provided opcode. Return whether or not the +// optimization was successful. +static bool +jump_thread(struct instr *inst, struct instr *target, int opcode) +{ + assert(is_jump(inst)); + assert(is_jump(target)); + // bpo-45773: If inst->i_target == target->i_target, then nothing actually + // changes (and we fall into an infinite loop): + 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; } - assert (bb->b_iused >= 2); - bb->b_instr[bb->b_iused-2].i_opcode = NOP; - return 0; + return false; } /* 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. */ case JUMP_IF_FALSE_OR_POP: - switch(target->i_opcode) { + switch (target->i_opcode) { case POP_JUMP_IF_FALSE: - if (inst->i_lineno == target->i_lineno) { - *inst = *target; - i--; - } + i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); break; case JUMP_ABSOLUTE: case JUMP_FORWARD: case JUMP_IF_FALSE_OR_POP: - if (inst->i_lineno == target->i_lineno && - inst->i_target != target->i_target) { - inst->i_target = target->i_target; - i--; - } + i -= jump_thread(inst, target, JUMP_IF_FALSE_OR_POP); break; 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) { + // 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_target = inst->i_target->b_next; --i; @@ -7425,27 +7422,22 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; } break; - case JUMP_IF_TRUE_OR_POP: - switch(target->i_opcode) { + switch (target->i_opcode) { case POP_JUMP_IF_TRUE: - if (inst->i_lineno == target->i_lineno) { - *inst = *target; - i--; - } + i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); break; case JUMP_ABSOLUTE: case JUMP_FORWARD: case JUMP_IF_TRUE_OR_POP: - if (inst->i_lineno == target->i_lineno && - inst->i_target != target->i_target) { - inst->i_target = target->i_target; - i--; - } + i -= jump_thread(inst, target, JUMP_IF_TRUE_OR_POP); break; 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) { + // 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_target = inst->i_target->b_next; --i; @@ -7453,54 +7445,33 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) break; } break; - case POP_JUMP_IF_FALSE: - switch(target->i_opcode) { + switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: - if (inst->i_lineno == target->i_lineno) { - inst->i_target = target->i_target; - i--; - } - break; + case JUMP_IF_FALSE_OR_POP: + i -= jump_thread(inst, target, POP_JUMP_IF_FALSE); } break; - case POP_JUMP_IF_TRUE: - switch(target->i_opcode) { + switch (target->i_opcode) { case JUMP_ABSOLUTE: case JUMP_FORWARD: - if (inst->i_lineno == target->i_lineno) { - inst->i_target = target->i_target; - i--; - } - break; + case JUMP_IF_TRUE_OR_POP: + i -= jump_thread(inst, target, POP_JUMP_IF_TRUE); } break; - case JUMP_ABSOLUTE: case JUMP_FORWARD: - assert (i == bb->b_iused-1); - switch(target->i_opcode) { - case JUMP_FORWARD: - if (eliminate_jump_to_jump(bb, inst->i_opcode)) { - goto error; - } - break; - + switch (target->i_opcode) { case JUMP_ABSOLUTE: - if (eliminate_jump_to_jump(bb, JUMP_ABSOLUTE)) { - goto error; - } - break; + case JUMP_FORWARD: + i -= jump_thread(inst, target, JUMP_ABSOLUTE); } break; case FOR_ITER: - assert (i == bb->b_iused-1); if (target->i_opcode == JUMP_FORWARD) { - if (eliminate_jump_to_jump(bb, inst->i_opcode)) { - goto error; - } + i -= jump_thread(inst, target, FOR_ITER); } break; case ROT_N: diff --git a/Python/importlib.h b/Python/importlib.h index dd1a9f1..ab3e69b 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -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, 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, - 161,1,125,3,87,0,110,13,4,0,116,5,121,64,1,0, - 1,0,1,0,100,2,125,3,89,0,110,3,119,0,100,6, + 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,113,67,119,0,100,6, 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, 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, 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, - 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, - 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, 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, diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 90c8d89..bd4d95a 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -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, 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, - 0,110,38,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,4,0,116,2,121,27,1,0,1,0,1,0,89, + 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, 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, @@ -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, 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, - 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, 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, diff --git a/Python/importlib_zipimport.h b/Python/importlib_zipimport.h index bb870c3..07c9dd5 100644 --- a/Python/importlib_zipimport.h +++ b/Python/importlib_zipimport.h @@ -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, 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, - 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, - 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, 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, |