diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index a818c78..cf0e3dd 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1889,7 +1889,8 @@ function drupal_handle_request($test_only = FALSE) {
     exit;
   }
 
-  $kernel = new DrupalKernel('prod', drupal_classloader(), !$test_only);
+  // @todo Figure out how best to handle the Kernel constructor parameters.
+  $kernel = new DrupalKernel('prod', FALSE, drupal_classloader(), !$test_only);
 
   // @todo Remove this once everything in the bootstrap has been
   //   converted to services in the DIC.
@@ -2025,7 +2026,7 @@ function _drupal_bootstrap_kernel() {
   // Normally, index.php puts a container in drupal_container() by creating a
   // kernel. If there is no container yet, create one.
   if (!drupal_container()) {
-    $kernel = new DrupalKernel('prod', drupal_classloader());
+    $kernel = new DrupalKernel('prod', FALSE, drupal_classloader());
     $kernel->boot();
   }
 }
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 4e9a319..77771d8 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -4,14 +4,14 @@
 
 use Drupal\Core\Config\FileStorage;
 use Drupal\Core\DrupalKernel;
-use Drupal\Core\CoreServiceProvider;
+use Drupal\Core\CoreBundle;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Database\Install\TaskException;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageManager;
 use Drupal\Core\StringTranslation\Translator\FileTranslation;
 
