diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
index 15924c3..c3b6994 100644
--- a/core/lib/Drupal/Core/CoreServiceProvider.php
+++ b/core/lib/Drupal/Core/CoreServiceProvider.php
@@ -22,6 +22,7 @@
 use Drupal\Core\DependencyInjection\Compiler\RegisterStringTranslatorsPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterBreadcrumbBuilderPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterAuthenticationPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterTwigExtensionsPass;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\DependencyInjection\Definition;
@@ -74,6 +75,8 @@ public function register(ContainerBuilder $container) {
     $container->addCompilerPass(new ModifyServiceDefinitionsPass());
     // Add the compiler pass that will process tagged authentication services.
     $container->addCompilerPass(new RegisterAuthenticationPass());
+    // Register Twig extensions.
+    $container->addCompilerPass(new RegisterTwigExtensionsPass());
   }
 
   /**
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterTwigExtensionsPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterTwigExtensionsPass.php
new file mode 100644
index 0000000..66fbb86
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterTwigExtensionsPass.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\DependencyInjection\Compiler\RegisterTwigExtensionsPass.
+ */
+
+namespace Drupal\Core\DependencyInjection\Compiler;
+
+use InvalidArgumentException;
+use ReflectionClass;
+use Twig_Extension;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+/**
+ * Register additional Twig extensions to the Twig service container.
+ */
+class RegisterTwigExtensionsPass implements CompilerPassInterface {
+
+  /**
+   * Adds services tagged 'twig.extension' to the Twig service container.
+   *
+   * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
+   *   The container to process.
+   */
+  public function process(ContainerBuilder $container) {
+    if (!$container->hasDefinition('twig')) {
+      return;
+    }
+
+    $definition = $container->getDefinition('twig');
+
+    foreach ($container->findTaggedServiceIds('twig.extension') as $id => $attributes) {
+      // We must assume that the class value has been correcly filled,
+      // even if the service is created by a factory.
+      $class = $container->getDefinition($id)->getClass();
+
+      $refClass = new ReflectionClass($class);
+      $interface = 'Twig_ExtensionInterface';
+      if (!$refClass->implementsInterface($interface)) {
+        throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
+      }
+      $definition->addMethodCall('addExtension', array(new Reference($id)));
+    }
+  }
+
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigExtensionTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigExtensionTest.php
new file mode 100644
index 0000000..3d7ae7e
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigExtensionTest.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Theme\TwigExtensionTest.
+ */
+
+namespace Drupal\system\Tests\Theme;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests Twig extensions.
+ */
+class TwigExtensionTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('theme_test', 'twig_theme_test', 'twig_extension_test');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Twig Extension',
+      'description' => 'Tests Twig extensions.',
+      'group' => 'Theme',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    theme_enable(array('test_theme'));
+  }
+
+  /**
+   * Tests that the provided Twig extension loads the service appropriately.
+   */
+  function testTwigExtensionLoaded() {
+    $twigService = \Drupal::service('twig');
+    $ext = $twigService->getExtension('twig_extension_test.test_extension');
+    $this->assertEqual(
+      get_class($ext),
+      'Drupal\twig_extension_test\TwigExtension\TestExtension',
+      'TestExtension loaded successfully.'
+    );
+  }
+
+  /**
+   * Tests that the Twig extension's filter produces expected output.
+   */
+  function testTwigExtensionFilter() {
+    config('system.theme')
+      ->set('default', 'test_theme')
+      ->save();
+
+    $this->drupalGet('twig-extension-test/filter');
+    $this->assertText(
+      'Every plant is not a mineral.',
+      'Success: String filtered.'
+    );
+  }
+
+  /**
+   * Tests that the Twig extension's function produces expected output.
+   */
+  function testTwigExtensionFunction() {
+    config('system.theme')
+      ->set('default', 'test_theme')
+      ->save();
+
+    $out = $this->drupalGet('twig-extension-test/function');
+    $this->assertText(
+      'THE QUICK BROWN BOX JUMPS OVER THE LAZY DOG 123.',
+      'Success: Text converted to uppercase.'
+    );
+    $this->assertText(
+      'the quick brown box jumps over the lazy dog 123.',
+      'Success: Text converted to lowercase.'
+    );
+    $this->assertNoText(
+      'The Quick Brown Fox Jumps Over The Lazy Dog 123.',
+      'Success: No text left behind.'
+    );
+  }
+
+}
diff --git a/core/modules/system/tests/modules/twig_extension_test/lib/Drupal/twig_extension_test/TwigExtension/TestExtension.php b/core/modules/system/tests/modules/twig_extension_test/lib/Drupal/twig_extension_test/TwigExtension/TestExtension.php
new file mode 100644
index 0000000..bda959f
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_extension_test/lib/Drupal/twig_extension_test/TwigExtension/TestExtension.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\twig_extension_test\TwigExtension\TestExtension.
+ */
+
+namespace Drupal\twig_extension_test\TwigExtension;
+
+use Drupal\Core\Template\TwigExtension;
+use Drupal\Core\Template\TwigReferenceFunction;
+
+/**
+ * A test Twig extension that adds a custom function and a custom filter.
+ */
+class TestExtension extends TwigExtension {
+
+  /**
+   * Generates a list of all Twig functions that this extension defines.
+   *
+   * @return array
+   *   A key/value array that defines custom Twig functions. The key denotes the
+   *   function name used in the tag, e.g.:
+   *   @code
+   *   {{ testfunc() }}
+   *   @endcode
+   *
+   *   The value is a standard PHP callback that defines what the function does.
+   */
+  public function getFunctions() {
+    return array(
+      'testfunc' => new \Twig_Function_Function(
+        array('Drupal\twig_extension_test\TwigExtension\TestExtension', 'testFunction')
+      ),
+    );
+  }
+
+  /**
+   * Generates a list of all Twig filters that this extension defines.
+   *
+   * @return array
+   *   A key/value array that defines custom Twig filters. The key denotes the
+   *   filter name used in the tag, e.g.:
+   *   @code
+   *   {{ foo|testfilter }}
+   *   @endcode
+   *
+   *   The value is a standard PHP callback that defines what the filter does.
+   */
+  public function getFilters() {
+    return array(
+      'testfilter' => new \Twig_Filter_Function(
+        array('Drupal\twig_extension_test\TwigExtension\TestExtension', 'testFilter')
+      ),
+    );
+  }
+
+  /**
+   * Gets a unique identifier for this Twig extension.
+   *
+   * @return string
+   *   A unique identifier for this Twig extension.
+   */
+  public function getName() {
+    return 'twig_extension_test.test_extension';
+  }
+
+  /**
+   * Outputs either an uppercase or lowercase test phrase.
+   *
+   * The function generates either an uppercase or lowercase version of the
+   * phrase "The quick brown fox jumps over the lazy dog 123.", depending on
+   * whether or not the $upperCase parameter evaluates to TRUE. If $upperCase
+   * evaluates to TRUE, the result will be uppercase, and if it evaluates to
+   * FALSE, the result will be lowercase.
+   *
+   * @param bool $upperCase
+   *   (optional) Whether the result is uppercase (true) or lowercase (false).
+   * @return string
+   *   The generated string.
+   *
+   * @see \Drupal\system\Tests\Theme\TwigExtensionTest::testTwigExtensionFunction()
+   */
+  public static function testFunction($upperCase = FALSE) {
+    $string = "The quick brown box jumps over the lazy dog 123.";
+    if ($upperCase == TRUE) {
+      return strtoupper($string);
+    }
+    else {
+      return strtolower($string);
+    }
+  }
+
+  /**
+   * Replaces all instances of "animal" in a string with "plant".
+   *
+   * @param string $string
+   *   The string to be filtered.
+   * @return string
+   *   The filtered string.
+   *
+   * @see \Drupal\system\Tests\Theme\TwigExtensionTest::testTwigExtensionFilter()
+   */
+  public static function testFilter($string) {
+    return str_replace(array('animal'), array('plant'), $string);
+  }
+
+}
diff --git a/core/modules/system/tests/modules/twig_extension_test/lib/Drupal/twig_extension_test/TwigExtensionTestController.php b/core/modules/system/tests/modules/twig_extension_test/lib/Drupal/twig_extension_test/TwigExtensionTestController.php
new file mode 100644
index 0000000..aa772b8
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_extension_test/lib/Drupal/twig_extension_test/TwigExtensionTestController.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\twig_extension_test\TwigExtensionTestController.
+ */
+
+namespace Drupal\twig_extension_test;
+
+use Drupal\Core\ControllerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Controller routines for Twig theme test routes.
+ */
+class TwigExtensionTestController implements ControllerInterface {
+
+  /**
+   * Creates the controller.
+   */
+  public static function create(ContainerInterface $container) {
+    return new static();
+  }
+
+  /**
+   * Menu callback for testing Twig filters in a Twig template.
+   */
+  public function testFilterRender() {
+    return theme('twig_extension_test_filter', array(
+      'message' => 'Every animal is not a mineral.',
+    ));
+  }
+
+  /**
+   * Menu callback for testing Twig functions in a Twig template.
+   */
+  public function testFunctionRender() {
+    return theme('twig_extension_test_function');
+  }
+
+}
diff --git a/core/modules/system/tests/modules/twig_extension_test/templates/twig_extension_test.filter.html.twig b/core/modules/system/tests/modules/twig_extension_test/templates/twig_extension_test.filter.html.twig
new file mode 100644
index 0000000..1e224d0
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_extension_test/templates/twig_extension_test.filter.html.twig
@@ -0,0 +1,3 @@
+<div class="testfilter">
+  {{ message|testfilter }}
+</div>
diff --git a/core/modules/system/tests/modules/twig_extension_test/templates/twig_extension_test.function.html.twig b/core/modules/system/tests/modules/twig_extension_test/templates/twig_extension_test.function.html.twig
new file mode 100644
index 0000000..76e870f
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_extension_test/templates/twig_extension_test.function.html.twig
@@ -0,0 +1,7 @@
+<div class="testfunction">
+  {{ testfunc(1) }}
+</div>
+
+<div class="testfunction">
+  {{ testfunc(0) }}
+</div>
diff --git a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.info.yml b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.info.yml
new file mode 100644
index 0000000..270352f
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.info.yml
@@ -0,0 +1,7 @@
+name: 'Twig Extension Test'
+type: module
+description: 'Support module for testing Twig extensions.'
+package: Testing
+version: VERSION
+core: 8.x
+hidden: true
diff --git a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.module b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.module
new file mode 100644
index 0000000..ae3723a
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.module
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * Implements hook_theme().
+ */
+function twig_extension_test_theme($existing, $type, $theme, $path) {
+  return array(
+    'twig_extension_test_filter' => array(
+      'variables' => array('message' => NULL),
+      'template' => 'twig_extension_test.filter',
+    ),
+    'twig_extension_test_function' => array(
+      'template' => 'twig_extension_test.function',
+    ),
+  );
+}
+
diff --git a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.routing.yml b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.routing.yml
new file mode 100644
index 0000000..8d4bace
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.routing.yml
@@ -0,0 +1,12 @@
+twig_extension_test.filter:
+  pattern: '/twig-extension-test/filter'
+  defaults:
+    _content: '\Drupal\twig_extension_test\TwigExtensionTestController::testFilterRender'
+  requirements:
+    _permission: 'access content'
+twig_extension_test.function:
+  pattern: '/twig-extension-test/function'
+  defaults:
+    _content: '\Drupal\twig_extension_test\TwigExtensionTestController::testFunctionRender'
+  requirements:
+    _permission: 'access content'
diff --git a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml
new file mode 100644
index 0000000..8784c0f
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml
@@ -0,0 +1,5 @@
+services:
+  twig_extension_test.twig.test_extension:
+    class: Drupal\twig_extension_test\TwigExtension\TestExtension
+    tags:
+      - { name: twig.extension }
