diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 77458a1..8ec2539 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -885,23 +885,22 @@ function drupal_get_filename($type, $name, $filename = NULL) {
   elseif (isset($files[$type][$name])) {
     // nothing
   }
-  // Verify that we have an active database connection, before querying
-  // the database. This is required because this function is called both
-  // before we have a database connection (i.e. during installation) and
-  // when a database connection fails.
   else {
-    try {
-      if (function_exists('db_query')) {
-        $file = db_query("SELECT filename FROM {system} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type))->fetchField();
-        if ($file && file_exists(DRUPAL_ROOT . '/' . $file)) {
-          $files[$type][$name] = $file;
+    // Verify that we have an keyvalue service before using it. This is required
+    // because this function is called during installation.
+    // @todo Inject database connection into KeyValueStore\DatabaseStorage.
+    if (drupal_container()->hasDefinition('keyvalue') && function_exists('db_query')) {
+      try {
+        $file_list = state()->get('system.' . $type . '.files');
+        if ($file_list && isset($file_list[$name]) && file_exists(DRUPAL_ROOT . '/' . $file_list[$name])) {
+          $files[$type][$name] = $file_list[$name];
         }
       }
-    }
-    catch (Exception $e) {
-      // The database table may not exist because Drupal is not yet installed,
-      // or the database might be down. We have a fallback for this case so we
-      // hide the error completely.
+      catch (Exception $e) {
+        // The keyvalue service raise an exception due because the backend might
+        // be down. We have a fallback for this case so we hide the error
+        // completely.
+      }
     }
     // Fallback to searching the filesystem if the database could not find the
     // file or the file returned by the database is not found.
@@ -2461,9 +2460,10 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) {
     $container
       ->register('config.storage.staging', 'Drupal\Core\Config\FileStorage')
       ->addArgument(config_get_config_directory(CONFIG_STAGING_DIRECTORY));
+
+    // KeyValueStore.
     $container
-      ->register('state.storage', 'Drupal\Core\KeyValueStore\DatabaseStorage')
-      ->addArgument('state');
+      ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueFactory');
   }
   return $container;
 }
@@ -2480,7 +2480,7 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) {
  * @return Drupal\Core\KeyValueStore\KeyValueStoreInterface
  */
 function state() {
-  return drupal_container()->get('state.storage');
+  return drupal_container()->get('keyvalue')->get('state');
 }
 
 /**
@@ -2499,16 +2499,21 @@ function typed_data() {
 /**
  * Returns the test prefix if this is an internal request from SimpleTest.
  *
+ * @param string $new_prefix
+ *   Internal use only. A new prefix to be stored.
+ *
  * @return
  *   Either the simpletest prefix (the string "simpletest" followed by any
  *   number of digits) or FALSE if the user agent does not contain a valid
  *   HMAC and timestamp.
  */
-function drupal_valid_test_ua() {
+function drupal_valid_test_ua($new_prefix = NULL) {
   global $drupal_hash_salt;
-  // No reason to reset this.
   static $test_prefix;
 
+  if (isset($new_prefix)) {
+    $test_prefix = $new_prefix;
+  }
   if (isset($test_prefix)) {
     return $test_prefix;
   }
diff --git a/core/includes/common.inc b/core/includes/common.inc
index b3dc9cb..ef63042 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -6824,8 +6824,7 @@ function drupal_flush_all_caches() {
   // None currently; kept if any static caches need to be reset in the future.
 
   // Rebuild module and theme data.
-  system_rebuild_module_data();
-  system_rebuild_theme_data();
+  system_list_reset();
 
   // Ensure that all modules that are currently supposed to be enabled are
   // actually loaded.
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index dfb41f5..ac94175 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -322,9 +322,9 @@ function install_begin_request(&$install_state) {
     $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
       ->addArgument(new Reference('config.storage'))
       ->addArgument(new Reference('dispatcher'));
+    // @todo State service is gone; needs keyvalue + NullStorage replacement.
     $container
-      ->register('state.storage', 'Drupal\Core\KeyValueStore\DatabaseStorage')
-      ->addArgument('state');
+      ->register('keyvalue', 'Drupal\Core\KeyValueStore\KeyValueFactory');
     drupal_container($container);
   }
 
@@ -1661,15 +1661,12 @@ function install_import_translations_remaining(&$install_state) {
  *   A message informing the user that the installation is complete.
  */
 function install_finished(&$install_state) {
+  $profile = drupal_get_profile();
   // Remember the profile which was used.
-  variable_set('install_profile', drupal_get_profile());
+  variable_set('install_profile', $profile);
 
   // Installation profiles are always loaded last.
-  db_update('system')
-    ->fields(array('weight' => 1000))
-    ->condition('type', 'module')
-    ->condition('name', drupal_get_profile())
-    ->execute();
+  module_set_weight($profile, 1000);
 
   // Flush all caches to ensure that any full bootstraps during the installer
   // do not leave stale cached data, and that any content types or other items
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 3c30c89..c242cbc 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -9,16 +9,6 @@
 use Drupal\locale\Gettext;
 
 /**
- * Indicates that a module has not been installed yet.
- */
-const SCHEMA_UNINSTALLED = -1;
-
-/**
- * Indicates that a module has been installed.
- */
-const SCHEMA_INSTALLED = 0;
-
-/**
  * Requirement severity -- Informational message only.
  */
 const REQUIREMENT_INFO = -1;
@@ -420,28 +410,26 @@ function drupal_install_system() {
   require_once DRUPAL_ROOT . '/' . $system_path . '/system.install';
   $system_versions = drupal_get_schema_versions('system');
   $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED;
-  db_insert('system')
-    ->fields(array('filename', 'name', 'type', 'owner', 'status', 'schema_version', 'bootstrap'))
-    ->values(array(
-        'filename' => $system_path . '/system.module',
-        'name' => 'system',
-        'type' => 'module',
-        'owner' => '',
-        'status' => 1,
-        'schema_version' => $system_version,
-        'bootstrap' => 0,
-      ))
-    ->execute();
-
-  // Clear out module list and hook implementation statics before calling
-  // system_rebuild_theme_data().
+  drupal_container()
+    ->get('keyvalue')
+    ->get('system.schema')
+    ->set('system', $system_version);
+
+  // Enable System module.
+  // System module needs to be enabled and the system/module lists need to be
+  // reset first in order to allow config_install_default_config() to invoke
+  // config import callbacks.
+  // @todo Installation profiles may override the system.module config object.
+  // @todo Config\InstallStorage should actually throw an exception on write, why does this work?
+  config('system.module')
+    ->set('enabled.system', 0)
+    ->save();
+
+  // Clear out module list and hook implementation statics.
   system_list_reset();
   module_list_reset();
   module_implements_reset();
 
-  system_rebuild_module_data();
-  system_rebuild_theme_data();
-
   config_install_default_config('module', 'system');
 
   module_invoke('system', 'install');
diff --git a/core/includes/module.inc b/core/includes/module.inc
index 5944543..1a2cf38 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -132,6 +132,11 @@ function module_list_reset() {
  *
  * @see module_list()
  * @see list_themes()
+ *
+ * @todo There are too many layers/levels of caching involved for system_list()
+ *   data. Consider to add a config($name, $cache = TRUE) argument to allow
+ *   callers like this to force-disable any possible configuration storage
+ *   caching, or some other direct access to circumvent it/take it over.
  */
 function system_list($type) {
   $lists = &drupal_static(__FUNCTION__);
@@ -147,15 +152,15 @@ function system_list($type) {
       $bootstrap_list = $cached->data;
     }
     else {
-      $bootstrap_list = db_query("SELECT name, filename FROM {system} WHERE status = 1 AND bootstrap = 1 AND type = 'module' ORDER BY weight ASC, name ASC")->fetchAllAssoc('name');
+      $bootstrap_list = state()->get('system.module.bootstrap') ?: array();
       cache('bootstrap')->set('bootstrap_modules', $bootstrap_list);
     }
     // To avoid a separate database lookup for the filepath, prime the
     // drupal_get_filename() static cache for bootstrap modules only.
     // The rest is stored separately to keep the bootstrap module cache small.
-    foreach ($bootstrap_list as $module) {
-      drupal_classloader_register($module->name, dirname($module->filename));
-      drupal_get_filename('module', $module->name, $module->filename);
+    foreach ($bootstrap_list as $name => $filename) {
+      drupal_classloader_register($name, dirname($filename));
+      drupal_get_filename('module', $name, $filename);
     }
     // We only return the module names here since module_list() doesn't need
     // the filename itself.
@@ -177,22 +182,48 @@ function system_list($type) {
       // Drupal installations, which might have modules installed in different
       // locations in the file system. The ordering here must also be
       // 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) {
+      $enabled_modules = config('system.module')->get('enabled');
+      $module_files = state()->get('system.module.files');
+      foreach ($enabled_modules as $name => $weight) {
         // Build a list of all enabled modules.
-        if ($record->type == 'module') {
-          $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;
-        }
+        $lists['module_enabled'][$name] = $name;
+        // Build a list of filenames so drupal_get_filename can use it.
+        $lists['filepaths'][] = array(
+          'type' => 'module',
+          'name' => $name,
+          'filepath' => $module_files[$name],
+        );
+      }
+
+      // Build a list of themes.
+      $enabled_themes = config('system.theme')->get('enabled');
+      $theme_files = state()->get('system.theme.files');
+      // @todo Themes include all themes, including disabled/uninstalled. This
+      //   system.theme.data state will go away entirely as soon as themes have
+      //   a proper installation status.
+      // @see http://drupal.org/node/1067408
+      $theme_data = state()->get('system.theme.data');
+      if (empty($theme_data)) {
+        // system_list() may be called from _drupal_bootstrap_code() and
+        // module_load_all(), in which case system.module is not loaded yet.
+        // Prevent a filesystem scan in drupal_load() and include it directly.
+        require_once DRUPAL_ROOT . '/core/modules/system/system.module';
+        $theme_data = system_rebuild_theme_data();
+      }
+      foreach ($theme_data as $name => $theme) {
+        $theme->status = (int) isset($enabled_themes[$name]);
+        $lists['theme'][$name] = $theme;
         // Build a list of filenames so drupal_get_filename can use it.
-        if ($record->status) {
-          $lists['filepaths'][] = array('type' => $record->type, 'name' => $record->name, 'filepath' => $record->filename);
+        if (isset($enabled_themes[$name])) {
+          $lists['filepaths'][] = array(
+            'type' => 'theme',
+            'name' => $name,
+            'filepath' => $theme_files[$name],
+          );
         }
       }
+      // @todo Move into list_themes(). Read info for a particular requested
+      //   theme from state instead.
       foreach ($lists['theme'] as $key => $theme) {
         if (!empty($theme->info['base theme'])) {
           // Make a list of the theme's base themes.
@@ -240,6 +271,14 @@ function system_list_reset() {
   drupal_static_reset('list_themes');
   cache('bootstrap')->deleteMultiple(array('bootstrap_modules', 'system_list'));
   cache()->delete('system_info');
+  // Remove last known theme data state.
+  // This causes system_list() to call system_rebuild_theme_data() on its next
+  // invocation. When enabling a module that implements hook_system_info_alter()
+  // to inject a new (testing) theme or manipulate an existing theme, then that
+  // will cause system_list_reset() to be called, but theme data is not
+  // necessarily rebuilt afterwards.
+  // @todo Obsolete with proper installation status for themes.
+  state()->delete('system.theme.data');
 }
 
 /**
@@ -436,26 +475,34 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
 
   $modules_installed = array();
   $modules_enabled = array();
+  $schema_store = drupal_container()->get('keyvalue')->get('system.schema');
+  $module_config = config('system.module');
+  $disabled_config = config('system.module.disabled');
   foreach ($module_list as $module) {
     // Only process modules that are not already enabled.
-    $existing = db_query("SELECT status FROM {system} WHERE type = :type AND name = :name", array(
-      ':type' => 'module',
-      ':name' => $module))
-      ->fetchObject();
-    if ($existing->status == 0) {
+    $enabled = TRUE;
+    $weight = 0;
+    if (!$schema_store->get($module)) {
+      $enabled = FALSE;
+    }
+    elseif (!$module_config->get("enabled.$module")) {
+      $enabled = FALSE;
+      $weight = $disabled_config->get($module);
+    }
+    if (!$enabled) {
+      $module_config
+        ->set("enabled.$module", $weight)
+        ->set('enabled', module_config_sort($module_config->get('enabled')))
+        ->save();
+      if ($weight) {
+        $disabled_config
+          ->clear($module)
+          ->save();
+      }
       // Load the module's code.
       drupal_load('module', $module);
       module_load_install($module);
 
-      // Update the database and module list to reflect the new module. This
-      // needs to be done first so that the module's hook implementations,
-      // hook_schema() in particular, can be called while it is being
-      // installed.
-      db_update('system')
-        ->fields(array('status' => 1))
-        ->condition('type', 'module')
-        ->condition('name', $module)
-        ->execute();
       // Refresh the module list to include it.
       system_list_reset();
       module_implements_reset();
@@ -565,15 +612,19 @@ function module_disable($module_list, $disable_dependents = TRUE) {
 
   $invoke_modules = array();
 
+  $module_config = config('system.module');
+  $disabled_config = config('system.module.disabled');
   foreach ($module_list as $module) {
     if (module_exists($module)) {
       module_load_install($module);
       module_invoke($module, 'disable');
-      db_update('system')
-        ->fields(array('status' => 0))
-        ->condition('type', 'module')
-        ->condition('name', $module)
-        ->execute();
+      $disabled_config
+        ->set($module, $module_config->get($module))
+        ->save();
+      $module_config
+        ->clear("enabled.$module")
+        ->set('enabled', module_config_sort($module_config->get('enabled')))
+        ->save();
       $invoke_modules[] = $module;
       watchdog('system', '%module module disabled.', array('%module' => $module), WATCHDOG_INFO);
     }
@@ -642,6 +693,8 @@ function module_uninstall($module_list = array(), $uninstall_dependents = TRUE)
   }
 
   $storage = drupal_container()->get('config.storage');
+  $schema_store = drupal_container()->get('keyvalue')->get('system.schema');
+  $disabled_config = config('system.module.disabled');
   foreach ($module_list as $module) {
     // Uninstall the module.
     module_load_install($module);
@@ -655,8 +708,11 @@ function module_uninstall($module_list = array(), $uninstall_dependents = TRUE)
     }
 
     watchdog('system', '%module module uninstalled.', array('%module' => $module), WATCHDOG_INFO);
-    drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED);
+    $schema_store->delete($module);
+    $disabled_config->clear($module);
   }
+  $disabled_config->save();
+  drupal_get_installed_schema_version(NULL, TRUE);
 
   if (!empty($module_list)) {
     // Call hook_module_uninstall to let other modules act
@@ -1124,3 +1180,59 @@ function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
     $function($data, $context1, $context2);
   }
 }
+
+/**
+ * Sets weight of a particular module.
+ *
+ * The weight of uninstalled modules cannot be changed.
+ *
+ * @param string $module
+ *   The name of the module (without the .module extension).
+ * @param int $weight
+ *   An integer representing the weight of the module.
+ */
+function module_set_weight($module, $weight) {
+  // Update the module weight in the config file that contains it.
+  $module_config = config('system.module');
+  if ($module_config->get("enabled.$module") !== NULL) {
+    $module_config
+      ->set("enabled.$module", $weight)
+      ->set('enabled', module_config_sort($module_config->get('enabled')))
+      ->save();
+    return;
+  }
+  $disabled_config = config('system.module.disabled');
+  if ($disabled_config->get($module) !== NULL) {
+    $disabled_config
+      ->set($module, $weight)
+      ->save();
+    return;
+  }
+}
+
+/**
+ * Sort module config.
+ *
+ * The list of enabled modules is expected to be weight and name order and it
+ * is faster to do this sort on write than on read.
+ *
+ * @param array $data
+ *   An array of module configuration data.
+ *
+ * @return array
+ *   An array of module configuration data sorted by weight.
+ */
+function module_config_sort($data) {
+  $sort = array();
+  foreach ($data as $name => $weight) {
+    // We can't use the sign directly because + (ASCII 43) is before
+    // - (ASCII 45). So negative nubmers get a 0, non-negative numbers
+    // a 1 prefix.
+    $prefix = (int) ($weight >= 0);
+    // PHP_INT_MAX is at most 19 characters so make every number equally
+    // 19 digits long.
+    $sort[] = $prefix . sprintf('%019d', abs($weight)) . $name;
+  }
+  array_multisort($sort, SORT_STRING, $data);
+  return $data;
+}
diff --git a/core/includes/schema.inc b/core/includes/schema.inc
index 155bb6b..bff33d3 100644
--- a/core/includes/schema.inc
+++ b/core/includes/schema.inc
@@ -15,6 +15,16 @@
  */
 
 /**
+ * Indicates that a module has not been installed yet.
+ */
+const SCHEMA_UNINSTALLED = -1;
+
+/**
+ * Indicates that a module has been installed.
+ */
+const SCHEMA_INSTALLED = 0;
+
+/**
  * Gets the schema definition of a table, or the whole database schema.
  *
  * The returned schema will include any modifications made by any
@@ -173,10 +183,8 @@ function drupal_get_installed_schema_version($module, $reset = FALSE, $array = F
   }
 
   if (!$versions) {
-    $versions = array();
-    $result = db_query("SELECT name, schema_version FROM {system} WHERE type = :type", array(':type' => 'module'));
-    foreach ($result as $row) {
-      $versions[$row->name] = $row->schema_version;
+    if (!$versions = drupal_container()->get('keyvalue')->get('system.schema')->getAll()) {
+      $versions = array();
     }
   }
 
@@ -197,11 +205,7 @@ function drupal_get_installed_schema_version($module, $reset = FALSE, $array = F
  *   The new schema version.
  */
 function drupal_set_installed_schema_version($module, $version) {
-  db_update('system')
-    ->fields(array('schema_version' => $version))
-    ->condition('name', $module)
-    ->execute();
-
+  drupal_container()->get('keyvalue')->get('system.schema')->set($module, $version);
   // Reset the static cache of module schema versions.
   drupal_get_installed_schema_version(NULL, TRUE);
 }
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 20c43ea..06e99fb 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1412,17 +1412,17 @@ function theme_render_template($template_file, $variables) {
  */
 function theme_enable($theme_list) {
   drupal_clear_css_cache();
-
+  $theme_config = config('system.theme');
+  $disabled_themes = config('system.theme.disabled');
   foreach ($theme_list as $key) {
-    db_update('system')
-      ->fields(array('status' => 1))
-      ->condition('type', 'theme')
-      ->condition('name', $key)
-      ->execute();
-
+    // The value is not used; the weight is ignored for themes currently.
+    $theme_config->set("enabled.$key", 0);
+    $disabled_themes->clear($key);
     // Install default configuration of the theme.
     config_install_default_config('theme', $key);
   }
+  $theme_config->save();
+  $disabled_themes->save();
 
   list_themes(TRUE);
   menu_router_rebuild();
@@ -1449,13 +1449,15 @@ function theme_disable($theme_list) {
 
   drupal_clear_css_cache();
 
+  $theme_config = config('system.theme');
+  $disabled_themes = config('system.theme.disabled');
   foreach ($theme_list as $key) {
-    db_update('system')
-      ->fields(array('status' => 0))
-      ->condition('type', 'theme')
-      ->condition('name', $key)
-      ->execute();
+    // The value is not used; the weight is ignored for themes currently.
+    $theme_config->clear("enabled.$key");
+    $disabled_themes->set($key, 0);
   }
+  $theme_config->save();
+  $disabled_themes->save();
 
   list_themes(TRUE);
   menu_router_rebuild();
diff --git a/core/includes/update.inc b/core/includes/update.inc
index 5d80188..2ee76ab 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -23,21 +23,24 @@
 const REQUIRED_D7_SCHEMA_VERSION = '7069';
 
 /**
- * Disable any items in the {system} table that are not core compatible.
+ * Disables any extensions that are incompatible with the current core version.
  */
 function update_fix_compatibility() {
-  $incompatible = array();
-  $result = db_query("SELECT name, type, status FROM {system} WHERE status = 1 AND type IN ('module','theme')");
-  foreach ($result as $row) {
-    if (update_check_incompatibility($row->name, $row->type)) {
-      $incompatible[] = $row->name;
+  foreach (array('module', 'theme') as $type) {
+    $config = config("system.$type");
+    $save = FALSE;
+    foreach ($config->get('enabled') as $name => $weight) {
+      if (update_check_incompatibility($name, $type)) {
+        $config->clear("enabled.$name");
+        $save = TRUE;
+      }
+    }
+    if ($save) {
+      if ($type == 'module') {
+        $config->set('enabled', module_config_sort($config->get('enabled')));
+      }
+      $config->save();
     }
-  }
-  if (!empty($incompatible)) {
-    db_update('system')
-      ->fields(array('status' => 0))
-      ->condition('name', $incompatible, 'IN')
-      ->execute();
   }
 }
 
@@ -116,7 +119,12 @@ function update_prepare_d8_bootstrap() {
   // running an up-to-date version of Drupal 7 before proceeding. Note this has
   // to happen AFTER the database bootstraps because of
   // drupal_get_installed_schema_version().
-  $system_schema = drupal_get_installed_schema_version('system');
+  try {
+    $system_schema = drupal_get_installed_schema_version('system');
+  }
+  catch (\Exception $e) {
+    $system_schema = db_query('SELECT schema_version FROM {system} WHERE name = :system', array(':system' => 'system'))->fetchField();
+  }
   if ($system_schema < 8000) {
     $has_required_schema = $system_schema >= REQUIRED_D7_SCHEMA_VERSION;
     $requirements = array(
@@ -129,6 +137,10 @@ function update_prepare_d8_bootstrap() {
     );
     update_extra_requirements($requirements);
 
+    // @todo update.php stages seem to be completely screwed up; the initial
+    //   requirements check is not supposed to change the system. All of the
+    //   following code seems to have been mistakenly/unknowingly added here and
+    //   does not belong into update_prepare_d8_bootstrap().
     if ($has_required_schema) {
       if (!db_table_exists('key_value')) {
         $specs = array(
@@ -163,18 +175,72 @@ function update_prepare_d8_bootstrap() {
       // Bootstrap variables so we can update theme while preparing the update
       // process.
       drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
-      // Update the dynamic include paths that might be used before running the
-      // proper update functions.
-      update_prepare_stored_includes();
-      // Update the environment for the language bootstrap if needed.
-      update_prepare_d8_language();
 
+      // @todo Race-condition: drupal_install_config_directories() calls into
+      //   install_ensure_config_directory(), which calls into
+      //   file_prepare_directory(), whichs calls into file_get_stream_wrappers(),
+      //   which attempts to invoke hooks with a non-existing module/hook system.
+      include_once DRUPAL_ROOT . '/core/includes/module.inc';
+      $module_list['system']['filename'] = 'core/modules/system/system.module';
+      module_list(NULL, $module_list);
+      require_once DRUPAL_ROOT . '/' . $module_list['system']['filename'];
       // Ensure the configuration directories exist and are writable, or create
       // them. If the directories have not been specified in settings.php and
       // created manually already, and either directory cannot be created by the
       // web server, an exception will be thrown, halting the update.
       drupal_install_config_directories();
 
+      $module_config = config('system.module');
+      $disabled_modules = config('system.module.disabled');
+      $theme_config = config('system.theme');
+      $disabled_themes = config('system.theme.disabled');
+      $schema_store = drupal_container()->get('keyvalue')->get('system.schema');
+
+      // Load system.module, because update_prepare_d8_bootstrap() is called in
+      // the initial minimal update.php bootstrap that performs the core
+      // requirements check.
+      require_once DRUPAL_ROOT . '/core/modules/system/system.module';
+
+      $result = db_query('SELECT name, status, weight, schema_version, type FROM {system} WHERE type = :theme OR (type = :module AND schema_version <> :schema_uninstalled)', array(
+        ':theme' => 'theme',
+        ':module' => 'module',
+        ':schema_uninstalled' => SCHEMA_UNINSTALLED,
+      ));
+      $module_data = _system_rebuild_module_data();
+
+      // Loop through each extension from the system table.
+      foreach ($result as $record) {
+        if ($record->type == 'module') {
+          if ($record->status && isset($module_data[$record->name])) {
+            $module_config->set('enabled.' . $record->name, $record->weight);
+          }
+          else {
+            $disabled_modules->set($record->name, $record->weight);
+          }
+          $schema_store->set($record->name, $record->schema_version);
+        }
+        elseif ($record->type == 'theme') {
+          if ($record->status) {
+            $theme_config->set('enabled.' . $record->name, 0);
+          }
+          else {
+            $disabled_themes->set($record->name, 0);
+          }
+        }
+      }
+      $module_config->set('enabled', module_config_sort($module_config->get('enabled')))->save();
+      $disabled_modules->save();
+      $theme_config->save();
+      $disabled_themes->save();
+
+      // Update the dynamic include paths that might be used before running the
+      // proper update functions.
+      update_prepare_stored_includes();
+      // Update the environment for the language bootstrap if needed.
+      update_prepare_d8_language();
+      // Prime the classloader.
+      system_list('module_enabled');
+
       // Change language column to langcode in url_alias.
       if (db_table_exists('url_alias') && db_field_exists('url_alias', 'language')) {
         db_drop_index('url_alias', 'alias_language_pid');
@@ -259,7 +325,6 @@ function update_prepare_d8_language() {
     // version of this function to ensure schema conflicts don't happen due to
     // our updated data.
     $modules = array('language');
-    update_module_add_to_system($modules);
     update_module_enable($modules);
 
     // Rename language column to langcode and set it again as the primary key.
@@ -331,41 +396,6 @@ function update_prepare_d8_language() {
 }
 
 /**
- * Adds modules to the system table in a Drupal core update.
- *
- * @param $modules
- *   Array of module names.
- */
-function update_module_add_to_system($modules = array()) {
-  // Insert module data, so we can enable the module. Calling a full module
-  // list rebuild so early is costly and complex, so we just have a stop-gap.
-  $info_defaults = array(
-    'dependencies' => array(),
-    'description' => '',
-    'package' => 'Other',
-    'version' => NULL,
-    'php' => DRUPAL_MINIMUM_PHP,
-    'files' => array(),
-    'bootstrap' => 0,
-  );
-  foreach ($modules as $module) {
-    $module_info = drupal_parse_info_file('core/modules/' . $module . '/' . $module . '.info');
-    db_insert('system')
-      ->fields(array(
-        'filename' => 'core/modules/' . $module . '/' . $module . '.module',
-        'name' => $module,
-        'type' => 'module',
-        'status' => 0,
-        'bootstrap' => 0,
-        'schema_version' => -1,
-        'weight' => 0,
-        'info' => serialize($module_info + $info_defaults),
-      ))
-      ->execute();
-  }
-}
-
-/**
  * Perform Drupal 7.x to 8.x updates that are required for update.php
  * to function properly.
  *
@@ -387,6 +417,7 @@ function update_fix_d8_requirements() {
  * Helper function to install a new module in Drupal 8 via hook_update_N().
  */
 function update_module_enable(array $modules) {
+  $schema_store = drupal_container()->get('keyvalue')->get('system.schema');
   foreach ($modules as $module) {
     // Check for initial schema and install it. The schema version of a newly
     // installed module is always 0. Using 8000 here would be inconsistent
@@ -399,13 +430,19 @@ function update_module_enable(array $modules) {
         db_create_table($table, $spec);
       }
     }
+    // Enable the module with a weight of 0.
+    $module_config = config('system.module');
+    $module_config
+      ->set("enabled.$module", 0)
+      ->set('enabled', module_config_sort($module_config->get('enabled')))
+      ->save();
+    // Ensure the module is not contained in disabled modules.
+    config('system.module.disabled')
+      ->clear($module)
+      ->save();
     // Change the schema version from SCHEMA_UNINSTALLED to 0, so any module
     // updates since the module's inception are executed in a core upgrade.
-    db_update('system')
-      ->condition('type', 'module')
-      ->condition('name', $module)
-      ->fields(array('schema_version' => 0, 'status' => 1))
-      ->execute();
+    $schema_store->set($module, 0);
 
     // system_list_reset() is in module.inc but that would only be available
     // once the variable bootstrap is done.
@@ -940,8 +977,7 @@ function update_retrieve_dependencies() {
   $return = array();
   // Get a list of installed modules, arranged so that we invoke their hooks in
   // the same order that module_invoke_all() does.
-  $modules = db_query("SELECT name FROM {system} WHERE type = 'module' AND schema_version <> :schema ORDER BY weight ASC, name ASC", array(':schema' => SCHEMA_UNINSTALLED))->fetchCol();
-  foreach ($modules as $module) {
+  foreach (config('system.module')->get('enabled') as $module => $weight) {
     $function = $module . '_update_dependencies';
     if (function_exists($function)) {
       $result = $function();
diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php
index 7c150e9..034dff1 100644
--- a/core/lib/Drupal/Core/Config/Config.php
+++ b/core/lib/Drupal/Core/Config/Config.php
@@ -346,7 +346,6 @@ public function load() {
    *   The configuration object.
    */
   public function save() {
-    $this->sortByKey($this->data);
     $this->storage->write($this->name, $this->data);
     $this->isNew = FALSE;
     $this->notify('save');
@@ -370,26 +369,6 @@ public function rename($new_name) {
   }
 
   /**
-   * Sorts all keys in configuration data.
-   *
-   * Ensures that re-inserted keys appear in the same location as before, in
-   * order to ensure an identical order regardless of storage controller.
-   * A consistent order is important for any storage that allows any kind of
-   * diff operation.
-   *
-   * @param array $data
-   *   An associative array to sort recursively by key name.
-   */
-  public function sortByKey(array &$data) {
-    ksort($data);
-    foreach ($data as &$value) {
-      if (is_array($value)) {
-        $this->sortByKey($value);
-      }
-    }
-  }
-
-  /**
    * Deletes the configuration object.
    *
    * @return Drupal\Core\Config\Config
diff --git a/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php b/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php
new file mode 100644
index 0000000..864697f
--- /dev/null
+++ b/core/lib/Drupal/Core/KeyValueStore/KeyValueFactory.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\KeyValueStore\KeyValueFactory.
+ */
+
+namespace Drupal\Core\KeyValueStore;
+
+class KeyValueFactory {
+
+  protected $stores = array();
+
+  /**
+   * Constructs a new key/value store for a given collection name.
+   *
+   * @param string $collection
+   *   The name of the collection holding key and value pairs.
+   *
+   * @return Drupal\Core\KeyValueStore\DatabaseStorage
+   *   A key/value store implementation for the given $collection.
+   */
+  public function get($collection) {
+    if (!isset($this->stores[$collection])) {
+      $this->stores[$collection] = new DatabaseStorage($collection);
+    }
+    return $this->stores[$collection];
+  }
+}
diff --git a/core/modules/action/tests/action_loop_test/action_loop_test.install b/core/modules/action/tests/action_loop_test/action_loop_test.install
index 50e3603..7085aed 100644
--- a/core/modules/action/tests/action_loop_test/action_loop_test.install
+++ b/core/modules/action/tests/action_loop_test/action_loop_test.install
@@ -4,8 +4,5 @@
  * Implements hook_install().
  */
 function action_loop_test_install() {
-   db_update('system')
-    ->fields(array('weight' => 1))
-    ->condition('name', 'action_loop_test')
-    ->execute();
+  module_set_weight('action_loop_test', 1);
 }
diff --git a/core/modules/block/block.install b/core/modules/block/block.install
index 09ba522..ee72e0f 100644
--- a/core/modules/block/block.install
+++ b/core/modules/block/block.install
@@ -217,10 +217,7 @@ function block_install() {
   // Block should go first so that other modules can alter its output
   // during hook_page_alter(). Almost everything on the page is a block,
   // so before block module runs, there will not be much to alter.
-  db_update('system')
-    ->fields(array('weight' => -5))
-    ->condition('name', 'block')
-    ->execute();
+  module_set_weight('block', -5);
 }
 
 /**
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 0626c08..2978146 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -958,12 +958,10 @@ function block_cache_flush() {
  * Implements hook_rebuild().
  */
 function block_rebuild() {
-  // Rehash blocks for active themes. We don't use list_themes() here,
-  // because if MAINTENANCE_MODE is defined it skips reading the database,
-  // and we can't tell which themes are active.
-  $themes = db_query("SELECT name FROM {system} WHERE type = 'theme' AND status = 1");
-  foreach ($themes as $theme) {
-    _block_rehash($theme->name);
+  foreach (list_themes() as $name => $data) {
+    if ($data->status) {
+      _block_rehash($name);
+    }
   }
 }
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php
index 9eea495..2414728 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php
@@ -93,7 +93,7 @@ function testCRUD() {
   }
 
   /**
-   * Tests Drupal\Core\Config\Config::sortByKey().
+   * Tests key injection order.
    */
   function testDataKeySort() {
     $config = config('config_test.keysort');
@@ -112,10 +112,10 @@ function testDataKeySort() {
     $new_config->set('new', 'Value to be replaced');
     $new_config->save();
 
-    // Verify that the data of both objects is in the identical order.
+    // Verify that the data of the new object is in the reverse order.
     // assertIdentical() is the required essence of this test; it performs a
     // strict comparison, which means that keys and values must be identical and
-    // their order must be identical.
-    $this->assertIdentical($new_config->get(), $config->get());
+    // their order must be as expected.
+    $this->assertIdentical($new_config->get(), array_reverse($config->get()));
   }
 }
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php
index 9316962..2266732 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigImportTest.php
@@ -128,10 +128,10 @@ function testNew() {
     $staging->write($name, $original_name_data);
     $original_dynamic_data = array(
       'id' => 'new',
+      'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651',
       'label' => 'New',
-      'langcode' => 'und',
       'style' => '',
-      'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651',
+      'langcode' => 'und',
     );
     $staging->write($dynamic_name, $original_dynamic_data);
     $this->assertIdentical($staging->exists($name), TRUE, $name . ' found.');
diff --git a/core/modules/field/tests/modules/field_test/field_test.install b/core/modules/field/tests/modules/field_test/field_test.install
index 5957561..5355e9b 100644
--- a/core/modules/field/tests/modules/field_test/field_test.install
+++ b/core/modules/field/tests/modules/field_test/field_test.install
@@ -10,10 +10,7 @@
  */
 function field_test_install() {
   // hook_entity_info_alter() needs to be executed as last.
-  db_update('system')
-    ->fields(array('weight' => 1))
-    ->condition('name', 'field_test')
-    ->execute();
+  module_set_weight('field_test', 1);
 }
 
 /**
diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install
index 8e6fddf..56f8402 100644
--- a/core/modules/forum/forum.install
+++ b/core/modules/forum/forum.install
@@ -10,10 +10,7 @@
  */
 function forum_install() {
   // Set the weight of the forum.module to 1 so it is loaded after the taxonomy.module.
-  db_update('system')
-    ->fields(array('weight' => 1))
-    ->condition('name', 'forum')
-    ->execute();
+  module_set_weight('forum', 1);
   // Forum topics are published by default, but do not have any other default
   // options set (for example, they are not promoted to the front page).
   // @todo Convert to default module configuration, once Node module's content
diff --git a/core/modules/help/lib/Drupal/help/Tests/HelpTest.php b/core/modules/help/lib/Drupal/help/Tests/HelpTest.php
index 0bd35e6..7d5d20e 100644
--- a/core/modules/help/lib/Drupal/help/Tests/HelpTest.php
+++ b/core/modules/help/lib/Drupal/help/Tests/HelpTest.php
@@ -107,12 +107,9 @@ protected function verifyHelp($response = 200) {
    */
   protected function getModuleList() {
     $modules = array();
-    $result = db_query("SELECT name, filename, info FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, filename ASC");
-    foreach ($result as $module) {
-      if (file_exists($module->filename) && function_exists($module->name . '_help')) {
-        $fullname = unserialize($module->info);
-        $modules[$module->name] = $fullname['name'];
-      }
+    $module_data = system_rebuild_module_data();
+    foreach (module_implements('help') as $module) {
+      $modules[$module] = $module_data[$module]->info['name'];
     }
     return $modules;
   }
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareTest.php
index 2e85afa..112fee8 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleCompareTest.php
@@ -47,6 +47,8 @@ function testLocaleCompare() {
     // modules not hidden. locale_test_system_info_alter() modifies the project
     // info of the locale_test and locale_test_disabled modules.
     variable_set('locale_translation_test_system_info_alter', TRUE);
+    // Reset system lists to reflect changes.
+    system_list_reset();
 
     // Check if interface translation data is collected from hook_info.
     drupal_static_reset('locale_translation_project_list');
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 6370033..aeff65e 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -122,6 +122,13 @@
   protected $verboseDirectory;
 
   /**
+   * The original database prefix when running inside Simpletest.
+   *
+   * @var string
+   */
+  protected $originalPrefix;
+
+  /**
    * Constructor for Test.
    *
    * @param $test_id
@@ -742,6 +749,10 @@ protected function prepareEnvironment() {
     foreach (array(CONFIG_ACTIVE_DIRECTORY, CONFIG_STAGING_DIRECTORY) as $type) {
       $GLOBALS['config_directories'][$type]['path'] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config_' . $type;
     }
+    if (drupal_valid_test_ua()) {
+      $this->originalPrefix = drupal_valid_test_ua();
+      drupal_valid_test_ua($this->databasePrefix);
+    }
 
     // Reset and create a new service container.
     $this->container = drupal_container(NULL, TRUE);
@@ -829,6 +840,9 @@ protected function tearDown() {
     drupal_container($this->originalContainer);
     $language_interface = $this->originalLanguage;
     $GLOBALS['config_directories'] = $this->originalConfigDirectories;
+    if (isset($this->originalPrefix)) {
+      drupal_valid_test_ua($this->originalPrefix);
+    }
 
     // Restore original shutdown callbacks.
     $callbacks = &drupal_register_shutdown_function();
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index dd5ee4d..0c996e7 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -133,6 +133,9 @@ function simpletest_run_tests($test_list, $reporter = 'drupal') {
   // Clear out the previous verbose files.
   file_unmanaged_delete_recursive('public://simpletest/verbose');
 
+  // Prime module data.
+  simpletest_prepare_module_data();
+
   // Get the info for the first test being run.
   $first_test = array_shift($test_list);
   $first_instance = new $first_test();
@@ -313,7 +316,8 @@ function simpletest_test_get_all() {
   if (!$groups) {
     // Make sure that namespaces for disabled modules are registered so that the
     // checks below will find them.
-    simpletest_classloader_register();
+    $module_data = system_rebuild_module_data();
+    simpletest_classloader_register($module_data);
 
     // Load test information from cache if available, otherwise retrieve the
     // information from each tests getInfo() method.
@@ -323,16 +327,16 @@ function simpletest_test_get_all() {
     else {
       // Select all PSR-0 classes in the Tests namespace of all modules.
       $classes = array();
-      $system_list = db_query("SELECT name, filename FROM {system}")->fetchAllKeyed();
 
-      foreach ($system_list as $name => $filename) {
+      foreach ($module_data as $name => $data) {
+        $dirname = dirname($data->filename);
         // Build directory in which the test files would reside.
-        $tests_dir = DRUPAL_ROOT . '/' . dirname($filename) . '/lib/Drupal/' . $name . '/Tests';
+        $tests_dir = DRUPAL_ROOT . '/' . $dirname . '/lib/Drupal/' . $name . '/Tests';
         // Scan it for test files if it exists.
         if (is_dir($tests_dir)) {
           $files = file_scan_directory($tests_dir, '/.*\.php/');
           if (!empty($files)) {
-            $basedir = DRUPAL_ROOT . '/' . dirname($filename) . '/lib/';
+            $basedir = DRUPAL_ROOT . '/' . $dirname . '/lib/';
             foreach ($files as $file) {
               // Convert the file name into the namespaced class name.
               $replacements = array(
@@ -357,7 +361,7 @@ function simpletest_test_get_all() {
           // If this test class requires a non-existing module, skip it.
           if (!empty($info['dependencies'])) {
             foreach ($info['dependencies'] as $module) {
-              if (!drupal_get_filename('module', $module)) {
+              if (!isset($module_data[$module])) {
                 continue 2;
               }
             }
@@ -384,16 +388,21 @@ function simpletest_test_get_all() {
 /**
  * Registers namespaces for disabled modules.
  */
-function simpletest_classloader_register() {
-  // Get the cached test modules list and register a test namespace for each.
-  $disabled_modules = db_query("SELECT name, filename FROM {system} WHERE status = 0")->fetchAllKeyed();
-  if ($disabled_modules) {
-    foreach ($disabled_modules as $name => $filename) {
-      drupal_classloader_register($name, dirname($filename));
-    }
+function simpletest_classloader_register($module_data = NULL) {
+  if (!$module_data) {
+    // This is only needed to register namespaces and it is safe to
+    // re-register existing namespaces so go with raw data.
+    $module_data = _system_rebuild_module_data('simpletest_module_data');
+  }
+  foreach ($module_data as $name => $data) {
+    drupal_classloader_register($name, dirname($data->filename));
   }
 }
 
+function simpletest_prepare_module_data() {
+  _system_rebuild_module_data('simpletest_module_data', TRUE);
+}
+
 /**
  * Generate test file.
  */
diff --git a/core/modules/system/config/system.module.yml b/core/modules/system/config/system.module.yml
new file mode 100644
index 0000000..696bedc
--- /dev/null
+++ b/core/modules/system/config/system.module.yml
@@ -0,0 +1,2 @@
+enabled:
+  system: '0'
diff --git a/core/modules/system/config/system.theme.yml b/core/modules/system/config/system.theme.yml
new file mode 100644
index 0000000..40fad06
--- /dev/null
+++ b/core/modules/system/config/system.theme.yml
@@ -0,0 +1,2 @@
+enabled:
+  stark: '0'
diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/RangeQueryTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/RangeQueryTest.php
index 4b15603..f85750b 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Database/RangeQueryTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Database/RangeQueryTest.php
@@ -34,11 +34,11 @@ public static function getInfo() {
    */
   function testRangeQuery() {
     // Test if return correct number of rows.
-    $range_rows = db_query_range("SELECT name FROM {system} ORDER BY name", 2, 3)->fetchAll();
+    $range_rows = db_query_range("SELECT name FROM {variable} ORDER BY name", 2, 3)->fetchAll();
     $this->assertEqual(count($range_rows), 3, 'Range query work and return correct number of rows.');
 
     // Test if return target data.
-    $raw_rows = db_query('SELECT name FROM {system} ORDER BY name')->fetchAll();
+    $raw_rows = db_query('SELECT name FROM {variable} ORDER BY name')->fetchAll();
     $raw_rows = array_slice($raw_rows, 2, 3);
     $this->assertEqual($range_rows, $raw_rows, 'Range query work and return target data.');
   }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/TemporaryQueryTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/TemporaryQueryTest.php
index dab4a70..110f5a8 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Database/TemporaryQueryTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Database/TemporaryQueryTest.php
@@ -43,7 +43,7 @@ function testTemporaryQuery() {
     $this->drupalGet('database_test/db_query_temporary');
     $data = json_decode($this->drupalGetContent());
     if ($data) {
-      $this->assertEqual($this->countTableRows("system"), $data->row_count, 'The temporary table contains the correct amount of rows.');
+      $this->assertEqual($this->countTableRows("filter"), $data->row_count, 'The temporary table contains the correct amount of rows.');
       $this->assertFalse(db_table_exists($data->table_name), 'The temporary table is, indeed, temporary.');
     }
     else {
@@ -51,10 +51,10 @@ function testTemporaryQuery() {
     }
 
     // Now try to run two db_query_temporary() in the same request.
-    $table_name_system = db_query_temporary('SELECT status FROM {system}', array());
+    $table_name_system = db_query_temporary('SELECT name FROM {variable}', array());
     $table_name_users = db_query_temporary('SELECT uid FROM {users}', array());
 
-    $this->assertEqual($this->countTableRows($table_name_system), $this->countTableRows("system"), 'A temporary table was created successfully in this request.');
+    $this->assertEqual($this->countTableRows($table_name_system), $this->countTableRows("variable"), 'A temporary table was created successfully in this request.');
     $this->assertEqual($this->countTableRows($table_name_users), $this->countTableRows("users"), 'A second temporary table was created successfully in this request.');
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleApiTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleApiTest.php
index 3a54336..f6e6929 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleApiTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleApiTest.php
@@ -49,11 +49,7 @@ function testModuleList() {
     $this->assertModuleList($module_list, t('After adding a module'));
 
     // Try to mess with the module weights.
-    db_update('system')
-      ->fields(array('weight' => 20))
-      ->condition('name', 'contact')
-      ->condition('type', 'module')
-      ->execute();
+    module_set_weight('contact', 20);
     // Reset the module list.
     system_list_reset();
     // Move contact to the end of the array.
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php b/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php
index 9bdeac4..603af18 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/InfoAlterTest.php
@@ -27,13 +27,14 @@ public static function getInfo() {
    * return freshly altered info.
    */
   function testSystemInfoAlter() {
-    // Enable our test module. Flush all caches, which we assert is the only
-    // thing necessary to use the rebuilt {system}.info.
+    // Enable seven and the test module. Flush all caches, which we assert is
+    // the only thing necessary to use the rebuilt {system}.info.
+    theme_enable(array('seven'));
     module_enable(array('module_test'), FALSE);
     $this->resetAll();
     $this->assertTrue(module_exists('module_test'), t('Test module is enabled.'));
 
-    $info = $this->getSystemInfo('seven', 'theme');
+    $info = system_get_info('theme', 'seven');
     $this->assertTrue(isset($info['regions']['test_region']), t('Altered theme info was added to {system}.info.'));
     $seven_regions = system_region_list('seven');
     $this->assertTrue(isset($seven_regions['test_region']), t('Altered theme info was returned by system_region_list().'));
@@ -48,7 +49,7 @@ function testSystemInfoAlter() {
     $this->resetAll();
     $this->assertFalse(module_exists('module_test'), t('Test module is disabled.'));
 
-    $info = $this->getSystemInfo('seven', 'theme');
+    $info = system_get_info('theme', 'seven');
     $this->assertFalse(isset($info['regions']['test_region']), t('Altered theme info was removed from {system}.info.'));
     $seven_regions = system_region_list('seven');
     $this->assertFalse(isset($seven_regions['test_region']), t('Altered theme info was not returned by system_region_list().'));
@@ -58,20 +59,4 @@ function testSystemInfoAlter() {
     $list_themes = list_themes();
     $this->assertFalse(isset($list_themes['seven']->info['regions']['test_region']), t('Altered theme info was not returned by list_themes().'));
   }
-
-  /**
-   * Returns the info array as it is stored in {system}.
-   *
-   * @param $name
-   *   The name of the record in {system}.
-   * @param $type
-   *   The type of record in {system}.
-   *
-   * @return
-   *   Array of info, or FALSE if the record is not found.
-   */
-  function getSystemInfo($name, $type) {
-    $raw_info = db_query("SELECT info FROM {system} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type))->fetchField();
-    return $raw_info ? unserialize($raw_info) : FALSE;
-  }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php
index 1231af4..f3275a7 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php
@@ -129,10 +129,10 @@ function testThemeSystem() {
     // Since visiting update.php triggers a rebuild of the theme system from an
     // unusual maintenance mode environment, we check that this rebuild did not
     // put any incorrect information about the themes into the database.
-    $original_theme_data = db_query("SELECT * FROM {system} WHERE type = 'theme' ORDER BY name")->fetchAll();
+    $original_theme_data = config('system.theme')->get('enabled');
     $this->drupalLogin($this->update_user);
     $this->drupalGet($this->update_url, array('external' => TRUE));
-    $final_theme_data = db_query("SELECT * FROM {system} WHERE type = 'theme' ORDER BY name")->fetchAll();
+    $final_theme_data = config('system.theme')->get('enabled');
     $this->assertEqual($original_theme_data, $final_theme_data, t('Visiting update.php does not alter the information about themes stored in the database.'));
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
index 812bde7..6c32faa 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
@@ -189,8 +189,7 @@ protected function refreshVariables() {
   protected function performUpgrade($register_errors = TRUE) {
 
     // Load the first update screen.
-    $update_url = $GLOBALS['base_url'] . '/core/update.php';
-    $this->drupalGet($update_url, array('external' => TRUE));
+    $this->getUpdatePhp();
     if (!$this->assertResponse(200)) {
       throw new Exception('Initial GET to update.php did not return HTTP 200 status.');
     }
@@ -230,7 +229,7 @@ protected function performUpgrade($register_errors = TRUE) {
     }
 
     // Check if there still are pending updates.
-    $this->drupalGet($update_url, array('external' => TRUE));
+    $this->getUpdatePhp();
     $this->drupalPost(NULL, array(), t('Continue'));
     if (!$this->assertText(t('No pending updates.'), t('No pending updates at the end of the update process.'))) {
       throw new Exception('update.php still shows pending updates after execution.');
@@ -264,21 +263,35 @@ protected function performUpgrade($register_errors = TRUE) {
   }
 
   /**
-   * Force uninstall all modules from a test database, except those listed.
+   * Gets update.php without calling url().
    *
-   * @param $modules
-   *   The list of modules to keep installed. Required core modules will
-   *   always be kept.
+   * Required since WebTestBase::drupalGet() calls t(), which calls into
+   * system_list(), from the parent site/test runner, before update.php is even
+   * executed.
+   *
+   * @see WebTestBase::drupalGet()
    */
-  protected function uninstallModulesExcept(array $modules) {
-    $required_modules = array('block', 'dblog', 'filter', 'node', 'system', 'update', 'user');
-
-    $modules = array_merge($required_modules, $modules);
+  protected function getUpdatePhp() {
+    $path = $GLOBALS['base_url'] . '/core/update.php';
+    $out = $this->curlExec(array(CURLOPT_HTTPGET => TRUE, CURLOPT_URL => $path, CURLOPT_NOBODY => FALSE));
+    // Ensure that any changes to variables in the other thread are picked up.
+    $this->refreshVariables();
 
-    db_delete('system')
-      ->condition('type', 'module')
-      ->condition('name', $modules, 'NOT IN')
-      ->execute();
+    // Replace original page output with new output from redirected page(s).
+    if ($new = $this->checkForMetaRefresh()) {
+      $out = $new;
+    }
+    // @todo WebTestBase::verbose() cannot be called here yet, since Simpletest
+    //   verbose output parameters are not prepared before test execution and
+    //   instead determined at runtime; i.e., file_create_url() calls into
+    //   system_list(), before update.php has upgraded the system list.
+    // @see http://drupal.org/node/1611430
+    /*
+    $this->verbose('GET request to: ' . $path .
+      '<hr />Ending URL: ' . $this->getUrl() .
+      '<hr />' . $out);
+    */
+    return $out;
   }
 
 }
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 2d7e194..46c7a36 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -1252,7 +1252,7 @@ function system_modules_uninstall($form, $form_state = NULL) {
   $all_modules = system_rebuild_module_data();
   $disabled_modules = array();
   foreach ($all_modules as $name => $module) {
-    if (empty($module->status) && $module->schema_version > SCHEMA_UNINSTALLED) {
+    if (empty($module->status) && drupal_get_installed_schema_version($name) > SCHEMA_UNINSTALLED) {    
       $disabled_modules[$name] = $module;
     }
   }
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 8331d55..e2b1eee 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -510,11 +510,6 @@ function system_install() {
   // Enable the default theme. Can't use theme_enable() this early in
   // installation.
   variable_set('theme_default', 'stark');
-  db_update('system')
-    ->fields(array('status' => 1))
-    ->condition('type', 'theme')
-    ->condition('name', 'stark')
-    ->execute();
   config_install_default_config('theme', 'stark');
 
   // Populate the cron key variable.
@@ -1385,75 +1380,6 @@ function system_schema() {
     ),
   );
 
-  $schema['system'] = array(
-    'description' => "A list of all modules, themes, and theme engines that are or have been installed in Drupal's file system.",
-    'fields' => array(
-      'filename' => array(
-        'description' => 'The path of the primary file for this item, relative to the Drupal root; e.g. modules/node/node.module.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'name' => array(
-        'description' => 'The name of the item; e.g. node.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'type' => array(
-        'description' => 'The type of the item, either module, theme, or theme_engine.',
-        'type' => 'varchar',
-        'length' => 12,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'owner' => array(
-        'description' => "A theme's 'parent' . Can be either a theme or an engine.",
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-      'status' => array(
-        'description' => 'Boolean indicating whether or not this item is enabled.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'bootstrap' => array(
-        'description' => "Boolean indicating whether this module is loaded during Drupal's early bootstrapping phase (e.g. even before the page cache is consulted).",
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'schema_version' => array(
-        'description' => "The module's database schema version number. -1 if the module is not installed (its tables do not exist); 0 or the largest N of the module's hook_update_N() function that has either been run or existed when the module was first installed.",
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => -1,
-        'size' => 'small',
-      ),
-      'weight' => array(
-        'description' => "The order in which this module's hooks should be invoked relative to other modules. Equal-weighted modules are ordered by name.",
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'info' => array(
-        'description' => "A serialized array containing information from the module's .info file; keys can include name, description, package, version, core, dependencies, and php.",
-        'type' => 'blob',
-        'not null' => FALSE,
-      ),
-    ),
-    'primary key' => array('filename'),
-    'indexes' => array(
-      'system_list' => array('status', 'bootstrap', 'type', 'weight', 'name'),
-      'type_name' => array('type', 'name'),
-    ),
-  );
-
   $schema['url_alias'] = array(
     'description' => 'A list of URL aliases for Drupal paths; a user may visit either the source or destination path.',
     'fields' => array(
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 4524a49..7b34f3f 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2653,116 +2653,6 @@ function system_check_directory($form_element) {
 }
 
 /**
- * Retrieves the current status of an array of files in the system table.
- *
- * @param $files
- *   An array of files to check.
- * @param $type
- *   The type of the files.
- */
-function system_get_files_database(&$files, $type) {
-  // Extract current files from database.
-  $result = db_query("SELECT filename, name, type, status, schema_version, weight FROM {system} WHERE type = :type", array(':type' => $type));
-  foreach ($result as $file) {
-    if (isset($files[$file->name]) && is_object($files[$file->name])) {
-      $file->uri = $file->filename;
-      foreach ($file as $key => $value) {
-        if (!isset($files[$file->name]->$key)) {
-          $files[$file->name]->$key = $value;
-        }
-      }
-    }
-  }
-}
-
-/**
- * Updates the records in the system table based on the files array.
- *
- * @param $files
- *   An array of files.
- * @param $type
- *   The type of the files.
- */
-function system_update_files_database(&$files, $type) {
-  $result = db_query("SELECT * FROM {system} WHERE type = :type", array(':type' => $type));
-
-  // Add all files that need to be deleted to a DatabaseCondition.
-  $delete = db_or();
-  foreach ($result as $file) {
-    if (isset($files[$file->name]) && is_object($files[$file->name])) {
-      // Keep the old filename from the database in case the file has moved.
-      $old_filename = $file->filename;
-
-      $updated_fields = array();
-
-      // Handle info specially, compare the serialized value.
-      $serialized_info = serialize($files[$file->name]->info);
-      if ($serialized_info != $file->info) {
-        $updated_fields['info'] = $serialized_info;
-      }
-      unset($file->info);
-
-      // Scan remaining fields to find only the updated values.
-      foreach ($file as $key => $value) {
-        if (isset($files[$file->name]->$key) && $files[$file->name]->$key != $value) {
-          $updated_fields[$key] = $files[$file->name]->$key;
-        }
-      }
-
-      // Update the record.
-      if (count($updated_fields)) {
-        db_update('system')
-          ->fields($updated_fields)
-          ->condition('filename', $old_filename)
-          ->execute();
-      }
-
-      // Indicate that the file exists already.
-      $files[$file->name]->exists = TRUE;
-    }
-    else {
-      // File is not found in file system, so delete record from the system table.
-      $delete->condition('filename', $file->filename);
-    }
-  }
-
-  if (count($delete) > 0) {
-    // Delete all missing files from the system table, but only if the plugin
-    // has never been installed.
-    db_delete('system')
-      ->condition($delete)
-      ->condition('schema_version', -1)
-      ->execute();
-  }
-
-  // All remaining files are not in the system table, so we need to add them.
-  $query = db_insert('system')->fields(array('filename', 'name', 'type', 'owner', 'info'));
-  foreach ($files as &$file) {
-    if (isset($file->exists)) {
-      unset($file->exists);
-    }
-    else {
-      $query->values(array(
-        'filename' => $file->uri,
-        'name' => $file->name,
-        'type' => $type,
-        'owner' => isset($file->owner) ? $file->owner : '',
-        'info' => serialize($file->info),
-      ));
-      $file->type = $type;
-      $file->status = 0;
-      $file->schema_version = -1;
-    }
-  }
-  $query->execute();
-
-  // If any module or theme was moved to a new location, we need to reset the
-  // system_list() cache or we will continue to load the old copy, look for
-  // schema updates in the wrong place, etc.
-  system_list_reset();
-}
-
-/**
  * Returns an array of information about enabled modules or themes.
  *
  * This function returns the information from the {system} table corresponding
@@ -2787,9 +2677,9 @@ function system_update_files_database(&$files, $type) {
 function system_get_info($type, $name = NULL) {
   $info = array();
   if ($type == 'module') {
-    $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);
+    $data = system_rebuild_module_data();
+    foreach (module_list() as $module) {
+      $info[$module] = $data[$module]->info;
     }
   }
   else {
@@ -2927,11 +2817,25 @@ function system_rebuild_module_data() {
   // reference from system_list_reset() during the rebuild.
   if (!isset($modules_cache)) {
     $modules = _system_rebuild_module_data();
+    $files = array();
     ksort($modules);
-    system_get_files_database($modules, 'module');
-    system_update_files_database($modules, 'module');
+    // Add name, status, weight, and schema version.
+    $enabled_modules = config('system.module')->get('enabled');
+    $disabled_modules = config('system.module.disabled')->get();
+    $all_modules = $enabled_modules + $disabled_modules;
+    foreach ($modules as $module => $record) {
+      $record->name = $module;
+      $record->weight = isset($all_modules[$module]) ? $all_modules[$module] : 0;
+      $record->status = (int) isset($enabled_modules[$module]);
+      $record->schema_version = SCHEMA_UNINSTALLED;
+      $files[$module] = $record->filename;
+    }
     $modules = _module_build_dependencies($modules);
     $modules_cache = $modules;
+
+    // Store filenames to allow system_list() and drupal_get_filename() to
+    // retrieve them without having to rebuild or scan the filesystem.
+    state()->set('system.module.files', $files);
   }
   return $modules_cache;
 }
@@ -2947,20 +2851,10 @@ function _system_update_bootstrap_status() {
   $bootstrap_modules = array();
   foreach (bootstrap_hooks() as $hook) {
     foreach (module_implements($hook) as $module) {
-      $bootstrap_modules[] = $module;
+      $bootstrap_modules[$module] = drupal_get_filename('module', $module);
     }
   }
-  $query = db_update('system')->fields(array('bootstrap' => 0));
-  if ($bootstrap_modules) {
-    db_update('system')
-      ->fields(array('bootstrap' => 1))
-      ->condition('name', $bootstrap_modules, 'IN')
-      ->execute();
-    $query->condition('name', $bootstrap_modules, 'NOT IN');
-  }
-  $query->execute();
-  // Reset the cached list of bootstrap modules.
-  system_list_reset();
+  state()->set('system.module.bootstrap', $bootstrap_modules);
 }
 
 /**
@@ -3092,8 +2986,27 @@ function _system_rebuild_theme_data() {
 function system_rebuild_theme_data() {
   $themes = _system_rebuild_theme_data();
   ksort($themes);
-  system_get_files_database($themes, 'theme');
-  system_update_files_database($themes, 'theme');
+  // @todo This function has no business in determining/setting the status of
+  //   a theme, but various other functions expect it to return themes with a
+  //   $status property. system_list() stores the return value of this function
+  //   in state, and ensures to set/override the $status property for each theme
+  //   based on the current config. Remove this code here when themes have a
+  //   proper installation status.
+  // @see http://drupal.org/node/1067408
+  $enabled_themes = config('system.theme')->get('enabled');
+  $files = array();
+  foreach ($themes as $name => $theme) {
+    $theme->status = (int) isset($enabled_themes[$name]);
+    $files[$name] = $theme->filename;
+  }
+  // Replace last known theme data state.
+  // @todo Obsolete with proper installation status for themes.
+  state()->set('system.theme.data', $themes);
+
+  // Store filenames to allow system_list() and drupal_get_filename() to
+  // retrieve them without having to rebuild or scan the filesystem.
+  state()->set('system.theme.files', $files);
+
   return $themes;
 }
 
diff --git a/core/modules/system/tests/modules/database_test/database_test.module b/core/modules/system/tests/modules/database_test/database_test.module
index 0180b03..93135c9 100644
--- a/core/modules/system/tests/modules/database_test/database_test.module
+++ b/core/modules/system/tests/modules/database_test/database_test.module
@@ -84,7 +84,7 @@ function database_test_menu() {
  * table should automatically dropped.
  */
 function database_test_db_query_temporary() {
-  $table_name = db_query_temporary('SELECT status FROM {system}', array());
+  $table_name = db_query_temporary('SELECT status FROM {filter}', array());
   return new JsonResponse(array(
     'table_name' => $table_name,
     'row_count' => db_select($table_name)->countQuery()->execute()->fetchField(),
diff --git a/core/modules/system/tests/modules/url_alter_test/url_alter_test.install b/core/modules/system/tests/modules/url_alter_test/url_alter_test.install
index 6e09ab5..eb4864f 100644
--- a/core/modules/system/tests/modules/url_alter_test/url_alter_test.install
+++ b/core/modules/system/tests/modules/url_alter_test/url_alter_test.install
@@ -5,8 +5,5 @@
  */
 function url_alter_test_install() {
   // Set the weight of this module to one higher than forum.module.
-  db_update('system')
-    ->fields(array('weight' => 2))
-    ->condition('name', 'url_alter_test')
-    ->execute();
+  module_set_weight('url_alter_test', 2);
 }
diff --git a/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php b/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php
index 27328c0..4f51883 100644
--- a/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php
+++ b/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php
@@ -166,11 +166,7 @@ function testUpdateContribOrder() {
    */
   function testUpdateBaseThemeSecurityUpdate() {
     // Only enable the subtheme, not the base theme.
-    db_update('system')
-      ->fields(array('status' => 1))
-      ->condition('type', 'theme')
-      ->condition('name', 'update_test_subtheme')
-      ->execute();
+    theme_enable(array('update_test_subtheme'));
 
     // Define the initial state for core and the subtheme.
     $system_info = array(
@@ -208,11 +204,13 @@ function testUpdateBaseThemeSecurityUpdate() {
   function testUpdateShowDisabledThemes() {
     $update_settings = config('update.settings');
     // Make sure all the update_test_* themes are disabled.
-    db_update('system')
-      ->fields(array('status' => 0))
-      ->condition('type', 'theme')
-      ->condition('name', 'update_test_%', 'LIKE')
-      ->execute();
+    $theme_config = config('system.theme');
+    foreach ($theme_config->get('enabled') as $theme => $weight) {
+      if (preg_match('/^update_test_/', $theme)) {
+        $theme_config->clear("enabled.$theme");
+      }
+    }
+    $theme_config->save();
 
     // Define the initial state for core and the test contrib themes.
     $system_info = array(
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 2395a84..7a5bbb1 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -68,6 +68,9 @@
 
 simpletest_script_reporter_init();
 
+// Prime module data.
+simpletest_prepare_module_data();
+
 // Execute tests.
 simpletest_script_execute_batch(simpletest_script_get_test_list());
 
