diff options
Diffstat (limited to 'Python/ceval.c')
| -rw-r--r-- | Python/ceval.c | 728 | 
1 files changed, 353 insertions, 375 deletions
| diff --git a/Python/ceval.c b/Python/ceval.c index f0ea7c9..870d19d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -136,8 +136,6 @@ static PyObject * import_from(PyObject *, PyObject *);  static int import_all_from(PyObject *, PyObject *);  static void format_exc_check_arg(PyObject *, const char *, PyObject *);  static void format_exc_unbound(PyCodeObject *co, int oparg); -static PyObject * unicode_concatenate(PyObject *, PyObject *, -                                      PyFrameObject *, unsigned char *);  static PyObject * special_lookup(PyObject *, char *, PyObject **);  #define NAME_ERROR_MSG \ @@ -491,7 +489,6 @@ static struct {  } pendingcalls[NPENDINGCALLS];  static int pendingfirst = 0;  static int pendinglast = 0; -static char pendingbusy = 0;  int  Py_AddPendingCall(int (*func)(void *), void *arg) @@ -538,6 +535,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg)  int  Py_MakePendingCalls(void)  { +    static int busy = 0;      int i;      int r = 0; @@ -552,9 +550,9 @@ Py_MakePendingCalls(void)      if (main_thread && PyThread_get_thread_ident() != main_thread)          return 0;      /* don't perform recursive pending calls */ -    if (pendingbusy) +    if (busy)          return 0; -    pendingbusy = 1; +    busy = 1;      /* perform a bounded number of calls, in case of recursion */      for (i=0; i<NPENDINGCALLS; i++) {          int j; @@ -583,7 +581,7 @@ Py_MakePendingCalls(void)          if (r)              break;      } -    pendingbusy = 0; +    busy = 0;      return r;  } @@ -749,6 +747,9 @@ enum why_code {          WHY_SILENCED =  0x0080  /* Exception silenced by 'with' */  }; +static void save_exc_state(PyThreadState *, PyFrameObject *); +static void swap_exc_state(PyThreadState *, PyFrameObject *); +static void restore_and_clear_exc_state(PyThreadState *, PyFrameObject *);  static enum why_code do_raise(PyObject *, PyObject *);  static int unpack_iterable(PyObject *, int, int, PyObject **); @@ -817,10 +818,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)      unsigned char *first_instr;      PyObject *names;      PyObject *consts; -#if defined(Py_DEBUG) || defined(LLTRACE) -    /* Make it easier to find out where we are with a debugger */ -    char *filename; -#endif  /* Computed GOTOs, or         the-optimization-commonly-but-improperly-known-as-"threaded code" @@ -1114,59 +1111,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)          Py_XDECREF(traceback); \      } -#define SAVE_EXC_STATE() \ -    { \ -        PyObject *type, *value, *traceback; \ -        Py_XINCREF(tstate->exc_type); \ -        Py_XINCREF(tstate->exc_value); \ -        Py_XINCREF(tstate->exc_traceback); \ -        type = f->f_exc_type; \ -        value = f->f_exc_value; \ -        traceback = f->f_exc_traceback; \ -        f->f_exc_type = tstate->exc_type; \ -        f->f_exc_value = tstate->exc_value; \ -        f->f_exc_traceback = tstate->exc_traceback; \ -        Py_XDECREF(type); \ -        Py_XDECREF(value); \ -        Py_XDECREF(traceback); \ -    } - -#define SWAP_EXC_STATE() \ -    { \ -        PyObject *tmp; \ -        tmp = tstate->exc_type; \ -        tstate->exc_type = f->f_exc_type; \ -        f->f_exc_type = tmp; \ -        tmp = tstate->exc_value; \ -        tstate->exc_value = f->f_exc_value; \ -        f->f_exc_value = tmp; \ -        tmp = tstate->exc_traceback; \ -        tstate->exc_traceback = f->f_exc_traceback; \ -        f->f_exc_traceback = tmp; \ -    } - -#define RESTORE_AND_CLEAR_EXC_STATE() \ -    { \ -        PyObject *type, *value, *tb; \ -        type = tstate->exc_type; \ -        value = tstate->exc_value; \ -        tb = tstate->exc_traceback; \ -        tstate->exc_type = f->f_exc_type; \ -        tstate->exc_value = f->f_exc_value; \ -        tstate->exc_traceback = f->f_exc_traceback; \ -        f->f_exc_type = NULL; \ -        f->f_exc_value = NULL; \ -        f->f_exc_traceback = NULL; \ -        Py_XDECREF(type); \ -        Py_XDECREF(value); \ -        Py_XDECREF(tb); \ -    } -  /* Start of code */ -    if (f == NULL) -        return NULL; -      /* push frame */      if (Py_EnterRecursiveCall(""))          return NULL; @@ -1240,28 +1186,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)              /* We were in an except handler when we left,                 restore the exception state which was put aside                 (see YIELD_VALUE). */ -            SWAP_EXC_STATE(); -        } -        else { -            SAVE_EXC_STATE(); +            swap_exc_state(tstate, f);          } +        else +            save_exc_state(tstate, f);      }  #ifdef LLTRACE      lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL;  #endif -#if defined(Py_DEBUG) || defined(LLTRACE) -    { -        PyObject *error_type, *error_value, *error_traceback; -        PyErr_Fetch(&error_type, &error_value, &error_traceback); -        filename = _PyUnicode_AsString(co->co_filename); -        if (filename == NULL && tstate->overflowed) { -            /* maximum recursion depth exceeded */ -            goto exit_eval_frame; -        } -        PyErr_Restore(error_type, error_value, error_traceback); -    } -#endif      why = WHY_NOT;      err = 0; @@ -1412,8 +1345,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)             x to NULL, err to nonzero, or why to anything but WHY_NOT,             and that no operation that succeeds does this! */ -        /* case STOP_CODE: this is an error! */ -          TARGET(NOP)              FAST_DISPATCH(); @@ -1576,17 +1507,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)          TARGET(BINARY_ADD)              w = POP();              v = TOP(); -            if (PyUnicode_CheckExact(v) && -                     PyUnicode_CheckExact(w)) { -                x = unicode_concatenate(v, w, f, next_instr); -                /* unicode_concatenate consumed the ref to v */ -                goto skip_decref_vx; -            } -            else { -                x = PyNumber_Add(v, w); -            } +            x = PyNumber_Add(v, w);              Py_DECREF(v); -          skip_decref_vx:              Py_DECREF(w);              SET_TOP(x);              if (x != NULL) DISPATCH(); @@ -1737,17 +1659,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)          TARGET(INPLACE_ADD)              w = POP();              v = TOP(); -            if (PyUnicode_CheckExact(v) && -                     PyUnicode_CheckExact(w)) { -                x = unicode_concatenate(v, w, f, next_instr); -                /* unicode_concatenate consumed the ref to v */ -                goto skip_decref_v; -            } -            else { -                x = PyNumber_InPlaceAdd(v, w); -            } +            x = PyNumber_InPlaceAdd(v, w);              Py_DECREF(v); -          skip_decref_v:              Py_DECREF(w);              SET_TOP(x);              if (x != NULL) DISPATCH(); @@ -2121,7 +2034,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)                  /* Inline the PyDict_GetItem() calls.                     WARNING: this is an extreme speed hack.                     Do not try this at home. */ -                Py_hash_t hash = ((PyUnicodeObject *)w)->hash; +                Py_hash_t hash = ((PyASCIIObject *)w)->hash;                  if (hash != -1) {                      PyDictObject *d;                      PyDictEntry *e; @@ -2725,7 +2638,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)                  Py_DECREF(*pfunc);                  *pfunc = self;                  na++; -                n++; +                /* n++; */              } else                  Py_INCREF(func);              sp = stack_pointer; @@ -3049,9 +2962,9 @@ fast_yield:                  break;          if (i == f->f_iblock)              /* We did not create this exception. */ -            RESTORE_AND_CLEAR_EXC_STATE() +            restore_and_clear_exc_state(tstate, f);          else -            SWAP_EXC_STATE() +            swap_exc_state(tstate, f);      }      if (tstate->use_tracing) { @@ -3081,7 +2994,7 @@ fast_yield:                                  PyTrace_RETURN, retval)) {                  Py_XDECREF(retval);                  retval = NULL; -                why = WHY_EXCEPTION; +                /* why = WHY_EXCEPTION; */              }          }      } @@ -3094,6 +3007,154 @@ exit_eval_frame:      return retval;  } +static void +format_missing(const char *kind, PyCodeObject *co, PyObject *names) +{ +    int err; +    Py_ssize_t len = PyList_GET_SIZE(names); +    PyObject *name_str, *comma, *tail, *tmp; + +    assert(PyList_CheckExact(names)); +    assert(len >= 1); +    /* Deal with the joys of natural language. */ +    switch (len) { +    case 1: +        name_str = PyList_GET_ITEM(names, 0); +        Py_INCREF(name_str); +        break; +    case 2: +        name_str = PyUnicode_FromFormat("%U and %U", +                                        PyList_GET_ITEM(names, len - 2), +                                        PyList_GET_ITEM(names, len - 1)); +        break; +    default: +        tail = PyUnicode_FromFormat(", %U, and %U", +                                    PyList_GET_ITEM(names, len - 2), +                                    PyList_GET_ITEM(names, len - 1)); +        /* Chop off the last two objects in the list. This shouldn't actually +           fail, but we can't be too careful. */ +        err = PyList_SetSlice(names, len - 2, len, NULL); +        if (err == -1) { +            Py_DECREF(tail); +            return; +        } +        /* Stitch everything up into a nice comma-separated list. */ +        comma = PyUnicode_FromString(", "); +        if (comma == NULL) { +            Py_DECREF(tail); +            return; +        } +        tmp = PyUnicode_Join(comma, names); +        Py_DECREF(comma); +        if (tmp == NULL) { +            Py_DECREF(tail); +            return; +        } +        name_str = PyUnicode_Concat(tmp, tail); +        Py_DECREF(tmp); +        Py_DECREF(tail); +        break; +    } +    if (name_str == NULL) +        return; +    PyErr_Format(PyExc_TypeError, +                 "%U() missing %i required %s argument%s: %U", +                 co->co_name, +                 len, +                 kind, +                 len == 1 ? "" : "s", +                 name_str); +    Py_DECREF(name_str); +} + +static void +missing_arguments(PyCodeObject *co, int missing, int defcount, +                  PyObject **fastlocals) +{ +    int i, j = 0; +    int start, end; +    int positional = defcount != -1; +    const char *kind = positional ? "positional" : "keyword-only"; +    PyObject *missing_names; + +    /* Compute the names of the arguments that are missing. */ +    missing_names = PyList_New(missing); +    if (missing_names == NULL) +        return; +    if (positional) { +        start = 0; +        end = co->co_argcount - defcount; +    } +    else { +        start = co->co_argcount; +        end = start + co->co_kwonlyargcount; +    } +    for (i = start; i < end; i++) { +        if (GETLOCAL(i) == NULL) { +            PyObject *raw = PyTuple_GET_ITEM(co->co_varnames, i); +            PyObject *name = PyObject_Repr(raw); +            if (name == NULL) { +                Py_DECREF(missing_names); +                return; +            } +            PyList_SET_ITEM(missing_names, j++, name); +        } +    } +    assert(j == missing); +    format_missing(kind, co, missing_names); +    Py_DECREF(missing_names); +} + +static void +too_many_positional(PyCodeObject *co, int given, int defcount, PyObject **fastlocals) +{ +    int plural; +    int kwonly_given = 0; +    int i; +    PyObject *sig, *kwonly_sig; + +    assert((co->co_flags & CO_VARARGS) == 0); +    /* Count missing keyword-only args. */ +    for (i = co->co_argcount; i < co->co_argcount + co->co_kwonlyargcount; i++) +        if (GETLOCAL(i) != NULL) +            kwonly_given++; +    if (defcount) { +        int atleast = co->co_argcount - defcount; +        plural = 1; +        sig = PyUnicode_FromFormat("from %d to %d", atleast, co->co_argcount); +    } +    else { +        plural = co->co_argcount != 1; +        sig = PyUnicode_FromFormat("%d", co->co_argcount); +    } +    if (sig == NULL) +        return; +    if (kwonly_given) { +        const char *format = " positional argument%s (and %d keyword-only argument%s)"; +        kwonly_sig = PyUnicode_FromFormat(format, given != 1 ? "s" : "", kwonly_given, +                                              kwonly_given != 1 ? "s" : ""); +        if (kwonly_sig == NULL) { +            Py_DECREF(sig); +            return; +        } +    } +    else { +        /* This will not fail. */ +        kwonly_sig = PyUnicode_FromString(""); +        assert(kwonly_sig != NULL); +    } +    PyErr_Format(PyExc_TypeError, +                 "%U() takes %U positional argument%s but %d%U %s given", +                 co->co_name, +                 sig, +                 plural ? "s" : "", +                 given, +                 kwonly_sig, +                 given == 1 && !kwonly_given ? "was" : "were"); +    Py_DECREF(sig); +    Py_DECREF(kwonly_sig); +} +  /* This is gonna seem *real weird*, but if you put some other code between     PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust     the test in the if statements in Misc/gdbinit (pystack and pystackv). */ @@ -3110,6 +3171,9 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,      PyThreadState *tstate = PyThreadState_GET();      PyObject *x, *u;      int total_args = co->co_argcount + co->co_kwonlyargcount; +    int i; +    int n = argcount; +    PyObject *kwdict = NULL;      if (globals == NULL) {          PyErr_SetString(PyExc_SystemError, @@ -3126,212 +3190,153 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,      fastlocals = f->f_localsplus;      freevars = f->f_localsplus + co->co_nlocals; -    if (total_args || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { -        int i; -        int n = argcount; -        PyObject *kwdict = NULL; -        if (co->co_flags & CO_VARKEYWORDS) { -            kwdict = PyDict_New(); -            if (kwdict == NULL) -                goto fail; -            i = total_args; -            if (co->co_flags & CO_VARARGS) -                i++; -            SETLOCAL(i, kwdict); -        } -        if (argcount > co->co_argcount) { -            if (!(co->co_flags & CO_VARARGS)) { -                PyErr_Format(PyExc_TypeError, -                    "%U() takes %s %d " -                    "positional argument%s (%d given)", -                    co->co_name, -                    defcount ? "at most" : "exactly", -                    co->co_argcount, -                    co->co_argcount == 1 ? "" : "s", -                    argcount + kwcount); -                goto fail; -            } -            n = co->co_argcount; -        } -        for (i = 0; i < n; i++) { +    /* Parse arguments. */ +    if (co->co_flags & CO_VARKEYWORDS) { +        kwdict = PyDict_New(); +        if (kwdict == NULL) +            goto fail; +        i = total_args; +        if (co->co_flags & CO_VARARGS) +            i++; +        SETLOCAL(i, kwdict); +    } +    if (argcount > co->co_argcount) +        n = co->co_argcount; +    for (i = 0; i < n; i++) { +        x = args[i]; +        Py_INCREF(x); +        SETLOCAL(i, x); +    } +    if (co->co_flags & CO_VARARGS) { +        u = PyTuple_New(argcount - n); +        if (u == NULL) +            goto fail; +        SETLOCAL(total_args, u); +        for (i = n; i < argcount; i++) {              x = args[i];              Py_INCREF(x); -            SETLOCAL(i, x); +            PyTuple_SET_ITEM(u, i-n, x);          } -        if (co->co_flags & CO_VARARGS) { -            u = PyTuple_New(argcount - n); -            if (u == NULL) -                goto fail; -            SETLOCAL(total_args, u); -            for (i = n; i < argcount; i++) { -                x = args[i]; -                Py_INCREF(x); -                PyTuple_SET_ITEM(u, i-n, x); -            } +    } +    for (i = 0; i < kwcount; i++) { +        PyObject **co_varnames; +        PyObject *keyword = kws[2*i]; +        PyObject *value = kws[2*i + 1]; +        int j; +        if (keyword == NULL || !PyUnicode_Check(keyword)) { +            PyErr_Format(PyExc_TypeError, +                         "%U() keywords must be strings", +                         co->co_name); +            goto fail;          } -        for (i = 0; i < kwcount; i++) { -            PyObject **co_varnames; -            PyObject *keyword = kws[2*i]; -            PyObject *value = kws[2*i + 1]; -            int j; -            if (keyword == NULL || !PyUnicode_Check(keyword)) { -                PyErr_Format(PyExc_TypeError, -                    "%U() keywords must be strings", -                    co->co_name); -                goto fail; -            } -            /* Speed hack: do raw pointer compares. As names are -               normally interned this should almost always hit. */ -            co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; -            for (j = 0; j < total_args; j++) { -                PyObject *nm = co_varnames[j]; -                if (nm == keyword) -                    goto kw_found; -            } -            /* Slow fallback, just in case */ -            for (j = 0; j < total_args; j++) { -                PyObject *nm = co_varnames[j]; -                int cmp = PyObject_RichCompareBool( -                    keyword, nm, Py_EQ); -                if (cmp > 0) -                    goto kw_found; -                else if (cmp < 0) -                    goto fail; -            } -            if (j >= total_args && kwdict == NULL) { -                PyErr_Format(PyExc_TypeError, -                             "%U() got an unexpected " -                             "keyword argument '%S'", -                             co->co_name, -                             keyword); +        /* Speed hack: do raw pointer compares. As names are +           normally interned this should almost always hit. */ +        co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; +        for (j = 0; j < total_args; j++) { +            PyObject *nm = co_varnames[j]; +            if (nm == keyword) +                goto kw_found; +        } +        /* Slow fallback, just in case */ +        for (j = 0; j < total_args; j++) { +            PyObject *nm = co_varnames[j]; +            int cmp = PyObject_RichCompareBool( +                keyword, nm, Py_EQ); +            if (cmp > 0) +                goto kw_found; +            else if (cmp < 0)                  goto fail; -            } -            PyDict_SetItem(kwdict, keyword, value); -            continue; -          kw_found: -            if (GETLOCAL(j) != NULL) { -                PyErr_Format(PyExc_TypeError, +        } +        if (j >= total_args && kwdict == NULL) { +            PyErr_Format(PyExc_TypeError, +                         "%U() got an unexpected " +                         "keyword argument '%S'", +                         co->co_name, +                         keyword); +            goto fail; +        } +        PyDict_SetItem(kwdict, keyword, value); +        continue; +      kw_found: +        if (GETLOCAL(j) != NULL) { +            PyErr_Format(PyExc_TypeError,                           "%U() got multiple " -                         "values for keyword " -                         "argument '%S'", +                         "values for argument '%S'",                           co->co_name,                           keyword); -                goto fail; -            } -            Py_INCREF(value); -            SETLOCAL(j, value); +            goto fail;          } -        if (co->co_kwonlyargcount > 0) { -            for (i = co->co_argcount; i < total_args; i++) { -                PyObject *name; -                if (GETLOCAL(i) != NULL) -                    continue; -                name = PyTuple_GET_ITEM(co->co_varnames, i); -                if (kwdefs != NULL) { -                    PyObject *def = PyDict_GetItem(kwdefs, name); -                    if (def) { -                        Py_INCREF(def); -                        SETLOCAL(i, def); -                        continue; -                    } -                } -                PyErr_Format(PyExc_TypeError, -                    "%U() needs keyword-only argument %S", -                    co->co_name, name); -                goto fail; -            } +        Py_INCREF(value); +        SETLOCAL(j, value); +    } +    if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { +        too_many_positional(co, argcount, defcount, fastlocals); +        goto fail; +    } +    if (argcount < co->co_argcount) { +        int m = co->co_argcount - defcount; +        int missing = 0; +        for (i = argcount; i < m; i++) +            if (GETLOCAL(i) == NULL) +                missing++; +        if (missing) { +            missing_arguments(co, missing, defcount, fastlocals); +            goto fail;          } -        if (argcount < co->co_argcount) { -            int m = co->co_argcount - defcount; -            for (i = argcount; i < m; i++) { -                if (GETLOCAL(i) == NULL) { -                    int j, given = 0; -                    for (j = 0; j < co->co_argcount; j++) -                        if (GETLOCAL(j)) -                            given++; -                    PyErr_Format(PyExc_TypeError, -                        "%U() takes %s %d " -                        "argument%s " -                        "(%d given)", -                        co->co_name, -                        ((co->co_flags & CO_VARARGS) || -                         defcount) ? "at least" -                                   : "exactly", -                             m, m == 1 ? "" : "s", given); -                    goto fail; -                } +        if (n > m) +            i = n - m; +        else +            i = 0; +        for (; i < defcount; i++) { +            if (GETLOCAL(m+i) == NULL) { +                PyObject *def = defs[i]; +                Py_INCREF(def); +                SETLOCAL(m+i, def);              } -            if (n > m) -                i = n - m; -            else -                i = 0; -            for (; i < defcount; i++) { -                if (GETLOCAL(m+i) == NULL) { -                    PyObject *def = defs[i]; +        } +    } +    if (co->co_kwonlyargcount > 0) { +        int missing = 0; +        for (i = co->co_argcount; i < total_args; i++) { +            PyObject *name; +            if (GETLOCAL(i) != NULL) +                continue; +            name = PyTuple_GET_ITEM(co->co_varnames, i); +            if (kwdefs != NULL) { +                PyObject *def = PyDict_GetItem(kwdefs, name); +                if (def) {                      Py_INCREF(def); -                    SETLOCAL(m+i, def); +                    SETLOCAL(i, def); +                    continue;                  }              } +            missing++; +        } +        if (missing) { +            missing_arguments(co, missing, -1, fastlocals); +            goto fail;          }      } -    else if (argcount > 0 || kwcount > 0) { -        PyErr_Format(PyExc_TypeError, -                     "%U() takes no arguments (%d given)", -                     co->co_name, -                     argcount + kwcount); -        goto fail; -    } +      /* Allocate and initialize storage for cell vars, and copy free -       vars into frame.  This isn't too efficient right now. */ -    if (PyTuple_GET_SIZE(co->co_cellvars)) { -        int i, j, nargs, found; -        Py_UNICODE *cellname, *argname; +       vars into frame. */ +    for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) {          PyObject *c; - -        nargs = total_args; -        if (co->co_flags & CO_VARARGS) -            nargs++; -        if (co->co_flags & CO_VARKEYWORDS) -            nargs++; - -        /* Initialize each cell var, taking into account -           cell vars that are initialized from arguments. - -           Should arrange for the compiler to put cellvars -           that are arguments at the beginning of the cellvars -           list so that we can march over it more efficiently? -        */ -        for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) { -            cellname = PyUnicode_AS_UNICODE( -                PyTuple_GET_ITEM(co->co_cellvars, i)); -            found = 0; -            for (j = 0; j < nargs; j++) { -                argname = PyUnicode_AS_UNICODE( -                    PyTuple_GET_ITEM(co->co_varnames, j)); -                if (Py_UNICODE_strcmp(cellname, argname) == 0) { -                    c = PyCell_New(GETLOCAL(j)); -                    if (c == NULL) -                        goto fail; -                    GETLOCAL(co->co_nlocals + i) = c; -                    found = 1; -                    break; -                } -            } -            if (found == 0) { -                c = PyCell_New(NULL); -                if (c == NULL) -                    goto fail; -                SETLOCAL(co->co_nlocals + i, c); -            } -        } +        int arg; +        /* Possibly account for the cell variable being an argument. */ +        if (co->co_cell2arg != NULL && +            (arg = co->co_cell2arg[i]) != CO_CELL_NOT_AN_ARG) +            c = PyCell_New(GETLOCAL(arg)); +        else +            c = PyCell_New(NULL); +        if (c == NULL) +            goto fail; +        SETLOCAL(co->co_nlocals + i, c);      } -    if (PyTuple_GET_SIZE(co->co_freevars)) { -        int i; -        for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) { -            PyObject *o = PyTuple_GET_ITEM(closure, i); -            Py_INCREF(o); -            freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o; -        } +    for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) { +        PyObject *o = PyTuple_GET_ITEM(closure, i); +        Py_INCREF(o); +        freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;      }      if (co->co_flags & CO_GENERATOR) { @@ -3377,6 +3382,60 @@ special_lookup(PyObject *o, char *meth, PyObject **cache)  } +/* These 3 functions deal with the exception state of generators. */ + +static void +save_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ +    PyObject *type, *value, *traceback; +    Py_XINCREF(tstate->exc_type); +    Py_XINCREF(tstate->exc_value); +    Py_XINCREF(tstate->exc_traceback); +    type = f->f_exc_type; +    value = f->f_exc_value; +    traceback = f->f_exc_traceback; +    f->f_exc_type = tstate->exc_type; +    f->f_exc_value = tstate->exc_value; +    f->f_exc_traceback = tstate->exc_traceback; +    Py_XDECREF(type); +    Py_XDECREF(value); +    Py_XDECREF(traceback);  +} + +static void +swap_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ +    PyObject *tmp; +    tmp = tstate->exc_type; +    tstate->exc_type = f->f_exc_type; +    f->f_exc_type = tmp; +    tmp = tstate->exc_value; +    tstate->exc_value = f->f_exc_value; +    f->f_exc_value = tmp; +    tmp = tstate->exc_traceback; +    tstate->exc_traceback = f->f_exc_traceback; +    f->f_exc_traceback = tmp; +} + +static void +restore_and_clear_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ +    PyObject *type, *value, *tb; +    type = tstate->exc_type; +    value = tstate->exc_value; +    tb = tstate->exc_traceback; +    tstate->exc_type = f->f_exc_type; +    tstate->exc_value = f->f_exc_value; +    tstate->exc_traceback = f->f_exc_traceback; +    f->f_exc_type = NULL; +    f->f_exc_value = NULL; +    f->f_exc_traceback = NULL; +    Py_XDECREF(type); +    Py_XDECREF(value); +    Py_XDECREF(tb); +} + +  /* Logic for the raise statement (too complicated for inlining).     This *consumes* a reference count to each of its arguments. */  static enum why_code @@ -4192,7 +4251,7 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)                  if (PyErr_ExceptionMatches(PyExc_TypeError)) {                      PyErr_Format(PyExc_TypeError,                                   "%.200s%.200s argument after * " -                                 "must be a sequence, not %200s", +                                 "must be a sequence, not %.200s",                                   PyEval_GetFuncName(func),                                   PyEval_GetFuncDesc(func),                                   stararg->ob_type->tp_name); @@ -4377,7 +4436,8 @@ import_all_from(PyObject *locals, PyObject *v)          }          if (skip_leading_underscores &&              PyUnicode_Check(name) && -            PyUnicode_AS_UNICODE(name)[0] == '_') +            PyUnicode_READY(name) != -1 && +            PyUnicode_READ_CHAR(name, 0) == '_')          {              Py_DECREF(name);              continue; @@ -4435,88 +4495,6 @@ format_exc_unbound(PyCodeObject *co, int oparg)      }  } -static PyObject * -unicode_concatenate(PyObject *v, PyObject *w, -                   PyFrameObject *f, unsigned char *next_instr) -{ -    /* This function implements 'variable += expr' when both arguments -       are (Unicode) strings. */ -    Py_ssize_t v_len = PyUnicode_GET_SIZE(v); -    Py_ssize_t w_len = PyUnicode_GET_SIZE(w); -    Py_ssize_t new_len = v_len + w_len; -    if (new_len < 0) { -        PyErr_SetString(PyExc_OverflowError, -                        "strings are too large to concat"); -        return NULL; -    } - -    if (Py_REFCNT(v) == 2) { -        /* In the common case, there are 2 references to the value -         * stored in 'variable' when the += is performed: one on the -         * value stack (in 'v') and one still stored in the -         * 'variable'.  We try to delete the variable now to reduce -         * the refcnt to 1. -         */ -        switch (*next_instr) { -        case STORE_FAST: -        { -            int oparg = PEEKARG(); -            PyObject **fastlocals = f->f_localsplus; -            if (GETLOCAL(oparg) == v) -                SETLOCAL(oparg, NULL); -            break; -        } -        case STORE_DEREF: -        { -            PyObject **freevars = (f->f_localsplus + -                                   f->f_code->co_nlocals); -            PyObject *c = freevars[PEEKARG()]; -            if (PyCell_GET(c) == v) -                PyCell_Set(c, NULL); -            break; -        } -        case STORE_NAME: -        { -            PyObject *names = f->f_code->co_names; -            PyObject *name = GETITEM(names, PEEKARG()); -            PyObject *locals = f->f_locals; -            if (PyDict_CheckExact(locals) && -                PyDict_GetItem(locals, name) == v) { -                if (PyDict_DelItem(locals, name) != 0) { -                    PyErr_Clear(); -                } -            } -            break; -        } -        } -    } - -    if (Py_REFCNT(v) == 1 && !PyUnicode_CHECK_INTERNED(v)) { -        /* Now we own the last reference to 'v', so we can resize it -         * in-place. -         */ -        if (PyUnicode_Resize(&v, new_len) != 0) { -            /* XXX if PyUnicode_Resize() fails, 'v' has been -             * deallocated so it cannot be put back into -             * 'variable'.  The MemoryError is raised when there -             * is no value in 'variable', which might (very -             * remotely) be a cause of incompatibilities. -             */ -            return NULL; -        } -        /* copy 'w' into the newly allocated area of 'v' */ -        memcpy(PyUnicode_AS_UNICODE(v) + v_len, -               PyUnicode_AS_UNICODE(w), w_len*sizeof(Py_UNICODE)); -        return v; -    } -    else { -        /* When in-place resizing is not an option. */ -        w = PyUnicode_Concat(v, w); -        Py_DECREF(v); -        return w; -    } -} -  #ifdef DYNAMIC_EXECUTION_PROFILE  static PyObject * | 
