Commits

Armin Rigo committed f26956c

Fix for 92546f437072.

Comments (0)

Files changed (2)

pypy/interpreter/baseobjspace.py

         except AttributeError:
             return self.__class__.__name__
 
-    def setbuiltinmodule(self, importname):
-        """NOT_RPYTHON. load a lazy pypy/module and put it into sys.modules"""
+    def _prepare_mixedmodule(self, importname):
+        """NOT_RPYTHON.  Load the RPython code of a lazy pypy/module and put
+        it into 'self.builtin_modules', without any further initialization.
+        """
         if '.' in importname:
             fullname = importname
             importname = fullname.rsplit('.', 1)[1]
 
         return name
 
-    def getbuiltinmodule(self, name, force_init=False):
-        w_name = self.wrap(name)
-        w_modules = self.sys.get('modules')
-        try:
-            w_mod = self.getitem(w_modules, w_name)
-        except OperationError, e:
-            if not e.match(self, self.w_KeyError):
-                raise
-        else:
-            if not force_init:
-                return w_mod
+    @jit.elidable
+    def getbuiltinmodule(self, name):
+        """Return the built-in module 'name'.  The first time it is seen,
+        it is initialized and stored in 'sys.modules'.  This function is
+        elidable by the JIT because its effect is idempotent (if you call
+        it twice with the same name, you're getting the same effect as if
+        it was only called once).
+        """
+        return self.loadbuiltinmodule(name, force_in_sys_modules=False,
+                                      force_init=False)
 
-        # If the module is a builtin but not yet imported,
-        # retrieve it and initialize it
+    def loadbuiltinmodule(self, name, force_in_sys_modules, force_init):
+        """For the importing logic.  Get the built-in module, stick it
+        into 'sys.modules' if not initialized or if force_in_sys_modules,
+        and initialize it if it was not already or if force_init.
+        """
         try:
             w_mod = self.builtin_modules[name]
         except KeyError:
                 self.w_SystemError,
                 "getbuiltinmodule() called "
                 "with non-builtin module %s", name)
-        else:
-            # Add the module to sys.modules
-            self.setitem(w_modules, w_name, w_mod)
 
-            # And initialize it
-            from pypy.interpreter.module import Module
-            if isinstance(w_mod, Module):
-                w_mod.init(self)
-            return w_mod
+        from pypy.interpreter.module import Module
+        if isinstance(w_mod, Module) and not w_mod.startup_called:
+            force_in_sys_modules = True          # not initialized so far:
+            force_init = True                    # force initialization
+
+        if force_in_sys_modules:
+            w_sys_modules = self.sys.get('modules')
+            self.setitem(w_sys_modules, self.wrap(name), w_mod)
+
+        if force_init and isinstance(w_mod, Module):
+            w_mod.init(self)
+
+        return w_mod
 
     def get_builtinmodule_to_install(self):
         """NOT_RPYTHON"""
 
     def install_mixedmodule(self, mixedname, installed_builtin_modules):
         """NOT_RPYTHON"""
-        modname = self.setbuiltinmodule(mixedname)
-        if modname:
-            assert modname not in installed_builtin_modules, (
-                "duplicate interp-level module enabled for the "
-                "app-level module %r" % (modname,))
-            installed_builtin_modules.append(modname)
+        modname = self._prepare_mixedmodule(mixedname)
+        assert modname
+        assert modname not in installed_builtin_modules, (
+            "duplicate interp-level module enabled for the "
+            "app-level module %r" % (modname,))
+        installed_builtin_modules.append(modname)
 
     def setup_builtin_modules(self):
         "NOT_RPYTHON: only for initializing the space."

pypy/module/imp/importing.py

     load_extension_module(space, filename, modulename)
 
 @jit.dont_look_inside
-def load_module(space, w_modulename, find_info, reuse=False):
+def load_module(space, w_modulename, find_info, reuse=False, force_init=False):
     if find_info is None:
         return
     if find_info.w_loader:
         return space.call_method(find_info.w_loader, "load_module", w_modulename)
 
     if find_info.modtype == C_BUILTIN:
-        return space.getbuiltinmodule(find_info.filename, force_init=True)
+        return space.loadbuiltinmodule(find_info.filename,
+                                       force_in_sys_modules=True,
+                                       force_init=force_init)
 
     if find_info.modtype in (PY_SOURCE, PY_COMPILED, C_EXTENSION, PKG_DIRECTORY):
         w_mod = None
 
         try:
             try:
-                return load_module(space, w_modulename, find_info, reuse=True)
+                return load_module(space, w_modulename, find_info, reuse=True,
+                                   force_init=True)
             finally:
                 if find_info.stream:
                     find_info.stream.close()