diff --git a/core/includes/common.inc b/core/includes/common.inc
index edcbe2c..0b399ba 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1372,6 +1372,10 @@ function drupal_flush_all_caches() {
   foreach ($theme_handler->listInfo() as $theme_name => $theme) {
     $keys[] = 'theme.active_theme.' . $theme_name;
   }
+
+  // Remove container definition.
+  //$keys[] = 'container_definition';
+
   \Drupal::state()->deleteMultiple($keys);
   // In case the active theme gets requested later in the same request we need
   // to reset the theme manager.
diff --git a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
index cb85878..d6b1cd6 100644
--- a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
+++ b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
@@ -41,6 +41,9 @@ public function __construct(ParameterBagInterface $parameterBag = NULL) {
    *   services in a frozen builder.
    */
   public function set($id, $service, $scope = self::SCOPE_CONTAINER) {
+    if (strtolower($id) !== $id) {
+      throw new \InvalidArgumentException("Service ID names must be lowercase: $id");
+    }
     SymfonyContainer::set($id, $service, $scope);
 
     // Ensure that the _serviceId property is set on synthetic services as well.
@@ -50,6 +53,26 @@ public function set($id, $service, $scope = self::SCOPE_CONTAINER) {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function register($id, $class = null) {
+    if (strtolower($id) !== $id) {
+      throw new \InvalidArgumentException("Service ID names must be lowercase: $id");
+    }
+    return parent::register($id, $class);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setParameter($name, $value) {
+    if (strtolower($name) !== $name) {
+      throw new \InvalidArgumentException("Parameter names must be lowercase: $name");
+    }
+    parent::setParameter($name, $value);
+  }
+
+  /**
    * Synchronizes a service change.
    *
    * This method is a copy of the ContainerBuilder of symfony.
diff --git a/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php b/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php
new file mode 100644
index 0000000..46c695b
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php
@@ -0,0 +1,362 @@
+<?php
+
+/*
+ * @file
+ * Contains \Drupal\Core\DependencyInjection\Dumper
+ */
+
+namespace Drupal\Core\DependencyInjection\Dumper;
+
+use Symfony\Component\DependencyInjection\Alias;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Parameter;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Dumper\Dumper;
+use Symfony\Component\ExpressionLanguage\Expression;
+
+/**
+ * PhpArrayDumper dumps a service container as a serialized PHP array.
+ */
+class PhpArrayDumper extends Dumper
+{
+  /**
+   * {@inheritdoc}
+   */
+  public function dump(array $options = array())
+  {
+    return serialize($this->getArray());
+  }
+
+  /**
+   * Returns the service container as a PHP array.
+   *
+   * @return array
+   *  A PHP array represention of the service container
+   */
+  public function getArray()
+  {
+    $definition = [];
+    $definition['parameters'] = $this->getParameters();
+    $definition['services'] = $this->getServiceDefinitions();
+    return $definition;
+  }
+
+
+  /**
+   * Returns parameters of the container as a PHP Array.
+   *
+   * @return array
+   *   The escaped and prepared parameters of the container.
+   */
+  protected function getParameters()
+  {
+    if (!$this->container->getParameterBag()->all()) {
+      return [];
+    }
+
+    $parameters = $this->container->getParameterBag()->all();
+    $is_frozen = $this->container->isFrozen();
+    return $this->prepareParameters($parameters, $is_frozen);
+  }
+
+  /**
+   * Returns services of the container as a PHP Array.
+   *
+   * @return array
+   *   The service definitions.
+   */
+  protected function getServiceDefinitions()
+  {
+    if (!$this->container->getDefinitions()) {
+      return [];
+    }
+
+    $services = [];
+    foreach ($this->container->getDefinitions() as $id => $definition) {
+      $services[$id] = $this->getServiceDefinition($definition);
+    }
+
+    $aliases = $this->container->getAliases();
+    foreach ($aliases as $alias => $id) {
+      while (isset($aliases[(string) $id])) {
+        $id = $aliases[(string) $id];
+      }
+      $services[$alias] = $this->getServiceAliasDefinition($id);
+    }
+
+    return $services;
+  }
+
+  /**
+   * Prepares parameters.
+   *
+   * @param array $parameters
+   * @param bool  $escape
+   *
+   * @return array
+   */
+  protected function prepareParameters($parameters, $escape = true)
+  {
+    $filtered = array();
+    foreach ($parameters as $key => $value) {
+      if (is_array($value)) {
+        $value = $this->prepareParameters($value, $escape);
+      }
+      elseif ($value instanceof Reference) {
+        $value = '@'.$value;
+      }
+
+      $filtered[$key] = $value;
+    }
+
+    return $escape ? $this->escape($filtered) : $filtered;
+  }
+
+  /**
+   * Escapes arguments.
+   *
+   * @param array $arguments
+   *   The arguments to escape.
+   *
+   * @return array
+   *   The escaped arguments.
+   */
+  protected function escape($arguments)
+  {
+    $args = array();
+    foreach ($arguments as $k => $v) {
+      if (is_array($v)) {
+        $args[$k] = $this->escape($v);
+      }
+      elseif (is_string($v)) {
+        $args[$k] = str_replace('%', '%%', $v);
+      }
+      else {
+        $args[$k] = $v;
+      }
+    }
+
+    return $args;
+  }
+
+  /**
+   * Gets a service definition as PHP array.
+   *
+   * @param \Symfony\Component\DependencyInjection\Definition $definition
+   *   The definition to process.
+   *
+   * @return array
+   *   The service definition as PHP array.
+   */
+  protected function getServiceDefinition($definition)
+  {
+    $service = [];
+    if ($definition->getClass()) {
+      $service['class'] = $definition->getClass();
+    }
+
+    if (!$definition->isPublic()) {
+      $service['public'] = FALSE;
+    }
+
+/*
+    $tagsCode = '';
+    foreach ($definition->getTags() as $name => $tags) {
+      foreach ($tags as $attributes) {
+        $att = array();
+        foreach ($attributes as $key => $value) {
+          $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value));
+        }
+        $att = $att ? ', '.implode(', ', $att) : '';
+
+        $tagsCode .= sprintf("      - { name: %s%s }\n", $this->dumper->dump($name), $att);
+      }
+    }
+    if ($tagsCode) {
+      $code .= "    tags:\n".$tagsCode;
+    }
+*/
+
+    if ($definition->getFile()) {
+      $service['file'] = $definition->getFile();
+    }
+
+    if ($definition->isSynthetic()) {
+      $service['synthetic'] = TRUE;
+    }
+
+    if ($definition->isLazy()) {
+      $service['lazy'] = TRUE;
+    }
+
+    if ($definition->getArguments()) {
+      $service['arguments'] = $this->dumpValue($definition->getArguments());
+    }
+
+    if ($definition->getProperties()) {
+      $service['properties'] = $this->dumpValue($definition->getProperties());
+    }
+
+    if ($definition->getMethodCalls()) {
+      $service['calls'] = $this->dumpValue($definition->getMethodCalls());
+    }
+
+    if (($scope = $definition->getScope()) !== ContainerInterface::SCOPE_CONTAINER) {
+      $service['scope'] = $scope;
+    }
+
+    if (($decorated = $definition->getDecoratedService()) !== NULL) {
+      $service['decorates'] = $decorated;
+    }
+
+    if ($callable = $definition->getFactory()) {
+      $service['factory'] = $this->dumpCallable($callable);
+    }
+
+    if ($callable = $definition->getConfigurator()) {
+      $service['configurator'] = $this->dumpCallable($callable);
+    }
+
+    return $service;
+  }
+
+  /**
+   * Returns a service alias definiton.
+   *
+   * @param string $alias
+   * @param Alias  $id
+   *
+   * @return string
+   */
+  protected function getServiceAliasDefinition($id)
+  {
+    if ($id->isPublic()) {
+      return [
+        'alias' => '@' . $id,
+      ];
+    } else {
+      return [
+        'alias' => '@' . $id,
+        'public' => FALSE,
+      ];
+    }
+  }
+  /**
+   * Dumps callable to YAML format
+   *
+   * @param callable $callable
+   *
+   * @return callable
+   */
+  protected function dumpCallable($callable)
+  {
+    if (is_array($callable)) {
+      if ($callable[0] instanceof Reference) {
+        $callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]);
+      }
+      elseif ($callable[0] instanceof Definition) {
+        $callable[0] = $this->getPrivateService($callable[0]);
+        $callable = array($callable[0], $callable[1]);
+      }
+      else {
+        $callable = array($callable[0], $callable[1]);
+      }
+    }
+
+    return $callable;
+  }
+
+  /**
+   * Returns a private service definition in a suitable format.
+   *
+   * @param \Symfony\Component\DependencyInjection\Definition $definition
+   *   The definition to process.
+   *
+   * @return \stdClass
+   *   A very lightweight private service value object.
+   */
+  protected function getPrivateService(Definition $definition) {
+    $service_definition = $this->getServiceDefinition($definition);
+    $hash = sha1(serialize($service_definition));
+    return (object) [
+      'type' => 'service',
+      'id' => 'private__' . $hash,
+      'value' => $service_definition,
+    ];
+  }
+
+  /**
+   * Dumps the value to YAML format.
+   *
+   * @param mixed $value
+   *
+   * @return mixed
+   *
+   * @throws RuntimeException When trying to dump object or resource
+   */
+  protected function dumpValue($value)
+  {
+    if (is_array($value)) {
+      $code = array();
+      foreach ($value as $k => $v) {
+        $code[$k] = $this->dumpValue($v);
+      }
+
+      return $code;
+    } elseif ($value instanceof Reference) {
+      return $this->getServiceCall((string) $value, $value);
+    } elseif ($value instanceof Definition) {
+      return $this->getPrivateService($value);
+    } elseif ($value instanceof Parameter) {
+      return $this->getParameterCall((string) $value);
+    } elseif ($value instanceof Expression) {
+      return $this->getExpressionCall((string) $value);
+    } elseif (is_object($value)) {
+      if (isset($value->_serviceId)) {
+        return '@' . $value->_serviceId;
+      }
+      throw new RuntimeException('Unable to dump a service container if a parameter is an object without _serviceId.');
+    } elseif (is_resource($value)) {
+      throw new RuntimeException('Unable to dump a service container if a parameter is a resource.');
+    }
+
+    return $value;
+  }
+
+  /**
+   * Gets the service call.
+   *
+   * @param string  $id
+   * @param Reference $reference
+   *
+   * @return string
+   */
+  protected function getServiceCall($id, Reference $reference = null)
+  {
+    if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
+      return sprintf('@?%s', $id);
+    }
+
+    return sprintf('@%s', $id);
+  }
+
+  /**
+   * Gets parameter call.
+   *
+   * @param string $id
+   *
+   * @return string
+   */
+  protected function getParameterCall($id)
+  {
+    return sprintf('%%%s%%', $id);
+  }
+
+  protected function getExpressionCall($expression)
+  {
+    return sprintf('@=%s', $expression);
+  }
+}
diff --git a/core/lib/Drupal/Core/DependencyInjection/PhpArray/Container.php b/core/lib/Drupal/Core/DependencyInjection/PhpArray/Container.php
new file mode 100644
index 0000000..2ca8a91
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/PhpArray/Container.php
@@ -0,0 +1,387 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Core\DependencyInjection\PhpArray\Container
+ */
+
+namespace Drupal\Core\DependencyInjection\PhpArray;
+
+use ReflectionClass;
+use RuntimeException;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\IntrospectableContainerInterface;
+use Symfony\Component\DependencyInjection\ScopeInterface;
+
+/**
+ * Container is a DI container that provides services to users of the class.
+ *
+ * @ingroup dic
+ */
+class Container implements IntrospectableContainerInterface {
+
+  /**
+   * The parameters of the container.
+   *
+   * @var array
+   */
+  protected $parameters = array();
+
+  /**
+   * The service definitions of the container.
+   *
+   * @var array
+   */
+  protected $serviceDefinitions = array();
+
+  /**
+   * The instantiated services.
+   *
+   * @var array
+   */
+  protected $services = array();
+
+  /**
+   * The currently loading services.
+   *
+   * @var array
+   */
+  protected $loading = array();
+
+  /**
+   * Can the container parameters still be changed.
+   *
+   * For testing purposes the container needs to be changed.
+   *
+   * @var bool
+   */
+  protected $frozen = TRUE;
+
+  /**
+   * Constructs a new Container instance.
+   *
+   * @param array $container_definition
+   *   An array containing the 'services' and 'parameters'
+   * @param bool $frozen
+   *   (optional) Determines whether the container parameters can be changed,
+   *   defaults to TRUE;
+   */
+  public function __construct(array $container_definition, $frozen = TRUE) {
+    $this->parameters = $container_definition['parameters'];
+    $this->serviceDefinitions = $container_definition['services'];
+    $this->services['service_container'] = $this;
+    $this->frozen = $frozen;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get($name, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
+    if (isset($this->services[$name]) || ($invalidBehavior === ContainerInterface::NULL_ON_INVALID_REFERENCE && array_key_exists($name, $this->services))) {
+      return $this->services[$name];
+    }
+
+    if (isset($this->loading[$name])) {
+      throw new RuntimeException(sprintf('Circular reference detected for service "%s", path: "%s".', $name, implode(' -> ', array_keys($this->loading))));
+    }
+
+    $definition = $this->getDefinition($name, $invalidBehavior === ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
+
+    if (!$definition) {
+      $this->services[$name] = NULL;
+      return $this->services[$name];
+    }
+
+    if (isset($definition['alias'])) {
+      return $this->get(substr($definition['alias'], 1), $invalidBehavior);
+    }
+
+    $this->loading[$name] = TRUE;
+
+    $definition += array(
+      'class' => '',
+      'factory' => '',
+      'factory_class' => '',
+      'factory_method' => '',
+      'factory_service' => '',
+      'arguments' => array(),
+      'properties' => array(),
+      'calls' => array(),
+      'tags' => array(),
+    ); // @codeCoverageIgnore
+
+    try {
+      $arguments = $this->expandArguments($definition['arguments'], $invalidBehavior);
+      if (!empty($definition['factory'])) {
+        $factory = $definition['factory'];
+        if (is_array($factory)) {
+          $factory = $this->expandArguments($factory, $invalidBehavior);
+        }
+        $service = call_user_func_array($factory, $arguments);
+      }
+      elseif (!empty($definition['factory_method'])) {
+        $method = $definition['factory_method'];
+
+        if (!empty($definition['factory_class'])) {
+          $factory = $definition['factory_class'];
+        }
+        elseif (!empty($definition['factory_service'])) {
+          $factory = $this->get($definition['factory_service'], $invalidBehavior);
+        }
+        else {
+          throw new RuntimeException(sprintf('Cannot create service "%s" from factory method without a factory service or factory class.', $name));
+        }
+        $service = call_user_func_array(array($factory, $method), $arguments);
+      }
+      else {
+        // @todo Allow dynamic class definitions via parameters.
+        $class = $definition['class'];
+        $length = count($arguments);
+
+        switch ($length) {
+          case 0:
+            $service = new $class();
+            break;
+          case 1:
+            $service = new $class($arguments[0]);
+            break;
+          case 2:
+            $service = new $class($arguments[0], $arguments[1]);
+            break;
+          case 3:
+            $service = new $class($arguments[0], $arguments[1], $arguments[2]);
+            break;
+          case 4:
+            $service = new $class($arguments[0], $arguments[1], $arguments[2], $arguments[3]);
+            break;
+          case 5:
+            $service = new $class($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4]);
+            break;
+          case 6:
+            $service = new $class($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5]);
+            break;
+          case 7:
+            $service = new $class($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5], $arguments[6]);
+            break;
+          case 8:
+            $service = new $class($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5], $arguments[6], $arguments[7]);
+            break;
+          case 9:
+            $service = new $class($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5], $arguments[6], $arguments[7], $arguments[8]);
+            break;
+          case 10:
+            $service = new $class($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4], $arguments[5], $arguments[6], $arguments[7], $arguments[8], $arguments[9]);
+            break;
+          default:
+            $r = new ReflectionClass($class);
+            $service = $r->newInstanceArgs($arguments);
+            break;
+        }
+      }
+    }
+    catch (\Exception $e) {
+      unset($this->loading[$name]);
+      throw $e;
+    }
+    $this->services[$name] = $service;
+    unset($this->loading[$name]);
+
+    foreach ($definition['calls'] as $call) {
+      $method = $call[0];
+      $arguments = array();
+      if (!empty($call[1])) {
+        $arguments = $this->expandArguments($call[1], $invalidBehavior);
+      }
+      call_user_func_array(array($service, $method), $arguments);
+    }
+    foreach ($definition['properties'] as $key => $value) {
+      $service->{$key} = $value;
+    }
+
+    return $this->services[$name];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function set($id, $service, $scope = self::SCOPE_CONTAINER) {
+    if (isset($service)) {
+      $service->_serviceId = $id;
+    }
+    $this->services[$id] = $service;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function has($id) {
+    return isset($this->services[$id]) || isset($this->serviceDefinitions[$id]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
+    $definition = isset($this->serviceDefinitions[$plugin_id]) ? $this->serviceDefinitions[$plugin_id] : NULL;
+
+    if (!$definition && $exception_on_invalid) {
+      throw new RuntimeException(sprintf('The "%s" service definition does not exist.', $plugin_id));
+    }
+
+    return $definition;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefinitions() {
+    return $this->serviceDefinitions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasDefinition($plugin_id) {
+    return isset($this->serviceDefinitions[$plugin_id]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getParameter($name) {
+    return isset($this->parameters[$name]) ? $this->parameters[$name] : NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function hasParameter($name) {
+    return isset($this->parameters[$name]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setParameter($name, $value) {
+    if ($this->frozen) {
+      throw new \BadMethodCallException("Container parameters can't be changed on runtime.");
+    }
+    $this->parameters[$name] = $value;
+  }
+
+  /**
+   * Expands arguments from %parameter and @service to the resolved values.
+   *
+   * @param array $arguments
+   *   The arguments to expand.
+   * @param int $invalidBehavior
+   *   The behavior when the service does not exist
+   *
+   * @return array
+   *   The expanded arguments.
+   *
+   * @throws \RuntimeException if a parameter/service could not be resolved.
+   */
+  protected function expandArguments($arguments, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
+    foreach ($arguments as $key => $argument) {
+      if ($argument instanceof \stdClass) {
+        $name = $argument->id;
+        $this->serviceDefinitions[$name] = $argument->value;
+        $arguments[$key] = $this->get($name, $invalidBehavior);
+        unset($this->serviceDefinitions[$name]);
+        unset($this->services[$name]);
+        continue;
+      }
+
+      if (is_array($argument)) {
+        $arguments[$key] = $this->expandArguments($argument, $invalidBehavior);
+        continue;
+      }
+
+      if (!is_string($argument)) {
+        continue;
+      }
+
+      if (strpos($argument, '%') === 0) {
+        $name = substr($argument, 1, -1);
+        if (!isset($this->parameters[$name])) {
+          if ($invalidBehavior === ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
+            throw new RuntimeException("Could not find parameter: $name");
+          }
+          $arguments[$key] = NULL;
+          continue;
+        }
+        $arguments[$key] = $this->parameters[$name];
+      }
+      else if (strpos($argument, '@') === 0) {
+        $name = substr($argument, 1);
+        if (strpos($name, '?') === 0) {
+          $name = substr($name, 1);
+          $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
+        }
+        if (!isset($this->serviceDefinitions[$name])) {
+          if ($invalidBehavior === ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) {
+            throw new RuntimeException("Could not find service: $name");
+          }
+          $arguments[$key] = NULL;
+          continue;
+        }
+        $arguments[$key] = $this->get($name, $invalidBehavior);
+      }
+    }
+
+    return $arguments;
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @codeCoverageIgnore
+   */
+  public function enterScope($name) {
+    throw new \BadMethodCallException(sprintf("'%s' is not implemented", __FUNCTION__));
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @codeCoverageIgnore
+   */
+  public function leaveScope($name) {
+    throw new \BadMethodCallException(sprintf("'%s' is not implemented", __FUNCTION__));
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @codeCoverageIgnore
+   */
+  public function addScope(ScopeInterface $scope) {
+    throw new \BadMethodCallException(sprintf("'%s' is not implemented", __FUNCTION__));
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @codeCoverageIgnore
+   */
+  public function hasScope($name) {
+    throw new \BadMethodCallException(sprintf("'%s' is not implemented", __FUNCTION__));
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @codeCoverageIgnore
+   */
+  public function isScopeActive($name) {
+    throw new \BadMethodCallException(sprintf("'%s' is not implemented", __FUNCTION__));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function initialized($id) {
+    return isset($this->services[$id]);
+  }
+
+}
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index c8ba628..0abb753 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -15,9 +15,11 @@
 use Drupal\Core\Config\BootstrapConfigStorageFactory;
 use Drupal\Core\Config\NullStorage;
 use Drupal\Core\Database\Database;
+use Drupal\Core\DependencyInjection\PhpArray\Container as PhpArrayContainer;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceProviderInterface;
 use Drupal\Core\DependencyInjection\YamlFileLoader;
+use Drupal\Core\DependencyInjection\Dumper\PhpArrayDumper;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\File\MimeType\MimeTypeGuesser;
 use Drupal\Core\Http\TrustedHostsRequestFactory;
@@ -29,6 +31,8 @@
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
+use Symfony\Component\DependencyInjection\Dumper\XmlDumper;
 use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
@@ -56,6 +60,45 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
   const CONTAINER_BASE_CLASS = '\Drupal\Core\DependencyInjection\Container';
 
   /**
+   * Holds the bootstrap container definition.
+   *
+   * @var array
+   */
+  protected static $bootstrapContainerDefinition = [
+    'parameters' => [],
+    'services' => [
+      'database' => [
+        'class' => 'Drupal\Core\Database\Connection',
+        'factory_class' => 'Drupal\Core\Database\Database',
+        'factory_method' => 'getConnection',
+        'arguments' => ['default'],
+      ],
+      'lock' => [
+        'class' => 'Drupal\Core\Lock\DatabaseLockBackend',
+        'arguments' => ['@database'],
+      ],
+      'serialization.phpserialize' => [
+        'class' => 'Drupal\Component\Serialization\PhpSerialize',
+      ],
+      'keyvalue' => [
+        'class' => 'Drupal\Core\KeyValueStore\KeyValueDatabaseFactory',
+        'arguments' => ['@serialization.phpserialize', '@database'],
+      ],
+      'state' => [
+        'class' => 'Drupal\Core\State\State',
+        'arguments' => array('@keyvalue'),
+      ],
+    ],
+  ];
+
+  /**
+   * Holds the boostrap container instance.
+   *
+   * @var \Symfony\Component\DependencyInjection\ContainerInterface
+   */
+  protected $bootstrapContainer;
+
+  /**
    * Holds the container instance.
    *
    * @var \Symfony\Component\DependencyInjection\ContainerInterface
@@ -430,6 +473,8 @@ public function boot() {
     FileCacheFactory::setConfiguration($configuration);
     FileCacheFactory::setPrefix(Settings::getApcuPrefix('file_cache', $this->root));
 
+    $this->bootstrapContainer = new PhpArrayContainer(Settings::get('bootstrap_container_definition', static::$bootstrapContainerDefinition));
+
     // Initialize the container.
     $this->initializeContainer();
 
@@ -735,25 +780,30 @@ protected function initializeContainer($rebuild = FALSE) {
       }
     }
 
+    //$state = $this->bootstrapContainer->get('state');
+
     // If the module list hasn't already been set in updateModules and we are
     // not forcing a rebuild, then try and load the container from the disk.
     if (empty($this->moduleList) && !$rebuild) {
-      $fully_qualified_class_name = '\\' . $this->getClassNamespace() . '\\' . $this->getClassName();
-
-      // First, try to load from storage.
-      if (!class_exists($fully_qualified_class_name, FALSE)) {
-        $this->storage()->load($this->getClassName() . '.php');
-      }
-      // If the load succeeded or the class already existed, use it.
-      if (class_exists($fully_qualified_class_name, FALSE)) {
-        $container = new $fully_qualified_class_name;
+      // @todo State service does fail tests atm. as table is not created automatically.
+      // @todo Use cache service?
+      //$container_definition = $state->get('container_definition');
+      if ($file = $this->storage()->getFullPath('container_definition.php')) {
+        $container_definition = @include $file;
+        if (!$container_definition) {
+          $container_definition = NULL;
+        }
       }
     }
 
-    if (!isset($container)) {
-      $container = $this->compileContainer();
+    if (!isset($container_definition)) {
+      $container_builder = $this->compileContainerWithLock();
+      $dumper = new PhpArrayDumper($container_builder);
+      $container_definition = $dumper->getArray();
     }
 
+    $container = new PhpArrayContainer($container_definition);
+
     $this->attachSynthetic($container);
 
     $this->container = $container;
@@ -778,7 +828,7 @@ protected function initializeContainer($rebuild = FALSE) {
     \Drupal::setContainer($this->container);
 
     // If needs dumping flag was set, dump the container.
-    if ($this->containerNeedsDumping && !$this->dumpDrupalContainer($this->container, static::CONTAINER_BASE_CLASS)) {
+    if ($this->containerNeedsDumping && !$this->cacheDrupalContainer($container_definition)) {
       $this->container->get('logger.factory')->get('DrupalKernel')->notice('Container cannot be written to disk');
     }
 
@@ -907,7 +957,7 @@ protected function initializeRequestGlobals(Request $request) {
    */
   protected function getServicesToPersist(ContainerInterface $container) {
     $persist = array();
-    foreach ($container->getParameter('persistIds') as $id) {
+    foreach ($container->getParameter('persist_ids') as $id) {
       // It's pointless to persist services not yet initialized.
       if ($container->initialized($id)) {
         $persist[$id] = $container->get($id);
@@ -968,6 +1018,16 @@ protected function attachSynthetic(ContainerInterface $container) {
   }
 
   /**
+   * Compiles a new service container using a lock.
+   *
+   * @return ContainerBuilder The compiled service container
+   */
+  protected function compileContainerWithLock() {
+    // @todo Implement lock here.
+    return $this->compileContainer();
+  }
+
+  /**
    * Compiles a new service container.
    *
    * @return ContainerBuilder The compiled service container
@@ -1057,7 +1117,7 @@ protected function compileContainer() {
         $persist_ids[] = $id;
       }
     }
-    $container->setParameter('persistIds', $persist_ids);
+    $container->setParameter('persist_ids', $persist_ids);
 
     $container->compile();
     return $container;
@@ -1091,36 +1151,24 @@ protected function getContainerBuilder() {
   }
 
   /**
-   * Dumps the service container to PHP code in the config directory.
-   *
-   * This method is based on the dumpContainer method in the parent class, but
-   * that method is reliant on the Config component which we do not use here.
-   *
-   * @param ContainerBuilder $container
-   *   The service container.
-   * @param string $baseClass
-   *   The name of the container's base class
+   * Stores the container definition in a cache.
    *
    * @return bool
-   *   TRUE if the container was successfully dumped to disk.
+   *   TRUE if the container was successfully cached.
    */
-  protected function dumpDrupalContainer(ContainerBuilder $container, $baseClass) {
+  protected function cacheDrupalContainer($container_definition) {
+    // @todo Use a cache backend - if possible.
+    // @todo State service does fail tests atm. as table is not created automatically.
+    //return $this->bootstrapContainer->get('state')->set('container_definition', $container_definition);
     if (!$this->storage()->writeable()) {
       return FALSE;
     }
-    // Cache the container.
-    $dumper = new PhpDumper($container);
-    $dumper->setProxyDumper(new ProxyDumper(new ProxyBuilder()));
-    $class = $this->getClassName();
-    $namespace = $this->getClassNamespace();
-    $content = $dumper->dump([
-      'class' => $class,
-      'base_class' => $baseClass,
-      'namespace' => $namespace,
-    ]);
-    return $this->storage()->save($class . '.php', $content);
-  }
 
+    $code = var_export($container_definition, TRUE);
+    $code = str_replace("stdClass::__set_state", "(object)", $code);
+
+    return $this->storage()->save('container_definition.php', '<?php return ' . $code . ';');
+  }
 
   /**
    * Gets a http kernel from the container
diff --git a/core/lib/Drupal/Core/Site/Settings.php b/core/lib/Drupal/Core/Site/Settings.php
index 18f55ff..63e13db 100644
--- a/core/lib/Drupal/Core/Site/Settings.php
+++ b/core/lib/Drupal/Core/Site/Settings.php
@@ -107,15 +107,17 @@ public static function getAll() {
    *   The class loader that is used for this request. Passed by reference and
    *   exposed to the local scope of settings.php, so as to allow it to be
    *   decorated with Symfony's ApcClassLoader, for example.
+   * @param array $settings
+   *   Initial settings, set by DrupalKernel.
    *
    * @see default.settings.php
    */
   public static function initialize($app_root, $site_path, &$class_loader) {
     // Export these settings.php variables to the global namespace.
     global $base_url, $config_directories, $config;
-    $settings = array();
     $config = array();
     $databases = array();
+    $settings = array();
 
     // Make conf_path() available as local variable in settings.php.
     if (is_readable($app_root . '/' . $site_path . '/settings.php')) {
diff --git a/core/modules/config/src/Tests/DefaultConfigTest.php b/core/modules/config/src/Tests/DefaultConfigTest.php
index 99ff07a..9e32a45 100644
--- a/core/modules/config/src/Tests/DefaultConfigTest.php
+++ b/core/modules/config/src/Tests/DefaultConfigTest.php
@@ -53,12 +53,12 @@ protected function setUp() {
    */
   public function containerBuild(ContainerBuilder $container) {
     parent::containerBuild($container);
-    $container->register('DefaultConfigTest.schema_storage')
+    $container->register('default_config_test.schema_storage')
       ->setClass('\Drupal\config_test\TestInstallStorage')
       ->addArgument(InstallStorage::CONFIG_SCHEMA_DIRECTORY);
 
     $definition = $container->getDefinition('config.typed');
-    $definition->replaceArgument(1, new Reference('DefaultConfigTest.schema_storage'));
+    $definition->replaceArgument(1, new Reference('default_config_test.schema_storage'));
   }
 
   /**
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index e8d1ba2..76c83f2 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -289,6 +289,7 @@ protected function tearDown() {
   public function containerBuild(ContainerBuilder $container) {
     // Keep the container object around for tests.
     $this->container = $container;
+    $this->containerBuilder = $container;
 
     // Set the default language on the minimal container.
     $this->container->setParameter('language.default_values', $this->defaultLanguageData());
@@ -298,7 +299,7 @@ public function containerBuild(ContainerBuilder $container) {
 
     $container
       ->register('config.storage', 'Drupal\Core\Config\DatabaseStorage')
-      ->addArgument(Database::getConnection())
+      ->addArgument(new Reference('database'))
       ->addArgument('config');
 
     if ($this->strictConfigSchema) {
@@ -312,6 +313,7 @@ public function containerBuild(ContainerBuilder $container) {
     $keyvalue_options['default'] = 'keyvalue.memory';
     $container->setParameter('factory.keyvalue', $keyvalue_options);
     $container->set('keyvalue.memory', $this->keyValueFactory);
+    $container->register('keyvalue.memory', 'Drupal\Core\KeyValueStore\KeyValueMemoryFactory')->setSynthetic(TRUE);
     if (!$container->has('keyvalue')) {
       // TestBase::setUp puts a completely empty container in
       // $this->container which is somewhat the mirror of the empty
@@ -511,6 +513,10 @@ protected function enableModules(array $modules) {
     $module_filenames = $module_handler->getModuleList();
     $this->kernel->updateModules($module_filenames, $module_filenames);
 
+    // Get a fresh container, because ::containerBuild set $this->container to
+    // the active container builder, but that is no longer the active container.
+    $this->container = $this->kernel->getContainer();
+
     // Ensure isLoaded() is TRUE in order to make _theme() work.
     // Note that the kernel has rebuilt the container; this $module_handler is
     // no longer the $module_handler instance from above.
diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php
index 9078d39..1179296 100644
--- a/core/modules/simpletest/src/TestBase.php
+++ b/core/modules/simpletest/src/TestBase.php
@@ -277,6 +277,13 @@
   protected $container;
 
   /**
+   * The dependency injection container builder used in the test.
+   *
+   * @var \Symfony\Component\DependencyInjection\ContainerBuilder
+   */
+  protected $containerBuilder;
+
+  /**
    * The config importer that can used in a test.
    *
    * @var \Drupal\Core\Config\ConfigImporter
diff --git a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
index ab6c224..0be7b60 100644
--- a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
@@ -98,9 +98,7 @@ public function testCompileDIC() {
     $kernel = $this->getTestKernel($request);
     $container = $kernel->getContainer();
     $refClass = new \ReflectionClass($container);
-    $is_compiled_container =
-      $refClass->getParentClass()->getName() == 'Drupal\Core\DependencyInjection\Container' &&
-      !$refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder');
+    $is_compiled_container = !$refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder');
     $this->assertTrue($is_compiled_container);
     // Verify that the list of modules is the same for the initial and the
     // compiled container.
@@ -113,9 +111,7 @@ public function testCompileDIC() {
       ->getContainer();
 
     $refClass = new \ReflectionClass($container);
-    $is_compiled_container =
-      $refClass->getParentClass()->getName() == 'Drupal\Core\DependencyInjection\Container' &&
-      !$refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder');
+    $is_compiled_container = !$refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder');
     $this->assertTrue($is_compiled_container);
 
     // Verify that the list of modules is the same for the initial and the
@@ -146,7 +142,7 @@ public function testCompileDIC() {
 
     $refClass = new \ReflectionClass($container);
     $is_container_builder = $refClass->isSubclassOf('Symfony\Component\DependencyInjection\ContainerBuilder');
-    $this->assertTrue($is_container_builder, 'Container is a builder');
+    $this->assertFalse($is_container_builder, 'Container is not a builder');
 
     // Assert that the new module's bundle was registered to the new container.
     $this->assertTrue($container->has('service_provider_test_class'), 'Container has test service');
diff --git a/core/modules/system/src/Tests/HttpKernel/StackKernelIntegrationTest.php b/core/modules/system/src/Tests/HttpKernel/StackKernelIntegrationTest.php
index 3096310..4e9feee 100644
--- a/core/modules/system/src/Tests/HttpKernel/StackKernelIntegrationTest.php
+++ b/core/modules/system/src/Tests/HttpKernel/StackKernelIntegrationTest.php
@@ -53,19 +53,19 @@ public function testRequest() {
    * Tests that late middlewares are automatically flagged lazy.
    */
   public function testLazyLateMiddlewares() {
-    $this->assertFalse($this->container->getDefinition('http_middleware.reverse_proxy')->isLazy(), 'lazy flag on http_middleware.reverse_proxy definition is not set');
-    $this->assertFalse($this->container->getDefinition('http_middleware.kernel_pre_handle')->isLazy(), 'lazy flag on http_middleware.kernel_pre_handle definition is not set');
-    $this->assertFalse($this->container->getDefinition('http_middleware.session')->isLazy(), 'lazy flag on http_middleware.session definition is not set');
-    $this->assertFalse($this->container->getDefinition('http_kernel.basic')->isLazy(), 'lazy flag on http_kernel.basic definition is not set');
+    $this->assertFalse($this->containerBuilder->getDefinition('http_middleware.reverse_proxy')->isLazy(), 'lazy flag on http_middleware.reverse_proxy definition is not set');
+    $this->assertFalse($this->containerBuilder->getDefinition('http_middleware.kernel_pre_handle')->isLazy(), 'lazy flag on http_middleware.kernel_pre_handle definition is not set');
+    $this->assertFalse($this->containerBuilder->getDefinition('http_middleware.session')->isLazy(), 'lazy flag on http_middleware.session definition is not set');
+    $this->assertFalse($this->containerBuilder->getDefinition('http_kernel.basic')->isLazy(), 'lazy flag on http_kernel.basic definition is not set');
 
     \Drupal::service('module_installer')->install(['page_cache']);
     $this->container = $this->kernel->rebuildContainer();
 
-    $this->assertFalse($this->container->getDefinition('http_middleware.reverse_proxy')->isLazy(), 'lazy flag on http_middleware.reverse_proxy definition is not set');
-    $this->assertFalse($this->container->getDefinition('http_middleware.page_cache')->isLazy(), 'lazy flag on http_middleware.page_cache definition is not set');
-    $this->assertTrue($this->container->getDefinition('http_middleware.kernel_pre_handle')->isLazy(), 'lazy flag on http_middleware.kernel_pre_handle definition is automatically set if page_cache is enabled.');
-    $this->assertTrue($this->container->getDefinition('http_middleware.session')->isLazy(), 'lazy flag on http_middleware.session definition is automatically set if page_cache is enabled.');
-    $this->assertTrue($this->container->getDefinition('http_kernel.basic')->isLazy(), 'lazy flag on http_kernel.basic definition is automatically set if page_cache is enabled.');
+    $this->assertFalse($this->containerBuilder->getDefinition('http_middleware.reverse_proxy')->isLazy(), 'lazy flag on http_middleware.reverse_proxy definition is not set');
+    $this->assertFalse($this->containerBuilder->getDefinition('http_middleware.page_cache')->isLazy(), 'lazy flag on http_middleware.page_cache definition is not set');
+    $this->assertTrue($this->containerBuilder->getDefinition('http_middleware.kernel_pre_handle')->isLazy(), 'lazy flag on http_middleware.kernel_pre_handle definition is automatically set if page_cache is enabled.');
+    $this->assertTrue($this->containerBuilder->getDefinition('http_middleware.session')->isLazy(), 'lazy flag on http_middleware.session definition is automatically set if page_cache is enabled.');
+    $this->assertTrue($this->containerBuilder->getDefinition('http_kernel.basic')->isLazy(), 'lazy flag on http_kernel.basic definition is automatically set if page_cache is enabled.');
   }
 
 }
diff --git a/core/modules/system/src/Tests/ServiceProvider/ServiceProviderTest.php b/core/modules/system/src/Tests/ServiceProvider/ServiceProviderTest.php
index 9b67692..53b5a00 100644
--- a/core/modules/system/src/Tests/ServiceProvider/ServiceProviderTest.php
+++ b/core/modules/system/src/Tests/ServiceProvider/ServiceProviderTest.php
@@ -27,7 +27,9 @@ class ServiceProviderTest extends WebTestBase {
    * Tests that services provided by module service providers get registered to the DIC.
    */
   function testServiceProviderRegistration() {
-    $this->assertTrue(\Drupal::getContainer()->getDefinition('file.usage')->getClass() == 'Drupal\\service_provider_test\\TestFileUsage', 'Class has been changed');
+    // @todo This wants to test the container builder, but that is not available at run-time.
+    $definition = \Drupal::getContainer()->getDefinition('file.usage');
+    $this->assertTrue($definition['class'] == 'Drupal\\service_provider_test\\TestFileUsage', 'Class has been changed');
     $this->assertTrue(\Drupal::hasService('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
diff --git a/core/modules/system/tests/modules/form_test/form_test.routing.yml b/core/modules/system/tests/modules/form_test/form_test.routing.yml
index 140b17c..8a200a3 100644
--- a/core/modules/system/tests/modules/form_test/form_test.routing.yml
+++ b/core/modules/system/tests/modules/form_test/form_test.routing.yml
@@ -15,7 +15,7 @@ form_test.route2:
 form_test.route3:
   path: '/form-test/object-service-builder'
   defaults:
-    _form: 'form_test.form.serviceForm'
+    _form: 'form_test.form.serviceform'
   requirements:
     _access: 'TRUE'
 
diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/ContainerBuilderTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/ContainerBuilderTest.php
index 8a93b6d..295587a 100644
--- a/core/tests/Drupal/Tests/Core/DependencyInjection/ContainerBuilderTest.php
+++ b/core/tests/Drupal/Tests/Core/DependencyInjection/ContainerBuilderTest.php
@@ -38,4 +38,14 @@ public function testSet() {
     $this->assertEquals('bar', $class->_serviceId);
   }
 
+  /**
+   * @covers ::setParameter
+   * @expectedException \InvalidArgumentException
+   * @expectedExceptionMessage Parameter names must be lowercase: Buzz
+   */
+  public function testSetParameter() {
+    $container = new ContainerBuilder();
+    $container->setParameter('Buzz', 'buzz');
+  }
+
 }
diff --git a/core/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php b/core/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php
index 0a78967..cd40934 100644
--- a/core/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php
+++ b/core/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php
@@ -30,6 +30,8 @@ class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
      */
     public function process(ContainerBuilder $container)
     {
+// @todo Remove compiler pass via getPasses() / setPasses().
+return;
         $parameterBag = $container->getParameterBag();
 
         foreach ($container->getDefinitions() as $id => $definition) {
