diff --git a/core/core.services.yml b/core/core.services.yml
index f8c428f..e3b176b 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -384,9 +384,14 @@ services:
     arguments: ['@settings']
     tags:
       - { name: http_middleware, priority: 300 }
+  http_middleware.init_cookie:
+    class: Drupal\Core\StackMiddleware\InitCookies
+    arguments: ['@kernel']
+    tags:
+      - { name: http_middleware, priority: 210 }
   http_middleware.page_cache:
     class: Drupal\Core\StackMiddleware\PageCache
-    arguments: ['@kernel']
+    arguments: ['@config.factory', '@settings']
     tags:
       - { name: http_middleware, priority: 200 }
   http_middleware.kernel_pre_handle:
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 8c96031..ff0bbc3 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1033,9 +1033,6 @@ function drupal_bootstrap($phase = NULL) {
           break;
 
         case DRUPAL_BOOTSTRAP_PAGE_CACHE:
-          $kernel->handlePageCache($request);
-          break;
-
         case DRUPAL_BOOTSTRAP_CODE:
         case DRUPAL_BOOTSTRAP_FULL:
           $kernel->prepareLegacyRequest($request);
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index c1069a1..5c60fbd 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -154,13 +154,6 @@ 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
@@ -427,9 +420,6 @@ public function preHandle(Request $request) {
     // Initialize legacy request globals.
     $this->initializeRequestGlobals($request);
 
-    // Initialize cookie globals.
-    $this->initializeCookieGlobals($request);
-
     // Put the request on the stack.
     $this->container->get('request_stack')->push($request);
 
@@ -450,44 +440,6 @@ public function preHandle(Request $request) {
 
   /**
    * {@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}
    */
   public function discoverServiceProviders() {
     $this->serviceYamls = array(
@@ -871,67 +823,6 @@ protected function initializeRequestGlobals(Request $request) {
   }
 
   /**
-   * 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.
    */
   protected function getServicesToPersist(ContainerInterface $container) {
diff --git a/core/lib/Drupal/Core/DrupalKernelInterface.php b/core/lib/Drupal/Core/DrupalKernelInterface.php
index ca7af2b..0db4405 100644
--- a/core/lib/Drupal/Core/DrupalKernelInterface.php
+++ b/core/lib/Drupal/Core/DrupalKernelInterface.php
@@ -86,16 +86,6 @@ public function getSitePath();
   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
diff --git a/core/lib/Drupal/Core/StackMiddleware/InitCookies.php b/core/lib/Drupal/Core/StackMiddleware/InitCookies.php
new file mode 100644
index 0000000..d8c495b
--- /dev/null
+++ b/core/lib/Drupal/Core/StackMiddleware/InitCookies.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\StackMiddleware\InitCookies.
+ */
+
+namespace Drupal\Core\StackMiddleware;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+class InitCookies implements HttpKernelInterface {
+
+  /**
+   * The wrapped HTTP kernel.
+   *
+   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
+   */
+  protected $httpKernel;
+
+  /**
+   * Whether the request globals have been initialized.
+   *
+   * @var bool
+   */
+  protected static $isRequestInitialized = FALSE;
+
+  /**
+   * Constructs a ReverseProxyMiddleware object.
+   *
+   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
+   *   The decorated kernel.
+   */
+  public function __construct(HttpKernelInterface $http_kernel) {
+    $this->httpKernel = $http_kernel;
+  }
+
+  /**
+   * Initialize cookie settings.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The current request.
+   */
+  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;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
+    $this->initializeCookieGlobals($request);
+
+    return $this->httpKernel->handle($request, $type, $catch);
+  }
+
+}
+
diff --git a/core/lib/Drupal/Core/StackMiddleware/PageCache.php b/core/lib/Drupal/Core/StackMiddleware/PageCache.php
index ba59e93..519a184 100644
--- a/core/lib/Drupal/Core/StackMiddleware/PageCache.php
+++ b/core/lib/Drupal/Core/StackMiddleware/PageCache.php
@@ -7,7 +7,8 @@
 
 namespace Drupal\Core\StackMiddleware;
 
-use Drupal\Core\DrupalKernelInterface;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Site\Settings;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 
@@ -24,31 +25,72 @@ class PageCache implements HttpKernelInterface {
   protected $httpKernel;
 
   /**
-   * The main Drupal kernel.
+   * The system performance config object.
    *
-   * @var \Drupal\Core\DrupalKernelInterface
+   * @var \Drupal\Core\Config\Config
    */
-  protected $drupalKernel;
+  protected $config;
+
+  /**
+   * The config factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+
+  /**
+   * The settings.
+   *
+   * @var \Drupal\Core\Site\Settings
+   */
+  protected $settings;
 
   /**
    * Constructs a ReverseProxyMiddleware object.
    *
    * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
    *   The decorated kernel.
-   * @param \Drupal\Core\DrupalKernelInterface $drupal_kernel
-   *   The main Drupal kernel.
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The config factory.
+   * @param \Drupal\Core\Site\Settings $settings
+   *   The settings.
    */
-  public function __construct(HttpKernelInterface $http_kernel, DrupalKernelInterface $drupal_kernel) {
+  public function __construct(HttpKernelInterface $http_kernel, ConfigFactoryInterface $config_factory, Settings $settings) {
     $this->httpKernel = $http_kernel;
-    $this->drupalKernel = $drupal_kernel;
+    $this->configFactory = $config_factory;
+    $this->settings = $settings;
   }
 
   /**
    * {@inheritdoc}
    */
   public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
-    $this->drupalKernel->handlePageCache($request);
+    // Check for a cache mode force from settings.php.
+    if ($this->settings->get('page_cache_without_database')) {
+      $cache_enabled = TRUE;
+    }
+    else {
+      $cache_enabled = $this->configFactory->get('system.performance')->get('cache.page.use_internal');
+    }
+
+    // If there is no session cookie and cache is enabled (or forced), try to
+    // serve a cached page.
+    if ($cache_enabled && !$request->cookies->has(session_name()) && 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.
+        return $response;
+      }
+    }
 
+    // Otherwise, just pass the request on.
     return $this->httpKernel->handle($request, $type, $catch);
   }
 
