diff --git a/core/includes/module.inc b/core/includes/module.inc
index df9c138..7ff871c 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -85,9 +85,7 @@ function module_list($refresh = FALSE, $bootstrap_refresh = FALSE, $sort = FALSE
         $list = system_list('bootstrap');
       }
       else {
-        // Not using drupal_map_assoc() here as that requires common.inc.
-        $list = array_keys(system_list('module_enabled'));
-        $list = (!empty($list) ? array_combine($list, $list) : array());
+        $list = system_list('module_enabled');
       }
     }
   }
@@ -112,9 +110,9 @@ function module_list($refresh = FALSE, $bootstrap_refresh = FALSE, $sort = FALSE
  *
  * @return
  *   An associative array of modules or themes, keyed by name. For $type
- *   'bootstrap', the array values equal the keys. For $type 'module_enabled'
- *   or 'theme', the array values are objects representing the respective
- *   database row, with the 'info' property already unserialized.
+ *   'bootstrap' and 'module_enabled', the array values equal the keys.
+ *   For $type 'theme', the array values are objects representing the
+ *   respective database row, with the 'info' property already unserialized.
  *
  * @see module_list()
  * @see list_themes()
@@ -165,13 +163,13 @@ function system_list($type) {
       // consistent with the one used in module_implements().
       $result = db_query("SELECT * FROM {system} WHERE type = 'theme' OR (type = 'module' AND status = 1) ORDER BY weight ASC, name ASC");
       foreach ($result as $record) {
-        $record->info = unserialize($record->info);
         // Build a list of all enabled modules.
         if ($record->type == 'module') {
-          $lists['module_enabled'][$record->name] = $record;
+          $lists['module_enabled'][$record->name] = $record->name;
         }
         // Build a list of themes.
         if ($record->type == 'theme') {
+          $record->info = unserialize($record->info);
           $lists['theme'][$record->name] = $record;
         }
         // Build a list of filenames so drupal_get_filename can use it.
@@ -224,6 +222,7 @@ function system_list_reset() {
   drupal_static_reset('system_rebuild_module_data');
   drupal_static_reset('list_themes');
   cache('bootstrap')->deleteMultiple(array('bootstrap_modules', 'system_list'));
+  cache()->delete('system_info');
 }
 
 /**
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 94fd3e0..a91ee47 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\Core\Utilities\CacheArray;
+
 /**
  * @file
  * Configuration system that lets administrators modify the workings of the site.
@@ -1948,18 +1950,16 @@ function system_init() {
  * Adds CSS and JavaScript files declared in module .info files.
  */
 function system_add_module_assets() {
-  foreach (system_get_info('module') as $module => $info) {
-    if (!empty($info['stylesheets'])) {
-      foreach ($info['stylesheets'] as $media => $stylesheets) {
-        foreach ($stylesheets as $stylesheet) {
-          drupal_add_css($stylesheet, array('every_page' => TRUE, 'media' => $media));
-        }
+  foreach (system_get_module_info('stylesheets') as $module => $value) {
+    foreach ($value as $media => $stylesheets) {
+      foreach ($stylesheets as $stylesheet) {
+        drupal_add_css($stylesheet, array('every_page' => TRUE, 'media' => $media));
       }
     }
-    if (!empty($info['scripts'])) {
-      foreach ($info['scripts'] as $script) {
-        drupal_add_js($script, array('every_page' => TRUE));
-      }
+  }
+  foreach (system_get_module_info('scripts') as $module => $scripts) {
+    foreach ($scripts as $script) {
+      drupal_add_js($script, array('every_page' => TRUE));
     }
   }
 }
@@ -2363,12 +2363,17 @@ function system_update_files_database(&$files, $type) {
 function system_get_info($type, $name = NULL) {
   $info = array();
   if ($type == 'module') {
-    $type = 'module_enabled';
+    $result = db_query('SELECT name, info FROM {system} WHERE type = :type AND status = 1', array(':type' => 'module'));
+    foreach ($result as $record) {
+      $info[$record->name] = unserialize($record->info);
+    }
   }
-  $list = system_list($type);
-  foreach ($list as $shortname => $item) {
-    if (!empty($item->status)) {
-      $info[$shortname] = $item->info;
+  else {
+    $list = system_list($type);
+    foreach ($list as $shortname => $item) {
+      if (!empty($item->status)) {
+        $info[$shortname] = $item->info;
+      }
     }
   }
   if (isset($name)) {
@@ -2378,6 +2383,57 @@ function system_get_info($type, $name = NULL) {
 }
 
 /**
+ * Return .info data for modules.
+ *
+ * @param $property
+ *   The .info property to retrieve.
+ *
+ * @return
+ *   An array keyed by module name, with the .info file property as values.
+ *   Only modules with the property specified in their .info file will be
+ *   returned.
+ *
+ * @see SystemModuleInfo()
+ */
+function system_get_module_info($property) {
+  static $info;
+  if (!isset($info)) {
+    $info = new SystemModuleInfo('system_info', 'cache');
+  }
+
+  return $info[$property];
+}
+
+/**
+ * Extends DrupalCacheArray to lazy load .info properties for modules.
+ *
+ * Use system_get_module_info() rather than instantiating this class directly.
+ * @see system_get_module_info()
+ */
+class SystemModuleInfo extends CacheArray {
+
+  /**
+   * The full module info array as returned by system_get_info().
+   */
+  protected $info;
+
+  function resolveCacheMiss($offset) {
+    $data = array();
+    if (!isset($this->info)) {
+      $this->info = system_get_info('module');
+    }
+    foreach ($this->info as $module => $info) {
+      if (isset($info[$offset])) {
+        $data[$module] = $info[$offset];
+      }
+    }
+    $this->storage[$offset] = $data;
+    $this->persist($offset);
+    return $data;
+  }
+}
+
+/**
  * Helper function to scan and collect module .info data.
  *
  * @return