-use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
@@ -354,7 +354,7 @@ function install_begin_request(&$install_state) {
   // @see drupal_install_config_directories()
   // @see install_settings_form_submit()
   if ($install_state['settings_verified']) {
-    $kernel = new DrupalKernel('install', drupal_classloader(), FALSE);
+    $kernel = new DrupalKernel('install', FALSE, drupal_classloader(), FALSE);
     $kernel->boot();
     $container = $kernel->getContainer();
     // Add the file translation service to the container.
@@ -426,7 +426,7 @@ function install_begin_request(&$install_state) {
     $conf['keyvalue_expirable_default'] = 'keyvalue.expirable.null';
 
     // Register Twig template engine for use during install.
-    CoreServiceProvider::registerTwig($container);
+    CoreBundle::registerTwig($container);
 
     $container->register('url_generator', 'Drupal\Core\Routing\NullGenerator');
 
@@ -1453,11 +1453,11 @@ function install_translations_directory() {
  */
 function install_register_translation_service(ContainerBuilder $container) {
   $container->register('string_translator.file_translation', 'Drupal\Core\StringTranslation\Translator\FileTranslation')
-    ->addArgument(install_translations_directory());
-  $container->register('string_translator.custom_strings', 'Drupal\Core\StringTranslation\Translator\CustomStrings');
-  $container->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager')
-    ->addMethodCall('addTranslator', array(new Reference('string_translator.file_translation')))
-    ->addMethodCall('addTranslator', array(new Reference('string_translator.custom_strings')));
+    ->addArgument(install_translations_directory())
+    ->addTag('string_translator');
+  $container->register('string_translator.custom_strings', 'Drupal\Core\StringTranslation\Translator\CustomStrings')
+    ->addTag('string_translator');
+  $container->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager');
 }
 
 /**
diff --git a/core/includes/install.inc b/core/includes/install.inc
index e0e86cc..b0ca296 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -619,7 +619,7 @@ function drupal_install_system() {
 
   if (!drupal_container()->has('kernel')) {
     // Immediately boot a kernel to have real services ready.
-    $kernel = new DrupalKernel('install', drupal_classloader(), FALSE);
+    $kernel = new DrupalKernel('install', FALSE, drupal_classloader(), FALSE);
     $kernel->boot();
   }
 
diff --git a/core/includes/project.inc b/core/includes/project.inc
new file mode 100644
index 0000000..df9c50c
--- /dev/null
+++ b/core/includes/project.inc
@@ -0,0 +1,242 @@
+<?php
+
+/**
+ * @file
+ * API for building lists of installed projects.
+ */
+
+/**
+ * Populates an array of project data.
+ *
+ * This iterates over a list of the installed modules or themes and groups
+ * them by project and status. A few parts of this function assume that
+ * enabled modules and themes are always processed first, and if disabled
+ * modules or themes are being processed (there is a setting to control if
+ * disabled code should be included in the Available updates report or not),
+ * those are only processed after $projects has been populated with
+ * information about the enabled code. 'Hidden' modules are always ignored.
+ * 'Hidden' themes are ignored only if they have no enabled sub-themes.
+ * This function also records the latest change time on the .info.yml
+ * files for each module or theme, which is important data which is used when
+ * deciding if the available update data should be invalidated.
+ *
+ * @param $projects
+ *   Reference to the array of project data of what's installed on this site.
+ * @param $list
+ *   Array of data to process to add the relevant info to the $projects array.
+ * @param $project_type
+ *   The kind of data in the list. Can be 'module' or 'theme'.
+ * @param $status
+ *   Boolean that controls what status (enabled or disabled) to process out of
+ *   the $list and add to the $projects array.
+ * @param $additional_whitelist
+ *   (optional) Array of additional elements to be collected from the .info.yml
+ *   file. Defaults to array().
+ *
+ * @see update_get_projects()
+ */
+function drupal_project_process_info_list(&$projects, $list, $project_type, $status, $additional_whitelist = array()) {
+  foreach ($list as $file) {
+    // A disabled or hidden base theme of an enabled sub-theme still has all
+    // of its code run by the sub-theme, so we include it in our "enabled"
+    // projects list.
+    if ($status && !empty($file->sub_themes)) {
+      foreach ($file->sub_themes as $key => $name) {
+        // Build a list of enabled sub-themes.
+        if ($list[$key]->status) {
+          $file->enabled_sub_themes[$key] = $name;
+        }
+      }
+      // If the theme is disabled and there are no enabled subthemes, we
+      // should ignore this base theme for the enabled case. If the site is
+      // trying to display disabled themes, we'll catch it then.
+      if (!$file->status && empty($file->enabled_sub_themes)) {
+        continue;
+      }
+    }
+    // Otherwise, just add projects of the proper status to our list.
+    elseif ($file->status != $status) {
+      continue;
+    }
+
+    // Skip if the .info.yml file is broken.
+    if (empty($file->info)) {
+      continue;
+    }
+
+    // Skip if it's a hidden module or hidden theme without enabled sub-themes.
+    if (!empty($file->info['hidden']) && empty($file->enabled_sub_themes)) {
+      continue;
+    }
+
+    // If the .info.yml doesn't define the 'project', try to figure it out.
+    if (!isset($file->info['project'])) {
+      $file->info['project'] = drupal_project_get_project_name($file);
+    }
+
+    // If we still don't know the 'project', give up.
+    if (empty($file->info['project'])) {
+      continue;
+    }
+
+    // If we don't already know it, grab the change time on the .info.yml file
+    // itself. Note: we need to use the ctime, not the mtime (modification
+    // time) since many (all?) tar implementations will go out of their way to
+    // set the mtime on the files it creates to the timestamps recorded in the
+    // tarball. We want to see the last time the file was changed on disk,
+    // which is left alone by tar and correctly set to the time the .info.yml
+    // file was unpacked.
+    if (!isset($file->info['_info_file_ctime'])) {
+      $info_filename = dirname($file->uri) . '/' . $file->name . '.info.yml';
+      $file->info['_info_file_ctime'] = filectime($info_filename);
+    }
+
+    if (!isset($file->info['datestamp'])) {
+      $file->info['datestamp'] = 0;
+    }
+
+    $project_name = $file->info['project'];
+
+    // Figure out what project type we're going to use to display this module
+    // or theme. If the project name is 'drupal', we don't want it to show up
+    // under the usual "Modules" section, we put it at a special "Drupal Core"
+    // section at the top of the report.
+    if ($project_name == 'drupal') {
+      $project_display_type = 'core';
+    }
+    else {
+      $project_display_type = $project_type;
+    }
+    if (empty($status) && empty($file->enabled_sub_themes)) {
+      // If we're processing disabled modules or themes, append a suffix.
+      // However, we don't do this to a a base theme with enabled
+      // subthemes, since we treat that case as if it is enabled.
+      $project_display_type .= '-disabled';
+    }
+    // Add a list of sub-themes that "depend on" the project and a list of base
+    // themes that are "required by" the project.
+    if ($project_name == 'drupal') {
+      // Drupal core is always required, so this extra info would be noise.
+      $sub_themes = array();
+      $base_themes = array();
+    }
+    else {
+      // Add list of enabled sub-themes.
+      $sub_themes = !empty($file->enabled_sub_themes) ? $file->enabled_sub_themes : array();
+      // Add list of base themes.
+      $base_themes = !empty($file->base_themes) ? $file->base_themes : array();
+    }
+    if (!isset($projects[$project_name])) {
+      // Only process this if we haven't done this project, since a single
+      // project can have multiple modules or themes.
+      $projects[$project_name] = array(
+        'name' => $project_name,
+        // Only save attributes from the .info.yml file we care about so we do
+        // not bloat our RAM usage needlessly.
+        'info' => update_filter_project_info($file->info, $additional_whitelist),
+        'datestamp' => $file->info['datestamp'],
+        'includes' => array($file->name => $file->info['name']),
+        'project_type' => $project_display_type,
+        'project_status' => $status,
+        'sub_themes' => $sub_themes,
+        'base_themes' => $base_themes,
+      );
+    }
+    elseif ($projects[$project_name]['project_type'] == $project_display_type) {
+      // Only add the file we're processing to the 'includes' array for this
+      // project if it is of the same type and status (which is encoded in the
+      // $project_display_type). This prevents listing all the disabled
+      // modules included with an enabled project if we happen to be checking
+      // for disabled modules, too.
+      $projects[$project_name]['includes'][$file->name] = $file->info['name'];
+      $projects[$project_name]['info']['_info_file_ctime'] = max($projects[$project_name]['info']['_info_file_ctime'], $file->info['_info_file_ctime']);
+      $projects[$project_name]['datestamp'] = max($projects[$project_name]['datestamp'], $file->info['datestamp']);
+      if (!empty($sub_themes)) {
+        $projects[$project_name]['sub_themes'] += $sub_themes;
+      }
+      if (!empty($base_themes)) {
+        $projects[$project_name]['base_themes'] += $base_themes;
+      }
+    }
+    elseif (empty($status)) {
+      // If we have a project_name that matches, but the project_display_type
+      // does not, it means we're processing a disabled module or theme that
+      // belongs to a project that has some enabled code. In this case, we add
+      // the disabled thing into a separate array for separate display.
+      $projects[$project_name]['disabled'][$file->name] = $file->info['name'];
+    }
+  }
+}
+
+/**
+ * Determines what project a given file object belongs to.
+ *
+ * @param $file
+ *   A file object as returned by system_get_files_database().
+ *
+ * @return
+ *   The canonical project short name.
+ *
+ * @see system_get_files_database()
+ */
+function drupal_project_get_project_name($file) {
+  $project_name = '';
+  if (isset($file->info['project'])) {
+    $project_name = $file->info['project'];
+  }
+  elseif (isset($file->filename) && (strpos($file->filename, 'core/modules') === 0)) {
+    $project_name = 'drupal';
+  }
+  return $project_name;
+}
+
+/**
+ * Determines version and type information for currently installed projects.
+ *
+ * Processes the list of projects on the system to figure out the currently
+ * installed versions, and other information that is required before we can
+ * compare against the available releases to produce the status report.
+ *
+ * @param $projects
+ *   Array of project information from update_get_projects().
+ */
+function drupal_project_process_project_info(&$projects) {
+  foreach ($projects as $key => $project) {
+    // Assume an official release until we see otherwise.
+    $install_type = 'official';
+
+    $info = $project['info'];
+
+    if (isset($info['version'])) {
+      // Check for development snapshots
+      if (preg_match('@(dev|HEAD)@', $info['version'])) {
+        $install_type = 'dev';
+      }
+
+      // Figure out what the currently installed major version is. We need
+      // to handle both contribution (e.g. "5.x-1.3", major = 1) and core
+      // (e.g. "5.1", major = 5) version strings.
+      $matches = array();
+      if (preg_match('/^(\d+\.x-)?(\d+)\..*$/', $info['version'], $matches)) {
+        $info['major'] = $matches[2];
+      }
+      elseif (!isset($info['major'])) {
+        // This would only happen for version strings that don't follow the
+        // drupal.org convention. We let contribs define "major" in their
+        // .info.yml in this case, and only if that's missing would we hit this.
+        $info['major'] = -1;
+      }
+    }
+    else {
+      // No version info available at all.
+      $install_type = 'unknown';
+      $info['version'] = t('Unknown');
+      $info['major'] = -1;
+    }
+
+    // Finally, save the results we care about into the $projects array.
+    $projects[$key]['existing_version'] = $info['version'];
+    $projects[$key]['existing_major'] = $info['major'];
+    $projects[$key]['install_type'] = $install_type;
+  }
+}
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 846d28a..a7da8d0 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2223,7 +2223,7 @@ function template_preprocess_tablesort_indicator(&$variables) {
  *     MARK_UPDATED, MARK_READ.
  */
 function theme_mark($variables) {
-  $type = $variables['status'];
+  $type = $variables['mark_type'];
   global $user;
   if ($user->uid) {
     if ($type == MARK_NEW) {
@@ -3113,7 +3113,7 @@ function drupal_common_theme() {
       'template' => 'tablesort-indicator',
     ),
     'mark' => array(
-      'variables' => array('status' => MARK_NEW),
+      'variables' => array('mark_type' => MARK_NEW),
     ),
     'item_list' => array(
       'variables' => array('items' => array(), 'title' => '', 'list_type' => 'ul', 'attributes' => array()),
diff --git a/core/includes/update.inc b/core/includes/update.inc
index fe83e31..3659caf 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -103,9 +103,10 @@ function update_prepare_d8_bootstrap() {
   $settings['cache']['default'] = 'cache.backend.memory';
   new Settings($settings);
 
-  // Enable UpdateServiceProvider service overrides.
-  // @see update_flush_all_caches()
-  $GLOBALS['conf']['container_service_providers']['UpdateServiceProvider'] = 'Drupal\Core\DependencyInjection\UpdateServiceProvider';
+  // Enable UpdateBundle service overrides. While the container_bundles array
+  // does not need a key, let's use so it can be removed once the upgrade are
+  // finished. @see update_flush_all_caches()
+  $GLOBALS['conf']['container_bundles']['UpdateBundle'] = 'Drupal\Core\DependencyInjection\UpdateBundle';
 
   // Check whether settings.php needs to be rewritten.
   $settings_exist = !empty($GLOBALS['config_directories']);
@@ -116,7 +117,7 @@ function update_prepare_d8_bootstrap() {
 
   // Bootstrap the kernel.
   // Do not attempt to dump and write it.
-  $kernel = new DrupalKernel('update', drupal_classloader(), FALSE);
+  $kernel = new DrupalKernel('update', FALSE, drupal_classloader(), FALSE);
   $kernel->boot();
 
   // If any of the required settings needs to be written, then settings.php
@@ -439,7 +440,7 @@ function update_prepare_d8_bootstrap() {
   $settings = settings()->getAll();
   unset($settings['cache']['default']);
   new Settings($settings);
-  $kernel = new DrupalKernel('update', drupal_classloader(), FALSE);
+  $kernel = new DrupalKernel('update', FALSE, drupal_classloader(), FALSE);
   $kernel->boot();
 }
 
diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php
index 1fa80fc..bb4368c 100644
--- a/core/lib/Drupal.php
+++ b/core/lib/Drupal.php
@@ -19,8 +19,8 @@
  *
  * The container is built by the kernel and passed in to this class which stores
  * it statically. The container always contains the services from
- * \Drupal\Core\CoreServiceProvider, the service providers of enabled modules and any other
- * service providers defined in $GLOBALS['conf']['container_service_providers'].
+ * \Drupal\Core\CoreBundle, the bundles of enabled modules and any other bundles
+ * defined in $GLOBALS['conf']['container_bundles'].
  *
  * This class exists only to support legacy code that cannot be dependency
  * injected. If your code needs it, consider refactoring it to be object
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
new file mode 100644
index 0000000..9af0c74
--- /dev/null
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\CoreBundle.
+ */
+
+namespace Drupal\Core;
+
+use Drupal\Core\Cache\ListCacheBinsPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterAccessChecksPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterMatchersPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterPathProcessorsPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterRouteFiltersPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterRouteEnhancersPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterParamConvertersPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterServicesForDestructionPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterStringTranslatorsPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterBreadcrumbBuilderPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Scope;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\DependencyInjection\Compiler\PassConfig;
+
+/**
+ * Bundle class for mandatory core services.
+ *
+ * This is where Drupal core registers all of its compiler passes.
+ * The service definitions themselves are in core/core.services.yml with a
+ * few, documented exceptions (typically, install requirements).
+ *
+ * Modules wishing to register services to the container should use
+ * modulename.services.yml in their respective directories.
+ */
+class CoreBundle extends Bundle {
+
+  /**
+   * Implements \Symfony\Component\HttpKernel\Bundle\BundleInterface::build().
+   */
+  public function build(ContainerBuilder $container) {
+    // The 'request' scope and service enable services to depend on the Request
+    // object and get reconstructed when the request object changes (e.g.,
+    // during a subrequest).
+    $container->addScope(new Scope('request'));
+    $this->registerTwig($container);
+    $this->registerModuleHandler($container);
+
+    $container->addCompilerPass(new RegisterMatchersPass());
+    $container->addCompilerPass(new RegisterRouteFiltersPass());
+    // Add a compiler pass for registering event subscribers.
+    $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
+    $container->addCompilerPass(new RegisterAccessChecksPass());
+    // Add a compiler pass for upcasting of entity route parameters.
+    $container->addCompilerPass(new RegisterParamConvertersPass());
+    $container->addCompilerPass(new RegisterRouteEnhancersPass());
+    // Add a compiler pass for registering services needing destruction.
+    $container->addCompilerPass(new RegisterServicesForDestructionPass());
+    // Add the compiler pass that will process the tagged services.
+    $container->addCompilerPass(new RegisterPathProcessorsPass());
+    $container->addCompilerPass(new ListCacheBinsPass());
+    // Add the compiler pass for appending string translators.
+    $container->addCompilerPass(new RegisterStringTranslatorsPass());
+    // Add the compiler pass that will process the tagged breadcrumb builder
+    // services.
+    $container->addCompilerPass(new RegisterBreadcrumbBuilderPass());
+  }
+
+  /**
+   * Registers the module handler.
+   *
+   * As this is different during install, it needs to stay in PHP.
+   */
+  protected function registerModuleHandler(ContainerBuilder $container) {
+    // The ModuleHandler manages enabled modules and provides the ability to
+    // invoke hooks in all enabled modules.
+    if ($container->getParameter('kernel.environment') == 'install') {
+      // During installation we use the non-cached version.
+      $container->register('module_handler', 'Drupal\Core\Extension\ModuleHandler')
+        ->addArgument('%container.modules%');
+    }
+    else {
+      $container->register('module_handler', 'Drupal\Core\Extension\CachedModuleHandler')
+        ->addArgument('%container.modules%')
+        ->addArgument(new Reference('state'))
+        ->addArgument(new Reference('cache.bootstrap'));
+    }
+  }
+
+  /**
+   * Registers Twig services.
+   *
+   * This method is public and static so that it can be reused in the installer.
+   */
+  public static function registerTwig(ContainerBuilder $container) {
+    $container->register('twig.loader.filesystem', 'Twig_Loader_Filesystem')
+      ->addArgument(DRUPAL_ROOT);
+    $container->setAlias('twig.loader', 'twig.loader.filesystem');
+
+    $container->register('twig', 'Drupal\Core\Template\TwigEnvironment')
+      ->addArgument(new Reference('twig.loader'))
+      ->addArgument(array(
+        // This is saved / loaded via drupal_php_storage().
+        // All files can be refreshed by clearing caches.
+        // @todo ensure garbage collection of expired files.
+        // When in the installer, twig_cache must be FALSE until we know the
+        // files folder is writable.
+        'cache' => drupal_installation_attempted() ? FALSE : settings()->get('twig_cache', TRUE),
+        'base_template_class' => 'Drupal\Core\Template\TwigTemplate',
+        // @todo Remove in followup issue
+        // @see http://drupal.org/node/1712444.
+        'autoescape' => FALSE,
+        // @todo Remove in followup issue
+        // @see http://drupal.org/node/1806538.
+        'strict_variables' => FALSE,
+        'debug' => settings()->get('twig_debug', FALSE),
+        'auto_reload' => settings()->get('twig_auto_reload', NULL),
+      ))
+      ->addMethodCall('addExtension', array(new Definition('Drupal\Core\Template\TwigExtension')))
+      // @todo Figure out what to do about debugging functions.
+      // @see http://drupal.org/node/1804998
+      ->addMethodCall('addExtension', array(new Definition('Twig_Extension_Debug')));
+  }
+
+}
diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
deleted file mode 100644
index 310343e..0000000
--- a/core/lib/Drupal/Core/CoreServiceProvider.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Core\CoreServiceProvider.
- */
-
-namespace Drupal\Core;
-
-use Drupal\Core\Cache\ListCacheBinsPass;
-use Drupal\Core\DependencyInjection\ServiceProviderInterface;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\Compiler\ModifyServiceDefinitionsPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterAccessChecksPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterMatchersPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterPathProcessorsPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterRouteFiltersPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterRouteEnhancersPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterParamConvertersPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterServicesForDestructionPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterStringTranslatorsPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterBreadcrumbBuilderPass;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\Scope;
-use Symfony\Component\DependencyInjection\Compiler\PassConfig;
-
-/**
- * ServiceProvider class for mandatory core services.
- *
- * This is where Drupal core registers all of its compiler passes.
- * The service definitions themselves are in core/core.services.yml with a
- * few, documented exceptions (typically, install requirements).
- *
- * Modules wishing to register services to the container should use
- * modulename.services.yml in their respective directories.
- */
-class CoreServiceProvider implements ServiceProviderInterface  {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function register(ContainerBuilder $container) {
-    // The 'request' scope and service enable services to depend on the Request
-    // object and get reconstructed when the request object changes (e.g.,
-    // during a subrequest).
-    $container->addScope(new Scope('request'));
-    $this->registerTwig($container);
-    $this->registerModuleHandler($container);
-
-    $container->addCompilerPass(new RegisterMatchersPass());
-    $container->addCompilerPass(new RegisterRouteFiltersPass());
-    // Add a compiler pass for registering event subscribers.
-    $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
-    $container->addCompilerPass(new RegisterAccessChecksPass());
-    // Add a compiler pass for upcasting of entity route parameters.
-    $container->addCompilerPass(new RegisterParamConvertersPass());
-    $container->addCompilerPass(new RegisterRouteEnhancersPass());
-    // Add a compiler pass for registering services needing destruction.
-    $container->addCompilerPass(new RegisterServicesForDestructionPass());
-    // Add the compiler pass that will process the tagged services.
-    $container->addCompilerPass(new RegisterPathProcessorsPass());
-    $container->addCompilerPass(new ListCacheBinsPass());
-    // Add the compiler pass for appending string translators.
-    $container->addCompilerPass(new RegisterStringTranslatorsPass());
-    // Add the compiler pass that will process the tagged breadcrumb builder
-    // services.
-    $container->addCompilerPass(new RegisterBreadcrumbBuilderPass());
-    // Add the compiler pass that lets service providers modify existing
-    // service definitions.
-    $container->addCompilerPass(new ModifyServiceDefinitionsPass());
-  }
-
-  /**
-   * Registers the module handler.
-   *
-   * As this is different during install, it needs to stay in PHP.
-   */
-  protected function registerModuleHandler(ContainerBuilder $container) {
-    // The ModuleHandler manages enabled modules and provides the ability to
-    // invoke hooks in all enabled modules.
-    if ($container->getParameter('kernel.environment') == 'install') {
-      // During installation we use the non-cached version.
-      $container->register('module_handler', 'Drupal\Core\Extension\ModuleHandler')
-        ->addArgument('%container.modules%');
-    }
-    else {
-      $container->register('module_handler', 'Drupal\Core\Extension\CachedModuleHandler')
-        ->addArgument('%container.modules%')
-        ->addArgument(new Reference('state'))
-        ->addArgument(new Reference('cache.bootstrap'));
-    }
-  }
-
-  /**
-   * Registers Twig services.
-   *
-   * This method is public and static so that it can be reused in the installer.
-   */
-  public static function registerTwig(ContainerBuilder $container) {
-    $container->register('twig.loader.filesystem', 'Twig_Loader_Filesystem')
-      ->addArgument(DRUPAL_ROOT);
-    $container->setAlias('twig.loader', 'twig.loader.filesystem');
-
-    $container->register('twig', 'Drupal\Core\Template\TwigEnvironment')
-      ->addArgument(new Reference('twig.loader'))
-      ->addArgument(array(
-        // This is saved / loaded via drupal_php_storage().
-        // All files can be refreshed by clearing caches.
-        // @todo ensure garbage collection of expired files.
-        // When in the installer, twig_cache must be FALSE until we know the
-        // files folder is writable.
-        'cache' => drupal_installation_attempted() ? FALSE : settings()->get('twig_cache', TRUE),
-        'base_template_class' => 'Drupal\Core\Template\TwigTemplate',
-        // @todo Remove in followup issue
-        // @see http://drupal.org/node/1712444.
-        'autoescape' => FALSE,
-        // @todo Remove in followup issue
-        // @see http://drupal.org/node/1806538.
-        'strict_variables' => FALSE,
-        'debug' => settings()->get('twig_debug', FALSE),
-        'auto_reload' => settings()->get('twig_auto_reload', NULL),
-      ))
-      ->addMethodCall('addExtension', array(new Definition('Drupal\Core\Template\TwigExtension')))
-      // @todo Figure out what to do about debugging functions.
-      // @see http://drupal.org/node/1804998
-      ->addMethodCall('addExtension', array(new Definition('Twig_Extension_Debug')));
-  }
-
-}
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/ModifyServiceDefinitionsPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/ModifyServiceDefinitionsPass.php
deleted file mode 100644
index 25614e3..0000000
--- a/core/lib/Drupal/Core/DependencyInjection/Compiler/ModifyServiceDefinitionsPass.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains Drupal\Core\DependencyInjection\Compiler\ModifyServiceDefinitionsPass.
- */
-
-namespace Drupal\Core\DependencyInjection\Compiler;
-
-use Drupal\Core\DrupalKernelInterface;
-use Drupal\Core\DependencyInjection\ServiceModifierInterface;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-
-/**
- * Passes the container to the alter() method of all service providers.
- */
-class ModifyServiceDefinitionsPass implements CompilerPassInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function process(ContainerBuilder $container) {
-    if (!$container->has('kernel')) {
-      return;
-    }
-    $kernel = $container->get('kernel');
-    if (!($kernel instanceof DrupalKernelInterface)) {
-      return;
-    }
-    $providers = $kernel->getServiceProviders();
-    foreach ($providers as $provider) {
-      if ($provider instanceof ServiceModifierInterface) {
-        $provider->alter($container);
-      }
-    }
-  }
-
-}
diff --git a/core/lib/Drupal/Core/DependencyInjection/ServiceModifierInterface.php b/core/lib/Drupal/Core/DependencyInjection/ServiceModifierInterface.php
deleted file mode 100644
index 000366c..0000000
--- a/core/lib/Drupal/Core/DependencyInjection/ServiceModifierInterface.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-namespace Drupal\Core\DependencyInjection;
-
-/**
- * Interface that service providers can implement to modify services.
- */
-interface ServiceModifierInterface {
-
-  /**
-   * Modifies existing service definitions.
-   *
-   * @param ContainerBuilder $container
-   *   The ContainerBuilder whose service definitions can be altered.
-   */
-  public function alter(ContainerBuilder $container);
-
-}
diff --git a/core/lib/Drupal/Core/DependencyInjection/ServiceProviderInterface.php b/core/lib/Drupal/Core/DependencyInjection/ServiceProviderInterface.php
deleted file mode 100644
index 98d1f02..0000000
--- a/core/lib/Drupal/Core/DependencyInjection/ServiceProviderInterface.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-namespace Drupal\Core\DependencyInjection;
-
-/**
- * Interface that all service providers must implement.
- */
-interface ServiceProviderInterface {
-
-  /**
-   * Registers services to the container.
-   *
-   * @param ContainerBuilder $container
-   *   The ContainerBuilder to register services to.
-   */
-  public function register(ContainerBuilder $container);
-
-}
diff --git a/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php b/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php
new file mode 100644
index 0000000..91528e5
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/UpdateBundle.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\DependencyInjection\UpdateBundle.
+ */
+
+namespace Drupal\Core\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder as SymfonyContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * Bundle class for update.php service overrides.
+ *
+ * This bundle is manually added by update.php via $conf['container_bundles']
+ * and required to prevent various services from trying to retrieve data from
+ * storages that do not exist yet.
+ */
+class UpdateBundle extends Bundle {
+
+  /**
+   * Implements \Symfony\Component\HttpKernel\Bundle\BundleInterface::build().
+   */
+  public function build(SymfonyContainerBuilder $container) {
+    // Disable the Lock service.
+    $container
+      ->register('lock', 'Drupal\Core\Lock\NullLockBackend');
+
+    // Prevent config from accessing {cache_config}.
+    // @see $conf['cache_classes'], update_prepare_d8_bootstrap()
+    $container
+      ->register('config.storage', 'Drupal\Core\Config\FileStorage')
+      ->addArgument(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY));
+    $container->register('module_handler', 'Drupal\Core\Extension\UpdateModuleHandler')
+      ->addArgument('%container.modules%');
+    $container
+      ->register("cache_factory", 'Drupal\Core\Cache\MemoryBackendFactory');
+    $container
+      ->register('router.builder', 'Drupal\Core\Routing\RouteBuilderStatic');
+  }
+
+}
diff --git a/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php b/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php
deleted file mode 100644
index d458665..0000000
--- a/core/lib/Drupal/Core/DependencyInjection/UpdateServiceProvider.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\DependencyInjection\UpdateServiceProvider.
- */
-
-namespace Drupal\Core\DependencyInjection;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\ServiceProviderInterface;
-
-/**
- * ServiceProvider class for update.php service overrides.
- *
- * This class is manually added by update.php via $conf['container_service_providers']
- * and required to prevent various services from trying to retrieve data from
- * storages that do not exist yet.
- */
-class UpdateServiceProvider implements ServiceProviderInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function register(ContainerBuilder $container) {
-    // Disable the Lock service.
-    $container
-      ->register('lock', 'Drupal\Core\Lock\NullLockBackend');
-
-    // Prevent config from accessing {cache_config}.
-    // @see $conf['cache_classes'], update_prepare_d8_bootstrap()
-    $container
-      ->register('config.storage', 'Drupal\Core\Config\FileStorage')
-      ->addArgument(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY));
-    $container->register('module_handler', 'Drupal\Core\Extension\UpdateModuleHandler')
-      ->addArgument('%container.modules%');
-    $container
-      ->register("cache_factory", 'Drupal\Core\Cache\MemoryBackendFactory');
-    $container
-      ->register('router.builder', 'Drupal\Core\Routing\RouteBuilderStatic');
-  }
-
-}
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index af1fe52..6d7d4fa 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -9,55 +9,26 @@
 
 use Drupal\Component\PhpStorage\PhpStorageFactory;
 use Drupal\Core\Config\BootstrapConfigStorageFactory;
-use Drupal\Core\CoreServiceProvider;
+use Drupal\Core\CoreBundle;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\YamlFileLoader;
 use Symfony\Component\ClassLoader\ClassLoader;
 use Symfony\Component\Config\Loader\LoaderInterface;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
-use Symfony\Component\HttpKernel\TerminableInterface;
+use Symfony\Component\HttpKernel\Kernel;
 
 /**
  * The DrupalKernel class is the core of Drupal itself.
  *
  * This class is responsible for building the Dependency Injection Container and
- * also deals with the registration of service providers. It allows registered
- * service providers to add their services to the container. Core provides the
- * CoreServiceProvider, which, in addition to registering any core services that
- * cannot be registered in the core.services.yaml file, adds any compiler passes
- * needed by core, e.g. for processing tagged services. Each module can add its
- * own service provider, i.e. a class implementing
- * Drupal\Core\DependencyInjection\ServiceProvider, to register services to the
- * container, or modify existing services.
+ * also deals with the registration of bundles. It allows registered bundles to
+ * add their services to the container. Core provides the CoreBundle, which adds
+ * the services required for all core subsystems. Each module can then add its
+ * own bundle, i.e. a subclass of Symfony\Component\HttpKernel\Bundle, to
+ * register services to the container.
  */
-class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
-
-  const CONTAINER_BASE_CLASS = 'Container';
-
-  /**
-   * Holds the container instance.
-   *
-   * @var \Symfony\Component\DependencyInjection\ContainerInterface
-   */
-  protected $container;
-
-  /**
-   * The environment, e.g. 'testing', 'install'.
-   *
-   * @var string
-   */
-  protected $environment;
-
-  /**
-   * Whether the kernel has been booted.
-   *
-   * @var bool
-   */
-  protected $booted;
+class DrupalKernel extends Kernel implements DrupalKernelInterface {
 
   /**
    * Holds the list of enabled modules.
@@ -109,11 +80,11 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
   protected $configStorage;
 
   /**
-   * The list of the classnames of the service providers in this kernel.
+   * The list of the classnames of the bundles in this kernel.
    *
    * @var array
    */
-  protected $serviceProviderClasses;
+  protected $bundleClasses;
 
   /**
    * Whether the container can be dumped.
@@ -137,31 +108,27 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
   protected $serviceYamls;
 
   /**
-   * The array of registered service providers.
-   *
-   * @var array
-   */
-  protected $serviceProviders;
-
-  /**
    * Constructs a DrupalKernel object.
    *
    * @param string $environment
    *   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 bool $debug
+   *   Boolean indicating whether we are in debug mode. Used by
+   *   Symfony\Component\HttpKernel\Kernel::__construct(). Drupal does not use
+   *   this value currently. Pass TRUE.
    * @param \Symfony\Component\ClassLoader\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.
+   *   order to be able to find the module bundles.
    * @param bool $allow_dumping
    *   (optional) FALSE to stop the container from being written to or read
    *   from disk. Defaults to TRUE.
    */
-  public function __construct($environment, ClassLoader $class_loader, $allow_dumping = TRUE) {
-    $this->environment = $environment;
-    $this->booted = false;
+  public function __construct($environment, $debug, ClassLoader $class_loader, $allow_dumping = TRUE) {
+    parent::__construct($environment, $debug);
     $this->classLoader = $class_loader;
     $this->allowDumping = $allow_dumping;
   }
@@ -170,19 +137,29 @@ public function __construct($environment, ClassLoader $class_loader, $allow_dump
    * {@inheritdoc}
    */
   public function serialize() {
-    return serialize(array($this->environment, $this->classLoader, $this->allowDumping));
+    return serialize(array($this->environment, $this->debug, $this->classLoader, $this->allowDumping));
   }
 
   /**
    * {@inheritdoc}
    */
   public function unserialize($data) {
-    list($environment, $class_loader, $allow_dumping) = unserialize($data);
-    $this->__construct($environment, $class_loader, $allow_dumping);
+    list($environment, $debug, $class_loader, $allow_dumping) = unserialize($data);
+    $this->__construct($environment, $debug, $class_loader, $allow_dumping);
   }
 
   /**
-   * {@inheritdoc}
+   * Overrides Kernel::init().
+   */
+  public function init() {
+    // Intentionally empty. The sole purpose is to not execute Kernel::init(),
+    // since that overrides/breaks Drupal's current error handling.
+    // @todo Investigate whether it is possible to migrate Drupal's error
+    //   handling to the one of Kernel without losing functionality.
+  }
+
+  /**
+   * Overrides Kernel::boot().
    */
   public function boot() {
     if ($this->booted) {
@@ -190,41 +167,26 @@ public function boot() {
     }
     $this->initializeContainer();
     $this->booted = TRUE;
-    if ($this->containerNeedsDumping && !$this->dumpDrupalContainer($this->container, static::CONTAINER_BASE_CLASS)) {
+    if ($this->containerNeedsDumping && !$this->dumpDrupalContainer($this->container, $this->getContainerBaseClass())) {
       watchdog('DrupalKernel', 'Container cannot be written to disk');
     }
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public function shutdown() {
-    if (FALSE === $this->booted) {
-      return;
-    }
-    $this->booted = FALSE;
-    $this->container = null;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getContainer() {
-    return $this->container;
-  }
-
-  /**
-   * {@inheritdoc}
+   * Returns an array of available bundles.
+   *
+   * @return array
+   *   The available bundles.
    */
-  public function discoverServiceProviders() {
+  public function registerBundles() {
     $this->configStorage = BootstrapConfigStorageFactory::get();
-    $serviceProviders = array(
-      'CoreServiceProvider' => new CoreServiceProvider(),
+    $bundles = array(
+      new CoreBundle(),
     );
     $this->serviceYamls = array(
       'core/core.services.yml'
     );
-    $this->serviceProviderClasses = array('Drupal\Core\CoreServiceProvider');
+    $this->bundleClasses = array('Drupal\Core\CoreBundle');
 
     // Ensure we know what modules are enabled and that their namespaces are
     // registered.
@@ -235,14 +197,13 @@ public function discoverServiceProviders() {
     $module_filenames = $this->getModuleFileNames();
     $this->registerNamespaces($this->getModuleNamespaces($module_filenames));
 
-    // Load each module's serviceProvider class.
+    // Load each module's bundle class.
     foreach ($this->moduleList as $module => $weight) {
       $camelized = ContainerBuilder::camelize($module);
-      $name = "{$camelized}ServiceProvider";
-      $class = "Drupal\\{$module}\\{$name}";
+      $class = "Drupal\\{$module}\\{$camelized}Bundle";
       if (class_exists($class)) {
-        $serviceProviders[$name] = new $class();
-        $this->serviceProviderClasses[] = $class;
+        $bundles[] = new $class();
+        $this->bundleClasses[] = $class;
       }
       $filename = dirname($module_filenames[$module]) . "/$module.services.yml";
       if (file_exists($filename)) {
@@ -250,50 +211,18 @@ public function discoverServiceProviders() {
       }
     }
 
-    // Add site specific or test service providers.
-    if (!empty($GLOBALS['conf']['container_service_providers'])) {
-      foreach ($GLOBALS['conf']['container_service_providers'] as $name => $class) {
-        $serviceProviders[$name] = new $class();
-        $this->serviceProviderClasses[] = $class;
+    // Add site specific or test bundles.
+    if (!empty($GLOBALS['conf']['container_bundles'])) {
+      foreach ($GLOBALS['conf']['container_bundles'] as $class) {
+        $bundles[] = new $class();
+        $this->bundleClasses[] = $class;
       }
     }
     // Add site specific or test YAMLs.
     if (!empty($GLOBALS['conf']['container_yamls'])) {
       $this->serviceYamls = array_merge($this->serviceYamls, $GLOBALS['conf']['container_yamls']);
     }
-    return $serviceProviders;
-  }
-
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getServiceProviders() {
-    return $this->serviceProviders;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function terminate(Request $request, Response $response) {
-    if (FALSE === $this->booted) {
-      return;
-    }
-
-    if ($this->getHttpKernel() instanceof TerminableInterface) {
-      $this->getHttpKernel()->terminate($request, $response);
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) {
-    if (FALSE === $this->booted) {
-      $this->boot();
-    }
-
-    return $this->getHttpKernel()->handle($request, $type, $catch);
+    return $bundles;
   }
 
   /**
@@ -340,7 +269,7 @@ public function updateModules(array $module_list, array $module_filenames = arra
     }
     // If we haven't yet booted, we don't need to do anything: the new module
     // list will take effect when boot() is called. If we have already booted,
-    // then reboot in order to refresh the serviceProvider list and container.
+    // then reboot in order to refresh the bundle list and container.
     if ($this->booted) {
       $this->booted = FALSE;
       $this->boot();
@@ -348,13 +277,13 @@ public function updateModules(array $module_list, array $module_filenames = arra
   }
 
   /**
-   * Returns the classname based on environment and testing prefix.
+   * Returns the classname based on environment, debug and testing prefix.
    *
    * @return string
    *   The class name.
    */
   protected function getClassName() {
-    $parts = array('service_container', $this->environment);
+    $parts = array('service_container', $this->environment, $this->debug);
     // Make sure to use a testing-specific container even in the parent site.
     if (!empty($GLOBALS['drupal_test_info']['test_run_id'])) {
       $parts[] = $GLOBALS['drupal_test_info']['test_run_id'];
@@ -365,18 +294,6 @@ protected function getClassName() {
     return implode('_', $parts);
   }
 
-
-  /**
-   * Returns the kernel parameters.
-   *
-   * @return array An array of kernel parameters
-   */
-  protected function getKernelParameters() {
-    return array(
-      'kernel.environment' => $this->environment,
-    );
-  }
-
   /**
    * Initializes the service container.
    */
@@ -454,7 +371,6 @@ protected function initializeContainer() {
     }
 
     $this->container->set('kernel', $this);
-
     // Set the class loader which was registered as a synthetic service.
     $this->container->set('class_loader', $this->classLoader);
     // If we have a request set it back to the new container.
@@ -500,10 +416,9 @@ protected function persistServices(array $persist) {
    * @return ContainerBuilder The compiled service container
    */
   protected function buildContainer() {
-    $this->initializeServiceProviders();
+    $this->initializeBundles();
     $container = $this->getContainerBuilder();
-    $container->set('kernel', $this);
-    $container->setParameter('container.service_providers', $this->serviceProviderClasses);
+    $container->setParameter('container.bundles', $this->bundleClasses);
     $container->setParameter('container.modules', $this->getModuleFileNames());
 
     // Get a list of namespaces and put it onto the container.
@@ -528,8 +443,8 @@ protected function buildContainer() {
     foreach ($this->serviceYamls as $filename) {
       $yaml_loader->load($filename);
     }
-    foreach ($this->serviceProviders as $provider) {
-      $provider->register($container);
+    foreach ($this->bundles as $bundle) {
+      $bundle->build($container);
     }
 
     // Identify all services whose instances should be persisted when rebuilding
@@ -549,22 +464,6 @@ protected function buildContainer() {
   }
 
   /**
-   * Registers all service providers to the kernel.
-   *
-   * @throws \LogicException
-   */
-  protected function initializeServiceProviders() {
-    $this->serviceProviders = array();
-
-    foreach ($this->discoverServiceProviders() as $name => $provider) {
-      if (isset($this->serviceProviders[$name])) {
-        throw new \LogicException(sprintf('Trying to register two service providers with the same name "%s"', $name));
-      }
-      $this->serviceProviders[$name] = $provider;
-    }
-  }
-
-  /**
    * Gets a new ContainerBuilder instance used to build the service container.
    *
    * @return ContainerBuilder
@@ -598,16 +497,6 @@ protected function dumpDrupalContainer(ContainerBuilder $container, $baseClass)
     return $this->storage()->save($class . '.php', $content);
   }
 
-
-  /**
-   * Gets a http kernel from the container
-   *
-   * @return HttpKernel
-   */
-  protected function getHttpKernel() {
-    return $this->container->get('http_kernel');
-  }
-
   /**
    * Overrides and eliminates this method from the parent class. Do not use.
    *
diff --git a/core/lib/Drupal/Core/DrupalKernelInterface.php b/core/lib/Drupal/Core/DrupalKernelInterface.php
index 96b2f92..60d0403 100644
--- a/core/lib/Drupal/Core/DrupalKernelInterface.php
+++ b/core/lib/Drupal/Core/DrupalKernelInterface.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core;
 
-use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\KernelInterface;
 
 /**
  * The interface for DrupalKernel, the core of Drupal.
@@ -15,40 +15,7 @@
  * This interface extends Symfony's KernelInterface and adds methods for
  * responding to modules being enabled or disabled during its lifetime.
  */
-interface DrupalKernelInterface extends HttpKernelInterface, \Serializable {
-
-  /**
-   * Boots the current kernel.
-   */
-  public function boot();
-
-  /**
-   * Shuts down the kernel.
-   */
-  public function shutdown();
-
-  /**
-   * Discovers available serviceProviders.
-   *
-   * @return array
-   *   The available serviceProviders.
-   */
-  public function discoverServiceProviders();
-
-  /**
-   * Returns all registered service providers.
-   *
-   * @return array
-   *   An associative array of ServiceProvider objects, keyed by name.
-   */
-  public function getServiceProviders();
-
-  /**
-   * Gets the current container.
-   *
-   * @return ContainerInterface A ContainerInterface instance
-   */
-  public function getContainer();
+interface DrupalKernelInterface extends KernelInterface {
 
   /**
    * Updates the kernel's list of modules to the new list.
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index c510192..656e918 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -81,7 +81,7 @@ class ModuleHandler implements ModuleHandlerInterface {
    *   %container.modules% parameter being set up by DrupalKernel.
    *
    * @see \Drupal\Core\DrupalKernel
-   * @see \Drupal\Core\CoreServiceProvider
+   * @see \Drupal\Core\CoreBundle
    */
   public function __construct(array $module_list = array()) {
     $this->moduleList = $module_list;
diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index 3c86bd1..898fdf8 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -6,7 +6,7 @@
  *
  * This provides a Twig extension that registers various Drupal specific extensions to Twig.
  *
- * @see \Drupal\Core\CoreServiceProvider
+ * @see \Drupal\Core\CoreBundle
  */
 
 namespace Drupal\Core\Template;
@@ -14,7 +14,7 @@
 /**
  * A class for providing Twig extensions (specific Twig_NodeVisitors, filters and functions).
  *
- * @see \Drupal\Core\CoreServiceProvider
+ * @see \Drupal\Core\CoreBundle
  */
 class TwigExtension extends \Twig_Extension {
   public function getFunctions() {
diff --git a/core/modules/history/lib/Drupal/history/Plugin/views/field/HistoryUserTimestamp.php b/core/modules/history/lib/Drupal/history/Plugin/views/field/HistoryUserTimestamp.php
index 5d5a697..6ac6db1 100644
--- a/core/modules/history/lib/Drupal/history/Plugin/views/field/HistoryUserTimestamp.php
+++ b/core/modules/history/lib/Drupal/history/Plugin/views/field/HistoryUserTimestamp.php
@@ -92,7 +92,7 @@ function render($values) {
       }
       $build = array(
         '#theme' => 'mark',
-        '#status' => $mark,
+        '#mark_type' => $mark,
       );
       return $this->render_link(drupal_render($build), $values);
     }
diff --git a/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestBundle.php b/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestBundle.php
new file mode 100644
index 0000000..b711507
--- /dev/null
+++ b/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestBundle.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language_test\LanguageTestBundle.
+ */
+
+namespace Drupal\language_test;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * Defines the LanguageTest bundle.
+ */
+class LanguageTestBundle extends Bundle {
+
+  /**
+   * Overrides \Symfony\Component\HttpKernel\Bundle\Bundle::build().
+   */
+  public function build(ContainerBuilder $container) {
+    // Overrides language_manager class to test domain language negotiation.
+    $definition = $container->getDefinition('language_manager');
+    $definition->setClass('Drupal\language_test\LanguageTestManager');
+  }
+
+}
+
diff --git a/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestServiceProvider.php b/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestServiceProvider.php
deleted file mode 100644
index c8b1633..0000000
--- a/core/modules/language/tests/language_test/lib/Drupal/language_test/LanguageTestServiceProvider.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\language_test\LanguageTestServiceProvider.
- */
-
-namespace Drupal\language_test;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\ServiceModifierInterface;
-use Drupal\Core\DependencyInjection\ServiceProviderInterface;
-
-/**
- * Defines the LanguageTest service provider.
- */
-class LanguageTestServiceProvider implements ServiceProviderInterface, ServiceModifierInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function register(ContainerBuilder $container) {
-
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function alter(ContainerBuilder $container) {
-    // Overrides language_manager class to test domain language negotiation.
-    $definition = $container->getDefinition('language_manager');
-    $definition->setClass('Drupal\language_test\LanguageTestManager');
-  }
-
-}
-
diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc
index 3cbaac5..3288154 100644
--- a/core/modules/locale/locale.compare.inc
+++ b/core/modules/locale/locale.compare.inc
@@ -8,11 +8,12 @@
 use Drupal\Core\Cache;
 
 /**
- * Load the common translation API.
+ * Load common APIs.
  */
 // @todo Combine functions differently in files to avoid unnecessary includes.
 // Follow-up issue http://drupal.org/node/1834298
 require_once __DIR__ . '/locale.translation.inc';
+require_once DRUPAL_ROOT . '/core/includes/project.inc';
 
 /**
  * Clear the project data table.
@@ -126,11 +127,6 @@ function locale_translation_build_projects() {
  *   Array of project data including .info.yml file data.
  */
 function locale_translation_project_list() {
-  // This function depends on Update module. We degrade gracefully.
-  if (!Drupal::moduleHandler()->moduleExists('update')) {
-    return array();
-  }
-
   $projects = &drupal_static(__FUNCTION__, array());
   if (empty($projects)) {
     module_load_include('compare.inc', 'update');
@@ -143,11 +139,11 @@ function locale_translation_project_list() {
     );
     $module_data = _locale_translation_prepare_project_list(system_rebuild_module_data(), 'module');
     $theme_data = _locale_translation_prepare_project_list(system_rebuild_theme_data(), 'theme');
-    update_process_info_list($projects, $module_data, 'module', TRUE, $additional_whitelist);
-    update_process_info_list($projects, $theme_data, 'theme', TRUE, $additional_whitelist);
+    drupal_project_process_info_list($projects, $module_data, 'module', TRUE, $additional_whitelist);
+    drupal_project_process_info_list($projects, $theme_data, 'theme', TRUE, $additional_whitelist);
     if ($config->get('translation.check_disabled_modules')) {
-      update_process_info_list($projects, $module_data, 'module', FALSE, $additional_whitelist);
-      update_process_info_list($projects, $theme_data, 'theme', FALSE, $additional_whitelist);
+      drupal_project_process_info_list($projects, $module_data, 'module', FALSE, $additional_whitelist);
+      drupal_project_process_info_list($projects, $theme_data, 'theme', FALSE, $additional_whitelist);
     }
 
     // Allow other modules to alter projects before fetching and comparing.
@@ -159,9 +155,10 @@ function locale_translation_project_list() {
 /**
  * Prepare module and theme data.
  *
- * Modify .info.yml file data before it is processed by update_process_info_list().
- * In order for update_process_info_list() to recognize a project, it requires
- * the 'project' parameter in the .info.yml file data.
+ * Modify .info.yml file data before it is processed by
+ * drupal_project_process_info_list(). In order for
+ * drupal_project_process_info_list() to recognize a project, it requires the
+ * 'project' parameter in the .info.yml file data.
  *
  * Custom modules or themes can bring their own gettext translation file. To
  * enable import of this file the module or theme defines "interface translation
@@ -179,8 +176,9 @@ function locale_translation_project_list() {
 function _locale_translation_prepare_project_list($data, $type) {
   foreach ($data as $name => $file) {
     // Include interface translation projects. To allow
-    // update_process_info_list() to identify this as a project the 'project'
-    // property is filled with the 'interface translation project' value.
+    // drupal_project_process_info_list() to identify this as a project the
+    // 'project' property is filled with the 'interface translation project'
+    // value.
     if (isset($file->info['interface translation project'])) {
       $data[$name]->info['project'] = $file->info['interface translation project'];
     }
diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc
index c2b8524..821f41a 100644
--- a/core/modules/node/node.admin.inc
+++ b/core/modules/node/node.admin.inc
@@ -262,7 +262,7 @@ function node_admin_nodes() {
     $l_options = $node->langcode != Language::LANGCODE_NOT_SPECIFIED && isset($languages[$node->langcode]) ? array('language' => $languages[$node->langcode]) : array();
     $mark = array(
       '#theme' => 'mark',
-      '#status' => node_mark($node->nid, $node->changed),
+      '#mark_type' => node_mark($node->nid, $node->changed),
     );
     $form['nodes'][$node->nid]['title'] = array(
       '#type' => 'link',
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 7057db2..d01b8ae 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1571,7 +1571,7 @@ function theme_node_recent_content($variables) {
   $output .= l($node->label(), 'node/' . $node->id());
   $mark = array(
     '#theme' => 'mark',
-    '#status' => node_mark($node->id(), $node->getChangedTime()),
+    '#mark_type' => node_mark($node->id(), $node->getChangedTime()),
   );
   $output .= drupal_render($mark);
   $output .= '</div><div class="node-author">';
diff --git a/core/modules/serialization/lib/Drupal/serialization/SerializationBundle.php b/core/modules/serialization/lib/Drupal/serialization/SerializationBundle.php
new file mode 100644
index 0000000..f649052
--- /dev/null
+++ b/core/modules/serialization/lib/Drupal/serialization/SerializationBundle.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\serialization\SerializationBundle.
+ */
+
+namespace Drupal\serialization;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * Serialization dependency injection container.
+ */
+class SerializationBundle extends Bundle {
+
+  /**
+   * Overrides \Symfony\Component\HttpKernel\Bundle\Bundle::build().
+   */
+  public function build(ContainerBuilder $container) {
+    // Add a compiler pass for adding Normalizers and Encoders to Serializer.
+    $container->addCompilerPass(new RegisterSerializationClassesCompilerPass());
+    // Add a compiler pass for adding concrete Resolvers to chain Resolver.
+    $container->addCompilerPass(new RegisterEntityResolversCompilerPass());
+  }
+}
diff --git a/core/modules/serialization/lib/Drupal/serialization/SerializationServiceProvider.php b/core/modules/serialization/lib/Drupal/serialization/SerializationServiceProvider.php
deleted file mode 100644
index 2e89e5c..0000000
--- a/core/modules/serialization/lib/Drupal/serialization/SerializationServiceProvider.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\serialization\SerializationServiceProvider.
- */
-
-namespace Drupal\serialization;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\ServiceProviderInterface;
-
-/**
- * Serialization dependency injection container.
- */
-class SerializationServiceProvider implements ServiceProviderInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function register(ContainerBuilder $container) {
-    // Add a compiler pass for adding Normalizers and Encoders to Serializer.
-    $container->addCompilerPass(new RegisterSerializationClassesCompilerPass());
-    // Add a compiler pass for adding concrete Resolvers to chain Resolver.
-    $container->addCompilerPass(new RegisterEntityResolversCompilerPass());
-  }
-}
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
index e54e121..2c80dcd 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
@@ -90,7 +90,7 @@ protected function setUp() {
     // Build a minimal, partially mocked environment for unit tests.
     $this->containerBuild(drupal_container());
     // Make sure it survives kernel rebuilds.
-    $GLOBALS['conf']['container_service_providers']['TestServiceProvider'] = 'Drupal\simpletest\TestServiceProvider';
+    $GLOBALS['conf']['container_bundles'][] = 'Drupal\simpletest\TestBundle';
 
     \Drupal::state()->set('system.module.files', $this->moduleFiles);
     \Drupal::state()->set('system.theme.files', $this->themeFiles);
@@ -98,7 +98,7 @@ protected function setUp() {
 
     // Bootstrap the kernel.
     // No need to dump it; this test runs in-memory.
-    $this->kernel = new DrupalKernel('unit_testing', drupal_classloader(), FALSE);
+    $this->kernel = new DrupalKernel('unit_testing', TRUE, drupal_classloader(), FALSE);
     $this->kernel->boot();
 
     // Collect and set a fixed module list.
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 818b7b0..1b746e6 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -698,7 +698,7 @@ protected function verbose($message) {
    *   methods during debugging.
    */
   public function run(array $methods = array()) {
-    TestServiceProvider::$currentTest = $this;
+    TestBundle::$currentTest = $this;
     $simpletest_config = config('simpletest.settings');
 
     $class = get_class($this);
@@ -770,7 +770,7 @@ public function run(array $methods = array()) {
         }
       }
     }
-    TestServiceProvider::$currentTest = NULL;
+    TestBundle::$currentTest = NULL;
     // Clear out the error messages and restore error handler.
     drupal_get_messages();
     restore_error_handler();
@@ -993,7 +993,7 @@ protected function prepareConfigDirectories() {
    * @see TestBase::tearDown()
    */
   protected function rebuildContainer() {
-    $this->kernel = new DrupalKernel('testing', drupal_classloader(), FALSE);
+    $this->kernel = new DrupalKernel('testing', FALSE, drupal_classloader(), FALSE);
     $this->kernel->boot();
     // DrupalKernel replaces the container in drupal_container() with a
     // different object, so we need to replace the instance on this test class.
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBundle.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBundle.php
new file mode 100644
index 0000000..7e2fd2f
--- /dev/null
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBundle.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Drupal\simpletest;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+class TestBundle extends Bundle {
+
+  /**
+   * @var \Drupal\simpletest\TestBase;
+   */
+  public static $currentTest;
+
+  /**
+   * Implements \Symfony\Component\HttpKernel\Bundle\BundleInterface::build().
+   */
+  function build(ContainerBuilder $container) {
+    if (static::$currentTest && method_exists(static::$currentTest, 'containerBuild')) {
+      static::$currentTest->containerBuild($container);
+    }
+  }
+
+}
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestServiceProvider.php b/core/modules/simpletest/lib/Drupal/simpletest/TestServiceProvider.php
deleted file mode 100644
index 9b26f12..0000000
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestServiceProvider.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-
-namespace Drupal\simpletest;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\ServiceProviderInterface;
-
-class TestServiceProvider implements ServiceProviderInterface {
-
-  /**
-   * @var \Drupal\simpletest\TestBase;
-   */
-  public static $currentTest;
-
-  /**
-   * {@inheritdoc}
-   */
-  function register(ContainerBuilder $container) {
-    if (static::$currentTest && method_exists(static::$currentTest, 'containerBuild')) {
-      static::$currentTest->containerBuild($container);
-    }
-  }
-}
diff --git a/core/modules/system/language.api.php b/core/modules/system/language.api.php
index 7f4b0c2..fb165a4 100644
--- a/core/modules/system/language.api.php
+++ b/core/modules/system/language.api.php
@@ -201,7 +201,7 @@ function hook_language_fallback_candidates_alter(array &$fallback_candidates) {
  * hook_transliteration_overrides_alter() to provide further language-specific
  * overrides (including providing transliteration for Unicode characters that
  * are longer than 4 bytes). Modules can also completely override the
- * transliteration classes in \Drupal\Core\CoreServiceProvider.
+ * transliteration classes in \Drupal\Core\CoreBundle.
  */
 
 /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Bundle/BundleTest.php b/core/modules/system/lib/Drupal/system/Tests/Bundle/BundleTest.php
new file mode 100644
index 0000000..35faa3c
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Bundle/BundleTest.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Bundle\BundleTest.
+ */
+
+namespace Drupal\system\Tests\Bundle;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests bundle registration to the DIC.
+ */
+class BundleTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('bundle_test');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Bundle Registration',
+      'description' => 'Tests bundle registration to the DIC.',
+      'group' => 'Bundle',
+    );
+  }
+
+  /**
+   * Tests that services provided by module bundles get registered to the DIC.
+   */
+  function testBundleRegistration() {
+    $this->assertTrue(drupal_container()->getDefinition('file.usage')->getClass() == 'Drupal\\bundle_test\\TestFileUsage', 'Class has been changed');
+    $this->assertTrue(drupal_container()->has('bundle_test_class'), 'The bundle_test_class service has been registered to the DIC');
+    // The event subscriber method in the test class calls drupal_set_message with
+    // a message saying it has fired. This will fire on every page request so it
+    // should show up on the front page.
+    $this->drupalGet('');
+    $this->assertText(t('The bundle_test event subscriber fired!'), 'The bundle_test event subscriber fired');
+  }
+
+  /**
+   * Tests that the DIC keeps up with module enable/disable in the same request.
+   */
+  function testBundleRegistrationDynamic() {
+    // Disable the module and ensure the bundle's service is not registered.
+    module_disable(array('bundle_test'));
+    $this->assertFalse(drupal_container()->has('bundle_test_class'), 'The bundle_test_class service does not exist in the DIC.');
+
+    // Enable the module and ensure the bundle's service is registered.
+    module_enable(array('bundle_test'));
+    $this->assertTrue(drupal_container()->has('bundle_test_class'), 'The bundle_test_class service exists in the DIC.');
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
index db60d18..87c7019 100644
--- a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/DrupalKernelTest.php
@@ -49,12 +49,12 @@ function testCompileDIC() {
       'system' => 'system',
       'user' => 'user',
     );
-    $kernel = new DrupalKernel('testing', $classloader);
+    $kernel = new DrupalKernel('testing', FALSE, $classloader);
     $kernel->updateModules($module_enabled);
     $kernel->boot();
     // Instantiate it a second time and we should get the compiled Container
     // class.
-    $kernel = new DrupalKernel('testing', $classloader);
+    $kernel = new DrupalKernel('testing', FALSE, $classloader);
     $kernel->updateModules($module_enabled);
     $kernel->boot();
     $container = $kernel->getContainer();
@@ -68,7 +68,7 @@ function testCompileDIC() {
     // environment.
     global $conf;
     $conf['php_storage']['service_container']['class'] = 'Drupal\Component\PhpStorage\FileReadOnlyStorage';
-    $kernel = new DrupalKernel('testing', $classloader);
+    $kernel = new DrupalKernel('testing', FALSE, $classloader);
     $kernel->updateModules($module_enabled);
     $kernel->boot();
     $container = $kernel->getContainer();
@@ -86,17 +86,17 @@ function testCompileDIC() {
     // is functioning correctly, i.e. we get a brand new ContainerBuilder
     // which has the required new services, after changing the list of enabled
     // modules.
-    $this->assertFalse($container->has('service_provider_test_class'));
+    $this->assertFalse($container->has('bundle_test_class'));
 
     // Add another module so that we can test that the new module's bundle is
     // registered to the new container.
-    $module_enabled['service_provider_test'] = 'service_provider_test';
-    $kernel = new DrupalKernel('testing', $classloader);
+    $module_enabled['bundle_test'] = 'bundle_test';
+    $kernel = new DrupalKernel('testing', FALSE, $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 = new DrupalKernel('testing', $classloader);
+    $kernel = new DrupalKernel('testing', FALSE, $classloader);
     $kernel->updateModules($module_enabled);
     $kernel->boot();
     $container = $kernel->getContainer();
@@ -104,14 +104,14 @@ function testCompileDIC() {
     $is_container_builder = $refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder');
     $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'));
+    $this->assertTrue($container->has('bundle_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'], drupal_get_filename('module', 'service_provider_test'));
+    $this->assertEqual($modules['bundle_test'], drupal_get_filename('module', 'bundle_test'));
   }
 
   /**
@@ -119,7 +119,7 @@ function testCompileDIC() {
    */
   public function testSerialization() {
     $classloader = drupal_classloader();
-    $kernel = new DrupalKernel('testing', $classloader);
+    $kernel = new DrupalKernel('testing', FALSE, $classloader);
 
     $string = serialize($kernel);
     $unserialized_kernel = unserialize($string);
diff --git a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/ServiceDestructionTest.php b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/ServiceDestructionTest.php
index a48e883..9bfde63 100644
--- a/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/ServiceDestructionTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/DrupalKernel/ServiceDestructionTest.php
@@ -29,16 +29,16 @@ public static function getInfo() {
    */
   public function testDestructionUsed() {
     // Enable the test module to add it to the container.
-    $this->enableModules(array('service_provider_test'));
+    $this->enableModules(array('bundle_test'));
 
     // The service has not been destructed yet.
-    $this->assertNull(\Drupal::state()->get('service_provider_test.destructed'));
+    $this->assertNull(\Drupal::state()->get('bundle_test.destructed'));
 
     // Call the class and then terminate the kernel
-    $this->container->get('service_provider_test_class');
+    $this->container->get('bundle_test_class');
     $response = new Response();
     $this->container->get('kernel')->terminate($this->container->get('request'), $response);
-    $this->assertTrue(\Drupal::state()->get('service_provider_test.destructed'));
+    $this->assertTrue(\Drupal::state()->get('bundle_test.destructed'));
   }
 
   /**
@@ -46,15 +46,15 @@ public function testDestructionUsed() {
    */
   public function testDestructionUnused() {
     // Enable the test module to add it to the container.
-    $this->enableModules(array('service_provider_test'));
+    $this->enableModules(array('bundle_test'));
 
     // The service has not been destructed yet.
-    $this->assertNull(\Drupal::state()->get('service_provider_test.destructed'));
+    $this->assertNull(\Drupal::state()->get('bundle_test.destructed'));
 
     // Terminate the kernel. The test class has not been called, so it should not
     // be destructed.
     $response = new Response();
     $this->container->get('kernel')->terminate($this->container->get('request'), $response);
-    $this->assertNull(\Drupal::state()->get('service_provider_test.destructed'));
+    $this->assertNull(\Drupal::state()->get('bundle_test.destructed'));
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Installer/InstallerTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Installer/InstallerTranslationTest.php
deleted file mode 100644
index 2c6e10f..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Installer/InstallerTranslationTest.php
+++ /dev/null
@@ -1,136 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\system\Tests\Installer\InstallerTranslationTest.
- */
-
-namespace Drupal\system\Tests\Installer;
-
-use Drupal\Component\Utility\NestedArray;
-use Drupal\system\Tests\InstallerTest;
-
-/**
- * Tests the installer translation detection.
- */
-class InstallerTranslationTest extends InstallerTest {
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Installer translation test',
-      'description' => 'Selects German as the installation language and verifies the following page is not in English.',
-      'group' => 'Installer',
-    );
-  }
-
-  protected function setUp() {
-    global $conf;
-
-    // When running tests through the SimpleTest UI (vs. on the command line),
-    // SimpleTest's batch conflicts with the installer's batch. Batch API does
-    // not support the concept of nested batches (in which the nested is not
-    // progressive), so we need to temporarily pretend there was no batch.
-    // Back up the currently running SimpleTest batch.
-    $this->originalBatch = batch_get();
-
-    // Add the translations directory so we can retrieve German translations.
-    $conf['locale.settings']['translation.path'] = drupal_get_path('module', 'simpletest') . '/files/translations';
-
-    // Create the database prefix for this test.
-    $this->prepareDatabasePrefix();
-
-    // Prepare the environment for running tests.
-    $this->prepareEnvironment();
-    if (!$this->setupEnvironment) {
-      return FALSE;
-    }
-
-    // Reset all statics and variables to perform tests in a clean environment.
-    $conf = array();
-    drupal_static_reset();
-
-    // Change the database prefix.
-    // All static variables need to be reset before the database prefix is
-    // changed, since \Drupal\Core\Utility\CacheArray implementations attempt to
-    // write back to persistent caches when they are destructed.
-    $this->changeDatabasePrefix();
-    if (!$this->setupDatabasePrefix) {
-      return FALSE;
-    }
-    $variable_groups = array(
-      'system.file' => array(
-        'path.private' =>  $this->private_files_directory,
-        'path.temporary' => $this->temp_files_directory,
-      ),
-      'locale.settings' => array(
-        'translation.path' => $this->translation_files_directory,
-      ),
-    );
-    foreach ($variable_groups as $config_base => $variables) {
-      foreach ($variables as $name => $value) {
-        NestedArray::setValue($GLOBALS['conf'], array_merge(array($config_base), explode('.', $name)), $value);
-      }
-    }
-    $settings['conf_path'] = (object) array(
-      'value' => $this->public_files_directory,
-      'required' => TRUE,
-    );
-    $settings['config_directories'] = (object) array(
-      'value' => array(),
-      'required' => TRUE,
-    );
-    $this->writeSettings($settings);
-
-    // Submit the installer with German language.
-    $this->drupalPost($GLOBALS['base_url'] . '/core/install.php', array('langcode' => 'de'), 'Save and continue');
-
-    // On the following page where installation profile is being selected the
-    // interface should be already translated, so there is no "Set up database"
-    // text anymore.
-    $this->assertNoText('Set up database', '"Set up database" string was not found.');
-
-    // After this assertion all we needed to test is tested, but the test
-    // expects the installation to succeed. If the test would finish here, an
-    // exception would occur. That is why the full installation has to be
-    // finished in the further steps.
-
-    // Get the "Save and continue" submit button translated value from the
-    // translated interface.
-    $submit_value = (string) current($this->xpath('//input[@type="submit"]/@value'));
-
-    // Submit the minimal profile installation.
-    $this->drupalPost(NULL, array('profile' => 'minimal'), $submit_value);
-
-    // Submit the next step.
-    $this->drupalPost(NULL, array(), $submit_value);
-
-    // Reload config directories.
-    include $this->public_files_directory . '/settings.php';
-    $prefix = substr($this->public_files_directory, strlen(conf_path() . '/files/'));
-    foreach ($config_directories as $type => $data) {
-      $GLOBALS['config_directories'][$type]['path'] = $prefix . '/files/' . $data['path'];
-    }
-    $this->rebuildContainer();
-
-    foreach ($variable_groups as $config_base => $variables) {
-      $config = config($config_base);
-      foreach ($variables as $name => $value) {
-        $config->set($name, $value);
-      }
-      $config->save();
-    }
-
-    // Use the test mail class instead of the default mail handler class.
-    config('system.mail')->set('interface.default', 'Drupal\Core\Mail\VariableLog')->save();
-
-    drupal_set_time_limit($this->timeLimit);
-    // When running from run-tests.sh we don't get an empty current path which
-    // would indicate we're on the home page.
-    $path = current_path();
-    if (empty($path)) {
-      _current_path('run-tests');
-    }
-    $this->setup = TRUE;
-  }
-
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/ServiceProvider/ServiceProviderTest.php b/core/modules/system/lib/Drupal/system/Tests/ServiceProvider/ServiceProviderTest.php
deleted file mode 100644
index bffd0f0..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/ServiceProvider/ServiceProviderTest.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\ServiceProvider\ServiceProviderTest.
- */
-
-namespace Drupal\system\Tests\ServiceProvider;
-
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests service provider registration to the DIC.
- */
-class ServiceProviderTest extends WebTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('file', 'service_provider_test');
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Service Provider Registration',
-      'description' => 'Tests service provider registration to the DIC.',
-      'group' => 'Service Provider',
-    );
-  }
-
-  /**
-   * Tests that services provided by module service providers get registered to the DIC.
-   */
-  function testServiceProviderRegistration() {
-    $this->assertTrue(drupal_container()->getDefinition('file.usage')->getClass() == 'Drupal\\service_provider_test\\TestFileUsage', 'Class has been changed');
-    $this->assertTrue(drupal_container()->has('service_provider_test_class'), 'The service_provider_test_class service has been registered to the DIC');
-    // The event subscriber method in the test class calls drupal_set_message with
-    // a message saying it has fired. This will fire on every page request so it
-    // should show up on the front page.
-    $this->drupalGet('');
-    $this->assertText(t('The service_provider_test event subscriber fired!'), 'The service_provider_test event subscriber fired');
-  }
-
-  /**
-   * Tests that the DIC keeps up with module enable/disable in the same request.
-   */
-  function testServiceProviderRegistrationDynamic() {
-    // Disable the module and ensure the service provider's service is not registered.
-    module_disable(array('service_provider_test'));
-    $this->assertFalse(drupal_container()->has('service_provider_test_class'), 'The service_provider_test_class service does not exist in the DIC.');
-
-    // Enable the module and ensure the service provider's service is registered.
-    module_enable(array('service_provider_test'));
-    $this->assertTrue(drupal_container()->has('service_provider_test_class'), 'The service_provider_test_class service exists in the DIC.');
-  }
-
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/IgnoreSlaveSubscriberTest.php b/core/modules/system/lib/Drupal/system/Tests/System/IgnoreSlaveSubscriberTest.php
index da65377..bf004f9 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/IgnoreSlaveSubscriberTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/IgnoreSlaveSubscriberTest.php
@@ -38,7 +38,7 @@ function testSystemInitIgnoresSlaves() {
     Database::addConnectionInfo('default', 'slave', $connection_info['default']);
 
     db_ignore_slave();
-    $kernel = new DrupalKernel('testing', drupal_classloader(), FALSE);
+    $kernel = new DrupalKernel('testing', FALSE, drupal_classloader(), FALSE);
     $event = new GetResponseEvent($kernel, Request::create('http://example.com'), HttpKernelInterface::MASTER_REQUEST);
     $subscriber = new SlaveDatabaseIgnoreSubscriber();
     $subscriber->checkSlaveServer($event);
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
index 8a1cb68..b613121 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
@@ -114,7 +114,7 @@ protected function setUp() {
     // Build a minimal, partially mocked environment for unit tests.
     $this->containerBuild(drupal_container());
     // Make sure it survives kernel rebuilds.
-    $conf['container_service_providers']['TestServiceProvider'] = 'Drupal\simpletest\TestServiceProvider';
+    $conf['container_bundles'][] = 'Drupal\simpletest\TestBundle';
 
     // Change the database prefix.
     // All static variables need to be reset before the database prefix is
diff --git a/core/modules/system/tests/modules/bundle_test/bundle_test.info.yml b/core/modules/system/tests/modules/bundle_test/bundle_test.info.yml
new file mode 100644
index 0000000..49335fb
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/bundle_test.info.yml
@@ -0,0 +1,7 @@
+name: 'Bundle test'
+type: module
+description: 'Support module for bundle testing.'
+package: Testing
+version: VERSION
+core: 8.x
+hidden: true
diff --git a/core/modules/system/tests/modules/bundle_test/bundle_test.module b/core/modules/system/tests/modules/bundle_test/bundle_test.module
new file mode 100644
index 0000000..b3d9bbc
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/bundle_test.module
@@ -0,0 +1 @@
+<?php
diff --git a/core/modules/system/tests/modules/bundle_test/bundle_test.services.yml b/core/modules/system/tests/modules/bundle_test/bundle_test.services.yml
new file mode 100644
index 0000000..88b3caf
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/bundle_test.services.yml
@@ -0,0 +1,9 @@
+services:
+  bundle_test_class:
+    class: Drupal\bundle_test\TestClass
+    tags:
+      - { name: event_subscriber }
+      - { name: needs_destruction }
+    arguments: ['@state']
+  file.usage:
+    class: Drupal\bundle_test\TestFileUsage
diff --git a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php
new file mode 100644
index 0000000..ad711cb
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\bundle_test\TestClass.
+ */
+
+namespace Drupal\bundle_test;
+
+use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
+use Drupal\Core\DestructableInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+
+class TestClass implements EventSubscriberInterface, DestructableInterface {
+
+  /**
+   * The state keyvalue collection.
+   *
+   * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
+   */
+  protected $state;
+
+  /**
+   * Constructor.
+   *
+   * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $state
+   *   The state key value store.
+   */
+  public function __construct(KeyValueStoreInterface $state) {
+    $this->state = $state;
+  }
+
+  /**
+   * A simple kernel listener method.
+   */
+  public function onKernelRequestTest(GetResponseEvent $event) {
+    drupal_set_message(t('The bundle_test event subscriber fired!'));
+  }
+
+  /**
+   * Registers methods as kernel listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    $events[KernelEvents::REQUEST][] = array('onKernelRequestTest', 100);
+    return $events;
+  }
+
+  /**
+   * Implements \Drupal\Core\DestructableInterface::destruct().
+   */
+  public function destruct() {
+    $this->state->set('bundle_test.destructed', TRUE);
+  }
+}
diff --git a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestFileUsage.php b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestFileUsage.php
new file mode 100644
index 0000000..0ee5f2d
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestFileUsage.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\bundle_test\TestFileUsage.
+ */
+
+namespace Drupal\bundle_test;
+
+use Drupal\file\Plugin\Core\Entity\File;
+
+class TestFileUsage extends FileUsageBase {
+
+  /**
+   * Implements Drupal\file\FileUsage\FileUsageInterface::add().
+   */
+  public function add(File $file, $module, $type, $id, $count = 1) {
+  }
+
+  /**
+   * Implements Drupal\file\FileUsage\FileUsageInterface::delete().
+   */
+  public function delete(File $file, $module, $type = NULL, $id = NULL, $count = 1) {
+  }
+
+  /**
+   * Implements Drupal\file\FileUsage\FileUsageInterface::listUsage().
+   */
+  public function listUsage(File $file) {
+  }
+}
diff --git a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/RouterTestBundle.php b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/RouterTestBundle.php
new file mode 100644
index 0000000..114ddf4
--- /dev/null
+++ b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/RouterTestBundle.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Definition of \Drupal\router_test\RouterTestBundle.
+ */
+
+namespace Drupal\router_test;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * Registers a dynamic route provider.
+ */
+class RouterTestBundle extends Bundle {
+
+  /**
+   * Overrides Symfony\Component\HttpKernel\Bundle\Bundle::build().
+   */
+  public function build(ContainerBuilder $container) {
+    $container->register('router_test.subscriber', 'Drupal\router_test\RouteTestSubscriber')->addTag('event_subscriber');
+    $container->register('access_check.router_test', 'Drupal\router_test\Access\TestAccessCheck')
+      ->addTag('access_check');
+  }
+}
diff --git a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/RouterTestServiceProvider.php b/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/RouterTestServiceProvider.php
deleted file mode 100644
index 9c1dbc3..0000000
--- a/core/modules/system/tests/modules/router_test/lib/Drupal/router_test/RouterTestServiceProvider.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of \Drupal\router_test\RouterTestServiceProvider.
- */
-
-namespace Drupal\router_test;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\ServiceProviderInterface;
-
-/**
- * Registers a dynamic route provider.
- */
-class RouterTestServiceProvider implements ServiceProviderInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function register(ContainerBuilder $container) {
-    $container->register('router_test.subscriber', 'Drupal\router_test\RouteTestSubscriber')->addTag('event_subscriber');
-    $container->register('access_check.router_test', 'Drupal\router_test\Access\TestAccessCheck')
-      ->addTag('access_check');
-  }
-}
diff --git a/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/ServiceProviderTestServiceProvider.php b/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/ServiceProviderTestServiceProvider.php
deleted file mode 100644
index b2b85cb..0000000
--- a/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/ServiceProviderTestServiceProvider.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\service_provider_test\ServiceProviderTestServiceProvider.
- */
-
-namespace Drupal\service_provider_test;
-
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Drupal\Core\DependencyInjection\ServiceProviderInterface;
-use Drupal\Core\DependencyInjection\ServiceModifierInterface;
-
-class ServiceProviderTestServiceProvider implements ServiceProviderInterface, ServiceModifierInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function register(ContainerBuilder $container) {
-
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function alter(ContainerBuilder $container) {
-    if ($container->has('file.usage')) {
-      // Override the class used for the file.usage service.
-      $definition = $container->getDefinition('file.usage');
-      $definition->setClass('Drupal\service_provider_test\TestFileUsage');
-    }
-  }
-}
diff --git a/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestClass.php b/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestClass.php
deleted file mode 100644
index 1c8ea06..0000000
--- a/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestClass.php
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\service_provider_test\TestClass.
- */
-
-namespace Drupal\service_provider_test;
-
-use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
-use Drupal\Core\DestructableInterface;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\KernelEvents;
-
-class TestClass implements EventSubscriberInterface, DestructableInterface {
-
-  /**
-   * The state keyvalue collection.
-   *
-   * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
-   */
-  protected $state;
-
-  /**
-   * Constructor.
-   *
-   * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $state
-   *   The state key value store.
-   */
-  public function __construct(KeyValueStoreInterface $state) {
-    $this->state = $state;
-  }
-
-  /**
-   * A simple kernel listener method.
-   */
-  public function onKernelRequestTest(GetResponseEvent $event) {
-    drupal_set_message(t('The service_provider_test event subscriber fired!'));
-  }
-
-  /**
-   * Registers methods as kernel listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    $events[KernelEvents::REQUEST][] = array('onKernelRequestTest', 100);
-    return $events;
-  }
-
-  /**
-   * Implements \Drupal\Core\DestructableInterface::destruct().
-   */
-  public function destruct() {
-    $this->state->set('service_provider_test.destructed', TRUE);
-  }
-}
diff --git a/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestFileUsage.php b/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestFileUsage.php
deleted file mode 100644
index 93919dc..0000000
--- a/core/modules/system/tests/modules/service_provider_test/lib/Drupal/service_provider_test/TestFileUsage.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\service_provider_test\TestFileUsage.
- */
-
-namespace Drupal\service_provider_test;
-
-use Drupal\file\Plugin\Core\Entity\File;
-use Drupal\file\FileUsage\FileUsageBase;
-
-class TestFileUsage extends FileUsageBase {
-
-  /**
-   * Implements Drupal\file\FileUsage\FileUsageInterface::add().
-   */
-  public function add(File $file, $module, $type, $id, $count = 1) {
-  }
-
-  /**
-   * Implements Drupal\file\FileUsage\FileUsageInterface::delete().
-   */
-  public function delete(File $file, $module, $type = NULL, $id = NULL, $count = 1) {
-  }
-
-  /**
-   * Implements Drupal\file\FileUsage\FileUsageInterface::listUsage().
-   */
-  public function listUsage(File $file) {
-  }
-}
diff --git a/core/modules/system/tests/modules/service_provider_test/service_provider_test.info.yml b/core/modules/system/tests/modules/service_provider_test/service_provider_test.info.yml
deleted file mode 100644
index 620c897..0000000
--- a/core/modules/system/tests/modules/service_provider_test/service_provider_test.info.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-name: 'Service Provider test'
-type: module
-description: 'Support module for service provider testing.'
-package: Testing
-version: VERSION
-core: 8.x
-hidden: true
diff --git a/core/modules/system/tests/modules/service_provider_test/service_provider_test.module b/core/modules/system/tests/modules/service_provider_test/service_provider_test.module
deleted file mode 100644
index b3d9bbc..0000000
--- a/core/modules/system/tests/modules/service_provider_test/service_provider_test.module
+++ /dev/null
@@ -1 +0,0 @@
-<?php
diff --git a/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml b/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml
deleted file mode 100644
index dda70f5..0000000
--- a/core/modules/system/tests/modules/service_provider_test/service_provider_test.services.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-services:
-  service_provider_test_class:
-    class: Drupal\service_provider_test\TestClass
-    tags:
-      - { name: event_subscriber }
-      - { name: needs_destruction }
-    arguments: ['@state']
diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc
index 3d274e8..265031f 100644
--- a/core/modules/tracker/tracker.pages.inc
+++ b/core/modules/tracker/tracker.pages.inc
@@ -76,7 +76,7 @@ function tracker_page($account = NULL, $set_title = FALSE) {
 
       $mark_build = array(
         '#theme' => 'mark',
-        '#status' => node_mark($node->nid, $node->changed),
+        '#mark_type' => node_mark($node->nid, $node->changed),
       );
 
       $row = array(
diff --git a/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php b/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php
index 1fdd0b3..9129466 100644
--- a/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php
+++ b/core/modules/update/lib/Drupal/update/Tests/UpdateContribTest.php
@@ -287,7 +287,7 @@ function testUpdateHiddenBaseTheme() {
     config('update_test.settings')->set('system_info', $system_info)->save();
     $projects = update_get_projects();
     $theme_data = system_rebuild_theme_data();
-    update_process_info_list($projects, $theme_data, 'theme', TRUE);
+    drupal_project_process_info_list($projects, $theme_data, 'theme', TRUE);
 
     $this->assertTrue(!empty($projects['update_test_basetheme']), 'Valid base theme (update_test_basetheme) was found.');
   }
diff --git a/core/modules/update/update.api.php b/core/modules/update/update.api.php
index b5621dd..eb01a5b 100644
--- a/core/modules/update/update.api.php
+++ b/core/modules/update/update.api.php
@@ -28,11 +28,11 @@
  *   includes all the metadata documented in the comments below for each project
  *   (either module or theme) that is currently enabled. The array is initially
  *   populated inside update_get_projects() with the help of
- *   update_process_info_list(), so look there for examples of how to populate
- *   the array with real values.
+ *   drupal_project_process_info_list(), so look there for examples of how to
+ *   populate the array with real values.
  *
  * @see update_get_projects()
- * @see update_process_info_list()
+ * @see update_process_info_list(drupal_project_process_info_list
  */
 function hook_update_projects_alter(&$projects) {
   // Hide a site-specific module from the list.
diff --git a/core/modules/update/update.compare.inc b/core/modules/update/update.compare.inc
index c8f5958..3b53b40 100644
--- a/core/modules/update/update.compare.inc
+++ b/core/modules/update/update.compare.inc
@@ -6,13 +6,18 @@
  */
 
 /**
+ * Load the project API.
+ */
+require_once DRUPAL_ROOT . '/core/includes/project.inc';
+
+/**
  * Fetches an array of installed and enabled projects.
  *
  * This is only responsible for generating an array of projects (taking into
  * account projects that include more than one module or theme). Other
  * information like the specific version and install type (official release,
- * dev snapshot, etc) is handled later in update_process_project_info() since
- * that logic is only required when preparing the status report, not for
+ * dev snapshot, etc) is handled later in drupal_project_process_project_info()
+ * since that logic is only required when preparing the status report, not for
  * fetching the available release data.
  *
  * This array is fairly expensive to construct, since it involves a lot of disk
@@ -48,7 +53,7 @@
  *   - base_themes: If the project is a theme it contains an associative array
  *     of all base-themes.
  *
- * @see update_process_project_info()
+ * @see drupal_project_process_project_info()
  * @see update_calculate_project_data()
  * @see update_project_storage()
  */
@@ -61,11 +66,11 @@ function update_get_projects() {
       // Still empty, so we have to rebuild.
       $module_data = system_rebuild_module_data();
       $theme_data = system_rebuild_theme_data();
-      update_process_info_list($projects, $module_data, 'module', TRUE);
-      update_process_info_list($projects, $theme_data, 'theme', TRUE);
+      drupal_project_process_info_list($projects, $module_data, 'module', TRUE);
+      drupal_project_process_info_list($projects, $theme_data, 'theme', TRUE);
       if (config('update.settings')->get('check.disabled_extensions')) {
-        update_process_info_list($projects, $module_data, 'module', FALSE);
-        update_process_info_list($projects, $theme_data, 'theme', FALSE);
+        drupal_project_process_info_list($projects, $module_data, 'module', FALSE);
+        drupal_project_process_info_list($projects, $theme_data, 'theme', FALSE);
       }
       // Allow other modules to alter projects before fetching and comparing.
       drupal_alter('update_projects', $projects);
@@ -76,241 +81,7 @@ function update_get_projects() {
   return $projects;
 }
 
-/**
- * Populates an array of project data.
- *
- * This iterates over a list of the installed modules or themes and groups
- * them by project and status. A few parts of this function assume that
- * enabled modules and themes are always processed first, and if disabled
- * modules or themes are being processed (there is a setting to control if
- * disabled code should be included in the Available updates report or not),
- * those are only processed after $projects has been populated with
- * information about the enabled code. 'Hidden' modules are always ignored.
- * 'Hidden' themes are ignored only if they have no enabled sub-themes.
- * This function also records the latest change time on the .info.yml
- * files for each module or theme, which is important data which is used when
- * deciding if the available update data should be invalidated.
- *
- * @param $projects
- *   Reference to the array of project data of what's installed on this site.
- * @param $list
- *   Array of data to process to add the relevant info to the $projects array.
- * @param $project_type
- *   The kind of data in the list. Can be 'module' or 'theme'.
- * @param $status
- *   Boolean that controls what status (enabled or disabled) to process out of
- *   the $list and add to the $projects array.
- * @param $additional_whitelist
- *   (optional) Array of additional elements to be collected from the .info.yml
- *   file. Defaults to array().
- *
- * @see update_get_projects()
- */
-function update_process_info_list(&$projects, $list, $project_type, $status, $additional_whitelist = array()) {
-  foreach ($list as $file) {
-    // A disabled or hidden base theme of an enabled sub-theme still has all
-    // of its code run by the sub-theme, so we include it in our "enabled"
-    // projects list.
-    if ($status && !empty($file->sub_themes)) {
-      foreach ($file->sub_themes as $key => $name) {
-        // Build a list of enabled sub-themes.
-        if ($list[$key]->status) {
-          $file->enabled_sub_themes[$key] = $name;
-        }
-      }
-      // If the theme is disabled and there are no enabled subthemes, we
-      // should ignore this base theme for the enabled case. If the site is
-      // trying to display disabled themes, we'll catch it then.
-      if (!$file->status && empty($file->enabled_sub_themes)) {
-        continue;
-      }
-    }
-    // Otherwise, just add projects of the proper status to our list.
-    elseif ($file->status != $status) {
-      continue;
-    }
-
-    // Skip if the .info.yml file is broken.
-    if (empty($file->info)) {
-      continue;
-    }
-
-    // Skip if it's a hidden module or hidden theme without enabled sub-themes.
-    if (!empty($file->info['hidden']) && empty($file->enabled_sub_themes)) {
-      continue;
-    }
-
-    // If the .info.yml doesn't define the 'project', try to figure it out.
-    if (!isset($file->info['project'])) {
-      $file->info['project'] = update_get_project_name($file);
-    }
-
-    // If we still don't know the 'project', give up.
-    if (empty($file->info['project'])) {
-      continue;
-    }
-
-    // If we don't already know it, grab the change time on the .info.yml file
-    // itself. Note: we need to use the ctime, not the mtime (modification
-    // time) since many (all?) tar implementations will go out of their way to
-    // set the mtime on the files it creates to the timestamps recorded in the
-    // tarball. We want to see the last time the file was changed on disk,
-    // which is left alone by tar and correctly set to the time the .info.yml
-    // file was unpacked.
-    if (!isset($file->info['_info_file_ctime'])) {
-      $info_filename = dirname($file->uri) . '/' . $file->name . '.info.yml';
-      $file->info['_info_file_ctime'] = filectime($info_filename);
-    }
-
-    if (!isset($file->info['datestamp'])) {
-      $file->info['datestamp'] = 0;
-    }
-
-    $project_name = $file->info['project'];
-
-    // Figure out what project type we're going to use to display this module
-    // or theme. If the project name is 'drupal', we don't want it to show up
-    // under the usual "Modules" section, we put it at a special "Drupal Core"
-    // section at the top of the report.
-    if ($project_name == 'drupal') {
-      $project_display_type = 'core';
-    }
-    else {
-      $project_display_type = $project_type;
-    }
-    if (empty($status) && empty($file->enabled_sub_themes)) {
-      // If we're processing disabled modules or themes, append a suffix.
-      // However, we don't do this to a a base theme with enabled
-      // subthemes, since we treat that case as if it is enabled.
-      $project_display_type .= '-disabled';
-    }
-    // Add a list of sub-themes that "depend on" the project and a list of base
-    // themes that are "required by" the project.
-    if ($project_name == 'drupal') {
-      // Drupal core is always required, so this extra info would be noise.
-      $sub_themes = array();
-      $base_themes = array();
-    }
-    else {
-      // Add list of enabled sub-themes.
-      $sub_themes = !empty($file->enabled_sub_themes) ? $file->enabled_sub_themes : array();
-      // Add list of base themes.
-      $base_themes = !empty($file->base_themes) ? $file->base_themes : array();
-    }
-    if (!isset($projects[$project_name])) {
-      // Only process this if we haven't done this project, since a single
-      // project can have multiple modules or themes.
-      $projects[$project_name] = array(
-        'name' => $project_name,
-        // Only save attributes from the .info.yml file we care about so we do
-        // not bloat our RAM usage needlessly.
-        'info' => update_filter_project_info($file->info, $additional_whitelist),
-        'datestamp' => $file->info['datestamp'],
-        'includes' => array($file->name => $file->info['name']),
-        'project_type' => $project_display_type,
-        'project_status' => $status,
-        'sub_themes' => $sub_themes,
-        'base_themes' => $base_themes,
-      );
-    }
-    elseif ($projects[$project_name]['project_type'] == $project_display_type) {
-      // Only add the file we're processing to the 'includes' array for this
-      // project if it is of the same type and status (which is encoded in the
-      // $project_display_type). This prevents listing all the disabled
-      // modules included with an enabled project if we happen to be checking
-      // for disabled modules, too.
-      $projects[$project_name]['includes'][$file->name] = $file->info['name'];
-      $projects[$project_name]['info']['_info_file_ctime'] = max($projects[$project_name]['info']['_info_file_ctime'], $file->info['_info_file_ctime']);
-      $projects[$project_name]['datestamp'] = max($projects[$project_name]['datestamp'], $file->info['datestamp']);
-      if (!empty($sub_themes)) {
-        $projects[$project_name]['sub_themes'] += $sub_themes;
-      }
-      if (!empty($base_themes)) {
-        $projects[$project_name]['base_themes'] += $base_themes;
-      }
-    }
-    elseif (empty($status)) {
-      // If we have a project_name that matches, but the project_display_type
-      // does not, it means we're processing a disabled module or theme that
-      // belongs to a project that has some enabled code. In this case, we add
-      // the disabled thing into a separate array for separate display.
-      $projects[$project_name]['disabled'][$file->name] = $file->info['name'];
-    }
-  }
-}
-
-/**
- * Determines what project a given file object belongs to.
- *
- * @param $file
- *   A file object as returned by system_get_files_database().
- *
- * @return
- *   The canonical project short name.
- *
- * @see system_get_files_database()
- */
-function update_get_project_name($file) {
-  $project_name = '';
-  if (isset($file->info['project'])) {
-    $project_name = $file->info['project'];
-  }
-  elseif (isset($file->filename) && (strpos($file->filename, 'core/modules') === 0)) {
-    $project_name = 'drupal';
-  }
-  return $project_name;
-}
-
-/**
- * Determines version and type information for currently installed projects.
- *
- * Processes the list of projects on the system to figure out the currently
- * installed versions, and other information that is required before we can
- * compare against the available releases to produce the status report.
- *
- * @param $projects
- *   Array of project information from update_get_projects().
- */
-function update_process_project_info(&$projects) {
-  foreach ($projects as $key => $project) {
-    // Assume an official release until we see otherwise.
-    $install_type = 'official';
-
-    $info = $project['info'];
 
-    if (isset($info['version'])) {
-      // Check for development snapshots
-      if (preg_match('@(dev|HEAD)@', $info['version'])) {
-        $install_type = 'dev';
-      }
-
-      // Figure out what the currently installed major version is. We need
-      // to handle both contribution (e.g. "5.x-1.3", major = 1) and core
-      // (e.g. "5.1", major = 5) version strings.
-      $matches = array();
-      if (preg_match('/^(\d+\.x-)?(\d+)\..*$/', $info['version'], $matches)) {
-        $info['major'] = $matches[2];
-      }
-      elseif (!isset($info['major'])) {
-        // This would only happen for version strings that don't follow the
-        // drupal.org convention. We let contribs define "major" in their
-        // .info.yml in this case, and only if that's missing would we hit this.
-        $info['major'] = -1;
-      }
-    }
-    else {
-      // No version info available at all.
-      $install_type = 'unknown';
-      $info['version'] = t('Unknown');
-      $info['major'] = -1;
-    }
-
-    // Finally, save the results we care about into the $projects array.
-    $projects[$key]['existing_version'] = $info['version'];
-    $projects[$key]['existing_major'] = $info['major'];
-    $projects[$key]['install_type'] = $install_type;
-  }
-}
 
 /**
  * Calculates the current update status of all projects on the site.
@@ -330,9 +101,9 @@ function update_process_project_info(&$projects) {
  * @return
  *   An array of installed projects with current update status information.
  *
+ * @see drupal_project_process_project_info()
  * @see update_get_available()
  * @see update_get_projects()
- * @see update_process_project_info()
  * @see update_project_storage()
  */
 function update_calculate_project_data($available) {
@@ -344,7 +115,7 @@ function update_calculate_project_data($available) {
     return $projects;
   }
   $projects = update_get_projects();
-  update_process_project_info($projects);
+  drupal_project_process_project_info($projects);
   foreach ($projects as $project => $project_info) {
     if (isset($available[$project])) {
       update_calculate_project_update_status($projects[$project], $available[$project]);
@@ -813,7 +584,7 @@ function update_project_storage($key) {
  * @return
  *   Array of .info.yml file data we need for the update manager.
  *
- * @see update_process_info_list()
+ * @see update_process_info_list(drupal_project_process_info_list
  */
 function update_filter_project_info($info, $additional_whitelist = array()) {
   $whitelist = array(
diff --git a/core/update.php b/core/update.php
index 3b6afe3..b73e3ce 100644
--- a/core/update.php
+++ b/core/update.php
@@ -186,7 +186,7 @@ function update_helpful_links() {
  * while updates are running.
  */
 function update_flush_all_caches() {
-  unset($GLOBALS['conf']['container_service_providers']['UpdateServiceProvider']);
+  unset($GLOBALS['conf']['container_bundles']['UpdateBundle']);
   Drupal::service('kernel')->updateModules(Drupal::moduleHandler()->getModuleList());
 
   // No updates to run, so caches won't get flushed later.  Clear them now.
