From 915a1a4f0fbbcf8ee15f06406a2e7417063fefbf Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Fri, 15 Dec 2017 18:14:50 +0900 Subject: [PATCH 1/5] bpo-29469: peephole: Remove const_stack Constant folding was moved to AST optimizer. But compiler may emit LOAD_CONSTs + BUILD_TUPLE. For example, default arguments can be constant tuple if all arguments are constant. This commit makes peephole's tuple folding simple. It doesn't support nested tuples because nested tuples are folded by AST optimizer already. --- Python/peephole.c | 99 ++++++++++++----------------------------------- 1 file changed, 24 insertions(+), 75 deletions(-) diff --git a/Python/peephole.c b/Python/peephole.c index 49d62a2c3422cf..da95314d5c092c 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -23,51 +23,6 @@ (blocks[start]==blocks[end]) -#define CONST_STACK_CREATE() { \ - const_stack_size = 256; \ - const_stack = PyMem_New(PyObject *, const_stack_size); \ - if (!const_stack) { \ - PyErr_NoMemory(); \ - goto exitError; \ - } \ - } - -#define CONST_STACK_DELETE() do { \ - if (const_stack) \ - PyMem_Free(const_stack); \ - } while(0) - -#define CONST_STACK_LEN() ((unsigned)(const_stack_top + 1)) - -#define CONST_STACK_PUSH_OP(i) do { \ - PyObject *_x; \ - assert(_Py_OPCODE(codestr[i]) == LOAD_CONST); \ - assert(PyList_GET_SIZE(consts) > (Py_ssize_t)get_arg(codestr, i)); \ - _x = PyList_GET_ITEM(consts, get_arg(codestr, i)); \ - if (++const_stack_top >= const_stack_size) { \ - const_stack_size *= 2; \ - PyMem_Resize(const_stack, PyObject *, const_stack_size); \ - if (!const_stack) { \ - PyErr_NoMemory(); \ - goto exitError; \ - } \ - } \ - const_stack[const_stack_top] = _x; \ - in_consts = 1; \ - } while(0) - -#define CONST_STACK_RESET() do { \ - const_stack_top = -1; \ - } while(0) - -#define CONST_STACK_LASTN(i) \ - &const_stack[CONST_STACK_LEN() - i] - -#define CONST_STACK_POP(i) do { \ - assert(CONST_STACK_LEN() >= i); \ - const_stack_top -= i; \ - } while(0) - /* Scans back N consecutive LOAD_CONST instructions, skipping NOPs, returns index of the Nth last's LOAD_CONST's EXTENDED_ARG prefix. Callers are responsible to check CONST_STACK_LEN beforehand. @@ -172,15 +127,12 @@ copy_op_arg(_Py_CODEUNIT *codestr, Py_ssize_t i, unsigned char op, The consts table must still be in list form so that the new constant (c1, c2, ... cn) can be appended. Called with codestr pointing to the first LOAD_CONST. - Bails out with no change if one or more of the LOAD_CONSTs is missing. */ static Py_ssize_t fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, - Py_ssize_t opcode_end, unsigned char opcode, - PyObject *consts, PyObject **objs, int n) + Py_ssize_t opcode_end, PyObject *consts, int n) { PyObject *newconst, *constant; - Py_ssize_t i, len_consts; /* Pre-conditions */ assert(PyList_CheckExact(consts)); @@ -190,14 +142,27 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, if (newconst == NULL) { return -1; } - for (i=0 ; i 0 && CONST_STACK_LEN() >= j) { + if (j > 0 && lastlc >= j) { h = lastn_const_start(codestr, op_start, j); if (ISBASICBLOCK(blocks, h, op_start)) { - h = fold_tuple_on_constants(codestr, h, i + 1, opcode, - consts, CONST_STACK_LASTN(j), j); - if (h >= 0) { - CONST_STACK_POP(j); - CONST_STACK_PUSH_OP(h); - } + h = fold_tuple_on_constants(codestr, h, i+1, consts, j); break; } } @@ -374,12 +327,10 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, } else if (j == 2) { codestr[op_start] = PACKOPARG(ROT_TWO, 0); fill_nops(codestr, op_start + 1, nexti + 1); - CONST_STACK_RESET(); } else if (j == 3) { codestr[op_start] = PACKOPARG(ROT_THREE, 0); codestr[op_start + 1] = PACKOPARG(ROT_TWO, 0); fill_nops(codestr, op_start + 2, nexti + 1); - CONST_STACK_RESET(); } break; @@ -538,7 +489,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, } assert(h + (Py_ssize_t)nops == codelen); - CONST_STACK_DELETE(); PyMem_Free(blocks); code = PyBytes_FromStringAndSize((char *)codestr, h * sizeof(_Py_CODEUNIT)); PyMem_Free(codestr); @@ -549,7 +499,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, exitUnchanged: Py_XINCREF(code); - CONST_STACK_DELETE(); PyMem_Free(blocks); PyMem_Free(codestr); return code; From ca5bacf7c64bda717b8cd3836be30395e12d9a64 Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Fri, 15 Dec 2017 22:29:30 +0900 Subject: [PATCH 2/5] fixup --- Python/peephole.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Python/peephole.c b/Python/peephole.c index da95314d5c092c..8ef0eb3d500aee 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -43,8 +43,7 @@ lastn_const_start(const _Py_CODEUNIT *codestr, Py_ssize_t i, Py_ssize_t n) } } else { - assert(_Py_OPCODE(codestr[i]) == NOP || - _Py_OPCODE(codestr[i]) == EXTENDED_ARG); + assert(_Py_OPCODE(codestr[i]) == EXTENDED_ARG); } } } @@ -144,23 +143,19 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, } Py_ssize_t len_consts = PyList_GET_SIZE(consts); - Py_ssize_t pos = c_start; + Py_ssize_t i, pos; - for (Py_ssize_t i=0; i Date: Mon, 18 Dec 2017 12:04:01 +0900 Subject: [PATCH 3/5] Reformat code. http://wiki.c2.com/?DeclareVariablesAtFirstUse --- Python/peephole.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Python/peephole.c b/Python/peephole.c index 8ef0eb3d500aee..2d7c74fe191080 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -131,31 +131,25 @@ static Py_ssize_t fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, Py_ssize_t opcode_end, PyObject *consts, int n) { - PyObject *newconst, *constant; - /* Pre-conditions */ assert(PyList_CheckExact(consts)); /* Buildup new tuple of constants */ - newconst = PyTuple_New(n); + PyObject *newconst = PyTuple_New(n); if (newconst == NULL) { return -1; } - Py_ssize_t len_consts = PyList_GET_SIZE(consts); - Py_ssize_t i, pos; - - for (i=0, pos=c_start; i Date: Mon, 18 Dec 2017 12:39:06 +0900 Subject: [PATCH 4/5] More cleanup --- Python/peephole.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Python/peephole.c b/Python/peephole.c index 2d7c74fe191080..9fd3f154bea3f9 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -158,8 +158,8 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, } Py_DECREF(newconst); - Py_ssize_t len_consts = PyList_GET_SIZE(consts); - return copy_op_arg(codestr, c_start, LOAD_CONST, len_consts, opcode_end); + return copy_op_arg(codestr, c_start, LOAD_CONST, + PyList_GET_SIZE(consts), opcode_end); } static unsigned int * @@ -229,7 +229,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, unsigned char *lnotab; unsigned int cum_orig_offset, last_offset; Py_ssize_t tabsiz; - unsigned int cumlc=0, lastlc=0; // Count runs of consecutive LOAD_CONSTs + // Count runs of consecutive LOAD_CONSTs + unsigned int cumlc = 0, lastlc = 0; unsigned int *blocks = NULL; /* Bail out if an exception is set */ From 492f47313f47767d1ab88fc0425bb9193fe0660b Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Mon, 18 Dec 2017 15:26:41 +0900 Subject: [PATCH 5/5] fix --- Python/peephole.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/peephole.c b/Python/peephole.c index 9fd3f154bea3f9..76a0edbcc2bcac 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -159,7 +159,7 @@ fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t c_start, Py_DECREF(newconst); return copy_op_arg(codestr, c_start, LOAD_CONST, - PyList_GET_SIZE(consts), opcode_end); + PyList_GET_SIZE(consts)-1, opcode_end); } static unsigned int *