mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Merged revisions 67818 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r67818 | antoine.pitrou | 2008-12-17 01:38:28 +0100 (mer., 17 déc. 2008) | 3 lines Issue #2183: Simplify and optimize bytecode for list comprehensions. ........
This commit is contained in:
parent
621601a698
commit
f289ae6f01
8 changed files with 70 additions and 55 deletions
|
@ -357,14 +357,25 @@ Miscellaneous opcodes.
|
||||||
address to jump to (which should be a ``FOR_ITER`` instruction).
|
address to jump to (which should be a ``FOR_ITER`` instruction).
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: SET_ADD ()
|
.. opcode:: SET_ADD (i)
|
||||||
|
|
||||||
Calls ``set.add(TOS1, TOS)``. Used to implement set comprehensions.
|
Calls ``set.add(TOS1[-i], TOS)``. Used to implement set comprehensions.
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: LIST_APPEND ()
|
.. opcode:: LIST_APPEND (i)
|
||||||
|
|
||||||
Calls ``list.append(TOS1, TOS)``. Used to implement list comprehensions.
|
Calls ``list.append(TOS[-i], TOS)``. Used to implement list comprehensions.
|
||||||
|
|
||||||
|
|
||||||
|
.. opcode:: MAP_ADD (i)
|
||||||
|
|
||||||
|
Calls ``dict.setitem(TOS1[-i], TOS, TOS1)``. Used to implement dict
|
||||||
|
comprehensions.
|
||||||
|
|
||||||
|
|
||||||
|
For all of the SET_ADD, LIST_APPEND and MAP_ADD instructions, while the
|
||||||
|
added value or key/value pair is popped off, the container object remains on
|
||||||
|
the stack so that it is available for further iterations of the loop.
|
||||||
|
|
||||||
|
|
||||||
.. opcode:: LOAD_LOCALS ()
|
.. opcode:: LOAD_LOCALS ()
|
||||||
|
|
|
@ -21,8 +21,6 @@ extern "C" {
|
||||||
|
|
||||||
#define UNARY_INVERT 15
|
#define UNARY_INVERT 15
|
||||||
|
|
||||||
#define SET_ADD 17
|
|
||||||
#define LIST_APPEND 18
|
|
||||||
#define BINARY_POWER 19
|
#define BINARY_POWER 19
|
||||||
|
|
||||||
#define BINARY_MULTIPLY 20
|
#define BINARY_MULTIPLY 20
|
||||||
|
@ -133,6 +131,10 @@ extern "C" {
|
||||||
/* Support for opargs more than 16 bits long */
|
/* Support for opargs more than 16 bits long */
|
||||||
#define EXTENDED_ARG 143
|
#define EXTENDED_ARG 143
|
||||||
|
|
||||||
|
#define LIST_APPEND 145
|
||||||
|
#define SET_ADD 146
|
||||||
|
#define MAP_ADD 147
|
||||||
|
|
||||||
|
|
||||||
/* EXCEPT_HANDLER is a special, implicit block type which is created when
|
/* EXCEPT_HANDLER is a special, implicit block type which is created when
|
||||||
entering an except handler. It is not an opcode but we define it here
|
entering an except handler. It is not an opcode but we define it here
|
||||||
|
|
|
@ -57,8 +57,6 @@ def_op('UNARY_NOT', 12)
|
||||||
|
|
||||||
def_op('UNARY_INVERT', 15)
|
def_op('UNARY_INVERT', 15)
|
||||||
|
|
||||||
def_op('SET_ADD', 17)
|
|
||||||
def_op('LIST_APPEND', 18)
|
|
||||||
def_op('BINARY_POWER', 19)
|
def_op('BINARY_POWER', 19)
|
||||||
def_op('BINARY_MULTIPLY', 20)
|
def_op('BINARY_MULTIPLY', 20)
|
||||||
|
|
||||||
|
@ -169,4 +167,9 @@ def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8)
|
||||||
def_op('EXTENDED_ARG', 143)
|
def_op('EXTENDED_ARG', 143)
|
||||||
EXTENDED_ARG = 143
|
EXTENDED_ARG = 143
|
||||||
|
|
||||||
|
def_op('LIST_APPEND', 145)
|
||||||
|
def_op('SET_ADD', 146)
|
||||||
|
def_op('MAP_ADD', 147)
|
||||||
|
|
||||||
|
|
||||||
del def_op, name_op, jrel_op, jabs_op
|
del def_op, name_op, jrel_op, jabs_op
|
||||||
|
|
|
@ -55,29 +55,25 @@ def bug1333982(x=[]):
|
||||||
|
|
||||||
dis_bug1333982 = """\
|
dis_bug1333982 = """\
|
||||||
%-4d 0 LOAD_CONST 1 (0)
|
%-4d 0 LOAD_CONST 1 (0)
|
||||||
3 JUMP_IF_TRUE 41 (to 47)
|
3 JUMP_IF_TRUE 33 (to 39)
|
||||||
6 POP_TOP
|
6 POP_TOP
|
||||||
7 LOAD_GLOBAL 0 (AssertionError)
|
7 LOAD_GLOBAL 0 (AssertionError)
|
||||||
10 BUILD_LIST 0
|
10 BUILD_LIST 0
|
||||||
13 DUP_TOP
|
13 LOAD_FAST 0 (x)
|
||||||
14 STORE_FAST 1 (_[1])
|
16 GET_ITER
|
||||||
17 LOAD_FAST 0 (x)
|
>> 17 FOR_ITER 12 (to 32)
|
||||||
20 GET_ITER
|
20 STORE_FAST 1 (s)
|
||||||
>> 21 FOR_ITER 13 (to 37)
|
23 LOAD_FAST 1 (s)
|
||||||
24 STORE_FAST 2 (s)
|
26 LIST_APPEND 2
|
||||||
27 LOAD_FAST 1 (_[1])
|
29 JUMP_ABSOLUTE 17
|
||||||
30 LOAD_FAST 2 (s)
|
|
||||||
33 LIST_APPEND
|
|
||||||
34 JUMP_ABSOLUTE 21
|
|
||||||
>> 37 DELETE_FAST 1 (_[1])
|
|
||||||
|
|
||||||
%-4d 40 LOAD_CONST 2 (1)
|
%-4d >> 32 LOAD_CONST 2 (1)
|
||||||
43 BINARY_ADD
|
35 BINARY_ADD
|
||||||
44 RAISE_VARARGS 2
|
36 RAISE_VARARGS 2
|
||||||
>> 47 POP_TOP
|
>> 39 POP_TOP
|
||||||
|
|
||||||
%-4d 48 LOAD_CONST 0 (None)
|
%-4d 40 LOAD_CONST 0 (None)
|
||||||
51 RETURN_VALUE
|
43 RETURN_VALUE
|
||||||
"""%(bug1333982.__code__.co_firstlineno + 1,
|
"""%(bug1333982.__code__.co_firstlineno + 1,
|
||||||
bug1333982.__code__.co_firstlineno + 2,
|
bug1333982.__code__.co_firstlineno + 2,
|
||||||
bug1333982.__code__.co_firstlineno + 3)
|
bug1333982.__code__.co_firstlineno + 3)
|
||||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 3.1 alpha 0
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #2183: Simplify and optimize bytecode for list, dict and set
|
||||||
|
comprehensions. Original patch for list comprehensions by Neal Norwitz.
|
||||||
|
|
||||||
- Issue #2467: gc.DEBUG_STATS reported invalid elapsed times. Also, always
|
- Issue #2467: gc.DEBUG_STATS reported invalid elapsed times. Also, always
|
||||||
print elapsed times, not only when some objects are uncollectable /
|
print elapsed times, not only when some objects are uncollectable /
|
||||||
unreachable. Original patch by Neil Schemenauer.
|
unreachable. Original patch by Neil Schemenauer.
|
||||||
|
|
|
@ -1306,9 +1306,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
|
|
||||||
case LIST_APPEND:
|
case LIST_APPEND:
|
||||||
w = POP();
|
w = POP();
|
||||||
v = POP();
|
v = stack_pointer[-oparg];
|
||||||
err = PyList_Append(v, w);
|
err = PyList_Append(v, w);
|
||||||
Py_DECREF(v);
|
|
||||||
Py_DECREF(w);
|
Py_DECREF(w);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
PREDICT(JUMP_ABSOLUTE);
|
PREDICT(JUMP_ABSOLUTE);
|
||||||
|
@ -1318,9 +1317,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
|
|
||||||
case SET_ADD:
|
case SET_ADD:
|
||||||
w = POP();
|
w = POP();
|
||||||
v = POP();
|
v = stack_pointer[-oparg];
|
||||||
err = PySet_Add(v, w);
|
err = PySet_Add(v, w);
|
||||||
Py_DECREF(v);
|
|
||||||
Py_DECREF(w);
|
Py_DECREF(w);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
PREDICT(JUMP_ABSOLUTE);
|
PREDICT(JUMP_ABSOLUTE);
|
||||||
|
@ -1935,6 +1933,21 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
if (err == 0) continue;
|
if (err == 0) continue;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MAP_ADD:
|
||||||
|
w = TOP(); /* key */
|
||||||
|
u = SECOND(); /* value */
|
||||||
|
STACKADJ(-2);
|
||||||
|
v = stack_pointer[-oparg]; /* dict */
|
||||||
|
assert (PyDict_CheckExact(v));
|
||||||
|
err = PyDict_SetItem(v, w, u); /* v[w] = u */
|
||||||
|
Py_DECREF(u);
|
||||||
|
Py_DECREF(w);
|
||||||
|
if (err == 0) {
|
||||||
|
PREDICT(JUMP_ABSOLUTE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case LOAD_ATTR:
|
case LOAD_ATTR:
|
||||||
w = GETITEM(names, oparg);
|
w = GETITEM(names, oparg);
|
||||||
v = TOP();
|
v = TOP();
|
||||||
|
|
|
@ -707,6 +707,8 @@ opcode_stack_effect(int opcode, int oparg)
|
||||||
|
|
||||||
case SET_ADD:
|
case SET_ADD:
|
||||||
case LIST_APPEND:
|
case LIST_APPEND:
|
||||||
|
return -1;
|
||||||
|
case MAP_ADD:
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
case BINARY_POWER:
|
case BINARY_POWER:
|
||||||
|
@ -2823,7 +2825,7 @@ compiler_call_helper(struct compiler *c,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compiler_comprehension_generator(struct compiler *c, PyObject *tmpname,
|
compiler_comprehension_generator(struct compiler *c,
|
||||||
asdl_seq *generators, int gen_index,
|
asdl_seq *generators, int gen_index,
|
||||||
expr_ty elt, expr_ty val, int type)
|
expr_ty elt, expr_ty val, int type)
|
||||||
{
|
{
|
||||||
|
@ -2871,7 +2873,7 @@ compiler_comprehension_generator(struct compiler *c, PyObject *tmpname,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++gen_index < asdl_seq_LEN(generators))
|
if (++gen_index < asdl_seq_LEN(generators))
|
||||||
if (!compiler_comprehension_generator(c, tmpname,
|
if (!compiler_comprehension_generator(c,
|
||||||
generators, gen_index,
|
generators, gen_index,
|
||||||
elt, val, type))
|
elt, val, type))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2886,27 +2888,19 @@ compiler_comprehension_generator(struct compiler *c, PyObject *tmpname,
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
break;
|
break;
|
||||||
case COMP_LISTCOMP:
|
case COMP_LISTCOMP:
|
||||||
if (!compiler_nameop(c, tmpname, Load))
|
|
||||||
return 0;
|
|
||||||
VISIT(c, expr, elt);
|
VISIT(c, expr, elt);
|
||||||
ADDOP(c, LIST_APPEND);
|
ADDOP_I(c, LIST_APPEND, gen_index + 1);
|
||||||
break;
|
break;
|
||||||
case COMP_SETCOMP:
|
case COMP_SETCOMP:
|
||||||
if (!compiler_nameop(c, tmpname, Load))
|
|
||||||
return 0;
|
|
||||||
VISIT(c, expr, elt);
|
VISIT(c, expr, elt);
|
||||||
ADDOP(c, SET_ADD);
|
ADDOP_I(c, SET_ADD, gen_index + 1);
|
||||||
break;
|
break;
|
||||||
case COMP_DICTCOMP:
|
case COMP_DICTCOMP:
|
||||||
if (!compiler_nameop(c, tmpname, Load))
|
|
||||||
return 0;
|
|
||||||
/* With 'd[k] = v', v is evaluated before k, so we do
|
/* With 'd[k] = v', v is evaluated before k, so we do
|
||||||
the same. STORE_SUBSCR requires (item, map, key),
|
the same. */
|
||||||
so we still end up ROTing once. */
|
|
||||||
VISIT(c, expr, val);
|
VISIT(c, expr, val);
|
||||||
ADDOP(c, ROT_TWO);
|
|
||||||
VISIT(c, expr, elt);
|
VISIT(c, expr, elt);
|
||||||
ADDOP(c, STORE_SUBSCR);
|
ADDOP_I(c, MAP_ADD, gen_index + 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2932,7 +2926,6 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
|
||||||
asdl_seq *generators, expr_ty elt, expr_ty val)
|
asdl_seq *generators, expr_ty elt, expr_ty val)
|
||||||
{
|
{
|
||||||
PyCodeObject *co = NULL;
|
PyCodeObject *co = NULL;
|
||||||
identifier tmp = NULL;
|
|
||||||
expr_ty outermost_iter;
|
expr_ty outermost_iter;
|
||||||
|
|
||||||
outermost_iter = ((comprehension_ty)
|
outermost_iter = ((comprehension_ty)
|
||||||
|
@ -2943,9 +2936,6 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
|
||||||
|
|
||||||
if (type != COMP_GENEXP) {
|
if (type != COMP_GENEXP) {
|
||||||
int op;
|
int op;
|
||||||
tmp = compiler_new_tmpname(c);
|
|
||||||
if (!tmp)
|
|
||||||
goto error_in_scope;
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case COMP_LISTCOMP:
|
case COMP_LISTCOMP:
|
||||||
op = BUILD_LIST;
|
op = BUILD_LIST;
|
||||||
|
@ -2963,12 +2953,9 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
|
||||||
}
|
}
|
||||||
|
|
||||||
ADDOP_I(c, op, 0);
|
ADDOP_I(c, op, 0);
|
||||||
ADDOP(c, DUP_TOP);
|
|
||||||
if (!compiler_nameop(c, tmp, Store))
|
|
||||||
goto error_in_scope;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!compiler_comprehension_generator(c, tmp, generators, 0, elt,
|
if (!compiler_comprehension_generator(c, generators, 0, elt,
|
||||||
val, type))
|
val, type))
|
||||||
goto error_in_scope;
|
goto error_in_scope;
|
||||||
|
|
||||||
|
@ -2984,7 +2971,6 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
|
||||||
if (!compiler_make_closure(c, co, 0))
|
if (!compiler_make_closure(c, co, 0))
|
||||||
goto error;
|
goto error;
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
Py_XDECREF(tmp);
|
|
||||||
|
|
||||||
VISIT(c, expr, outermost_iter);
|
VISIT(c, expr, outermost_iter);
|
||||||
ADDOP(c, GET_ITER);
|
ADDOP(c, GET_ITER);
|
||||||
|
@ -2994,7 +2980,6 @@ error_in_scope:
|
||||||
compiler_exit_scope(c);
|
compiler_exit_scope(c);
|
||||||
error:
|
error:
|
||||||
Py_XDECREF(co);
|
Py_XDECREF(co);
|
||||||
Py_XDECREF(tmp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,8 +87,10 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
|
||||||
3102 (__file__ points to source file)
|
3102 (__file__ points to source file)
|
||||||
Python 3.0a4: 3110 (WITH_CLEANUP optimization).
|
Python 3.0a4: 3110 (WITH_CLEANUP optimization).
|
||||||
Python 3.0a5: 3130 (lexical exception stacking, including POP_EXCEPT)
|
Python 3.0a5: 3130 (lexical exception stacking, including POP_EXCEPT)
|
||||||
|
Python 3.1a0: 3140 (optimize list, set and dict comprehensions:
|
||||||
|
change LIST_APPEND and SET_ADD, add MAP_ADD)
|
||||||
*/
|
*/
|
||||||
#define MAGIC (3130 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
#define MAGIC (3140 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
||||||
|
|
||||||
/* Magic word as global; note that _PyImport_Init() can change the
|
/* Magic word as global; note that _PyImport_Init() can change the
|
||||||
value of this global to accommodate for alterations of how the
|
value of this global to accommodate for alterations of how the
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue