mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
Issue #6690: Optimize the bytecode for expressions such as x in {1, 2, 3}
,
where the right hand operand is a set of constants, by turning the set into a frozenset and pre-building it as a constant. The comparison operation is made against the constant instead of building a new set each time it is executed (a similar optimization already existed which turned a list of constants into a pre-built tuple). Patch and additional tests by Dave Malcolm.
This commit is contained in:
parent
a8f480f545
commit
b7fbcd396f
3 changed files with 73 additions and 4 deletions
|
@ -31,7 +31,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 +42,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 +60,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);
|
||||
|
@ -436,20 +447,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 ||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue