diff --git a/.htaccess b/.htaccess
index 00830a527af6b2a3fe47f09070abd1e8fbfe1bee..3e742b6a1eb186c8528f49bb89aca88574e0b9c3 100644
--- a/.htaccess
+++ b/.htaccess
@@ -25,9 +25,8 @@ ErrorDocument 404 /index.php
 DirectoryIndex index.php index.html index.htm
 
 # Override PHP settings that cannot be changed at runtime. See
-# sites/default/default.settings.php and
-# Drupal\Core\DrupalKernel::bootEnvironment() for settings that can be
-# changed at runtime.
+# sites/default/default.settings.php and drupal_environment_initialize() in
+# core/includes/bootstrap.inc for settings that can be changed at runtime.
 
 # PHP 5, Apache 1 and 2.
 <IfModule mod_php5.c>
@@ -120,7 +119,7 @@ DirectoryIndex index.php index.html index.htm
   RewriteRule ^ %1/core/%2 [L,QSA,R=301]
 
   # Pass all requests not referring directly to files in the filesystem to
-  # index.php.
+  # index.php. Clean URLs are handled in drupal_environment_initialize().
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_URI} !=/favicon.ico
diff --git a/core/authorize.php b/core/authorize.php
index 96fe9aeb3b691c6cbb604241f00459d7fccde558..f938f3903324c6ad706d1bfa61e09ab7819af82d 100644
--- a/core/authorize.php
+++ b/core/authorize.php
@@ -20,15 +20,13 @@
  * @link authorize Authorized operation helper functions @endlink
  */
 
-use Drupal\Core\DrupalKernel;
-use Symfony\Component\HttpFoundation\Request;
 use Drupal\Core\Site\Settings;
 use Drupal\Core\Page\DefaultHtmlPageRenderer;
 
 // Change the directory to the Drupal root.
 chdir('..');
 
-$autoloader = require_once __DIR__ . '/vendor/autoload.php';
+require_once __DIR__ . '/vendor/autoload.php';
 
 /**
  * Global flag to identify update.php and authorize.php runs.
@@ -53,9 +51,18 @@ function authorize_access_allowed() {
   return Settings::get('allow_authorize_operations', TRUE) && user_access('administer software updates');
 }
 
-$request = Request::createFromGlobals();
-$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');
-$kernel->prepareLegacyRequest($request);
+// *** Real work of the script begins here. ***
+
+require_once __DIR__ . '/includes/bootstrap.inc';
+require_once __DIR__ . '/includes/common.inc';
+require_once __DIR__ . '/includes/file.inc';
+require_once __DIR__ . '/includes/module.inc';
+require_once __DIR__ . '/includes/ajax.inc';
+
+// Prepare a minimal bootstrap.
+drupal_bootstrap(DRUPAL_BOOTSTRAP_PAGE_CACHE);
+$request = \Drupal::request();
+\Drupal::service('request_stack')->push($request);
 
 // We have to enable the user and system modules, even to check access and
 // display errors via the maintenance theme.
diff --git a/core/core.services.yml b/core/core.services.yml
index 479b76c3e9ac3a8be4cbcdae13a0996f2848193a..b6decf34edd2b88964c0b93ed337194ab486f164 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -201,10 +201,6 @@ services:
     arguments: ['@access_check.theme', '@request_stack']
     tags:
       - { name: service_collector, tag: theme_negotiator, call: addNegotiator }
-  theme.negotiator.request_subscriber:
-    class: Drupal\Core\EventSubscriber\ThemeNegotiatorRequestSubscriber
-    tags:
-      - { name: event_subscriber }
   theme.negotiator.default:
     class: Drupal\Core\Theme\DefaultNegotiator
     arguments: ['@config.factory']
@@ -598,6 +594,10 @@ services:
     tags:
       - { name: event_subscriber }
     arguments: ['@path.alias_manager', '@path_processor_manager']
+  legacy_request_subscriber:
+    class: Drupal\Core\EventSubscriber\LegacyRequestSubscriber
+    tags:
+      - { name: event_subscriber }
   finish_response_subscriber:
     class: Drupal\Core\EventSubscriber\FinishResponseSubscriber
     tags:
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 3e4fca8f06db8c8da751e7c2cef893027b3f999b..3d41fcb419dc37b26a00ee787b48466dd40b4640 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -6,16 +6,28 @@
 
 use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\Environment;
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Component\Utility\String;
+use Drupal\Component\Utility\Timer;
 use Drupal\Component\Utility\Unicode;
+use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\DrupalKernel;
+use Drupal\Core\Database\Database;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\Site\Settings;
+use Drupal\Core\Utility\Title;
 use Drupal\Core\Utility\Error;
 use Symfony\Component\ClassLoader\ApcClassLoader;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException as DependencyInjectionRuntimeException;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Drupal\Core\Language\Language;
+use Drupal\Core\Lock\DatabaseLockBackend;
+use Drupal\Core\Lock\LockBackendInterface;
 use Drupal\Core\Session\AnonymousUserSession;
 
 /**
@@ -114,36 +126,26 @@
 
 /**
  * First bootstrap phase: initialize configuration.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
  */
 const DRUPAL_BOOTSTRAP_CONFIGURATION = 0;
 
 /**
- * Second bootstrap phase, initialize a kernel.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
+ * Second bootstrap phase, initalize a kernel.
  */
 const DRUPAL_BOOTSTRAP_KERNEL = 1;
 
 /**
  * Third bootstrap phase: try to serve a cached page.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
  */
 const DRUPAL_BOOTSTRAP_PAGE_CACHE = 2;
 
 /**
  * Fourth bootstrap phase: load code for subsystems and modules.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
  */
 const DRUPAL_BOOTSTRAP_CODE = 3;
 
 /**
  * Final bootstrap phase: initialize language, path, theme, and modules.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
  */
 const DRUPAL_BOOTSTRAP_FULL = 4;
 
@@ -205,6 +207,11 @@
 /**
  * Returns the appropriate configuration directory.
  *
+ * Returns the configuration path based on the site's hostname, port, and
+ * pathname. Uses find_conf_path() to find the current configuration directory.
+ * See default.settings.php for examples on how the URL is converted to a
+ * directory.
+ *
  * @param bool $require_settings
  *   Only configuration directories with an existing settings.php file
  *   will be recognized. Defaults to TRUE. During initial installation,
@@ -213,36 +220,100 @@
  * @param bool $reset
  *   Force a full search for matching directories even if one had been
  *   found previously. Defaults to FALSE.
- * @param \Symfony\Component\HttpFoundation\Request $request
- *   (optional) The current request. Defaults to \Drupal::request() or a new
- *   request created from globals.
  *
- * @return string
- *   The path of the matching directory.@see default.settings.php
+ * @return
+ *   The path of the matching directory.
  *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
- *   Use \Drupal\Core\DrupalKernel::getSitePath() instead. If the kernel is
- *   unavailable or the site path needs to be recalculated then
- *   Drupal\Core\DrupalKernel::findSitePath() can be used.
- */
-function conf_path($require_settings = TRUE, $reset = FALSE, Request $request = NULL) {
-  if (!isset($request)) {
-    if (\Drupal::hasRequest()) {
-      $request = \Drupal::request();
-    }
-    // @todo Remove once external CLI scripts (Drush) are updated.
-    else {
-      $request = Request::createFromGlobals();
-    }
+ * @see default.settings.php
+ */
+function conf_path($require_settings = TRUE, $reset = FALSE) {
+  static $conf_path;
+
+  if (isset($conf_path) && !$reset) {
+    return $conf_path;
   }
-  if (\Drupal::hasService('kernel')) {
-    $site_path = \Drupal::service('kernel')->getSitePath();
+
+  // Check for a simpletest override.
+  if ($test_prefix = drupal_valid_test_ua()) {
+    $conf_path = 'sites/simpletest/' . substr($test_prefix, 10);
+    return $conf_path;
   }
-  if (!isset($site_path) || empty($site_path)) {
-    $site_path = DrupalKernel::findSitePath($request, $require_settings);
+
+  // Otherwise, use the normal $conf_path.
+  $script_name = $_SERVER['SCRIPT_NAME'];
+  if (!$script_name) {
+    $script_name = $_SERVER['SCRIPT_FILENAME'];
   }
-  return $site_path;
+  $http_host = $_SERVER['HTTP_HOST'];
+  $conf_path = find_conf_path($http_host, $script_name, $require_settings);
+  return $conf_path;
 }
+
+/**
+ * Finds the appropriate configuration directory for a given host and path.
+ *
+ * Finds a matching configuration directory file by stripping the website's
+ * hostname from left to right and pathname from right to left. By default,
+ * the directory must contain a 'settings.php' file for it to match. If the
+ * parameter $require_settings is set to FALSE, then a directory without a
+ * 'settings.php' file will match as well. The first configuration
+ * file found will be used and the remaining ones will be ignored. If no
+ * configuration file is found, returns a default value '$confdir/default'. See
+ * default.settings.php for examples on how the URL is converted to a directory.
+ *
+ * If a file named sites.php is present in the $confdir, it will be loaded
+ * prior to scanning for directories. That file can define aliases in an
+ * associative array named $sites. The array is written in the format
+ * '<port>.<domain>.<path>' => 'directory'. As an example, to create a
+ * directory alias for http://www.drupal.org:8080/mysite/test whose configuration
+ * file is in sites/example.com, the array should be defined as:
+ * @code
+ * $sites = array(
+ *   '8080.www.drupal.org.mysite.test' => 'example.com',
+ * );
+ * @endcode
+ *
+ * @param $http_host
+ *   The hostname and optional port number, e.g. "www.example.com" or
+ *   "www.example.com:8080".
+ * @param $script_name
+ *   The part of the URL following the hostname, including the leading slash.
+ * @param $require_settings
+ *   Defaults to TRUE. If TRUE, then only match directories with a
+ *   'settings.php' file. Otherwise match any directory.
+ *
+ * @return
+ *   The path of the matching configuration directory.
+ *
+ * @see default.settings.php
+ * @see example.sites.php
+ * @see conf_path()
+ */
+function find_conf_path($http_host, $script_name, $require_settings = TRUE) {
+  // Determine whether multi-site functionality is enabled.
+  if (!file_exists(DRUPAL_ROOT . '/sites/sites.php')) {
+    return 'sites/default';
+  }
+
+  $sites = array();
+  include DRUPAL_ROOT . '/sites/sites.php';
+
+  $uri = explode('/', $script_name);
+  $server = explode('.', implode('.', array_reverse(explode(':', rtrim($http_host, '.')))));
+  for ($i = count($uri) - 1; $i > 0; $i--) {
+    for ($j = count($server); $j > 0; $j--) {
+      $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
+      if (isset($sites[$dir]) && file_exists(DRUPAL_ROOT . '/sites/' . $sites[$dir])) {
+        $dir = $sites[$dir];
+      }
+      if (file_exists(DRUPAL_ROOT . '/sites/' . $dir . '/settings.php') || (!$require_settings && file_exists(DRUPAL_ROOT . '/sites/' . $dir))) {
+        return "sites/$dir";
+      }
+    }
+  }
+  return 'sites/default';
+}
+
 /**
  * Returns the path of a configuration directory.
  *
@@ -262,6 +333,207 @@ function config_get_config_directory($type = CONFIG_ACTIVE_DIRECTORY) {
   throw new \Exception(format_string('The configuration directory type %type does not exist.', array('%type' => $type)));
 }
 
+/**
+ * Initializes the PHP environment.
+ */
+function drupal_environment_initialize() {
+  if (!isset($_SERVER['SERVER_PROTOCOL']) || ($_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.0' && $_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.1')) {
+    $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0';
+  }
+
+  if (isset($_SERVER['HTTP_HOST'])) {
+    // As HTTP_HOST is user input, ensure it only contains characters allowed
+    // in hostnames. See RFC 952 (and RFC 2181).
+    // $_SERVER['HTTP_HOST'] is lowercased here per specifications.
+    $_SERVER['HTTP_HOST'] = strtolower($_SERVER['HTTP_HOST']);
+    if (!drupal_valid_http_host($_SERVER['HTTP_HOST'])) {
+      // HTTP_HOST is invalid, e.g. if containing slashes it may be an attack.
+      header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
+      exit;
+    }
+  }
+  else {
+    // Some pre-HTTP/1.1 clients will not send a Host header. Ensure the key is
+    // defined for E_ALL compliance.
+    $_SERVER['HTTP_HOST'] = '';
+  }
+
+  // @todo Refactor with the Symfony Request object.
+  _current_path(request_path());
+
+  // Enforce E_STRICT, but allow users to set levels not part of E_STRICT.
+  error_reporting(E_STRICT | E_ALL | error_reporting());
+
+  // Override PHP settings required for Drupal to work properly.
+  // sites/default/default.settings.php contains more runtime settings.
+  // The .htaccess file contains settings that cannot be changed at runtime.
+
+  // Use session cookies, not transparent sessions that puts the session id in
+  // the query string.
+  ini_set('session.use_cookies', '1');
+  ini_set('session.use_only_cookies', '1');
+  ini_set('session.use_trans_sid', '0');
+  // Don't send HTTP headers using PHP's session handler.
+  // Send an empty string to disable the cache limiter.
+  ini_set('session.cache_limiter', '');
+  // Use httponly session cookies.
+  ini_set('session.cookie_httponly', '1');
+
+  // Set sane locale settings, to ensure consistent string, dates, times and
+  // numbers handling.
+  setlocale(LC_ALL, 'C');
+}
+
+/**
+ * Validates that a hostname (for example $_SERVER['HTTP_HOST']) is safe.
+ *
+ * @return
+ *  TRUE if only containing valid characters, or FALSE otherwise.
+ */
+function drupal_valid_http_host($host) {
+  return preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host);
+}
+
+/**
+ * Sets the base URL, cookie domain, and session name from configuration.
+ */
+function drupal_settings_initialize() {
+  // Export these settings.php variables to the global namespace.
+  global $base_url, $cookie_domain, $config_directories, $config;
+  $databases = array();
+  $settings = array();
+  $config = array();
+
+  // Make conf_path() available as local variable in settings.php.
+  $conf_path = conf_path();
+  if (is_readable(DRUPAL_ROOT . '/' . $conf_path . '/settings.php')) {
+    require DRUPAL_ROOT . '/' . $conf_path . '/settings.php';
+  }
+  // Initialize Database.
+  Database::setMultipleConnectionInfo($databases);
+  // Initialize Settings.
+  new Settings($settings);
+}
+
+/**
+ * Initializes global request variables.
+ *
+ * @todo D8: Eliminate this entirely in favor of Request object.
+ */
+function _drupal_request_initialize() {
+  // Provided by settings.php.
+  // @see drupal_settings_initialize()
+  global $base_url, $cookie_domain;
+  // Set and derived from $base_url by this function.
+  global $base_path, $base_root, $script_path;
+  global $base_secure_url, $base_insecure_url;
+
+  $is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on';
+
+  if (isset($base_url)) {
+    // Parse fixed base URL from settings.php.
+    $parts = parse_url($base_url);
+    if (!isset($parts['path'])) {
+      $parts['path'] = '';
+    }
+    $base_path = $parts['path'] . '/';
+    // Build $base_root (everything until first slash after "scheme://").
+    $base_root = substr($base_url, 0, strlen($base_url) - strlen($parts['path']));
+  }
+  else {
+    // Create base URL
+    $http_protocol = $is_https ? 'https' : 'http';
+    $base_root = $http_protocol . '://' . $_SERVER['HTTP_HOST'];
+
+    $base_url = $base_root;
+
+    // For a request URI of '/index.php/foo', $_SERVER['SCRIPT_NAME'] is
+    // '/index.php', whereas $_SERVER['PHP_SELF'] is '/index.php/foo'.
+    if ($dir = rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/')) {
+      // Remove "core" directory if present, allowing install.php, update.php,
+      // and others to auto-detect a base path.
+      $core_position = strrpos($dir, '/core');
+      if ($core_position !== FALSE && strlen($dir) - 5 == $core_position) {
+        $base_path = substr($dir, 0, $core_position);
+      }
+      else {
+        $base_path = $dir;
+      }
+      $base_url .= $base_path;
+      $base_path .= '/';
+    }
+    else {
+      $base_path = '/';
+    }
+  }
+  $base_secure_url = str_replace('http://', 'https://', $base_url);
+  $base_insecure_url = str_replace('https://', 'http://', $base_url);
+
+  // Determine the path of the script relative to the base path, and add a
+  // trailing slash. This is needed for creating URLs to Drupal pages.
+  if (!isset($script_path)) {
+    $script_path = '';
+    // We don't expect scripts outside of the base path, but sanity check
+    // anyway.
+    if (strpos($_SERVER['SCRIPT_NAME'], $base_path) === 0) {
+      $script_path = substr($_SERVER['SCRIPT_NAME'], strlen($base_path)) . '/';
+      // If the request URI does not contain the script name, then clean URLs
+      // are in effect and the script path can be similarly dropped from URL
+      // generation. For servers that don't provide $_SERVER['REQUEST_URI'], we
+      // do not know the actual URI requested by the client, and request_uri()
+      // returns a URI with the script name, resulting in non-clean URLs unless
+      // there's other code that intervenes.
+      if (strpos(request_uri(TRUE) . '/', $base_path . $script_path) !== 0) {
+        $script_path = '';
+      }
+      // @todo Temporary BC for install.php, update.php, and other scripts.
+      //   - http://drupal.org/node/1547184
+      //   - http://drupal.org/node/1546082
+      if ($script_path !== 'index.php/') {
+        $script_path = '';
+      }
+    }
+  }
+
+  if ($cookie_domain) {
+    // If the user specifies the cookie domain, also use it for session name.
+    $session_name = $cookie_domain;
+  }
+  else {
+    // Otherwise use $base_url as session name, without the protocol
+    // to use the same session identifiers across HTTP and HTTPS.
+    list( , $session_name) = explode('://', $base_url, 2);
+    // HTTP_HOST can be modified by a visitor, but we already sanitized it
+    // in drupal_settings_initialize().
+    if (!empty($_SERVER['HTTP_HOST'])) {
+      $cookie_domain = $_SERVER['HTTP_HOST'];
+      // Strip leading periods, www., and port numbers from cookie domain.
+      $cookie_domain = ltrim($cookie_domain, '.');
+      if (strpos($cookie_domain, 'www.') === 0) {
+        $cookie_domain = substr($cookie_domain, 4);
+      }
+      $cookie_domain = explode(':', $cookie_domain);
+      $cookie_domain = '.' . $cookie_domain[0];
+    }
+  }
+  // Per RFC 2109, cookie domains must contain at least one dot other than the
+  // first. For hosts such as 'localhost' or IP Addresses we don't set a cookie domain.
+  if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
+    ini_set('session.cookie_domain', $cookie_domain);
+  }
+  // To prevent session cookies from being hijacked, a user can configure the
+  // SSL version of their website to only transfer session cookies via SSL by
+  // using PHP's session.cookie_secure setting. The browser will then use two
+  // separate session cookies for the HTTPS and HTTP versions of the site. So we
+  // must use different session identifiers for HTTPS and HTTP to prevent a
+  // cookie collision.
+  if ($is_https) {
+    ini_set('session.cookie_secure', TRUE);
+  }
+  $prefix = ini_get('session.cookie_secure') ? 'SSESS' : 'SESS';
+  session_name($prefix . substr(hash('sha256', $session_name), 0, 32));
+}
+
 /**
  * Returns and optionally sets the filename for a system resource.
  *
@@ -984,54 +1256,138 @@ function drupal_anonymous_user() {
 }
 
 /**
- * Bootstraps DrupalKernel to a given boot level.
+ * Ensures Drupal is bootstrapped to the specified phase.
+ *
+ * In order to bootstrap Drupal from another PHP script, you can use this code:
+ * @code
+ *   require_once '/path/to/drupal/core/vendor/autoload.php';
+ *   require_once '/path/to/drupal/core/includes/bootstrap.inc';
+ *   drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+ * @endcode
  *
  * @param $phase
- *   A constant telling which phase to bootstrap to. Possible values:
+ *   A constant telling which phase to bootstrap to. When you bootstrap to a
+ *   particular phase, all earlier phases are run automatically. Possible
+ *   values:
  *   - DRUPAL_BOOTSTRAP_CONFIGURATION: Initializes configuration.
  *   - DRUPAL_BOOTSTRAP_KERNEL: Initalizes a kernel.
+ *   - DRUPAL_BOOTSTRAP_PAGE_CACHE: Tries to serve a cached page.
+ *   - DRUPAL_BOOTSTRAP_CODE: Loads code for subsystems and modules.
+ *   - DRUPAL_BOOTSTRAP_FULL: Fully loads Drupal. Validates and fixes input
+ *     data.
  *
- * @return int
+ * @return
  *   The most recently completed phase.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
- *   Interact directly with the kernel.
- *
- * @todo Obsolete. Remove once Drush has been updated.
  */
 function drupal_bootstrap($phase = NULL) {
-  // Temporary variables used for booting later legacy phases.
-  /** @var \Drupal\Core\DrupalKernel $kernel */
-  static $kernel;
-  static $boot_level = 0;
-
+  // Not drupal_static(), because does not depend on any run-time information.
+  static $phases = array(
+    DRUPAL_BOOTSTRAP_CONFIGURATION,
+    DRUPAL_BOOTSTRAP_KERNEL,
+    DRUPAL_BOOTSTRAP_PAGE_CACHE,
+    DRUPAL_BOOTSTRAP_CODE,
+    DRUPAL_BOOTSTRAP_FULL,
+  );
+  // Not drupal_static(), because the only legitimate API to control this is to
+  // call drupal_bootstrap() with a new phase parameter.
+  static $final_phase = -1;
+  // Not drupal_static(), because it's impossible to roll back to an earlier
+  // bootstrap state.
+  static $stored_phase = -1;
+
+  // Store the phase name so it's not forgotten during recursion. Additionally,
+  // ensure that $final_phase is never rolled back to an earlier bootstrap
+  // state.
+  if ($phase > $final_phase) {
+    $final_phase = $phase;
+  }
   if (isset($phase)) {
-    $request = Request::createFromGlobals();
-    for ($current_phase = $boot_level; $current_phase <= $phase; $current_phase++) {
+    // Call a phase if it has not been called before and is below the requested
+    // phase.
+    while ($phases && $phase > $stored_phase && $final_phase > $stored_phase) {
+      $current_phase = array_shift($phases);
+
+      // This function is re-entrant. Only update the completed phase when the
+      // current call actually resulted in a progress in the bootstrap process.
+      if ($current_phase > $stored_phase) {
+        $stored_phase = $current_phase;
+      }
 
       switch ($current_phase) {
         case DRUPAL_BOOTSTRAP_CONFIGURATION:
-          $kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod');
+          _drupal_bootstrap_configuration();
           break;
 
         case DRUPAL_BOOTSTRAP_KERNEL:
-          $kernel->boot();
+          _drupal_bootstrap_kernel();
           break;
 
         case DRUPAL_BOOTSTRAP_PAGE_CACHE:
-          $kernel->handlePageCache($request);
+          _drupal_bootstrap_page_cache();
           break;
 
         case DRUPAL_BOOTSTRAP_CODE:
+          require_once __DIR__ . '/common.inc';
+          _drupal_bootstrap_code();
+          break;
+
         case DRUPAL_BOOTSTRAP_FULL:
-          $kernel->prepareLegacyRequest($request);
+          _drupal_bootstrap_full();
           break;
       }
     }
-    $boot_level = $phase;
   }
+  return $stored_phase;
+}
+
+/**
+ * Handles an entire PHP request.
+ *
+ * This function may be called by PHP scripts (e.g., Drupal's index.php) that
+ * want Drupal to take over the entire PHP processing of the request. The only
+ * expectation is that PHP's superglobals are initialized as desired (PHP does
+ * this automatically, but some scripts might want to alter them) and that the
+ * DRUPAL_ROOT constant is defined and set to the absolute server directory of
+ * Drupal's codebase.
+ *
+ * Scripts and applications that want to invoke multiple Drupal requests within
+ * a single PHP request, or Drupal request handling within some larger workflow,
+ * should not call this function, but instead instantiate and use
+ * \Drupal\Core\DrupalKernel as needed.
+ *
+ * @param boolean $test_only
+ *   Whether to restrict handling to only requests invoked by SimpleTest.
+ *
+ * @see index.php
+ */
+function drupal_handle_request($test_only = FALSE) {
+  // Initialize the environment, load settings.php, and activate a PSR-0 class
+  // autoloader with required namespaces registered.
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+
+  // Exit if we should be in a test environment but aren't.
+  if ($test_only && !drupal_valid_test_ua()) {
+    header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
+    exit;
+  }
+
+  $kernel = new DrupalKernel('prod', drupal_classloader(), !$test_only);
 
-  return \Drupal::getContainer() ? DRUPAL_BOOTSTRAP_CODE : DRUPAL_BOOTSTRAP_CONFIGURATION;
+  // @todo Remove this once everything in the bootstrap has been
+  //   converted to services in the DIC.
+  $kernel->boot();
+
+  // Create a request object from the HttpFoundation.
+  $request = Request::createFromGlobals();
+  $container = \Drupal::getContainer();
+  $container->set('request', $request);
+  $container->get('request_stack')->push($request);
+
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
+
+  $response = $kernel->handle($request)->prepare($request)->send();
+
+  $kernel->terminate($request, $response);
 }
 
 /**
@@ -1113,14 +1469,111 @@ function _drupal_exception_handler($exception) {
   }
 }
 
+/**
+ * Sets up the script environment and loads settings.php.
+ */
+function _drupal_bootstrap_configuration() {
+  drupal_environment_initialize();
+
+  // Indicate that code is operating in a test child site.
+  if ($test_prefix = drupal_valid_test_ua()) {
+    // Only code that interfaces directly with tests should rely on this
+    // constant; e.g., the error/exception handler conditionally adds further
+    // error information into HTTP response headers that are consumed by
+    // Simpletest's internal browser.
+    define('DRUPAL_TEST_IN_CHILD_SITE', TRUE);
+
+    // Log fatal errors to the test site directory.
+    ini_set('log_errors', 1);
+    ini_set('error_log', DRUPAL_ROOT . '/sites/simpletest/' . substr($test_prefix, 10) . '/error.log');
+  }
+  else {
+    // Ensure that no other code defines this.
+    define('DRUPAL_TEST_IN_CHILD_SITE', FALSE);
+  }
+
+  // Initialize the configuration, including variables from settings.php.
+  drupal_settings_initialize();
+  _drupal_request_initialize();
+
+  // Activate the class loader.
+  drupal_classloader();
+
+  // Start a page timer:
+  Timer::start('page');
+
+  // Detect string handling method.
+  Unicode::check();
+
+  // Set the Drupal custom error handler. (requires \Drupal::config())
+  set_error_handler('_drupal_error_handler');
+  set_exception_handler('_drupal_exception_handler');
+
+  // Redirect the user to the installation script if Drupal has not been
+  // installed yet (i.e., if no $databases array has been defined in the
+  // settings.php file) and we are not already installing.
+  if (!Database::getConnectionInfo() && !drupal_installation_attempted() && !drupal_is_cli()) {
+    include_once __DIR__ . '/install.inc';
+    install_goto('core/install.php');
+  }
+}
+
+/**
+ * Initialize the kernel / service container.
+ */
+function _drupal_bootstrap_kernel() {
+  // Normally, index.php puts a container in the Drupal class by creating a
+  // kernel. If there is no container yet, create one.
+  if (!\Drupal::getContainer()) {
+    $kernel = new DrupalKernel('prod', drupal_classloader());
+    $kernel->boot();
+    $request = Request::createFromGlobals();
+    $container = \Drupal::getContainer();
+    $container->set('request', $request);
+    $container->get('request_stack')->push($request);
+  }
+}
+
+/**
+ * Attempts to serve a page from the cache.
+ */
+function _drupal_bootstrap_page_cache() {
+  require_once __DIR__ . '/database.inc';
+  // Check for a cache mode force from settings.php.
+  if (Settings::get('page_cache_without_database')) {
+    $cache_enabled = TRUE;
+  }
+  else {
+    $config = \Drupal::config('system.performance');
+    $cache_enabled = $config->get('cache.page.use_internal');
+  }
+
+  $request = \Drupal::request();
+  // If there is no session cookie and cache is enabled (or forced), try
+  // to serve a cached page.
+  if (!$request->cookies->has(session_name()) && $cache_enabled && drupal_page_is_cacheable()) {
+    // Get the page from the cache.
+    $response = drupal_page_get_cache($request);
+    // If there is a cached page, display it.
+    if ($response) {
+      $response->headers->set('X-Drupal-Cache', 'HIT');
+
+      drupal_serve_page_from_cache($response, $request);
+
+      // We are done.
+      $response->prepare($request);
+      $response->send();
+      exit;
+    }
+  }
+}
+
 /**
  * Returns the current bootstrap phase for this Drupal process.
  *
  * The current phase is the one most recently completed by drupal_bootstrap().
  *
  * @see drupal_bootstrap()
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
  */
 function drupal_get_bootstrap_phase() {
   return drupal_bootstrap();
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 62c8ed7131c71d6c00b85c86f84f75f6f4ba4a71..5572e547228efdef1871f6c9986fb9db9ec399ca 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2603,6 +2603,70 @@ function drupal_valid_token($token, $value = '') {
   return \Drupal::csrfToken()->validate($token, $value);
 }
 
+/**
+ * Loads code for subsystems and modules, and registers stream wrappers.
+ */
+function _drupal_bootstrap_code() {
+  require_once __DIR__ . '/../../' . Settings::get('path_inc', 'core/includes/path.inc');
+  require_once __DIR__ . '/module.inc';
+  require_once __DIR__ . '/theme.inc';
+  require_once __DIR__ . '/pager.inc';
+  require_once __DIR__ . '/../../' . Settings::get('menu_inc', 'core/includes/menu.inc');
+  require_once __DIR__ . '/tablesort.inc';
+  require_once __DIR__ . '/file.inc';
+  require_once __DIR__ . '/unicode.inc';
+  require_once __DIR__ . '/form.inc';
+  require_once __DIR__ . '/mail.inc';
+  require_once __DIR__ . '/ajax.inc';
+  require_once __DIR__ . '/errors.inc';
+  require_once __DIR__ . '/schema.inc';
+  require_once __DIR__ . '/entity.inc';
+
+  // Load all enabled modules
+  \Drupal::moduleHandler()->loadAll();
+
+  // Make sure all stream wrappers are registered.
+  file_get_stream_wrappers();
+  // Ensure mt_rand() is reseeded to prevent random values from one page load
+  // being exploited to predict random values in subsequent page loads.
+  $seed = unpack("L", Crypt::randomBytes(4));
+  mt_srand($seed[1]);
+
+  // Set the allowed protocols once we have the config available.
+  $allowed_protocols = \Drupal::config('system.filter')->get('protocols');
+  if (!isset($allowed_protocols)) {
+    // \Drupal\Component\Utility\UrlHelper::filterBadProtocol() is called by the
+    // installer and update.php, in which case the configuration may not exist
+    // (yet). Provide a minimal default set of allowed protocols for these
+    // cases.
+    $allowed_protocols = array('http', 'https');
+  }
+  UrlHelper::setAllowedProtocols($allowed_protocols);
+}
+
+/**
+ * Temporary BC function for scripts not using DrupalKernel.
+ *
+ * DrupalKernel skips this and replicates it via event listeners.
+ *
+ * @see \Drupal\Core\EventSubscriber\PathSubscriber;
+ * @see \Drupal\Core\EventSubscriber\LegacyRequestSubscriber;
+ */
+function _drupal_bootstrap_full($skip = FALSE) {
+  static $called = FALSE;
+
+  if ($called || $skip) {
+    $called = TRUE;
+    return;
+  }
+
+  // Let all modules take action before the menu system handles the request.
+  // We do not want this while running update.php.
+  if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
+    drupal_theme_initialize();
+  }
+}
+
 /**
  * Stores the current page in the cache.
  *
diff --git a/core/includes/errors.inc b/core/includes/errors.inc
index ebe1cd5cbda56a457648d3c8346f4ea4de537d3c..8b0b9e43ec04fa47dcab3398ea4831bccd13b84e 100644
--- a/core/includes/errors.inc
+++ b/core/includes/errors.inc
@@ -120,7 +120,7 @@ function _drupal_log_error($error, $fatal = FALSE) {
   $is_installer = drupal_installation_attempted();
   // Initialize a maintenance theme if the bootstrap was not complete.
   // Do it early because drupal_set_message() triggers a drupal_theme_initialize().
-  if ($fatal && drupal_get_bootstrap_phase() < DRUPAL_BOOTSTRAP_CODE) {
+  if ($fatal && (drupal_get_bootstrap_phase() != DRUPAL_BOOTSTRAP_FULL)) {
     // The installer initializes a maintenance theme at the earliest possible
     // point in time already. Do not unset that.
     if (!$is_installer) {
@@ -244,9 +244,9 @@ function _drupal_log_error($error, $fatal = FALSE) {
 /**
  * Returns the current error level.
  *
- * This function should only be used to get the current error level prior to
- * DRUPAL_BOOTSTRAP_KERNEL or before Drupal is installed. In all other situations
- * the following code is preferred:
+ * This function should only be used to get the current error level pre
+ * DRUPAL_BOOTSTRAP_KERNEL or before Drupal is installed. In all other
+ * situations the following code is preferred:
  * @code
  * \Drupal::config('system.logging')->get('error_level');
  * @endcode
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index ed2fc975bb8f9c01a95cf2f2857b2cf53fe3d4e8..b00d23b21d3829dbd7f88690dbb1edd88d363f2e 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -272,6 +272,12 @@ function install_begin_request(&$install_state) {
   // Allow command line scripts to override server variables used by Drupal.
   require_once __DIR__ . '/bootstrap.inc';
 
+  // Initialize conf_path().
+  // This primes the site path to be used during installation. By not requiring
+  // settings.php, a bare site folder can be prepared in the /sites directory,
+  // which will be used for installing Drupal.
+  conf_path(FALSE);
+
   // If the hash salt leaks, it becomes possible to forge a valid testing user
   // agent, install a new copy of Drupal, and take over the original site.
   // The user agent header is used to pass a database prefix in the request when
@@ -282,8 +288,7 @@ function install_begin_request(&$install_state) {
     exit;
   }
 
-  $site_path = DrupalKernel::findSitePath($request, FALSE);
-  Settings::initialize($site_path);
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
 
   // Ensure that procedural dependencies are loaded as early as possible,
   // since the error/exception handlers depend on them.
@@ -351,24 +356,27 @@ function install_begin_request(&$install_state) {
     $environment = 'prod';
   }
 
-  $kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), $environment, FALSE);
-  $kernel->setSitePath($site_path);
+  $kernel = new DrupalKernel($environment, drupal_classloader(), FALSE);
   $kernel->boot();
+
+  // Enter the request scope and add the Request.
+  // @todo Remove this after converting all installer screens into controllers.
   $container = $kernel->getContainer();
+  $container->enterScope('request');
+  $container->set('request', $request, 'request');
+  $container->get('request_stack')->push($request);
 
   // Register the file translation service.
   if (isset($GLOBALS['config']['locale.settings']['translation.path'])) {
     $directory = $GLOBALS['config']['locale.settings']['translation.path'];
   }
   else {
-    $directory = $site_path . '/files/translations';
+    $directory = conf_path() . '/files/translations';
   }
   $container->set('string_translator.file_translation', new FileTranslation($directory));
   $container->get('string_translation')
     ->addTranslator($container->get('string_translator.file_translation'));
 
-  $kernel->prepareLegacyRequest($request);
-
   // Set the default language to the selected language, if any.
   if (isset($install_state['parameters']['langcode'])) {
     $default_language = new Language(array('id' => $install_state['parameters']['langcode']));
@@ -1447,6 +1455,7 @@ function install_load_profile(&$install_state) {
  *   An array of information about the current installation state.
  */
 function install_bootstrap_full() {
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
   \Drupal::service('session_manager')->initialize();
 }
 
diff --git a/core/includes/install.inc b/core/includes/install.inc
index ce7db8771e0f1e672b74a7668f754e56c8f625f8..67e41f66225b8d8247f9c00424109b922c5875ce 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -9,6 +9,8 @@
 use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\OpCodeCache;
 use Drupal\Component\Utility\UrlHelper;
+use Drupal\Core\Database\Database;
+use Drupal\Core\DrupalKernel;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\Site\Settings;
 
@@ -632,29 +634,24 @@ function drupal_verify_profile($install_state) {
  *   to set the default language.
  */
 function drupal_install_system($install_state) {
-  // Remove the service provider of the early installer.
+  // Boot a new kernel into a regular production environment.
+  $request = \Drupal::hasRequest() ? \Drupal::request() : FALSE;
+
   unset($GLOBALS['conf']['container_service_providers']['InstallerServiceProvider']);
+  $kernel = new DrupalKernel('prod', drupal_classloader(), FALSE);
+  $kernel->boot();
 
-  // Reboot into a full production environment to continue the installation.
-  $kernel = \Drupal::service('kernel');
-  $kernel->shutdown();
-  $kernel->prepareLegacyRequest(\Drupal::request());
+  if ($request) {
+    $kernel->getContainer()->enterScope('request');
+    $kernel->getContainer()->set('request', $request, 'request');
+    $kernel->getContainer()->get('request_stack')->push($request);
+  }
 
   // Install base system configuration.
   \Drupal::service('config.installer')->installDefaultConfig('core', 'core');
 
   // Install System module.
-  $kernel->getContainer()->get('module_handler')->install(array('system'), FALSE);
-
-  // DrupalKernel::prepareLegacyRequest() above calls into
-  // DrupalKernel::bootCode(), which primes file_get_stream_wrappers()'s static
-  // list of custom stream wrappers that are based on the currently enabled
-  // list of modules (none).
-  // @todo Custom stream wrappers of a new module have to be registered as soon
-  //   as the module is installed/enabled. Fix either ModuleHandler::install()
-  //   and/or DrupalKernel::updateModules().
-  // @see https://drupal.org/node/2028109
-  drupal_static_reset('file_get_stream_wrappers');
+  \Drupal::moduleHandler()->install(array('system'), FALSE);
 
   // Ensure default language is saved.
   if (isset($install_state['parameters']['langcode'])) {
diff --git a/core/includes/path.inc b/core/includes/path.inc
index a10f0e73f39d830168944b5b22e086ba4bc088d4..60437495e6882263616be2e9ac699de14da5cbad 100644
--- a/core/includes/path.inc
+++ b/core/includes/path.inc
@@ -74,7 +74,9 @@ function drupal_match_path($path, $patterns) {
  * - http://example.com/path/alias (which is a path alias for node/306) returns
  *   "node/306" as opposed to the path alias.
  *
- * @return string
+ * This function is available only after DRUPAL_BOOTSTRAP_FULL.
+ *
+ * @return
  *   The current Drupal URL path.
  *
  * @see request_path()
diff --git a/core/includes/schema.inc b/core/includes/schema.inc
index f181c5467e3048ace5fb4e104b1c7f60aa4d30a2..a386e62d1c163e2a9387e2287d2a87764cb35518 100644
--- a/core/includes/schema.inc
+++ b/core/includes/schema.inc
@@ -86,7 +86,7 @@ function drupal_get_complete_schema($rebuild = FALSE) {
 
       // If the schema is empty, avoid saving it: some database engines require
       // the schema to perform queries, and this could lead to infinite loops.
-      if (!empty($schema)) {
+      if (!empty($schema) && (drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL)) {
         \Drupal::cache()->set('schema', $schema, Cache::PERMANENT);
       }
     }
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 7e92f959865aabcf9f3389295fedc412800a1656..2b06429a15e4414342e0951af30037484bbab63e 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -24,7 +24,6 @@
 use Drupal\Core\Theme\ThemeSettings;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Render\Element;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * @defgroup content_flags Content markers
@@ -92,11 +91,8 @@ function drupal_theme_access($theme) {
 
 /**
  * Initializes the theme system by loading the theme.
- *
- * @param \Symfony\Component\HttpFoundation\Request $request
- *   The request for which to initialize the theme.
  */
-function drupal_theme_initialize(Request $request = NULL) {
+function drupal_theme_initialize() {
   global $theme, $theme_key;
 
   // If $theme is already set, assume the others are set, too, and do nothing
@@ -109,9 +105,7 @@ function drupal_theme_initialize(Request $request = NULL) {
   // @todo Let the theme.negotiator listen to the kernel request event.
   // Determine the active theme for the theme negotiator service. This includes
   // the default theme as well as really specific ones like the ajax base theme.
-  if (!$request) {
-    $request = \Drupal::request();
-  }
+  $request = \Drupal::request();
   $theme = \Drupal::service('theme.negotiator')->determineActiveTheme($request);
 
   // If no theme could be negotiated, or if the negotiated theme is not within
diff --git a/core/includes/utility.inc b/core/includes/utility.inc
index 135ab2473c18858c85c8e0d81f4334ab5fff0539..66031666ada56665427b0a51d7b5ecbe5fd74c0b 100644
--- a/core/includes/utility.inc
+++ b/core/includes/utility.inc
@@ -8,9 +8,6 @@
 use Drupal\Component\Utility\Variable;
 use Drupal\Core\PhpStorage\PhpStorageFactory;
 use Drupal\Core\Cache\Cache;
-use Drupal\Core\DrupalKernel;
-use Symfony\Component\HttpFoundation\Request;
-use Composer\Autoload\ClassLoader;
 
 /**
  * Drupal-friendly var_export().
@@ -35,39 +32,34 @@ function drupal_var_export($var, $prefix = '') {
  *
  * Requires DRUPAL_BOOTSTRAP_CONFIGURATION.
  *
- * @param \Composer\Autoload\ClassLoader $classloader
- *   The classloader.
- * @param \Symfony\Component\HttpFoundation\Request $request
- *   The current request.
- *
  * @see rebuild.php
  */
-function drupal_rebuild(ClassLoader $classloader, Request $request) {
+function drupal_rebuild() {
   // Remove Drupal's error and exception handlers; they rely on a working
   // service container and other subsystems and will only cause a fatal error
   // that hides the actual error.
   restore_error_handler();
   restore_exception_handler();
 
-  // Force kernel to rebuild container.
+  // drupal_bootstrap(DRUPAL_BOOTSTRAP_KERNEL) will build a new kernel. This
+  // comes before DRUPAL_BOOTSTRAP_PAGE_CACHE.
   PhpStorageFactory::get('service_container')->deleteAll();
   PhpStorageFactory::get('twig')->deleteAll();
 
-  // Bootstrap up to where caches exist and clear them.
-  $kernel = new DrupalKernel('prod', $classloader);
-  $kernel->prepareLegacyRequest($request);
+  // Disable the page cache.
+  drupal_page_is_cacheable(FALSE);
 
+  // Bootstrap up to where caches exist and clear them.
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_PAGE_CACHE);
   foreach (Cache::getBins() as $bin) {
     $bin->deleteAll();
   }
 
-  // Disable the page cache.
-  drupal_page_is_cacheable(FALSE);
-
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
   drupal_flush_all_caches();
 
   // Restore Drupal's error and exception handlers.
-  // @see \Drupal\Core\DrupalKernel::boot()
+  // @see _drupal_bootstrap_configuration()
   set_error_handler('_drupal_error_handler');
   set_exception_handler('_drupal_exception_handler');
 }
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index 135ab43fa8c2207c117afb151b8985ca6c4f63e0..fe43d8647a4e96dcd977347953941b068ee6297d 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -7,25 +7,21 @@
 
 namespace Drupal\Core;
 
-use Drupal\Component\Utility\Crypt;
-use Drupal\Component\Utility\Timer;
-use Drupal\Component\Utility\Unicode;
-use Drupal\Component\Utility\UrlHelper;
+use Drupal\Core\PhpStorage\PhpStorageFactory;
 use Drupal\Core\Config\BootstrapConfigStorageFactory;
 use Drupal\Core\Config\NullStorage;
-use Drupal\Core\Database\Database;
+use Drupal\Core\CoreServiceProvider;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceProviderInterface;
 use Drupal\Core\DependencyInjection\YamlFileLoader;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\Language\Language;
-use Drupal\Core\PhpStorage\PhpStorageFactory;
-use Drupal\Core\Site\Settings;
+use Symfony\Component\Config\Loader\LoaderInterface;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
-use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
 use Symfony\Component\HttpKernel\TerminableInterface;
 use Composer\Autoload\ClassLoader;
 
@@ -65,7 +61,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
    *
    * @var bool
    */
-  protected $booted = FALSE;
+  protected $booted;
 
   /**
    * Holds the list of enabled modules.
@@ -167,79 +163,15 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
    */
   protected $serviceProviders;
 
-  /**
-   * Whether the request globals have been initialized.
-   *
-   * @var bool
-   */
-  protected static $isRequestInitialized = FALSE;
-
-  /**
-   * Whether the PHP environment has been initialized.
-   *
-   * This legacy phase can only be booted once because it sets session INI
-   * settings. If a session has already been started, re-generating these
-   * settings would break the session.
-   *
-   * @var bool
-   */
-  protected static $isEnvironmentInitialized = FALSE;
-
-  /**
-   * The site directory.
-   *
-   * @var string
-   */
-  protected $sitePath;
-
-  /**
-   * Create a DrupalKernel object from a request.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   * @param \Composer\Autoload\ClassLoader $class_loader
-   *   (optional) The classloader is only used if $storage is not given or
-   *   the load from storage fails and a container rebuild is required. In
-   *   this case, the loaded modules will be registered with this loader in
-   *   order to be able to find the module serviceProviders.
-   * @param string $environment
-   *   String indicating the environment, e.g. 'prod' or 'dev'.
-   * @param bool $allow_dumping
-   *   (optional) FALSE to stop the container from being written to or read
-   *   from disk. Defaults to TRUE.
-   * @return static
-   */
-  public static function createFromRequest(Request $request, ClassLoader $class_loader, $environment, $allow_dumping = TRUE) {
-    // Include our bootstrap file.
-    require_once dirname(dirname(dirname(__DIR__))) . '/includes/bootstrap.inc';
-
-    $kernel = new static($environment, $class_loader, $allow_dumping);
-
-    // Ensure sane php environment variables..
-    static::bootEnvironment();
-
-    // Get our most basic settings setup.
-    $site_path = static::findSitePath($request);
-    $kernel->setSitePath($site_path);
-    Settings::initialize($site_path);
-
-    // Redirect the user to the installation script if Drupal has not been
-    // installed yet (i.e., if no $databases array has been defined in the
-    // settings.php file) and we are not already installing.
-    if (!Database::getConnectionInfo() && !drupal_installation_attempted() && !drupal_is_cli()) {
-      $response = new RedirectResponse($request->getBasePath() . '/core/install.php');
-      $response->prepare($request)->send();
-    }
-
-    return $kernel;
-  }
-
   /**
    * Constructs a DrupalKernel object.
    *
    * @param string $environment
-   *   String indicating the environment, e.g. 'prod' or 'dev'.
+   *   String indicating the environment, e.g. 'prod' or 'dev'. Used by
+   *   Symfony\Component\HttpKernel\Kernel::__construct(). Drupal does not use
+   *   this value currently. Pass 'prod'.
    * @param \Composer\Autoload\ClassLoader $class_loader
-   *   (optional) The class loader is only used if $storage is not given or
+   *   (optional) The classloader is only used if $storage is not given or
    *   the load from storage fails and a container rebuild is required. In
    *   this case, the loaded modules will be registered with this loader in
    *   order to be able to find the module serviceProviders.
@@ -252,156 +184,24 @@ public static function createFromRequest(Request $request, ClassLoader $class_lo
    */
   public function __construct($environment, ClassLoader $class_loader, $allow_dumping = TRUE, $allow_loading = NULL) {
     $this->environment = $environment;
+    $this->booted = FALSE;
     $this->classLoader = $class_loader;
     $this->allowDumping = $allow_dumping;
     $this->allowLoading = isset($allow_loading) ? $allow_loading : $allow_dumping;
   }
 
-  /**
-   * Returns the appropriate site directory for a request.
-   *
-   * Once the kernel has been created DrupalKernelInterface::getSitePath() is
-   * preferred since it gets the statically cached result of this method.
-   *
-   * Site directories contain all site specific code. This includes settings.php
-   * for bootstrap level configuration, file configuration stores, public file
-   * storage and site specific modules and themes.
-   *
-   * Finds a matching site directory file by stripping the website's hostname
-   * from left to right and pathname from right to left. By default, the
-   * directory must contain a 'settings.php' file for it to match. If the
-   * parameter $require_settings is set to FALSE, then a directory without a
-   * 'settings.php' file will match as well. The first configuration file found
-   * will be used and the remaining ones will be ignored. If no configuration
-   * file is found, returns a default value 'sites/default'. See
-   * default.settings.php for examples on how the URL is converted to a
-   * directory.
-   *
-   * If a file named sites.php is present in the sites directory, it will be
-   * loaded prior to scanning for directories. That file can define aliases in
-   * an associative array named $sites. The array is written in the format
-   * '<port>.<domain>.<path>' => 'directory'. As an example, to create a
-   * directory alias for http://www.drupal.org:8080/mysite/test whose
-   * configuration file is in sites/example.com, the array should be defined as:
-   * @code
-   * $sites = array(
-   *   '8080.www.drupal.org.mysite.test' => 'example.com',
-   * );
-   * @endcode
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   * @param bool $require_settings
-   *   Only directories with an existing settings.php file will be recognized.
-   *   Defaults to TRUE. During initial installation, this is set to FALSE so
-   *   that Drupal can detect a matching directory, then create a new
-   *   settings.php file in it.
-   *
-   * @return string
-   *   The path of the matching directory.
-   *
-   * @see \Drupal\Core\DrupalKernelInterface::getSitePath()
-   * @see \Drupal\Core\DrupalKernelInterface::setSitePath()
-   * @see default.settings.php
-   * @see example.sites.php
-   */
-  public static function findSitePath(Request $request, $require_settings = TRUE) {
-    // Check for a simpletest override.
-    if ($test_prefix = drupal_valid_test_ua()) {
-      return 'sites/simpletest/' . substr($test_prefix, 10);
-    }
-
-    // Determine whether multi-site functionality is enabled.
-    if (!file_exists(DRUPAL_ROOT . '/sites/sites.php')) {
-      return 'sites/default';
-    }
-
-    // Otherwise, use find the site path using the request.
-    $script_name = $request->server->get('SCRIPT_NAME');
-    if (!$script_name) {
-      $script_name = $request->server->get('SCRIPT_FILENAME');
-    }
-    $http_host = $request->server->get('HTTP_HOST');
-
-    $sites = array();
-    include DRUPAL_ROOT . '/sites/sites.php';
-
-    $uri = explode('/', $script_name);
-    $server = explode('.', implode('.', array_reverse(explode(':', rtrim($http_host, '.')))));
-    for ($i = count($uri) - 1; $i > 0; $i--) {
-      for ($j = count($server); $j > 0; $j--) {
-        $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
-        if (isset($sites[$dir]) && file_exists(DRUPAL_ROOT . '/sites/' . $sites[$dir])) {
-          $dir = $sites[$dir];
-        }
-        if (file_exists(DRUPAL_ROOT . '/sites/' . $dir . '/settings.php') || (!$require_settings && file_exists(DRUPAL_ROOT . '/sites/' . $dir))) {
-          return "sites/$dir";
-        }
-      }
-    }
-    return 'sites/default';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setSitePath($path) {
-    $this->sitePath = $path;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getSitePath() {
-    return $this->sitePath;
-  }
-
   /**
    * {@inheritdoc}
    */
   public function boot() {
     if ($this->booted) {
-      return $this;
-    }
-
-    // Start a page timer:
-    Timer::start('page');
-
-    drupal_classloader();
-
-    // Load legacy and other functional code.
-    require_once DRUPAL_ROOT . '/core/includes/common.inc';
-    require_once DRUPAL_ROOT . '/core/includes/database.inc';
-    require_once DRUPAL_ROOT . '/' . Settings::get('path_inc', 'core/includes/path.inc');
-    require_once DRUPAL_ROOT . '/core/includes/module.inc';
-    require_once DRUPAL_ROOT . '/core/includes/theme.inc';
-    require_once DRUPAL_ROOT . '/core/includes/pager.inc';
-    require_once DRUPAL_ROOT . '/' . Settings::get('menu_inc', 'core/includes/menu.inc');
-    require_once DRUPAL_ROOT . '/core/includes/tablesort.inc';
-    require_once DRUPAL_ROOT . '/core/includes/file.inc';
-    require_once DRUPAL_ROOT . '/core/includes/unicode.inc';
-    require_once DRUPAL_ROOT . '/core/includes/form.inc';
-    require_once DRUPAL_ROOT . '/core/includes/mail.inc';
-    require_once DRUPAL_ROOT . '/core/includes/ajax.inc';
-    require_once DRUPAL_ROOT . '/core/includes/errors.inc';
-    require_once DRUPAL_ROOT . '/core/includes/schema.inc';
-    require_once DRUPAL_ROOT . '/core/includes/entity.inc';
-
-    // Ensure that findSitePath is set.
-    if (!$this->sitePath) {
-      throw new \Exception('Kernel does not have site path set before calling boot()');
+      return;
     }
-    // Intialize the container.
     $this->initializeContainer();
-
-    // Ensure mt_rand() is reseeded to prevent random values from one page load
-    // being exploited to predict random values in subsequent page loads.
-    $seed = unpack("L", Crypt::randomBytes(4));
-    mt_srand($seed[1]);
-
     $this->booted = TRUE;
-
-    return $this;
+    if ($this->containerNeedsDumping && !$this->dumpDrupalContainer($this->container, static::CONTAINER_BASE_CLASS)) {
+      watchdog('DrupalKernel', 'Container cannot be written to disk');
+    }
   }
 
   /**
@@ -413,103 +213,15 @@ public function shutdown() {
     }
     $this->booted = FALSE;
     $this->container = NULL;
-    $this->moduleList = NULL;
-    $this->moduleData = array();
   }
 
   /**
    * {@inheritdoc}
    */
   public function getContainer() {
-    if ($this->containerNeedsDumping && !$this->dumpDrupalContainer($this->container, static::CONTAINER_BASE_CLASS)) {
-      watchdog('DrupalKernel', 'Container cannot be written to disk');
-    }
     return $this->container;
   }
 
-  /**
-   * Helper method that does request related initialization.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   */
-  protected function preHandle(Request $request) {
-    // Load all enabled modules.
-    $this->container->get('module_handler')->loadAll();
-
-    // Initialize legacy request globals.
-    $this->initializeRequestGlobals($request);
-
-    // Initialize cookie globals.
-    $this->initializeCookieGlobals($request);
-
-    // Ensure container has a request scope so we can load file stream wrappers.
-    if (!$this->container->isScopeActive('request')) {
-      // Enter the request scope so that current_user service is available for
-      // locale/translation sake.
-      $this->container->enterScope('request');
-      $this->container->set('request', $request, 'request');
-      $this->container->get('request_stack')->push($request);
-    }
-
-    // Make sure all stream wrappers are registered.
-    file_get_stream_wrappers();
-
-    // Back out scope required to initialize the file stream wrappers.
-    if ($this->container->isScopeActive('request')) {
-      $this->container->leaveScope('request');
-    }
-
-    // Set the allowed protocols once we have the config available.
-    $allowed_protocols = $this->container->get('config.factory')->get('system.filter')->get('protocols');
-    if (!isset($allowed_protocols)) {
-      // \Drupal\Component\Utility\UrlHelper::filterBadProtocol() is called by
-      // the installer and update.php, in which case the configuration may not
-      // exist (yet). Provide a minimal default set of allowed protocols for
-      // these cases.
-      $allowed_protocols = array('http', 'https');
-    }
-    UrlHelper::setAllowedProtocols($allowed_protocols);
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * @todo Invoke proper request/response/terminate events.
-   */
-  public function handlePageCache(Request $request) {
-    $this->boot();
-    $this->initializeCookieGlobals($request);
-
-    // Check for a cache mode force from settings.php.
-    if (Settings::get('page_cache_without_database')) {
-      $cache_enabled = TRUE;
-    }
-    else {
-      $config = $this->getContainer()->get('config.factory')->get('system.performance');
-      $cache_enabled = $config->get('cache.page.use_internal');
-    }
-
-    // If there is no session cookie and cache is enabled (or forced), try to
-    // serve a cached page.
-    if (!$request->cookies->has(session_name()) && $cache_enabled && drupal_page_is_cacheable()) {
-      // Get the page from the cache.
-      $response = drupal_page_get_cache($request);
-      // If there is a cached page, display it.
-      if ($response) {
-        $response->headers->set('X-Drupal-Cache', 'HIT');
-
-        drupal_serve_page_from_cache($response, $request);
-
-        // We are done.
-        $response->prepare($request);
-        $response->send();
-        exit;
-      }
-    }
-    return $this;
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -534,14 +246,14 @@ public function discoverServiceProviders() {
     $this->classLoaderAddMultiplePsr4($this->getModuleNamespacesPsr4($module_filenames));
 
     // Load each module's serviceProvider class.
-    foreach ($module_filenames as $module => $filename) {
+    foreach ($this->moduleList as $module => $weight) {
       $camelized = ContainerBuilder::camelize($module);
       $name = "{$camelized}ServiceProvider";
       $class = "Drupal\\{$module}\\{$name}";
       if (class_exists($class)) {
         $this->serviceProviderClasses['app'][$module] = $class;
       }
-      $filename = dirname($filename) . "/$module.services.yml";
+      $filename = dirname($module_filenames[$module]) . "/$module.services.yml";
       if (file_exists($filename)) {
         $this->serviceYamls['app'][$module] = $filename;
       }
@@ -558,7 +270,7 @@ public function discoverServiceProviders() {
     if (!empty($GLOBALS['conf']['container_yamls'])) {
       $this->serviceYamls['site'] = $GLOBALS['conf']['container_yamls'];
     }
-    if (file_exists($site_services_yml = $this->getSitePath() . '/services.yml')) {
+    if (file_exists($site_services_yml = conf_path() . '/services.yml')) {
       $this->serviceYamls['site'][] = $site_services_yml;
     }
   }
@@ -586,25 +298,12 @@ public function terminate(Request $request, Response $response) {
   /**
    * {@inheritdoc}
    */
-  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
-    $this->boot();
-    $this->preHandle($request);
-    return $this->getHttpKernel()->handle($request, $type, $catch);
-  }
+  public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = TRUE) {
+    if (FALSE === $this->booted) {
+      $this->boot();
+    }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function prepareLegacyRequest(Request $request) {
-    $this->boot();
-    $this->preHandle($request);
-    // Enter the request scope so that current_user service is available for
-    // locale/translation sake.
-    $this->container->enterScope('request');
-    $this->container->set('request', $request);
-    $this->container->get('request_stack')->push($request);
-    $this->container->get('router.request_context')->fromRequest($request);
-    return $this;
+    return $this->getHttpKernel()->handle($request, $type, $catch);
   }
 
   /**
@@ -770,215 +469,6 @@ protected function initializeContainer() {
     \Drupal::setContainer($this->container);
   }
 
-  /**
-   * Setup a consistent PHP environment.
-   *
-   * This method sets PHP environment options we want to be sure are set
-   * correctly for security or just saneness.
-   */
-  public static function bootEnvironment() {
-    if (static::$isEnvironmentInitialized) {
-      return;
-    }
-
-    // Enforce E_STRICT, but allow users to set levels not part of E_STRICT.
-    error_reporting(E_STRICT | E_ALL);
-
-    // Override PHP settings required for Drupal to work properly.
-    // sites/default/default.settings.php contains more runtime settings.
-    // The .htaccess file contains settings that cannot be changed at runtime.
-
-    // Use session cookies, not transparent sessions that puts the session id in
-    // the query string.
-    ini_set('session.use_cookies', '1');
-    ini_set('session.use_only_cookies', '1');
-    ini_set('session.use_trans_sid', '0');
-    // Don't send HTTP headers using PHP's session handler.
-    // Send an empty string to disable the cache limiter.
-    ini_set('session.cache_limiter', '');
-    // Use httponly session cookies.
-    ini_set('session.cookie_httponly', '1');
-
-    // Set sane locale settings, to ensure consistent string, dates, times and
-    // numbers handling.
-    setlocale(LC_ALL, 'C');
-
-    // Detect string handling method.
-    Unicode::check();
-
-    // Indicate that code is operating in a test child site.
-    if (!defined('DRUPAL_TEST_IN_CHILD_SITE')) {
-      if ($test_prefix = drupal_valid_test_ua()) {
-        // Only code that interfaces directly with tests should rely on this
-        // constant; e.g., the error/exception handler conditionally adds further
-        // error information into HTTP response headers that are consumed by
-        // Simpletest's internal browser.
-        define('DRUPAL_TEST_IN_CHILD_SITE', TRUE);
-
-        // Log fatal errors to the test site directory.
-        ini_set('log_errors', 1);
-        ini_set('error_log', DRUPAL_ROOT . '/sites/simpletest/' . substr($test_prefix, 10) . '/error.log');
-      }
-      else {
-        // Ensure that no other code defines this.
-        define('DRUPAL_TEST_IN_CHILD_SITE', FALSE);
-      }
-    }
-
-    // Set the Drupal custom error handler.
-    set_error_handler('_drupal_error_handler');
-    set_exception_handler('_drupal_exception_handler');
-
-    static::$isEnvironmentInitialized = TRUE;
-  }
-
-  /**
-   * Bootstraps the legacy global request variables.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   *
-   * @todo D8: Eliminate this entirely in favor of Request object.
-   */
-  protected function initializeRequestGlobals(Request $request) {
-    // Provided by settings.php.
-    global $base_url;
-    // Set and derived from $base_url by this function.
-    global $base_path, $base_root, $script_path;
-    global $base_secure_url, $base_insecure_url;
-
-    // @todo Refactor with the Symfony Request object.
-    _current_path(request_path());
-
-    if (isset($base_url)) {
-      // Parse fixed base URL from settings.php.
-      $parts = parse_url($base_url);
-      if (!isset($parts['path'])) {
-        $parts['path'] = '';
-      }
-      $base_path = $parts['path'] . '/';
-      // Build $base_root (everything until first slash after "scheme://").
-      $base_root = substr($base_url, 0, strlen($base_url) - strlen($parts['path']));
-    }
-    else {
-      // Create base URL.
-      $http_protocol = $request->isSecure() ? 'https' : 'http';
-      $base_root = $http_protocol . '://' . $request->server->get('HTTP_HOST');
-
-      $base_url = $base_root;
-
-      // For a request URI of '/index.php/foo', $_SERVER['SCRIPT_NAME'] is
-      // '/index.php', whereas $_SERVER['PHP_SELF'] is '/index.php/foo'.
-      if ($dir = rtrim(dirname($request->server->get('SCRIPT_NAME')), '\/')) {
-        // Remove "core" directory if present, allowing install.php, update.php,
-        // and others to auto-detect a base path.
-        $core_position = strrpos($dir, '/core');
-        if ($core_position !== FALSE && strlen($dir) - 5 == $core_position) {
-          $base_path = substr($dir, 0, $core_position);
-        }
-        else {
-          $base_path = $dir;
-        }
-        $base_url .= $base_path;
-        $base_path .= '/';
-      }
-      else {
-        $base_path = '/';
-      }
-    }
-    $base_secure_url = str_replace('http://', 'https://', $base_url);
-    $base_insecure_url = str_replace('https://', 'http://', $base_url);
-
-    // Determine the path of the script relative to the base path, and add a
-    // trailing slash. This is needed for creating URLs to Drupal pages.
-    if (!isset($script_path)) {
-      $script_path = '';
-      // We don't expect scripts outside of the base path, but sanity check
-      // anyway.
-      if (strpos($request->server->get('SCRIPT_NAME'), $base_path) === 0) {
-        $script_path = substr($request->server->get('SCRIPT_NAME'), strlen($base_path)) . '/';
-        // If the request URI does not contain the script name, then clean URLs
-        // are in effect and the script path can be similarly dropped from URL
-        // generation. For servers that don't provide $_SERVER['REQUEST_URI'],
-        // we do not know the actual URI requested by the client, and
-        // request_uri() returns a URI with the script name, resulting in
-        // non-clean URLs unless
-        // there's other code that intervenes.
-        if (strpos(request_uri(TRUE) . '/', $base_path . $script_path) !== 0) {
-          $script_path = '';
-        }
-        // @todo Temporary BC for install.php, update.php, and other scripts.
-        //   - http://drupal.org/node/1547184
-        //   - http://drupal.org/node/1546082
-        if ($script_path !== 'index.php/') {
-          $script_path = '';
-        }
-      }
-    }
-
-  }
-
-  /**
-   * Initialize cookie settings.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   *
-   * @todo D8: Eliminate this entirely in favor of a session object.
-   */
-  protected function initializeCookieGlobals(Request $request) {
-    // If we do this more then once per page request we are likely to cause
-    // errors.
-    if (static::$isRequestInitialized) {
-      return;
-    }
-    global $cookie_domain;
-
-    if ($cookie_domain) {
-      // If the user specifies the cookie domain, also use it for session name.
-      $session_name = $cookie_domain;
-    }
-    else {
-      // Otherwise use $base_url as session name, without the protocol
-      // to use the same session identifiers across HTTP and HTTPS.
-      $session_name = $request->getHost() . $request->getBasePath();
-      // Replace "core" out of session_name so core scripts redirect properly,
-      // specifically install.php and update.php.
-      $session_name = preg_replace('/\/core$/', '', $session_name);
-      // HTTP_HOST can be modified by a visitor, but has been sanitized already
-      // in DrupalKernel::bootEnvironment().
-      if ($cookie_domain = $request->server->get('HTTP_HOST')) {
-        // Strip leading periods, www., and port numbers from cookie domain.
-        $cookie_domain = ltrim($cookie_domain, '.');
-        if (strpos($cookie_domain, 'www.') === 0) {
-          $cookie_domain = substr($cookie_domain, 4);
-        }
-        $cookie_domain = explode(':', $cookie_domain);
-        $cookie_domain = '.' . $cookie_domain[0];
-      }
-    }
-    // Per RFC 2109, cookie domains must contain at least one dot other than the
-    // first. For hosts such as 'localhost' or IP Addresses we don't set a
-    // cookie domain.
-    if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
-      ini_set('session.cookie_domain', $cookie_domain);
-    }
-    // To prevent session cookies from being hijacked, a user can configure the
-    // SSL version of their website to only transfer session cookies via SSL by
-    // using PHP's session.cookie_secure setting. The browser will then use two
-    // separate session cookies for the HTTPS and HTTP versions of the site. So
-    // we must use different session identifiers for HTTPS and HTTP to prevent a
-    // cookie collision.
-    if ($request->isSecure()) {
-      ini_set('session.cookie_secure', TRUE);
-    }
-    $prefix = ini_get('session.cookie_secure') ? 'SSESS' : 'SESS';
-
-    session_name($prefix . substr(hash('sha256', $session_name), 0, 32));
-
-    static::$isRequestInitialized = TRUE;
-  }
-
   /**
    * Returns service instances to persist from an old container to a new one.
    */
@@ -1144,7 +634,7 @@ protected function dumpDrupalContainer(ContainerBuilder $container, $baseClass)
   /**
    * Gets a http kernel from the container
    *
-   * @return \Symfony\Component\HttpKernel\HttpKernelInterface
+   * @return HttpKernel
    */
   protected function getHttpKernel() {
     return $this->container->get('http_kernel');
diff --git a/core/lib/Drupal/Core/DrupalKernelInterface.php b/core/lib/Drupal/Core/DrupalKernelInterface.php
index 08d007c49135cb00a4b119c2f7a58be697a4d626..1e2ed070fddcd2a719580a5a53cf0c6a66000110 100644
--- a/core/lib/Drupal/Core/DrupalKernelInterface.php
+++ b/core/lib/Drupal/Core/DrupalKernelInterface.php
@@ -8,7 +8,6 @@
 namespace Drupal\Core;
 
 use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * The interface for DrupalKernel, the core of Drupal.
@@ -20,8 +19,6 @@ interface DrupalKernelInterface extends HttpKernelInterface {
 
   /**
    * Boots the current kernel.
-   *
-   * @return $this
    */
   public function boot();
 
@@ -56,22 +53,6 @@ public function getServiceProviders($origin);
    */
   public function getContainer();
 
-  /**
-   * Set the current site path.
-   *
-   * @param $path
-   *   The current site path.
-   */
-  public function setSitePath($path);
-
-  /**
-   * Get the site path.
-   *
-   * @return string
-   *   The current site path.
-   */
-  public function getSitePath();
-
   /**
    * Updates the kernel's list of modules to the new list.
    *
@@ -84,28 +65,4 @@ public function getSitePath();
    *   List of module filenames, keyed by module name.
    */
   public function updateModules(array $module_list, array $module_filenames = array());
-
-  /**
-   * Attempts to serve a page from the cache.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   *
-   * @return $this
-   */
-  public function handlePageCache(Request $request);
-
-  /**
-   * Prepare the kernel for handling a request without handling the request.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   *
-   * @return $this
-   *
-   * @deprecated 8.x
-   *   Only used by legacy front-controller scripts.
-   */
-  public function prepareLegacyRequest(Request $request);
-
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/LegacyRequestSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/LegacyRequestSubscriber.php
new file mode 100644
index 0000000000000000000000000000000000000000..aa7774e90ffab7696c570ecfb70d1d176199ba48
--- /dev/null
+++ b/core/lib/Drupal/Core/EventSubscriber/LegacyRequestSubscriber.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\EventSubscriber\LegacyRequestSubscriber.
+ */
+
+namespace Drupal\Core\EventSubscriber;
+
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * KernelEvents::REQUEST event subscriber to initialize theme and modules.
+ *
+ * @todo Remove this subscriber when all of the code in it has been refactored.
+ */
+class LegacyRequestSubscriber implements EventSubscriberInterface {
+
+  /**
+   * Initializes the rest of the legacy Drupal subsystems.
+   *
+   * @param Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   *   The Event to process.
+   */
+  public function onKernelRequestLegacy(GetResponseEvent $event) {
+    if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
+      // Tell Drupal it is now fully bootstrapped (for the benefit of code that
+      // calls drupal_get_bootstrap_phase()), but without having
+      // _drupal_bootstrap_full() do anything, since we've already done the
+      // equivalent above and in earlier listeners.
+      _drupal_bootstrap_full(TRUE);
+      drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+    }
+  }
+
+  /**
+   * Initializes the theme system after the routing system.
+   *
+   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+   *   The Event to process.
+   */
+  public function onKernelRequestLegacyAfterRouting(GetResponseEvent $event) {
+    if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
+      drupal_theme_initialize();
+    }
+  }
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    $events[KernelEvents::REQUEST][] = array('onKernelRequestLegacy', 90);
+    // Initialize the theme system after the routing system.
+    $events[KernelEvents::REQUEST][] = array('onKernelRequestLegacyAfterRouting', 30);
+
+    return $events;
+  }
+}
diff --git a/core/lib/Drupal/Core/EventSubscriber/ThemeNegotiatorRequestSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ThemeNegotiatorRequestSubscriber.php
deleted file mode 100644
index 37ddfbb05a7ee0c6bd0a0ee6657bf73a5012470a..0000000000000000000000000000000000000000
--- a/core/lib/Drupal/Core/EventSubscriber/ThemeNegotiatorRequestSubscriber.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\EventSubscriber\ThemeNegotiatorRequestSubscriber.
- */
-
-namespace Drupal\Core\EventSubscriber;
-
-use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\HttpKernel\KernelEvents;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-/**
- * Initializes the theme for the current request.
- */
-class ThemeNegotiatorRequestSubscriber implements EventSubscriberInterface {
-
-  /**
-   * Initializes the theme system after the routing system.
-   *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
-   *   The Event to process.
-   */
-  public function onKernelRequestThemeNegotiator(GetResponseEvent $event) {
-    if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
-      if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
-        // @todo Refactor drupal_theme_initialize() into a request subscriber.
-        // @see https://drupal.org/node/2228093
-        drupal_theme_initialize($event->getRequest());
-      }
-    }
-  }
-
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  public static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestThemeNegotiator', 29);
-    return $events;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Site/Settings.php b/core/lib/Drupal/Core/Site/Settings.php
index e2d57d2b6e975ced8b01e1c0bc354faf11a64f94..3ac0f03328cf03232b138819ef67aae85c33e481 100644
--- a/core/lib/Drupal/Core/Site/Settings.php
+++ b/core/lib/Drupal/Core/Site/Settings.php
@@ -7,8 +7,6 @@
 
 namespace Drupal\Core\Site;
 
-use Drupal\Core\Database\Database;
-
 /**
  * Read only settings that are initialized with the class.
  *
@@ -82,31 +80,6 @@ public static function getAll() {
     return self::$instance->storage;
   }
 
-  /**
-   * Bootstraps settings.php and the Settings singleton.
-   *
-   * @param string $site_path
-   *   The current site path.
-   */
-  public static function initialize($site_path) {
-    // Export these settings.php variables to the global namespace.
-    global $base_url, $cookie_domain, $config_directories, $config;
-    $settings = array();
-    $config = array();
-    $databases = array();
-
-    // Make conf_path() available as local variable in settings.php.
-    if (is_readable(DRUPAL_ROOT . '/' . $site_path . '/settings.php')) {
-      require DRUPAL_ROOT . '/' . $site_path . '/settings.php';
-    }
-
-    // Initialize Database.
-    Database::setMultipleConnectionInfo($databases);
-
-    // Initialize Settings.
-    new Settings($settings);
-  }
-
   /**
    * Gets a salt useful for hardening against SQL injection.
    *
diff --git a/core/lib/Drupal/Core/Test/TestKernel.php b/core/lib/Drupal/Core/Test/TestKernel.php
index 6144dbf7cc555b65c2521891c7ffdfc45055efa8..12938ce73685c1b08a10eacaa0e5290518c28a4c 100644
--- a/core/lib/Drupal/Core/Test/TestKernel.php
+++ b/core/lib/Drupal/Core/Test/TestKernel.php
@@ -8,28 +8,46 @@
 namespace Drupal\Core\Test;
 
 use Drupal\Core\DrupalKernel;
-use Symfony\Component\HttpFoundation\Request;
+use Drupal\Core\Extension\Extension;
+use Drupal\Core\Installer\InstallerServiceProvider;
 use Composer\Autoload\ClassLoader;
 
 /**
- * Kernel to mock requests to test simpletest.
+ * Kernel for run-tests.sh.
  */
 class TestKernel extends DrupalKernel {
 
   /**
-   * {@inheritdoc}
+   * Constructs a TestKernel.
+   *
+   * @param \Composer\Autoload\ClassLoader $class_loader
+   *   The classloader.
    */
-  public static function createFromRequest(Request $request, ClassLoader $class_loader, $environment, $allow_dumping = TRUE) {
-    // Include our bootstrap file.
-    require_once __DIR__ . '/../../../../includes/bootstrap.inc';
-
-    // Exit if we should be in a test environment but aren't.
-    if (!drupal_valid_test_ua()) {
-      header($request->server->get('SERVER_PROTOCOL') . ' 403 Forbidden');
-      exit;
-    }
+  public function __construct(ClassLoader $class_loader) {
+    parent::__construct('test_runner', $class_loader, FALSE);
+
+    // Prime the module list and corresponding Extension objects.
+    // @todo Remove System module. Needed because \Drupal\Core\Datetime\Date
+    //   has a (needless) dependency on the 'date_format' entity, so calls to
+    //   format_date()/format_interval() cause a plugin not found exception.
+    $this->moduleList = array(
+      'system' => 0,
+      'simpletest' => 0,
+    );
+    $this->moduleData = array(
+      'system' => new Extension('module', 'core/modules/system/system.info.yml', 'system.module'),
+      'simpletest' => new Extension('module', 'core/modules/simpletest/simpletest.info.yml', 'simpletest.module'),
+    );
+  }
 
-    return parent::createFromRequest($request, $class_loader, $environment, $allow_dumping);
+  /**
+   * {@inheritdoc}
+   */
+  public function discoverServiceProviders() {
+    parent::discoverServiceProviders();
+    // The test runner does not require an installed Drupal site to exist.
+    // Therefore, its environment is identical to that of the early installer.
+    $this->serviceProviderClasses['app']['Test'] = 'Drupal\Core\Installer\InstallerServiceProvider';
   }
 
 }
diff --git a/core/lib/Drupal/Core/Test/TestRunnerKernel.php b/core/lib/Drupal/Core/Test/TestRunnerKernel.php
deleted file mode 100644
index 7b04673c3fd500a69a1d897230bdc8ebd55c532e..0000000000000000000000000000000000000000
--- a/core/lib/Drupal/Core/Test/TestRunnerKernel.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Test\TestRunnerKernel.
- */
-
-namespace Drupal\Core\Test;
-
-use Drupal\Core\DrupalKernel;
-use Drupal\Core\Extension\Extension;
-use Drupal\Core\Installer\InstallerServiceProvider;
-use Composer\Autoload\ClassLoader;
-use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Request;
-
-/**
- * Kernel for run-tests.sh.
- */
-class TestRunnerKernel extends DrupalKernel {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createFromRequest(Request $request, ClassLoader $class_loader, $environment = 'test_runner', $allow_dumping = TRUE) {
-    return parent::createFromRequest($request, $class_loader, $environment);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __construct($environment, ClassLoader $class_loader) {
-    parent::__construct($environment, $class_loader, FALSE);
-
-    // Prime the module list and corresponding Extension objects.
-    // @todo Remove System module. Needed because \Drupal\Core\Datetime\Date
-    //   has a (needless) dependency on the 'date_format' entity, so calls to
-    //   format_date()/format_interval() cause a plugin not found exception.
-    $this->moduleList = array(
-      'system' => 0,
-      'simpletest' => 0,
-    );
-    $this->moduleData = array(
-      'system' => new Extension('module', 'core/modules/system/system.info.yml', 'system.module'),
-      'simpletest' => new Extension('module', 'core/modules/simpletest/simpletest.info.yml', 'simpletest.module'),
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function boot() {
-    // Ensure that required Settings exist.
-    if (!Settings::getAll()) {
-      new Settings(array(
-        'hash_salt' => 'run-tests',
-      ));
-    }
-
-    // Remove Drupal's error/exception handlers; they are designed for HTML
-    // and there is no storage nor a (watchdog) logger here.
-    restore_error_handler();
-    restore_exception_handler();
-
-    // In addition, ensure that PHP errors are not hidden away in logs.
-    ini_set('display_errors', TRUE);
-
-    parent::boot();
-
-    $this->getContainer()->get('module_handler')->loadAll();
-
-    simpletest_classloader_register();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function discoverServiceProviders() {
-    parent::discoverServiceProviders();
-    // The test runner does not require an installed Drupal site to exist.
-    // Therefore, its environment is identical to that of the early installer.
-    $this->serviceProviderClasses['app']['Test'] = 'Drupal\Core\Installer\InstallerServiceProvider';
-  }
-
-}
diff --git a/core/modules/ckeditor/src/Tests/CKEditorLoadingTest.php b/core/modules/ckeditor/src/Tests/CKEditorLoadingTest.php
index ec00177518aa5988339ae07c249e9ee6adcabbef..e4231a3e515a73c762344bcb9db21f30eb2603f9 100644
--- a/core/modules/ckeditor/src/Tests/CKEditorLoadingTest.php
+++ b/core/modules/ckeditor/src/Tests/CKEditorLoadingTest.php
@@ -122,8 +122,6 @@ function testLoading() {
     // configuration also results in modified CKEditor configuration, so we
     // don't test that here.
     \Drupal::moduleHandler()->install(array('ckeditor_test'));
-    // Force container rebuild so module list is correct on request.
-    $this->rebuildContainer();
     $this->container->get('plugin.manager.ckeditor.plugin')->clearCachedDefinitions();
     $editor_settings = $editor->getSettings();
     $editor_settings['toolbar']['buttons'][0][] = 'Llama';
@@ -131,14 +129,12 @@ function testLoading() {
     $editor->save();
     $this->drupalGet('node/add/article');
     list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck();
-    $expected = array(
-      'formats' => array(
-        'filtered_html' => array(
-          'format' => 'filtered_html',
-          'editor' => 'ckeditor',
-          'editorSettings' => $ckeditor_plugin->getJSSettings($editor),
-          'editorSupportsContentFiltering' => TRUE,
-          'isXssSafe' => FALSE,
+    $expected = array('formats' => array('filtered_html' => array(
+      'format' => 'filtered_html',
+      'editor' => 'ckeditor',
+      'editorSettings' => $ckeditor_plugin->getJSSettings($editor),
+      'editorSupportsContentFiltering' => TRUE,
+      'isXssSafe' => FALSE,
     )));
     $this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
     $this->assertIdentical($expected, $settings['editor'], "Text Editor module's JavaScript settings on the page are correct.");
diff --git a/core/modules/dblog/src/Tests/DbLogTest.php b/core/modules/dblog/src/Tests/DbLogTest.php
index 0cb7d3ca020db5c0ae66d17ba63e092fe28e73fb..84c05cfd7c59d0c09e1863b6ec399c26287bd20c 100644
--- a/core/modules/dblog/src/Tests/DbLogTest.php
+++ b/core/modules/dblog/src/Tests/DbLogTest.php
@@ -138,7 +138,7 @@ private function generateLogEntries($count, $type = 'custom', $severity = WATCHD
       'user'        => $this->big_user,
       'uid'         => $this->big_user->id(),
       'request_uri' => $base_root . request_uri(),
-      'referer'     => \Drupal::request()->server->get('HTTP_REFERER'),
+      'referer'     => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '',
       'ip'          => '127.0.0.1',
       'timestamp'   => REQUEST_TIME,
       );
@@ -421,7 +421,7 @@ protected function testDBLogAddAndClear() {
       'user'        => $this->big_user,
       'uid'         => $this->big_user->id(),
       'request_uri' => $base_root . request_uri(),
-      'referer'     => \Drupal::request()->server->get('HTTP_REFERER'),
+      'referer'     => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '',
       'ip'          => '127.0.0.1',
       'timestamp'   => REQUEST_TIME,
     );
diff --git a/core/modules/field/src/Tests/FieldHelpTest.php b/core/modules/field/src/Tests/FieldHelpTest.php
index 2af6b923b680526996d40884d90df4434bf9da94..0f976e07c290974376b1a8fc1c575e2915c8ccc6 100644
--- a/core/modules/field/src/Tests/FieldHelpTest.php
+++ b/core/modules/field/src/Tests/FieldHelpTest.php
@@ -56,7 +56,6 @@ public function testFieldHelp() {
 
     // Enable the Options, E-mail and Field API Test modules.
     \Drupal::moduleHandler()->install(array('options', 'field_test'));
-    $this->rebuildContainer();
     \Drupal::service('plugin.manager.field.widget')->clearCachedDefinitions();
     \Drupal::service('plugin.manager.field.field_type')->clearCachedDefinitions();
 
diff --git a/core/modules/simpletest/src/InstallerTestBase.php b/core/modules/simpletest/src/InstallerTestBase.php
index 6fa42f9fcc57c01937588f002d76892fb74f35b3..e735ce3fe2795e607b1d8c0257811c3286a54b8b 100644
--- a/core/modules/simpletest/src/InstallerTestBase.php
+++ b/core/modules/simpletest/src/InstallerTestBase.php
@@ -7,10 +7,7 @@
 
 namespace Drupal\simpletest;
 
-use Drupal\Core\DrupalKernel;
 use Drupal\Core\Session\UserSession;
-use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Base class for testing the interactive installer.
@@ -112,8 +109,7 @@ protected function setUp() {
     $this->setUpSite();
 
     // Import new settings.php written by the installer.
-    $request = Request::createFromGlobals();
-    Settings::initialize(DrupalKernel::findSitePath($request));
+    drupal_settings_initialize();
     foreach ($GLOBALS['config_directories'] as $type => $path) {
       $this->configDirectories[$type] = $path;
     }
@@ -125,14 +121,12 @@ protected function setUp() {
     // WebTestBase::tearDown() will delete the entire test site directory.
     // Not using File API; a potential error must trigger a PHP warning.
     chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777);
-    $this->kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod', FALSE);
-    $this->kernel->prepareLegacyRequest($request);
-    $this->container = $this->kernel->getContainer();
-    $config = $this->container->get('config.factory');
+
+    $this->rebuildContainer();
 
     // Manually configure the test mail collector implementation to prevent
     // tests from sending out e-mails and collect them in state instead.
-    $config->get('system.mail')
+    \Drupal::config('system.mail')
       ->set('interface.default', 'test_mail_collector')
       ->save();
 
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index 7a76b5be8713a433d659fea96f0b194ce7a0be1f..409c1b95a8ea60a1cc451800f5b0a726848f84c5 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -13,7 +13,6 @@
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
 use Drupal\Core\Language\Language;
-use Drupal\Core\Site\Settings;
 use Drupal\Core\Entity\Schema\EntitySchemaProviderInterface;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\HttpFoundation\Request;
@@ -132,31 +131,23 @@ protected function setUp() {
     // Create and set new configuration directories.
     $this->prepareConfigDirectories();
 
-    // Add this test class as a service provider.
-    // @todo Remove the indirection; implement ServiceProviderInterface instead.
+    // Build a minimal, partially mocked environment for unit tests.
+    $this->containerBuild(\Drupal::getContainer());
+    // Make sure it survives kernel rebuilds.
     $GLOBALS['conf']['container_service_providers']['TestServiceProvider'] = 'Drupal\simpletest\TestServiceProvider';
 
-    // Back up settings from TestBase::prepareEnvironment().
-    $settings = Settings::getAll();
-    // Bootstrap a new kernel. Don't use createFromRequest so we don't mess with settings.
-    $this->kernel = new DrupalKernel('testing', drupal_classloader(), FALSE);
-    $request = Request::create('/');
-    $this->kernel->setSitePath(DrupalKernel::findSitePath($request));
-    $this->kernel->boot();
+    \Drupal::state()->set('system.module.files', $this->moduleFiles);
+    \Drupal::state()->set('system.theme.files', $this->themeFiles);
 
-    // Restore and merge settings.
-    // DrupalKernel::boot() initializes new Settings, and the containerBuild()
-    // method sets additional settings.
-    new Settings($settings + Settings::getAll());
+    // Bootstrap the kernel.
+    // No need to dump it; this test runs in-memory.
+    $this->kernel = new DrupalKernel('unit_testing', drupal_classloader(), FALSE);
+    $this->kernel->boot();
 
-    // Set the request scope.
-    $this->container = $this->kernel->getContainer();
+    $request = Request::create('/');
     $this->container->set('request', $request);
     $this->container->get('request_stack')->push($request);
 
-    $this->container->get('state')->set('system.module.files', $this->moduleFiles);
-    $this->container->get('state')->set('system.theme.files', $this->themeFiles);
-
     // Create a minimal core.extension configuration object so that the list of
     // enabled modules can be maintained allowing
     // \Drupal\Core\Config\ConfigInstaller::installDefaultConfig() to work.
@@ -413,7 +404,8 @@ protected function enableModules(array $modules) {
     // Ensure isLoaded() is TRUE in order to make _theme() work.
     // Note that the kernel has rebuilt the container; this $module_handler is
     // no longer the $module_handler instance from above.
-    $this->container->get('module_handler')->reload();
+    $module_handler = $this->container->get('module_handler');
+    $module_handler->reload();
     $this->pass(format_string('Enabled modules: %modules.', array(
       '%modules' => implode(', ', $modules),
     )));
diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php
index b133447f77d398a7c5ecaa07bf12ac16635bdba1..023cf8e53bcc8f531227ef6a20beb1adba4b01e5 100644
--- a/core/modules/simpletest/src/TestBase.php
+++ b/core/modules/simpletest/src/TestBase.php
@@ -15,6 +15,7 @@
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Database\ConnectionNotDefinedException;
 use Drupal\Core\Config\StorageInterface;
+use Drupal\Core\DrupalKernel;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Session\AccountProxy;
 use Drupal\Core\Session\AnonymousUserSession;
@@ -652,7 +653,7 @@ protected function assertIdenticalObject($object1, $object2, $message = '', $gro
    *   TRUE if the assertion succeeded, FALSE otherwise.
    *
    * @see TestBase::prepareEnvironment()
-   * @see \Drupal\Core\DrupalKernel::bootConfiguration()
+   * @see _drupal_bootstrap_configuration()
    */
   protected function assertNoErrorsLogged() {
     // Since PHP only creates the error.log file when an actual error is
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index e75411d62bbb6ea24d34126ef7542c07d9ce811c..ec50d4dd70f367bc02f8a2cfd79c62c5dff85e34 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -20,7 +20,6 @@
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Session\AnonymousUserSession;
 use Drupal\Core\Session\UserSession;
-use Drupal\Core\Site\Settings;
 use Drupal\Core\StreamWrapper\PublicStream;
 use Drupal\Core\Datetime\DrupalDateTime;
 use Drupal\block\Entity\Block;
@@ -174,8 +173,6 @@ abstract class WebTestBase extends TestBase {
 
   /**
    * The kernel used in this test.
-   *
-   * @var \Drupal\Core\DrupalKernel
    */
   protected $kernel;
 
@@ -847,11 +844,17 @@ protected function setUp() {
     );
     $this->writeSettings($settings);
 
+    // Since Drupal is bootstrapped already, install_begin_request() will not
+    // bootstrap into DRUPAL_BOOTSTRAP_CONFIGURATION (again). Hence, we have to
+    // reload the newly written custom settings.php manually.
+    drupal_settings_initialize();
+
     // Execute the non-interactive installer.
     require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
     install_drupal($parameters);
 
     // Import new settings.php written by the installer.
+    drupal_settings_initialize();
     foreach ($GLOBALS['config_directories'] as $type => $path) {
       $this->configDirectories[$type] = $path;
     }
@@ -864,11 +867,7 @@ protected function setUp() {
     // Not using File API; a potential error must trigger a PHP warning.
     chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777);
 
-    $request = \Drupal::request();
-    $this->kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod', TRUE);
-    $this->kernel->prepareLegacyRequest($request);
-    $container = $this->kernel->getContainer();
-    $config = $container->get('config.factory');
+    $this->rebuildContainer();
 
     // Manually create and configure private and temporary files directories.
     // While these could be preset/enforced in settings.php like the public
@@ -876,7 +875,7 @@ protected function setUp() {
     // UI. If declared in settings.php, they would no longer be configurable.
     file_prepare_directory($this->private_files_directory, FILE_CREATE_DIRECTORY);
     file_prepare_directory($this->temp_files_directory, FILE_CREATE_DIRECTORY);
-    $config->get('system.file')
+    \Drupal::config('system.file')
       ->set('path.private', $this->private_files_directory)
       ->set('path.temporary', $this->temp_files_directory)
       ->save();
@@ -885,7 +884,7 @@ protected function setUp() {
     // tests from sending out e-mails and collect them in state instead.
     // While this should be enforced via settings.php prior to installation,
     // some tests expect to be able to test mail system implementations.
-    $config->get('system.mail')
+    \Drupal::config('system.mail')
       ->set('interface.default', 'test_mail_collector')
       ->save();
 
@@ -893,10 +892,10 @@ protected function setUp() {
     // environment optimizations for all tests to avoid needless overhead and
     // ensure a sane default experience for test authors.
     // @see https://drupal.org/node/2259167
-    $config->get('system.logging')
+    \Drupal::config('system.logging')
       ->set('error_level', 'verbose')
       ->save();
-    $config->get('system.performance')
+    \Drupal::config('system.performance')
       ->set('css.preprocess', FALSE)
       ->set('js.preprocess', FALSE)
       ->save();
@@ -916,20 +915,22 @@ protected function setUp() {
     }
     if ($modules) {
       $modules = array_unique($modules);
-      $success = $container->get('module_handler')->install($modules, TRUE);
+      $success = \Drupal::moduleHandler()->install($modules, TRUE);
       $this->assertTrue($success, String::format('Enabled modules: %modules', array('%modules' => implode(', ', $modules))));
       $this->rebuildContainer();
     }
 
+    // Like DRUPAL_BOOTSTRAP_CONFIGURATION above, any further bootstrap phases
+    // are not re-executed by the installer, as Drupal is bootstrapped already.
     // Reset/rebuild all data structures after enabling the modules, primarily
     // to synchronize all data structures and caches between the test runner and
     // the child site.
     // Affects e.g. file_get_stream_wrappers().
-    // @see \Drupal\Core\DrupalKernel::bootCode()
+    // @see _drupal_bootstrap_code()
+    // @see _drupal_bootstrap_full()
     // @todo Test-specific setUp() methods may set up further fixtures; find a
     //   way to execute this after setUp() is done, or to eliminate it entirely.
     $this->resetAll();
-    $this->kernel->prepareLegacyRequest($request);
 
     // Temporary fix so that when running from run-tests.sh we don't get an
     // empty current path which would indicate we're on the home page.
@@ -1084,18 +1085,29 @@ protected function writeCustomTranslations() {
    *   tests can invoke this workaround when requiring services from newly
    *   enabled modules to be immediately available in the same request.
    */
-  protected function rebuildContainer() {
-    // Maintain the current global request object.
+  protected function rebuildContainer($environment = 'prod') {
+    // Preserve the request object after the container rebuild.
     $request = \Drupal::request();
+    // When called from InstallerTestBase, the current container is the minimal
+    // container from TestBase::prepareEnvironment(), which does not contain a
+    // request stack.
+    if (\Drupal::getContainer()->initialized('request_stack')) {
+      $request_stack = \Drupal::service('request_stack');
+    }
 
-    // Rebuild the kernel and bring it back to a fully bootstrapped state.
-    $this->kernel->shutdown();
-    $this->kernel->prepareLegacyRequest($request);
-
+    $this->kernel = new DrupalKernel($environment, drupal_classloader(), TRUE, FALSE);
+    $this->kernel->boot();
     // DrupalKernel replaces the container in \Drupal::getContainer() with a
     // different object, so we need to replace the instance on this test class.
-    $this->container = $this->kernel->getContainer();
-
+    $this->container = \Drupal::getContainer();
+    // The current user is set in TestBase::prepareEnvironment().
+    $this->container->set('request', $request);
+    if (isset($request_stack)) {
+      $this->container->set('request_stack', $request_stack);
+    }
+    else {
+      $this->container->get('request_stack')->push($request);
+    }
     $this->container->get('current_user')->setAccount(\Drupal::currentUser());
 
     // The request context is normally set by the router_listener from within
@@ -1417,7 +1429,7 @@ protected function curlClose() {
    *   TRUE if this test was instantiated in a request within the test site,
    *   FALSE otherwise.
    *
-   * @see \Drupal\Core\DrupalKernel::bootConfiguration()
+   * @see _drupal_bootstrap_configuration()
    */
   protected function isInChildSite() {
     return DRUPAL_TEST_IN_CHILD_SITE;
diff --git a/core/modules/statistics/statistics.php b/core/modules/statistics/statistics.php
index 4d2004646ae677a4afb40f9c17e29baaae234daf..85864e10b58749e5cdeaa9f43ad58c6a728af15d 100644
--- a/core/modules/statistics/statistics.php
+++ b/core/modules/statistics/statistics.php
@@ -5,22 +5,15 @@
  * Handles counts of node views via AJAX with minimal bootstrap.
  */
 
-use Drupal\Core\DrupalKernel;
-use Symfony\Component\HttpFoundation\Request;
-
+// Change the directory to the Drupal root.
 chdir('../../..');
 
-$autoloader = require_once dirname(dirname(__DIR__)) . '/vendor/autoload.php';
-
-$kernel = DrupalKernel::createFromRequest(Request::createFromGlobals(), $autoloader, 'prod');
-$kernel->boot();
-
-$views = $kernel->getContainer()
-  ->get('config.factory')
-  ->get('statistics.settings')
-  ->get('count_content_views');
+// Load the Drupal bootstrap.
+require_once dirname(dirname(__DIR__)) . '/vendor/autoload.php';
+require_once dirname(dirname(__DIR__)) . '/includes/bootstrap.inc';
+drupal_bootstrap(DRUPAL_BOOTSTRAP_KERNEL);
 
-if ($views) {
+if (\Drupal::config('statistics.settings')->get('count_content_views')) {
   $nid = filter_input(INPUT_POST, 'nid', FILTER_VALIDATE_INT);
   if ($nid) {
     \Drupal::database()->merge('node_counter')
diff --git a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
index 9ec9df936dcc495990c408bdc93fea6f592743d3..17e4b4b9f030ec77e7d6176802edaa9771e6a46c 100644
--- a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
@@ -10,18 +10,12 @@
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Site\Settings;
 use Drupal\simpletest\DrupalUnitTestBase;
-use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Tests compilation of the DIC.
  */
 class DrupalKernelTest extends DrupalUnitTestBase {
 
-  /**
-   * @var \Composer\Autoload\ClassLoader
-   */
-  protected $classloader;
-
   public static function getInfo() {
     return array(
       'name' => 'DrupalKernel tests',
@@ -44,60 +38,25 @@ function setUp() {
       'directory' => DRUPAL_ROOT . '/' . $this->public_files_directory . '/php',
       'secret' => drupal_get_hash_salt(),
     )));
-
-    $this->classloader = drupal_classloader();
-  }
-
-  /**
-   * Build a kernel for testings.
-   *
-   * Because the bootstrap is in DrupalKernel::boot and that involved loading
-   * settings from the filesystem we need to go to extra lengths to build a kernel
-   * for testing.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   A request object to use in booting the kernel.
-   * @param array $modules_enabled
-   *   A list of modules to enable on the kernel.
-   * @param bool $read_only
-   *   Build the kernel in a read only state.
-   * @return DrupalKernel
-   */
-  protected function getTestKernel(Request $request, array $modules_enabled = NULL, $read_only = FALSE) {
-    // Manually create kernel to avoid replacing settings.
-    $kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'testing');
-    $this->settingsSet('hash_salt', $this->databasePrefix);
-    if (isset($modules_enabled)) {
-      $kernel->updateModules($modules_enabled);
-    }
-    $kernel->boot();
-
-    if ($read_only) {
-      $php_storage = Settings::get('php_storage');
-      $php_storage['service_container']['class'] = 'Drupal\Component\PhpStorage\FileReadOnlyStorage';
-      $this->settingsSet('php_storage', $php_storage);
-    }
-    return $kernel;
   }
 
   /**
    * Tests DIC compilation.
    */
   function testCompileDIC() {
+    $classloader = drupal_classloader();
     // @todo: write a memory based storage backend for testing.
-    $modules_enabled = array(
+    $module_enabled = array(
       'system' => 'system',
       'user' => 'user',
     );
-
-    $request = Request::createFromGlobals();
-    $this->getTestKernel($request, $modules_enabled)
-      // Trigger Kernel dump.
-      ->getContainer();
-
+    $kernel = new DrupalKernel('testing', $classloader);
+    $kernel->updateModules($module_enabled);
+    $kernel->boot();
     // Instantiate it a second time and we should get the compiled Container
     // class.
-    $kernel = $this->getTestKernel($request);
+    $kernel = new DrupalKernel('testing', $classloader);
+    $kernel->boot();
     $container = $kernel->getContainer();
     $refClass = new \ReflectionClass($container);
     $is_compiled_container =
@@ -107,24 +66,25 @@ function testCompileDIC() {
     // Verify that the list of modules is the same for the initial and the
     // compiled container.
     $module_list = array_keys($container->get('module_handler')->getModuleList());
-    $this->assertEqual(array_values($modules_enabled), $module_list);
+    $this->assertEqual(array_values($module_enabled), $module_list);
 
     // Now use the read-only storage implementation, simulating a "production"
     // environment.
-    $container = $this->getTestKernel($request, NULL, TRUE)
-      ->getContainer();
-
+    $php_storage = Settings::get('php_storage');
+    $php_storage['service_container']['class'] = 'Drupal\Component\PhpStorage\FileReadOnlyStorage';
+    $this->settingsSet('php_storage', $php_storage);
+    $kernel = new DrupalKernel('testing', $classloader);
+    $kernel->boot();
+    $container = $kernel->getContainer();
     $refClass = new \ReflectionClass($container);
     $is_compiled_container =
       $refClass->getParentClass()->getName() == 'Drupal\Core\DependencyInjection\Container' &&
       !$refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder');
     $this->assertTrue($is_compiled_container);
-
     // Verify that the list of modules is the same for the initial and the
     // compiled container.
     $module_list = array_keys($container->get('module_handler')->getModuleList());
-    $this->assertEqual(array_values($modules_enabled), $module_list);
-
+    $this->assertEqual(array_values($module_enabled), $module_list);
     // Test that our synthetic services are there.
     $classloader = $container->get('class_loader');
     $refClass = new \ReflectionClass($classloader);
@@ -138,26 +98,25 @@ function testCompileDIC() {
 
     // Add another module so that we can test that the new module's bundle is
     // registered to the new container.
-    $modules_enabled['service_provider_test'] = 'service_provider_test';
-    $this->getTestKernel($request, $modules_enabled, TRUE);
-
+    $module_enabled['service_provider_test'] = 'service_provider_test';
+    $kernel = new DrupalKernel('testing', $classloader);
+    $kernel->updateModules($module_enabled);
+    $kernel->boot();
     // Instantiate it a second time and we should still get a ContainerBuilder
     // class because we are using the read-only PHP storage.
-    $kernel = $this->getTestKernel($request, $modules_enabled, TRUE);
+    $kernel = new DrupalKernel('testing', $classloader);
+    $kernel->updateModules($module_enabled);
+    $kernel->boot();
     $container = $kernel->getContainer();
-
     $refClass = new \ReflectionClass($container);
     $is_container_builder = $refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder');
-    $this->assertTrue($is_container_builder, 'Container is a builder');
-
+    $this->assertTrue($is_container_builder);
     // Assert that the new module's bundle was registered to the new container.
-    $this->assertTrue($container->has('service_provider_test_class'), 'Container has test service');
-
+    $this->assertTrue($container->has('service_provider_test_class'));
     // Test that our synthetic services are there.
     $classloader = $container->get('class_loader');
     $refClass = new \ReflectionClass($classloader);
     $this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a classloader');
-
     // Check that the location of the new module is registered.
     $modules = $container->getParameter('container.modules');
     $this->assertEqual($modules['service_provider_test'], array(
diff --git a/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php b/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
index 58e62bc2d272f3b325959158785d31325d717d81..4faec44b5673d1b360a545800493dac14008fd31 100644
--- a/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php
@@ -102,8 +102,6 @@ public function testFieldItemAttributes() {
     // Enable the RDF module to ensure that two modules can add attributes to
     // the same field item.
     \Drupal::moduleHandler()->install(array('rdf'));
-    $this->rebuildContainer();
-
     // Set an RDF mapping for the field_test_text field. This RDF mapping will
     // be turned into RDFa attributes in the field item output.
     $mapping = rdf_get_mapping('entity_test', 'entity_test');
diff --git a/core/modules/system/src/Tests/Menu/MenuRouterTest.php b/core/modules/system/src/Tests/Menu/MenuRouterTest.php
index 58258955b86a0459c66d06456a268d2f474f38f0..4383658ba25018e5854fa3ec298d72b0529c9a0e 100644
--- a/core/modules/system/src/Tests/Menu/MenuRouterTest.php
+++ b/core/modules/system/src/Tests/Menu/MenuRouterTest.php
@@ -312,7 +312,6 @@ protected function doTestMenuOptionalPlaceholders() {
   protected function doTestMenuOnRoute() {
     \Drupal::moduleHandler()->install(array('router_test'));
     \Drupal::service('router.builder')->rebuild();
-    $this->rebuildContainer();
 
     $this->drupalGet('router_test/test2');
     $this->assertLinkByHref('menu_no_title_callback');
diff --git a/core/modules/system/src/Tests/System/ScriptTest.php b/core/modules/system/src/Tests/System/ScriptTest.php
index 773cfa0b3f21edd31d8020801b1e092e1dab8059..9ba2e5c9f0c485796e2daf38d864d8a8cd2d0ade 100644
--- a/core/modules/system/src/Tests/System/ScriptTest.php
+++ b/core/modules/system/src/Tests/System/ScriptTest.php
@@ -45,14 +45,6 @@ public function testPasswordHashSh() {
    * Tests rebuild_token_calculator.sh.
    */
   public function testRebuildTokenCalculatorSh() {
-    // The script requires a settings.php with a hash salt setting.
-    $filename = $this->siteDirectory . '/settings.php';
-    touch($filename);
-    $settings['settings']['hash_salt'] = (object) array(
-      'value' => 'some_random_key',
-      'required' => TRUE,
-    );
-    drupal_rewrite_settings($settings, $filename);
     $_SERVER['argv'] = array(
       'core/scripts/rebuild_token_calculator.sh',
     );
diff --git a/core/modules/system/src/Tests/Theme/ThemeSuggestionsAlterTest.php b/core/modules/system/src/Tests/Theme/ThemeSuggestionsAlterTest.php
index e5c33a174e8532bff8416b512d65d6aade1fadb1..202ddd2a44bf45d42b6ffda14f58728d7166fea7 100644
--- a/core/modules/system/src/Tests/Theme/ThemeSuggestionsAlterTest.php
+++ b/core/modules/system/src/Tests/Theme/ThemeSuggestionsAlterTest.php
@@ -69,7 +69,6 @@ function testGeneralSuggestionsAlter() {
     // Enable the theme_suggestions_test module to test modules implementing
     // suggestions alter hooks.
     \Drupal::moduleHandler()->install(array('theme_suggestions_test'));
-    $this->rebuildContainer();
     $this->drupalGet('theme-test/general-suggestion-alter');
     $this->assertText('Template overridden based on new theme suggestion provided by a module via hook_theme_suggestions_alter().');
   }
@@ -91,7 +90,6 @@ function testTemplateSuggestionsAlter() {
     // Enable the theme_suggestions_test module to test modules implementing
     // suggestions alter hooks.
     \Drupal::moduleHandler()->install(array('theme_suggestions_test'));
-    $this->rebuildContainer();
     $this->drupalGet('theme-test/suggestion-alter');
     $this->assertText('Template overridden based on new theme suggestion provided by a module via hook_theme_suggestions_HOOK_alter().');
   }
@@ -115,7 +113,6 @@ function testSpecificSuggestionsAlter() {
 
     // Ensure that the base hook is used to determine the suggestion alter hook.
     \Drupal::moduleHandler()->install(array('theme_suggestions_test'));
-    $this->rebuildContainer();
     $this->drupalGet('theme-test/specific-suggestion-alter');
     $this->assertText('Template overridden based on suggestion alter hook determined by the base hook.');
     $this->assertTrue(strpos($this->drupalGetContent(), 'theme_test_specific_suggestions__variant') < strpos($this->drupalGetContent(), 'theme_test_specific_suggestions__variant__foo'), 'Specific theme call is added to the suggestions array before the suggestions alter hook.');
@@ -138,7 +135,6 @@ function testThemeFunctionSuggestionsAlter() {
     // Enable the theme_suggestions_test module to test modules implementing
     // suggestions alter hooks.
     \Drupal::moduleHandler()->install(array('theme_suggestions_test'));
-    $this->rebuildContainer();
     $this->drupalGet('theme-test/function-suggestion-alter');
     $this->assertText('Theme function overridden based on new theme suggestion provided by a module.');
   }
@@ -155,7 +151,6 @@ public function testSuggestionsAlterInclude() {
     // the include file is always loaded. The file will always be included for
     // the first request because the theme registry is being rebuilt.
     \Drupal::moduleHandler()->install(array('theme_suggestions_test'));
-    $this->rebuildContainer();
     $this->drupalGet('theme-test/suggestion-alter-include');
     $this->assertText('Function suggested via suggestion alter hook found in include file.', 'Include file loaded for initial request.');
     $this->drupalGet('theme-test/suggestion-alter-include');
@@ -174,7 +169,6 @@ function testExecutionOrder() {
       ->set('default', 'test_theme')
       ->save();
     \Drupal::moduleHandler()->install(array('theme_suggestions_test'));
-    $this->rebuildContainer();
 
     // Send two requests so that we get all the messages we've set via
     // drupal_set_message().
diff --git a/core/modules/system/tests/http.php b/core/modules/system/tests/http.php
index 33869799e316b1e398610774723187c985be3702..662031f79b456b4dc7117a09c3c69beb630e2e05 100644
--- a/core/modules/system/tests/http.php
+++ b/core/modules/system/tests/http.php
@@ -5,29 +5,19 @@
  * Fake an HTTP request, for use during testing.
  */
 
-use Drupal\Core\Test\TestKernel;
-use Symfony\Component\HttpFoundation\Request;
-
-chdir('../../../..');
-
-$autoloader = require_once './core/vendor/autoload.php';
-
 // Set a global variable to indicate a mock HTTP request.
 $is_http_mock = !empty($_SERVER['HTTPS']);
 
 // Change to HTTP.
 $_SERVER['HTTPS'] = NULL;
 ini_set('session.cookie_secure', FALSE);
-foreach ($_SERVER as &$value) {
-  $value = str_replace('core/modules/system/tests/http.php', 'index.php', $value);
-  $value = str_replace('https://', 'http://', $value);
+foreach ($_SERVER as $key => $value) {
+  $_SERVER[$key] = str_replace('core/modules/system/tests/http.php', 'index.php', $value);
+  $_SERVER[$key] = str_replace('https://', 'http://', $_SERVER[$key]);
 }
 
-$request = Request::createFromGlobals();
-$kernel = TestKernel::createFromRequest($request, $autoloader, 'testing', TRUE);
-$response = $kernel
-  ->handlePageCache($request)
-  ->handle($request)
-    // Handle the response object.
-    ->prepare($request)->send();
-$kernel->terminate($request, $response);
+// Change current directory to the Drupal root.
+chdir('../../../..');
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+require_once dirname(dirname(dirname(__DIR__))) . '/includes/bootstrap.inc';
+drupal_handle_request(TRUE);
diff --git a/core/modules/system/tests/https.php b/core/modules/system/tests/https.php
index 00a6b13d6155ee7bb55e0f4fe841913ded4329bd..247e6e515e0a86ae73fca91ba09377bc48a42af2 100644
--- a/core/modules/system/tests/https.php
+++ b/core/modules/system/tests/https.php
@@ -8,28 +8,18 @@
  *   see http.php.
  */
 
-use Drupal\Core\Test\TestKernel;
-use Symfony\Component\HttpFoundation\Request;
-
-chdir('../../../..');
-
-$autoloader = require_once './core/vendor/autoload.php';
-
 // Set a global variable to indicate a mock HTTPS request.
 $is_https_mock = empty($_SERVER['HTTPS']);
 
 // Change to HTTPS.
 $_SERVER['HTTPS'] = 'on';
-foreach ($_SERVER as &$value) {
-  $value = str_replace('core/modules/system/tests/https.php', 'index.php', $value);
-  $value = str_replace('http://', 'https://', $value);
+foreach ($_SERVER as $key => $value) {
+  $_SERVER[$key] = str_replace('core/modules/system/tests/https.php', 'index.php', $value);
+  $_SERVER[$key] = str_replace('http://', 'https://', $_SERVER[$key]);
 }
 
-$request = Request::createFromGlobals();
-$kernel = TestKernel::createFromRequest($request, $autoloader, 'testing', TRUE);
-$response = $kernel
-  ->handlePageCache($request)
-  ->handle($request)
-    // Handle the response object.
-    ->prepare($request)->send();
-$kernel->terminate($request, $response);
+// Change current directory to the Drupal root.
+chdir('../../../..');
+require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
+require_once dirname(dirname(dirname(__DIR__))) . '/includes/bootstrap.inc';
+drupal_handle_request(TRUE);
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index f46770abe1f9ef2246766dd6571acd42cad330b5..3599c5944b1a472204b8ab683918118601291ba7 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -109,7 +109,7 @@ function toolbar_element_info() {
  * Use Drupal's page cache for toolbar/subtrees/*, even for authenticated users.
  *
  * This gets invoked after full bootstrap, so must duplicate some of what's
- * done by \Drupal\Core\DrupalKernel::handlePageCache().
+ * done by _drupal_bootstrap_page_cache().
  *
  * @todo Replace this hack with something better integrated with DrupalKernel
  *   once Drupal's page caching itself is properly integrated.
@@ -119,7 +119,7 @@ function _toolbar_initialize_page_cache() {
   drupal_page_is_cacheable(TRUE);
 
   // If we have a cache, serve it.
-  // @see \Drupal\Core\DrupalKernel::handlePageCache()
+  // @see _drupal_bootstrap_page_cache()
   $request = \Drupal::request();
   $response = drupal_page_get_cache($request);
   if ($response) {
diff --git a/core/modules/user/src/Tests/UserLoginTest.php b/core/modules/user/src/Tests/UserLoginTest.php
index c6fefcf965367c2e5b4da49802a2306becceac7e..8016987f38df4aa3610befac5a798e0de692d625 100644
--- a/core/modules/user/src/Tests/UserLoginTest.php
+++ b/core/modules/user/src/Tests/UserLoginTest.php
@@ -135,7 +135,6 @@ function testPasswordRehashOnLogin() {
     // users password gets rehashed during the login.
     $overridden_count_log2 = 19;
     \Drupal::moduleHandler()->install(array('user_custom_phpass_params_test'));
-    $this->rebuildContainer();
 
     $account->pass_raw = $password;
     $this->drupalLogin($account);
diff --git a/core/modules/views_ui/src/Tests/PreviewTest.php b/core/modules/views_ui/src/Tests/PreviewTest.php
index 315ef98d620845847d9e87f7713992a4cc3b67f4..01feff62eda24643d3403afc7dc3cb3adc5b4c6b 100644
--- a/core/modules/views_ui/src/Tests/PreviewTest.php
+++ b/core/modules/views_ui/src/Tests/PreviewTest.php
@@ -34,8 +34,6 @@ public static function getInfo() {
    */
   protected function testPreviewContextual() {
     \Drupal::moduleHandler()->install(array('contextual'));
-    $this->rebuildContainer();
-
     $this->drupalGet('admin/structure/views/view/test_preview/edit');
     $this->assertResponse(200);
     $this->drupalPostForm(NULL, $edit = array(), t('Update preview'));
diff --git a/core/rebuild.php b/core/rebuild.php
index f7acbcea8a7c145d49c8172cd17cd85bb3ca848d..3e8ed1282c152a9ef231eca9041a4231bb689487 100644
--- a/core/rebuild.php
+++ b/core/rebuild.php
@@ -11,30 +11,25 @@
  */
 
 use Drupal\Component\Utility\Crypt;
-use Drupal\Core\DrupalKernel;
 use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Request;
 
 // Change the directory to the Drupal root.
 chdir('..');
 
-$autoloader = require_once __DIR__ . '/vendor/autoload.php';
+require_once __DIR__ . '/vendor/autoload.php';
+require_once __DIR__ . '/includes/bootstrap.inc';
 require_once __DIR__ . '/includes/utility.inc';
 
-$request = Request::createFromGlobals();
-// Manually resemble early bootstrap of DrupalKernel::boot().
-require_once __DIR__ . '/includes/bootstrap.inc';
-DrupalKernel::bootEnvironment();
-Settings::initialize(DrupalKernel::findSitePath($request));
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
 
 if (Settings::get('rebuild_access', FALSE) ||
-  ($request->get('token') && $request->get('timestamp') &&
-    ((REQUEST_TIME - $request->get('timestamp')) < 300) &&
-    ($request->get('token') === Crypt::hmacBase64($request->get('timestamp'), Settings::get('hash_salt')))
+  (isset($_GET['token'], $_GET['timestamp']) &&
+    ((REQUEST_TIME - $_GET['timestamp']) < 300) &&
+    ($_GET['token'] === Crypt::hmacBase64($_GET['timestamp'], Settings::get('hash_salt')))
   )) {
 
-  drupal_rebuild($autoloader, $request);
+  drupal_rebuild();
   drupal_set_message('Cache rebuild complete.');
 }
-$base_path = dirname(dirname($request->getBaseUrl()));
-header('Location: ' . $base_path);
+
+header('Location: ' . $GLOBALS['base_url']);
diff --git a/core/scripts/password-hash.sh b/core/scripts/password-hash.sh
index ee3c10246dc295e8fc34c1547346bda62c4e88f6..f80d75c6ca8a51c491b36393baf24068e246703b 100755
--- a/core/scripts/password-hash.sh
+++ b/core/scripts/password-hash.sh
@@ -9,7 +9,6 @@
  */
 
 use Drupal\Core\DrupalKernel;
-use Symfony\Component\HttpFoundation\Request;
 
 // Check for $_SERVER['argv'] instead of PHP_SAPI === 'cli' to allow this script
 // to be tested with the Simpletest UI test runner.
@@ -57,10 +56,14 @@
 // Password list to be processed.
 $passwords = $_SERVER['argv'];
 
-$autoloader = require __DIR__ . '/../vendor/autoload.php';
+$core = dirname(__DIR__);
+require_once $core . '/vendor/autoload.php';
+require_once $core . '/includes/bootstrap.inc';
 
-$request = Request::createFromGlobals();
-$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod', FALSE);
+// Bootstrap the code so we have the container.
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+
+$kernel = new DrupalKernel('prod', drupal_classloader(), FALSE);
 $kernel->boot();
 
 $password_hasher = $kernel->getContainer()->get('password');
diff --git a/core/scripts/rebuild_token_calculator.sh b/core/scripts/rebuild_token_calculator.sh
index bcfd2b6fc16add9b80089f219e18d0957aaebcb0..9e7dc03ddb0ff4563e266195413803163d406730 100755
--- a/core/scripts/rebuild_token_calculator.sh
+++ b/core/scripts/rebuild_token_calculator.sh
@@ -7,9 +7,7 @@
  */
 
 use Drupal\Component\Utility\Crypt;
-use Drupal\Core\DrupalKernel;
 use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Request;
 
 // Check for $_SERVER['argv'] instead of PHP_SAPI === 'cli' to allow this script
 // to be tested with the Simpletest UI test runner.
@@ -18,11 +16,11 @@
   return;
 }
 
-require __DIR__ . '/../vendor/autoload.php';
-require_once __DIR__ . '/../includes/bootstrap.inc';
+$core = dirname(__DIR__);
+require_once $core . '/vendor/autoload.php';
+require_once $core . '/includes/bootstrap.inc';
 
-$request = Request::createFromGlobals();
-Settings::initialize(DrupalKernel::findSitePath($request));
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
 
 $timestamp = time();
 $token = Crypt::hmacBase64($timestamp, Settings::get('hash_salt'));
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 4679325dcf38239c6a76efc9f47b2c22ae992946..8eff2a29805ee2852bc41daa3e936463f27113df 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -8,10 +8,10 @@
 use Drupal\Component\Utility\Timer;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Site\Settings;
-use Drupal\Core\Test\TestRunnerKernel;
+use Drupal\Core\Test\TestKernel;
 use Symfony\Component\HttpFoundation\Request;
 
-$autoloader = require_once __DIR__ . '/../vendor/autoload.php';
+require_once __DIR__ . '/../vendor/autoload.php';
 
 const SIMPLETEST_SCRIPT_COLOR_PASS = 32; // Green.
 const SIMPLETEST_SCRIPT_COLOR_FAIL = 31; // Red.
@@ -26,10 +26,7 @@
 }
 
 simpletest_script_init();
-
-$request = Request::createFromGlobals();
-$kernel = TestRunnerKernel::createFromRequest($request, $autoloader);
-$kernel->prepareLegacyRequest($request);
+simpletest_script_bootstrap();
 
 if ($args['execute-test']) {
   simpletest_script_setup_database();
@@ -356,6 +353,50 @@ function simpletest_script_init() {
   }
 
   chdir(realpath(__DIR__ . '/../..'));
+  require_once dirname(__DIR__) . '/includes/bootstrap.inc';
+}
+
+/**
+ * Bootstraps a minimal Drupal environment.
+ *
+ * @see install_begin_request()
+ */
+function simpletest_script_bootstrap() {
+  // Load legacy include files.
+  foreach (glob(DRUPAL_ROOT . '/core/includes/*.inc') as $include) {
+    require_once $include;
+  }
+
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+
+  // Remove Drupal's error/exception handlers; they are designed for HTML
+  // and there is no storage nor a (watchdog) logger here.
+  restore_error_handler();
+  restore_exception_handler();
+
+  // In addition, ensure that PHP errors are not hidden away in logs.
+  ini_set('display_errors', TRUE);
+
+  // Ensure that required Settings exist.
+  if (!Settings::getAll()) {
+    new Settings(array(
+      'hash_salt' => 'run-tests',
+    ));
+  }
+
+  $kernel = new TestKernel(drupal_classloader());
+  $kernel->boot();
+
+  $request = Request::createFromGlobals();
+  $container = $kernel->getContainer();
+  $container->enterScope('request');
+  $container->set('request', $request, 'request');
+  $container->get('request_stack')->push($request);
+
+  $module_handler = $container->get('module_handler');
+  $module_handler->loadAll();
+
+  simpletest_classloader_register();
 }
 
 /**
diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php
index 99fe34d05198ddaf71314addbbdb2c2686c388cd..72c5d5bc930047ca11d5bb6f9bb995134fd542d2 100644
--- a/core/tests/bootstrap.php
+++ b/core/tests/bootstrap.php
@@ -87,7 +87,7 @@ function drupal_phpunit_register_extension_dirs(Composer\Autoload\ClassLoader $l
 
 // Set sane locale settings, to ensure consistent string, dates, times and
 // numbers handling.
-// @see \Drupal\Core\DrupalKernel::bootEnvironment()
+// @see drupal_environment_initialize()
 setlocale(LC_ALL, 'C');
 
 // Set the default timezone. While this doesn't cause any tests to fail, PHP
diff --git a/core/update.php b/core/update.php
index 9147e9ef85f22c6ccd915b7f5f4aea19e07446a0..b6accf3a5f42d97d5682de51bc3bebd58e816167 100644
--- a/core/update.php
+++ b/core/update.php
@@ -25,7 +25,7 @@
 // Change the directory to the Drupal root.
 chdir('..');
 
-$autoloader = require_once __DIR__ . '/vendor/autoload.php';
+require_once __DIR__ . '/vendor/autoload.php';
 
 // Exit early if an incompatible PHP version would cause fatal errors.
 // The minimum version is specified explicitly, as DRUPAL_MINIMUM_PHP is not
@@ -297,17 +297,18 @@ function update_task_list($active = NULL) {
 
 // We prepare a minimal bootstrap for the update requirements check to avoid
 // reaching the PHP memory limit.
+require_once __DIR__ . '/includes/bootstrap.inc';
 require_once __DIR__ . '/includes/update.inc';
+require_once __DIR__ . '/includes/common.inc';
+require_once __DIR__ . '/includes/file.inc';
+require_once __DIR__ . '/includes/unicode.inc';
 require_once __DIR__ . '/includes/install.inc';
+require_once __DIR__ . '/includes/schema.inc';
+// Bootstrap to configuration.
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
 
-$request = Request::createFromGlobals();
-$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'update', FALSE);
-
-// Enable UpdateServiceProvider service overrides.
-// @see update_flush_all_caches()
-$GLOBALS['conf']['container_service_providers']['UpdateServiceProvider'] = 'Drupal\Core\DependencyInjection\UpdateServiceProvider';
-$GLOBALS['conf']['update_service_provider_overrides'] = TRUE;
-$kernel->boot();
+// Bootstrap the database.
+require_once __DIR__ . '/includes/database.inc';
 
 // Updating from a site schema version prior to 8000 should block the update
 // process. Ensure that the site is not attempting to update a database
@@ -320,9 +321,27 @@ function update_task_list($active = NULL) {
   }
 }
 
-$kernel->prepareLegacyRequest($request);
+// Enable UpdateServiceProvider service overrides.
+// @see update_flush_all_caches()
+$GLOBALS['conf']['container_service_providers']['UpdateServiceProvider'] = 'Drupal\Core\DependencyInjection\UpdateServiceProvider';
+$GLOBALS['conf']['update_service_provider_overrides'] = TRUE;
+
+// module.inc is not yet loaded but there are calls to module_config_sort()
+// below.
+require_once __DIR__ . '/includes/module.inc';
+
+$settings = Settings::getAll();
+new Settings($settings);
+$kernel = new DrupalKernel('update', drupal_classloader(), FALSE);
+$kernel->boot();
+$request = Request::createFromGlobals();
+$container = \Drupal::getContainer();
+$container->set('request', $request);
+$container->get('request_stack')->push($request);
 
 // Determine if the current user has access to run update.php.
+drupal_bootstrap(DRUPAL_BOOTSTRAP_PAGE_CACHE);
+
 \Drupal::service('session_manager')->initialize();
 
 // Ensure that URLs generated for the home and admin pages don't have 'update.php'
@@ -359,6 +378,7 @@ function update_task_list($active = NULL) {
   install_goto('core/update.php?op=info');
 }
 
+drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 drupal_maintenance_theme();
 
 // Turn error reporting back on. From now on, only fatal errors (which are
diff --git a/index.php b/index.php
index 6bff08359f7db56e2973166a0a93e8c15dc2356e..a453ecc1f910c0b56de4a2a020f6290bbef4b25f 100644
--- a/index.php
+++ b/index.php
@@ -8,22 +8,13 @@
  * See COPYRIGHT.txt and LICENSE.txt files in the "core" directory.
  */
 
-use Drupal\Core\DrupalKernel;
 use Drupal\Core\Site\Settings;
-use Symfony\Component\HttpFoundation\Request;
 
-$autoloader = require_once __DIR__ . '/core/vendor/autoload.php';
+require_once __DIR__ . '/core/vendor/autoload.php';
+require_once __DIR__ . '/core/includes/bootstrap.inc';
 
 try {
-
-  $request = Request::createFromGlobals();
-  $kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');
-  $response = $kernel
-    ->handlePageCache($request)
-    ->handle($request)
-      // Handle the response object.
-      ->prepare($request)->send();
-  $kernel->terminate($request, $response);
+  drupal_handle_request();
 }
 catch (Exception $e) {
   $message = 'If you have just changed code (for example deployed a new module or moved an existing one) read <a href="http://drupal.org/documentation/rebuild">http://drupal.org/documentation/rebuild</a>';
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 7781c0c14d21958924b9c860b074fb5bdc835a3e..587a9cc1a3c1db79e08d39ffc3ebad9db644551a 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -245,7 +245,7 @@
  * directory and reverse proxy address, and temporary configuration, such as
  * turning on Twig debugging and security overrides.
  *
- * @see \Drupal\Core\Site\Settings::get()
+ * @see \Drupal\Component\Utility\Settings::get()
  */
 
 /**
@@ -490,8 +490,8 @@
  * To see what PHP settings are possible, including whether they can be set at
  * runtime (by using ini_set()), read the PHP documentation:
  * http://php.net/manual/ini.list.php
- * See \Drupal\Core\DrupalKernel::bootEnvironment() for required runtime
- * settings and the .htaccess file for non-runtime settings.
+ * See drupal_environment_initialize() in core/includes/bootstrap.inc for
+ * required runtime settings and the .htaccess file for non-runtime settings.
  * Settings defined there should not be duplicated here so as to avoid conflict
  * issues.
  */
diff --git a/web.config b/web.config
index b71c37cdcb7ac5f48551cca1bf40c2a3f26ac764..3336222b476f6ce8268007bb80344c3b39bf8b0b 100644
--- a/web.config
+++ b/web.config
@@ -61,7 +61,8 @@
     -->
 
         <!-- Pass all requests not referring directly to files in the filesystem
-         to index.php. -->
+         to index.php. Clean URLs are handled in
+         drupal_environment_initialize(). -->
         <rule name="Short URLS" stopProcessing="true">
           <match url="^(.*)$" ignoreCase="false" />
           <conditions>