Two more patches by Tony Lownds (SF# 1607548).

(1)
Combines the code paths for MAKE_FUNCTION and MAKE_CLOSURE.
Fixes a crash where functions with closures and either annotations or
keyword-only arguments result in MAKE_CLOSURE, but only
MAKE_FUNCTION has the code to handle annotations or keyword-only
arguments.
Includes enough tests to trigger the bug.

(2)
Change peepholer to not bail in the presence of EXTENDED_ARG +
MAKE_FUNCTION.
Enforce the natural 16-bit limit of annotations in compile.c.

Also update Misc/NEWS with the "input = raw_input" change.
This commit is contained in:
Guido van Rossum 2007-02-26 21:23:50 +00:00
parent f74225d63b
commit 0240b92a6c
7 changed files with 68 additions and 38 deletions

View file

@ -2236,6 +2236,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
break;
}
case MAKE_CLOSURE:
case MAKE_FUNCTION:
{
int posdefaults = oparg & 0xff;
@ -2245,6 +2246,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
v = POP(); /* code object */
x = PyFunction_New(v, f->f_globals);
Py_DECREF(v);
if (x != NULL && opcode == MAKE_CLOSURE) {
v = POP();
err = PyFunction_SetClosure(x, v);
Py_DECREF(v);
}
if (x != NULL && num_annotations > 0) {
Py_ssize_t name_ix;
@ -2308,34 +2315,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
break;
}
case MAKE_CLOSURE:
{
v = POP(); /* code object */
x = PyFunction_New(v, f->f_globals);
Py_DECREF(v);
if (x != NULL) {
v = POP();
err = PyFunction_SetClosure(x, v);
Py_DECREF(v);
}
if (x != NULL && oparg > 0) {
v = PyTuple_New(oparg);
if (v == NULL) {
Py_DECREF(x);
x = NULL;
break;
}
while (--oparg >= 0) {
w = POP();
PyTuple_SET_ITEM(v, oparg, w);
}
err = PyFunction_SetDefaults(x, v);
Py_DECREF(v);
}
PUSH(x);
break;
}
case BUILD_SLICE:
if (oparg == 3)
w = POP();

View file

@ -836,6 +836,8 @@ opcode_stack_effect(int opcode, int oparg)
return -NARGS(oparg)-2;
case MAKE_FUNCTION:
return -NARGS(oparg) - ((oparg >> 16) & 0xffff);
case MAKE_CLOSURE:
return -1 - NARGS(oparg) - ((oparg >> 16) & 0xffff);
#undef NARGS
case BUILD_SLICE:
if (oparg == 3)
@ -843,8 +845,6 @@ opcode_stack_effect(int opcode, int oparg)
else
return -1;
case MAKE_CLOSURE:
return -oparg;
case LOAD_CLOSURE:
return 1;
case LOAD_DEREF:
@ -1367,8 +1367,12 @@ static int
compiler_visit_annotations(struct compiler *c, arguments_ty args,
expr_ty returns)
{
/* push arg annotations and a list of the argument names. return the #
of items pushed. this is out-of-order wrt the source code. */
/* Push arg annotations and a list of the argument names. Return the #
of items pushed. The expressions are evaluated out-of-order wrt the
source code.
More than 2^16-1 annotations is a SyntaxError. Returns -1 on error.
*/
static identifier return_str;
PyObject *names;
int len;
@ -1399,6 +1403,12 @@ compiler_visit_annotations(struct compiler *c, arguments_ty args,
}
len = PyList_GET_SIZE(names);
if (len > 65534) {
/* len must fit in 16 bits, and len is incremented below */
PyErr_SetString(PyExc_SyntaxError,
"too many annotations");
goto error;
}
if (len) {
/* convert names to a tuple and place on stack */
PyObject *elt;
@ -1449,6 +1459,9 @@ compiler_function(struct compiler *c, stmt_ty s)
if (args->defaults)
VISIT_SEQ(c, expr, args->defaults);
num_annotations = compiler_visit_annotations(c, args, returns);
if (num_annotations < 0)
return 0;
assert((num_annotations & 0xFFFF) == num_annotations);
if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s,
s->lineno))

View file

@ -261,10 +261,12 @@ markblocks(unsigned char *code, int len)
The consts object should still be in list form to allow new constants
to be appended.
To keep the optimizer simple, it bails out (does nothing) for code
containing extended arguments or that has a length over 32,700. That
allows us to avoid overflow and sign issues. Likewise, it bails when
the lineno table has complex encoding for gaps >= 255.
To keep the optimizer simple, it bails out (does nothing) for code that
has a length over 32,700, and does not calculate extended arguments.
That allows us to avoid overflow and sign issues. Likewise, it bails when
the lineno table has complex encoding for gaps >= 255. EXTENDED_ARG can
appear before MAKE_FUNCTION; in this case both opcodes are skipped.
EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
Optimizations are restricted to simple transformations occuring within a
single basic block. All transformations keep the code size the same or
@ -535,7 +537,11 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
break;
case EXTENDED_ARG:
goto exitUnchanged;
if (codestr[i+3] != MAKE_FUNCTION)
goto exitUnchanged;
/* don't visit MAKE_FUNCTION as GETARG will be wrong */
i += 3;
break;
/* Replace RETURN LOAD_CONST None RETURN with just RETURN */
/* Remove unreachable JUMPs after RETURN */