diff -r e3164c9edb0b Python/ceval.c --- a/Python/ceval.c Mon Jun 27 21:39:12 2016 +0300 +++ b/Python/ceval.c Mon Jun 27 23:17:54 2016 +0300 @@ -139,6 +139,7 @@ static int maybe_call_line_trace(Py_trac PyThreadState *, PyFrameObject *, int *, int *, int *); static PyObject * cmp_outcome(int, PyObject *, PyObject *); +static PyObject * import_name(PyFrameObject *, PyObject *, PyObject *, PyObject *); static PyObject * import_from(PyObject *, PyObject *); static int import_all_from(PyObject *, PyObject *); static void format_exc_check_arg(PyObject *, const char *, PyObject *); @@ -2808,37 +2809,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int } TARGET(IMPORT_NAME) { - _Py_IDENTIFIER(__import__); PyObject *name = GETITEM(names, oparg); - PyObject *func = _PyDict_GetItemId(f->f_builtins, &PyId___import__); - PyObject *from, *level, *args, *res; - if (func == NULL) { - PyErr_SetString(PyExc_ImportError, - "__import__ not found"); - goto error; - } - Py_INCREF(func); - from = POP(); - level = TOP(); - args = PyTuple_Pack(5, - name, - f->f_globals, - f->f_locals == NULL ? - Py_None : f->f_locals, - from, - level); + PyObject *fromlist = POP(); + PyObject *level = TOP(); + PyObject *res; + READ_TIMESTAMP(intr0); + res = import_name(f, name, fromlist, level); Py_DECREF(level); - Py_DECREF(from); - if (args == NULL) { - Py_DECREF(func); - STACKADJ(-1); - goto error; - } - READ_TIMESTAMP(intr0); - res = PyEval_CallObject(func, args); + Py_DECREF(fromlist); READ_TIMESTAMP(intr1); - Py_DECREF(args); - Py_DECREF(func); SET_TOP(res); if (res == NULL) goto error; @@ -5159,6 +5138,97 @@ cmp_outcome(int op, PyObject *v, PyObjec } static PyObject * +import_name(PyFrameObject *f, PyObject *name, PyObject *fromlist, PyObject *level) +{ + _Py_IDENTIFIER(__import__); + static PyObject *orig_func = NULL; + PyObject *func; + PyObject *args, *res; + + if (orig_func == NULL) { + orig_func = _PyDict_GetItemId( + PyThreadState_GET()->interp->builtins_copy, + &PyId___import__); + if (orig_func == NULL) { + PyErr_Clear(); + } + } + + func = _PyDict_GetItemId(f->f_builtins, &PyId___import__); + if (func == NULL) { + PyErr_SetString(PyExc_ImportError, "__import__ not found"); + return NULL; + } + + /* Fast path for not overloaded __import__. */ + if (func == orig_func) { + int ilevel = _PyLong_AsInt(level); + if (ilevel == -1 && PyErr_Occurred()) { + return NULL; + } + /* Fast path for simple import of the module which already is in + sys.modules. */ + if (fromlist == Py_None && ilevel == 0 && PyUnicode_Check(name)) { + res = PyDict_GetItem(PyImport_GetModuleDict(), name); + if (res == NULL) { + PyErr_Clear(); + } + else if (res != Py_None) { + Py_ssize_t dot = PyUnicode_FindChar(name, '.', + 0, PyUnicode_GET_LENGTH(name), 1); + if (dot == -2) { + PyErr_Clear(); + } + else if (dot == -1) { + Py_INCREF(res); + return res; + } + else { + PyObject *pkgname = PyUnicode_Substring(name, 0, dot); + if (pkgname == NULL) { + PyErr_Clear(); + } + else { + res = PyDict_GetItem(PyImport_GetModuleDict(), pkgname); + if (res == NULL) { + PyErr_Clear(); + } + else if (res != Py_None) { + Py_INCREF(res); + return res; + } + } + } + } + } + + res = PyImport_ImportModuleLevelObject( + name, + f->f_globals, + f->f_locals == NULL ? Py_None : f->f_locals, + fromlist, + ilevel); + return res; + } + + Py_INCREF(func); + args = PyTuple_Pack(5, + name, + f->f_globals, + f->f_locals == NULL ? Py_None : f->f_locals, + fromlist, + level); + if (args == NULL) { + Py_DECREF(func); + return NULL; + } + res = PyEval_CallObject(func, args); + Py_DECREF(args); + Py_DECREF(func); + return res; +} + +static PyObject * import_from(PyObject *v, PyObject *name) { PyObject *x;