summaryrefslogtreecommitdiff
path: root/Python/peephole.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/peephole.c')
-rw-r--r--Python/peephole.c69
1 files changed, 40 insertions, 29 deletions
diff --git a/Python/peephole.c b/Python/peephole.c
index c27878c1c7..7ae599bb11 100644
--- a/Python/peephole.c
+++ b/Python/peephole.c
@@ -4,10 +4,8 @@
#include "Python-ast.h"
#include "node.h"
-#include "pyarena.h"
#include "ast.h"
#include "code.h"
-#include "compile.h"
#include "symtable.h"
#include "opcode.h"
@@ -31,7 +29,8 @@
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.
- Also works for BUILD_LIST when followed by an "in" or "not in" test.
+ Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in"
+ test; for BUILD_SET it assembles a frozenset rather than a tuple.
*/
static int
tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts)
@@ -41,7 +40,7 @@ tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts)
/* Pre-conditions */
assert(PyList_CheckExact(consts));
- assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST);
+ assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST || codestr[n*3] == BUILD_SET);
assert(GETARG(codestr, (n*3)) == n);
for (i=0 ; i<n ; i++)
assert(codestr[i*3] == LOAD_CONST);
@@ -59,6 +58,16 @@ tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts)
PyTuple_SET_ITEM(newconst, i, constant);
}
+ /* If it's a BUILD_SET, use the PyTuple we just built to create a
+ PyFrozenSet, and use that as the constant instead: */
+ if (codestr[n*3] == BUILD_SET) {
+ PyObject *tuple = newconst;
+ newconst = PyFrozenSet_New(tuple);
+ Py_DECREF(tuple);
+ if (newconst == NULL)
+ return 0;
+ }
+
/* Append folded constant onto consts */
if (PyList_Append(consts, newconst)) {
Py_DECREF(newconst);
@@ -123,25 +132,14 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
newconst = PyNumber_Subtract(v, w);
break;
case BINARY_SUBSCR:
- newconst = PyObject_GetItem(v, w);
/* #5057: if v is unicode, there might be differences between
- wide and narrow builds in cases like '\U00012345'[0].
- Wide builds will return a non-BMP char, whereas narrow builds
- will return a surrogate. In both the cases skip the
- optimization in order to produce compatible pycs.
- */
- if (newconst != NULL &&
- PyUnicode_Check(v) && PyUnicode_Check(newconst)) {
- Py_UNICODE ch = PyUnicode_AS_UNICODE(newconst)[0];
-#ifdef Py_UNICODE_WIDE
- if (ch > 0xFFFF) {
-#else
- if (ch >= 0xD800 && ch <= 0xDFFF) {
-#endif
- Py_DECREF(newconst);
- return 0;
- }
- }
+ wide and narrow builds in cases like '\U00012345'[0] or
+ '\U00012345abcdef'[3], so it's better to skip the optimization
+ in order to produce compatible pycs.
+ */
+ if (PyUnicode_Check(v))
+ return 0;
+ newconst = PyObject_GetItem(v, w);
break;
case BINARY_LSHIFT:
newconst = PyNumber_Lshift(v, w);
@@ -166,13 +164,16 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
return 0;
}
if (newconst == NULL) {
- PyErr_Clear();
+ if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
+ PyErr_Clear();
return 0;
}
size = PyObject_Size(newconst);
- if (size == -1)
+ if (size == -1) {
+ if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
+ return 0;
PyErr_Clear();
- else if (size > 20) {
+ } else if (size > 20) {
Py_DECREF(newconst);
return 0;
}
@@ -215,6 +216,9 @@ fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
case UNARY_INVERT:
newconst = PyNumber_Invert(v);
break;
+ case UNARY_POSITIVE:
+ newconst = PyNumber_Positive(v);
+ break;
default:
/* Called with an unknown opcode */
PyErr_Format(PyExc_SystemError,
@@ -223,7 +227,8 @@ fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
return 0;
}
if (newconst == NULL) {
- PyErr_Clear();
+ if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
+ PyErr_Clear();
return 0;
}
@@ -269,6 +274,7 @@ markblocks(unsigned char *code, Py_ssize_t len)
case SETUP_LOOP:
case SETUP_EXCEPT:
case SETUP_FINALLY:
+ case SETUP_WITH:
j = GETJUMPTGT(code, i);
blocks[j] = 1;
break;
@@ -450,20 +456,21 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
cumlc = 0;
break;
- /* Try to fold tuples of constants (includes a case for lists
+ /* Try to fold tuples of constants (includes a case for lists and sets
which are only used for "in" and "not in" tests).
Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
case BUILD_TUPLE:
case BUILD_LIST:
+ case BUILD_SET:
j = GETARG(codestr, i);
h = i - 3 * j;
if (h >= 0 &&
j <= lastlc &&
((opcode == BUILD_TUPLE &&
ISBASICBLOCK(blocks, h, 3*(j+1))) ||
- (opcode == BUILD_LIST &&
+ ((opcode == BUILD_LIST || opcode == BUILD_SET) &&
codestr[i+3]==COMPARE_OP &&
ISBASICBLOCK(blocks, h, 3*(j+2)) &&
(GETARG(codestr,i+3)==6 ||
@@ -475,7 +482,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
}
if (codestr[i+3] != UNPACK_SEQUENCE ||
!ISBASICBLOCK(blocks,i,6) ||
- j != GETARG(codestr, i+3))
+ j != GETARG(codestr, i+3) ||
+ opcode == BUILD_SET)
continue;
if (j == 1) {
memset(codestr+i, NOP, 6);
@@ -517,6 +525,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
case UNARY_NEGATIVE:
case UNARY_INVERT:
+ case UNARY_POSITIVE:
if (lastlc >= 1 &&
ISBASICBLOCK(blocks, i-3, 4) &&
fold_unaryops_on_constants(&codestr[i-3], consts)) {
@@ -584,6 +593,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
case SETUP_LOOP:
case SETUP_EXCEPT:
case SETUP_FINALLY:
+ case SETUP_WITH:
tgt = GETJUMPTGT(codestr, i);
/* Replace JUMP_* to a RETURN into just a RETURN */
if (UNCONDITIONAL_JUMP(opcode) &&
@@ -666,6 +676,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
case SETUP_LOOP:
case SETUP_EXCEPT:
case SETUP_FINALLY:
+ case SETUP_WITH:
j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
SETARG(codestr, i, j);
break;