Issue #22557: Now importing already imported modules is up to 2.5 times faster.

This commit is contained in:
Serhiy Storchaka 2016-08-02 22:51:21 +03:00
parent cde03fa038
commit 133138a284
6 changed files with 244 additions and 252 deletions

View file

@ -139,6 +139,7 @@ static int maybe_call_line_trace(Py_tracefunc, PyObject *,
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 throwflag)
}
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);
Py_DECREF(level);
Py_DECREF(from);
if (args == NULL) {
Py_DECREF(func);
STACKADJ(-1);
goto error;
}
PyObject *fromlist = POP();
PyObject *level = TOP();
PyObject *res;
READ_TIMESTAMP(intr0);
res = PyEval_CallObject(func, args);
res = import_name(f, name, fromlist, level);
Py_DECREF(level);
Py_DECREF(fromlist);
READ_TIMESTAMP(intr1);
Py_DECREF(args);
Py_DECREF(func);
SET_TOP(res);
if (res == NULL)
goto error;
@ -5158,6 +5137,50 @@ cmp_outcome(int op, PyObject *v, PyObject *w)
return v;
}
static PyObject *
import_name(PyFrameObject *f, PyObject *name, PyObject *fromlist, PyObject *level)
{
_Py_IDENTIFIER(__import__);
PyObject *import_func, *args, *res;
import_func = _PyDict_GetItemId(f->f_builtins, &PyId___import__);
if (import_func == NULL) {
PyErr_SetString(PyExc_ImportError, "__import__ not found");
return NULL;
}
/* Fast path for not overloaded __import__. */
if (import_func == PyThreadState_GET()->interp->import_func) {
int ilevel = _PyLong_AsInt(level);
if (ilevel == -1 && PyErr_Occurred()) {
return NULL;
}
res = PyImport_ImportModuleLevelObject(
name,
f->f_globals,
f->f_locals == NULL ? Py_None : f->f_locals,
fromlist,
ilevel);
return res;
}
Py_INCREF(import_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(import_func);
return NULL;
}
res = PyEval_CallObject(import_func, args);
Py_DECREF(args);
Py_DECREF(import_func);
return res;
}
static PyObject *
import_from(PyObject *v, PyObject *name)
{