diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index fd3b719..746e2fb 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2499,6 +2499,16 @@ function drupal_container(Container $new_container = NULL, $rebuild = FALSE) {
     $container
       ->register('config.storage.staging', 'Drupal\Core\Config\FileStorage')
       ->addArgument(config_get_config_directory(CONFIG_STAGING_DIRECTORY));
+
+    // A call to url() could happen before the kernel gets initialized, so we
+    // need to have the path_aliaser service in place.
+    // @todo Remove this once hook_init is firing after kernel boot.
+    $container->register('database', 'Drupal\Core\Database\Connection')
+      ->setFactoryClass('Drupal\Core\Database\Database')
+      ->setFactoryMethod('getConnection')
+      ->addArgument('default');
+    $container->register('path.alias_manager', 'Drupal\Core\Path\AliasManager')
+      ->addArgument(new Reference('database'));
   }
   return $container;
 }
diff --git a/core/includes/common.inc b/core/includes/common.inc
index aceaac8..c86dd01 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2187,7 +2187,7 @@ function url($path = NULL, array $options = array()) {
   }
   elseif (!empty($path) && !$options['alias']) {
     $langcode = isset($options['language']) && isset($options['language']->langcode) ? $options['language']->langcode : '';
-    $alias = drupal_get_path_alias($original_path, $langcode);
+    $alias = drupal_container()->get('path.alias_manager')->getPathAlias($original_path, $langcode);
     if ($alias != $original_path) {
       $path = $alias;
     }
@@ -4908,9 +4908,6 @@ function _drupal_bootstrap_full($skip = FALSE) {
   // current_path().
   drupal_language_initialize();
 
-  // Initialize current_path() prior to invoking hook_init().
-  drupal_path_initialize();
-
   // Let all modules take action before the menu system handles the request.
   // We do not want this while running update.php.
   if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') {
diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index 8574dbe..27bb2de 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -2985,7 +2985,7 @@ function _menu_delete_item($item, $force = FALSE) {
  * @param $item
  *   An associative array representing a menu link item, with elements:
  *   - link_path: (required) The path of the menu item, which should be
- *     normalized first by calling drupal_get_normal_path() on it.
+ *     normalized first by calling drupal_container()->get('path.alias_manager')->getSystemPath() on it.
  *   - link_title: (required) Title to appear in menu for the link.
  *   - menu_name: (optional) The machine name of the menu for the link.
  *     Defaults to 'navigation'.
diff --git a/core/includes/path.inc b/core/includes/path.inc
index 07aeee5..d5fcfbb 100644
--- a/core/includes/path.inc
+++ b/core/includes/path.inc
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Functions to handle paths in Drupal, including path aliasing.
+ * Functions to handle paths in Drupal.
  *
  * These functions are not loaded for cached pages, but modules that need
  * to use them in hook_boot() or hook exit() can make them available, by
@@ -10,289 +10,6 @@
  */
 
 /**
- * Initializes the current path to the proper normal path.
- */
-function drupal_path_initialize() {
-  // At this point, the current path is either the request path (due to
-  // drupal_environment_initialize()) or some modified version of it due to
-  // other bootstrap code (e.g., language negotiation), but it has not yet been
-  // normalized by drupal_get_normal_path().
-  $path = _current_path();
-
-  // If on the front page, resolve to the front page path, including for calls
-  // to current_path() while drupal_get_normal_path() is in progress.
-  if (empty($path)) {
-    $path = config('system.site')->get('page.front');
-    _current_path($path);
-  }
-
-  // Normalize the path.
-  _current_path(drupal_get_normal_path($path));
-}
-
-/**
- * Given an alias, return its Drupal system URL if one exists. Given a Drupal
- * system URL return one of its aliases if such a one exists. Otherwise,
- * return FALSE.
- *
- * @param $action
- *   One of the following values:
- *   - wipe: delete the alias cache.
- *   - alias: return an alias for a given Drupal system path (if one exists).
- *   - source: return the Drupal system URL for a path alias (if one exists).
- * @param $path
- *   The path to investigate for corresponding aliases or system URLs.
- * @param $langcode
- *   Optional language code to search the path with. Defaults to the page language.
- *   If there's no path defined for that language it will search paths without
- *   language.
- *
- * @return
- *   Either a Drupal system path, an aliased path, or FALSE if no path was
- *   found.
- */
-function drupal_lookup_path($action, $path = '', $langcode = NULL) {
-  // Use the advanced drupal_static() pattern, since this is called very often.
-  static $drupal_static_fast;
-  if (!isset($drupal_static_fast)) {
-    $drupal_static_fast['cache'] = &drupal_static(__FUNCTION__);
-  }
-  $cache = &$drupal_static_fast['cache'];
-
-  if (!isset($cache)) {
-    $cache = array(
-      'map' => array(),
-      'no_source' => array(),
-      'whitelist' => NULL,
-      'system_paths' => array(),
-      'no_aliases' => array(),
-      'first_call' => TRUE,
-    );
-  }
-
-  // Retrieve the path alias whitelist.
-  if (!isset($cache['whitelist'])) {
-    $cache['whitelist'] = variable_get('path_alias_whitelist', NULL);
-    if (!isset($cache['whitelist'])) {
-      $cache['whitelist'] = drupal_path_alias_whitelist_rebuild();
-    }
-  }
-
-  // If no language is explicitly specified we default to the current URL
-  // language. If we used a language different from the one conveyed by the
-  // requested URL, we might end up being unable to check if there is a path
-  // alias matching the URL path.
-  $langcode = $langcode ? $langcode : language(LANGUAGE_TYPE_URL)->langcode;
-
-  if ($action == 'wipe') {
-    $cache = array();
-    $cache['whitelist'] = drupal_path_alias_whitelist_rebuild();
-  }
-  elseif ($cache['whitelist'] && $path != '') {
-    if ($action == 'alias') {
-      // During the first call to drupal_lookup_path() per language, load the
-      // expected system paths for the page from cache.
-      if (!empty($cache['first_call'])) {
-        $cache['first_call'] = FALSE;
-
-        $cache['map'][$langcode] = array();
-        // Load system paths from cache.
-        $cid = current_path();
-        if ($cached = cache('path')->get($cid)) {
-          $cache['system_paths'] = $cached->data;
-          // Now fetch the aliases corresponding to these system paths.
-          $args = array(
-            ':system' => $cache['system_paths'],
-            ':langcode' => $langcode,
-            ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED,
-          );
-          // Always get the language-specific alias before the language-neutral
-          // one. For example 'de' is less than 'und' so the order needs to be
-          // ASC, while 'xx-lolspeak' is more than 'und' so the order needs to
-          // be DESC. We also order by pid ASC so that fetchAllKeyed() returns
-          // the most recently created alias for each source. Subsequent queries
-          // using fetchField() must use pid DESC to have the same effect.
-          // For performance reasons, the query builder is not used here.
-          if ($langcode == LANGUAGE_NOT_SPECIFIED) {
-            // Prevent PDO from complaining about a token the query doesn't use.
-            unset($args[':langcode']);
-            $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode = :langcode_undetermined ORDER BY pid ASC', $args);
-          }
-          elseif ($langcode < LANGUAGE_NOT_SPECIFIED) {
-            $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid ASC', $args);
-          }
-          else {
-            $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid ASC', $args);
-          }
-          $cache['map'][$langcode] = $result->fetchAllKeyed();
-          // Keep a record of paths with no alias to avoid querying twice.
-          $cache['no_aliases'][$langcode] = array_flip(array_diff_key($cache['system_paths'], array_keys($cache['map'][$langcode])));
-        }
-      }
-      // If the alias has already been loaded, return it.
-      if (isset($cache['map'][$langcode][$path])) {
-        return $cache['map'][$langcode][$path];
-      }
-      // Check the path whitelist, if the top_level part before the first /
-      // is not in the list, then there is no need to do anything further,
-      // it is not in the database.
-      elseif (!isset($cache['whitelist'][strtok($path, '/')])) {
-        return FALSE;
-      }
-      // For system paths which were not cached, query aliases individually.
-      elseif (!isset($cache['no_aliases'][$langcode][$path])) {
-        $args = array(
-          ':source' => $path,
-          ':langcode' => $langcode,
-          ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED,
-        );
-        // See the queries above.
-        if ($langcode == LANGUAGE_NOT_SPECIFIED) {
-          unset($args[':langcode']);
-          $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode = :langcode_undetermined ORDER BY pid DESC", $args)->fetchField();
-        }
-        elseif ($langcode > LANGUAGE_NOT_SPECIFIED) {
-          $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args)->fetchField();
-        }
-        else {
-          $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args)->fetchField();
-        }
-        $cache['map'][$langcode][$path] = $alias;
-        return $alias;
-      }
-    }
-    // Check $no_source for this $path in case we've already determined that there
-    // isn't a path that has this alias
-    elseif ($action == 'source' && !isset($cache['no_source'][$langcode][$path])) {
-      // Look for the value $path within the cached $map
-      $source = FALSE;
-      if (!isset($cache['map'][$langcode]) || !($source = array_search($path, $cache['map'][$langcode]))) {
-        $args = array(
-          ':alias' => $path,
-          ':langcode' => $langcode,
-          ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED,
-        );
-        // See the queries above.
-        if ($langcode == LANGUAGE_NOT_SPECIFIED) {
-          unset($args[':langcode']);
-          $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode = :langcode_undetermined ORDER BY pid DESC", $args);
-        }
-        elseif ($langcode > LANGUAGE_NOT_SPECIFIED) {
-          $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args);
-        }
-        else {
-          $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args);
-        }
-        if ($source = $result->fetchField()) {
-          $cache['map'][$langcode][$source] = $path;
-        }
-        else {
-          // We can't record anything into $map because we do not have a valid
-          // index and there is no need because we have not learned anything
-          // about any Drupal path. Thus cache to $no_source.
-          $cache['no_source'][$langcode][$path] = TRUE;
-        }
-      }
-      return $source;
-    }
-  }
-
-  return FALSE;
-}
-
-/**
- * Cache system paths for a page.
- *
- * Cache an array of the system paths available on each page. We assume
- * that aliases will be needed for the majority of these paths during
- * subsequent requests, and load them in a single query during
- * drupal_lookup_path().
- */
-function drupal_cache_system_paths() {
-  // Check if the system paths for this page were loaded from cache in this
-  // request to avoid writing to cache on every request.
-  $cache = &drupal_static('drupal_lookup_path', array());
-  if (empty($cache['system_paths']) && !empty($cache['map'])) {
-
-    // @todo Because we are not within the request scope at this time, we cannot
-    //   use current_path(), which would give us the system path to use as the
-    //   key. Instead we call _current_path(), which may give us the alias
-    //   instead. However, at lookup time the system path will be used as the
-    //   key, because it uses current_path(), and so it will be a cache miss.
-    //   There is a critical issue for fixing the path alias logic here:
-    //   http://drupal.org/node/1269742
-
-    // Generate a cache ID (cid) specifically for this page.
-    $cid = _current_path();
-    // The static $map array used by drupal_lookup_path() includes all
-    // system paths for the page request.
-    if ($paths = current($cache['map'])) {
-      $data = array_keys($paths);
-      $expire = REQUEST_TIME + (60 * 60 * 24);
-      cache('path')->set($cid, $data, $expire);
-    }
-  }
-}
-
-/**
- * Given an internal Drupal path, return the alias set by the administrator.
- *
- * If no path is provided, the function will return the alias of the current
- * page.
- *
- * @param $path
- *   An internal Drupal path.
- * @param $langcode
- *   An optional language code to look up the path in.
- *
- * @return
- *   An aliased path if one was found, or the original path if no alias was
- *   found.
- */
-function drupal_get_path_alias($path = NULL, $langcode = NULL) {
-  // If no path is specified, use the current page's path.
-  if ($path == NULL) {
-    $path = current_path();
-  }
-  $result = $path;
-  if ($alias = drupal_lookup_path('alias', $path, $langcode)) {
-    $result = $alias;
-  }
-  return $result;
-}
-
-/**
- * Given a path alias, return the internal path it represents.
- *
- * @param $path
- *   A Drupal path alias.
- * @param $langcode
- *   An optional language code to look up the path in.
- *
- * @return
- *   The internal path represented by the alias, or the original alias if no
- *   internal path was found.
- */
-function drupal_get_normal_path($path, $langcode = NULL) {
-  $original_path = $path;
-
-  // Lookup the path alias first.
-  if ($source = drupal_lookup_path('source', $path, $langcode)) {
-    $path = $source;
-  }
-
-  // Allow other modules to alter the inbound URL. We cannot use drupal_alter()
-  // here because we need to run hook_url_inbound_alter() in the reverse order
-  // of hook_url_outbound_alter().
-  foreach (array_reverse(module_implements('url_inbound_alter')) as $module) {
-    $function = $module . '_url_inbound_alter';
-    $function($path, $original_path, $langcode);
-  }
-
-  return $path;
-}
-
-/**
  * Check if the current page is the front page.
  *
  * @return
@@ -379,125 +96,6 @@ function current_path() {
 }
 
 /**
- * Rebuild the path alias white list.
- *
- * @param $source
- *   An optional system path for which an alias is being inserted.
- *
- * @return
- *   An array containing a white list of path aliases.
- */
-function drupal_path_alias_whitelist_rebuild($source = NULL) {
-  // When paths are inserted, only rebuild the whitelist if the system path
-  // has a top level component which is not already in the whitelist.
-  if (!empty($source)) {
-    $whitelist = variable_get('path_alias_whitelist', NULL);
-    if (isset($whitelist[strtok($source, '/')])) {
-      return $whitelist;
-    }
-  }
-  // For each alias in the database, get the top level component of the system
-  // path it corresponds to. This is the portion of the path before the first
-  // '/', if present, otherwise the whole path itself.
-  $whitelist = array();
-  $result = db_query("SELECT DISTINCT SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias}");
-  foreach ($result as $row) {
-    $whitelist[$row->path] = TRUE;
-  }
-  variable_set('path_alias_whitelist', $whitelist);
-  return $whitelist;
-}
-
-/**
- * Fetch a specific URL alias from the database.
- *
- * @param $conditions
- *   A string representing the source, a number representing the pid, or an
- *   array of query conditions.
- *
- * @return
- *   FALSE if no alias was found or an associative array containing the
- *   following keys:
- *   - source: The internal system path.
- *   - alias: The URL alias.
- *   - pid: Unique path alias identifier.
- *   - langcode: The language code of the alias.
- */
-function path_load($conditions) {
-  if (is_numeric($conditions)) {
-    $conditions = array('pid' => $conditions);
-  }
-  elseif (is_string($conditions)) {
-    $conditions = array('source' => $conditions);
-  }
-  elseif (!is_array($conditions)) {
-    return FALSE;
-  }
-  $select = db_select('url_alias');
-  foreach ($conditions as $field => $value) {
-    $select->condition($field, $value);
-  }
-  return $select
-    ->fields('url_alias')
-    ->execute()
-    ->fetchAssoc();
-}
-
-/**
- * Save a path alias to the database.
- *
- * @param $path
- *   An associative array containing the following keys:
- *   - source: The internal system path.
- *   - alias: The URL alias.
- *   - pid: (optional) Unique path alias identifier.
- *   - langcode: (optional) The language code of the alias.
- */
-function path_save(&$path) {
-  $path += array('langcode' => LANGUAGE_NOT_SPECIFIED);
-
-  // Load the stored alias, if any.
-  if (!empty($path['pid']) && !isset($path['original'])) {
-    $path['original'] = path_load($path['pid']);
-  }
-
-  if (empty($path['pid'])) {
-    drupal_write_record('url_alias', $path);
-    module_invoke_all('path_insert', $path);
-  }
-  else {
-    drupal_write_record('url_alias', $path, array('pid'));
-    module_invoke_all('path_update', $path);
-  }
-
-  // Clear internal properties.
-  unset($path['original']);
-
-  // Clear the static alias cache.
-  drupal_clear_path_cache($path['source']);
-}
-
-/**
- * Delete a URL alias.
- *
- * @param $criteria
- *   A number representing the pid or an array of criteria.
- */
-function path_delete($criteria) {
-  if (!is_array($criteria)) {
-    $criteria = array('pid' => $criteria);
-  }
-  $path = path_load($criteria);
-  $query = db_delete('url_alias');
-  foreach ($criteria as $field => $value) {
-    $query->condition($field, $value);
-  }
-  $query->execute();
-  module_invoke_all('path_delete', $path);
-  drupal_clear_path_cache($path['source']);
-}
-
-/**
  * Determine whether a path is in the administrative section of the site.
  *
  * By default, paths are considered to be non-administrative. If a path does not
@@ -597,14 +195,3 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) {
   return $item && $item['access'];
 }
 
-/**
- * Clear the path cache.
- *
- * @param $source
- *   An optional system path for which an alias is being changed.
- */
-function drupal_clear_path_cache($source = NULL) {
-  // Clear the drupal_lookup_path() static cache.
-  drupal_static_reset('drupal_lookup_path');
-  drupal_path_alias_whitelist_rebuild($source);
-}
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index 4ad6726..850a650 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -52,17 +52,23 @@ class CoreBundle extends Bundle
       ->setFactoryClass('Drupal\Core\Database\Database')
       ->setFactoryMethod('getConnection')
       ->addArgument('slave');
+    $container->register('path.alias_manager', 'Drupal\Core\Path\AliasManager')
+      ->addArgument(new Reference('database'));
+    $container->register('path.crud', 'Drupal\Core\Path\Path')
+      ->addArgument(new Reference('database'))
+      ->addArgument(new Reference('path.alias_manager'));
 
     // @todo Replace below lines with the commented out block below it when it's
     //   performant to do so: http://drupal.org/node/1706064.
     $dispatcher = $container->get('dispatcher');
     $matcher = new \Drupal\Core\LegacyUrlMatcher();
     $content_negotation = new \Drupal\Core\ContentNegotiation();
+    $alias_manager = $container->get('path.alias_manager');
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\RouterListener($matcher));
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\ViewSubscriber($content_negotation));
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\AccessSubscriber());
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\MaintenanceModeSubscriber());
-    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\PathSubscriber());
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\PathSubscriber($alias_manager));
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\LegacyRequestSubscriber());
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\LegacyControllerSubscriber());
     $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\FinishResponseSubscriber());
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
index 7688107..631b770 100644
--- a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
@@ -7,8 +7,10 @@
 
 namespace Drupal\Core\EventSubscriber;
 
+use Drupal\Core\Path\AliasManagerInterface;
 use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\PostResponseEvent;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -16,25 +18,30 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  */
 class PathSubscriber extends PathListenerBase implements EventSubscriberInterface {
 
+  protected $alias_manager;
+
+  public function __construct(AliasManagerInterface $alias_manager) {
+    $this->alias_manager = $alias_manager;
+  }
+
   /**
    * Resolve the system path.
    *
-   * @todo The path system should be objectified to remove the function calls in
-   *   this method.
-   *
    * @param Symfony\Component\HttpKernel\Event\GetResponseEvent $event
    *   The Event to process.
    */
   public function onKernelRequestPathResolve(GetResponseEvent $event) {
     $request = $event->getRequest();
-
     $path = $this->extractPath($request);
-
-    $path = drupal_get_normal_path($path);
-
+    $path = $this->alias_manager->getSystemPath($path);
+    $this->alias_manager->startRequest($path);
     $this->setPath($request, $path);
   }
 
+  public function onKernelTerminate(PostResponseEvent $event) {
+    $this->alias_manager->endRequest();
+  }
+
   /**
    * Resolve the front-page default path.
    *
@@ -116,6 +123,7 @@ class PathSubscriber extends PathListenerBase implements EventSubscriberInterfac
     $events[KernelEvents::REQUEST][] = array('onKernelRequestLanguageResolve', 150);
     $events[KernelEvents::REQUEST][] = array('onKernelRequestFrontPageResolve', 101);
     $events[KernelEvents::REQUEST][] = array('onKernelRequestPathResolve', 100);
+    $events[KernelEvents::TERMINATE][] = array('onKernelTerminate', 200);
 
     return $events;
   }
diff --git a/core/lib/Drupal/Core/EventSubscriber/RequestCloseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RequestCloseSubscriber.php
index 175ce79..8d5f87a 100644
--- a/core/lib/Drupal/Core/EventSubscriber/RequestCloseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/RequestCloseSubscriber.php
@@ -29,7 +29,6 @@ class RequestCloseSubscriber implements EventSubscriberInterface {
    */
   public function onTerminate(PostResponseEvent $event) {
     module_invoke_all('exit');
-    drupal_cache_system_paths();
     module_implements_write_cache();
     system_run_automated_cron();
   }
@@ -41,7 +40,7 @@ class RequestCloseSubscriber implements EventSubscriberInterface {
    *   An array of event listener definitions.
    */
   static function getSubscribedEvents() {
-    $events[KernelEvents::TERMINATE][] = array('onTerminate');
+    $events[KernelEvents::TERMINATE][] = array('onTerminate', 100);
 
     return $events;
   }
diff --git a/core/lib/Drupal/Core/ExceptionController.php b/core/lib/Drupal/Core/ExceptionController.php
index 20c9ec2..20ae3ae 100644
--- a/core/lib/Drupal/Core/ExceptionController.php
+++ b/core/lib/Drupal/Core/ExceptionController.php
@@ -102,7 +102,7 @@ class ExceptionController extends ContainerAware {
     $system_path = $request->attributes->get('system_path');
     watchdog('access denied', $system_path, array(), WATCHDOG_WARNING);
 
-    $path = drupal_get_normal_path(config('system.site')->get('page.403'));
+    $path = $this->container->get('path.alias_manager')->getSystemPath(config('system.site')->get('page.403'));
     if ($path && $path != $system_path) {
       // Keep old path for reference, and to allow forms to redirect to it.
       if (!isset($_GET['destination'])) {
@@ -168,7 +168,7 @@ class ExceptionController extends ContainerAware {
       $_GET['destination'] = $system_path;
     }
 
-    $path = drupal_get_normal_path(config('system.site')->get('page.404'));
+    $path = drupal_container()->get('path.alias_manager')->getSystemPath(config('system.site')->get('page.404'));
     if ($path && $path != $system_path) {
       // @todo Um, how do I specify an override URL again? Totally not clear. Do
       //   that and sub-call the kernel rather than using meah().
diff --git a/core/lib/Drupal/Core/Path/AliasManager.php b/core/lib/Drupal/Core/Path/AliasManager.php
new file mode 100644
index 0000000..f58dbdf
--- /dev/null
+++ b/core/lib/Drupal/Core/Path/AliasManager.php
@@ -0,0 +1,291 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Path\AliasManager.
+ */
+
+namespace Drupal\Core\Path;
+
+use Drupal\Core\Database\Connection;
+
+class AliasManager implements AliasManagerInterface {
+
+  protected $lookup_cache = array();
+
+  protected $request_paths = array();
+
+  public function __construct(Connection $connection) {
+    $this->connection = $connection;
+  }
+
+  /**
+   * Implements \Drupal\Core\Path\AliasManagerInterface::startRequest().
+   */
+  public function startRequest($path) {
+    $this->request_paths[] = $path;
+  }
+
+  /**
+   * Implements \Drupal\Core\Path\AliasManagerInterface::getSystemPath().
+   */
+  public function getSystemPath($path, $path_language = NULL) {
+    $original_path = $path;
+    // Lookup the path alias first.
+    if ($source = $this->lookupPath('source', $path, $path_language)) {
+      $path = $source;
+    }
+
+    return $path;
+  }
+
+  /**
+   * Implements \Drupal\Core\Path\AliasManagerInterface::getPathAlias().
+   */
+  public function getPathAlias($path = NULL, $path_language = NULL) {
+    // If no path is specified, use the current page's path.
+    if ($path === NULL) {
+      $path = _current_path();
+    }
+    $result = $path;
+    if ($alias = $this->lookupPath('alias', $path, $path_language)) {
+      $result = $alias;
+    }
+    return $result;
+  }
+
+  /**
+   * Implements \Drupal\Core\Path\AliasManagerInterface::endRequest().
+   */
+  public function endRequest() {
+    $this->cacheSystemPaths();
+    // We are at the end of the request, so pop off the last request path.
+    array_pop($this->request_paths);
+  }
+
+  /**
+   * Cache system paths for a page.
+   *
+   * Cache an array of the system paths available on each page. We assume
+   * that aliases will be needed for the majority of these paths during
+   * subsequent requests, and load them in a single query during path alias
+   * lookup.
+   */
+  protected function cacheSystemPaths() {
+    // Check if the system paths for this page were loaded from cache in this
+    // request to avoid writing to cache on every request.
+    if (empty($this->lookup_cache['system_paths']) && !empty($this->lookup_cache['map']) && !empty($this->request_paths)) {
+      // Use the system path of the current request for the cache ID (cid).
+      $cid = end($this->request_paths);
+      // The $map array includes all system paths for the page request.
+      if ($paths = current($this->lookup_cache['map'])) {
+        $data = array_keys($paths);
+        $expire = REQUEST_TIME + (60 * 60 * 24);
+        cache('path')->set($cid, $data, $expire);
+      }
+    }
+  }
+
+  /**
+   * Implements \Drupal\Core\Path\AliasManagerInterface::cacheClear().
+   */
+  public function cacheClear($source = NULL) {
+    $this->lookup_cache = array();
+    $this->pathAliasWhitelistRebuild($source);
+  }
+
+  /**
+   * Given an alias, return its Drupal system URL if one exists. Given a Drupal
+   * system URL return one of its aliases if such a one exists. Otherwise,
+   * return FALSE.
+   *
+   * @param $action
+   *   One of the following values:
+   *   - wipe: delete the alias cache.
+   *   - alias: return an alias for a given Drupal system path (if one exists).
+   *   - source: return the Drupal system URL for a path alias (if one exists).
+   * @param $path
+   *   The path to investigate for corresponding aliases or system URLs.
+   * @param $langcode
+   *   Optional language code to search the path with. Defaults to the page language.
+   *   If there's no path defined for that language it will search paths without
+   *   language.
+   *
+   * @return
+   *   Either a Drupal system path, an aliased path, or FALSE if no path was
+   *   found.
+   */
+  protected function lookupPath($action, $path = '', $langcode = NULL) {
+
+    if (empty($this->lookup_cache)) {
+      $this->lookup_cache = array(
+        'map' => array(),
+        'no_source' => array(),
+        'whitelist' => NULL,
+        'system_paths' => array(),
+        'no_aliases' => array(),
+        'first_call' => TRUE,
+      );
+    }
+
+    // Retrieve the path alias whitelist.
+    if (!isset($this->lookup_cache['whitelist'])) {
+      $this->lookup_cache['whitelist'] = variable_get('path_alias_whitelist', NULL);
+      if (!isset($this->lookup_cache['whitelist'])) {
+        $this->lookup_cache['whitelist'] = $this->pathAliasWhitelistRebuild();
+      }
+    }
+
+    // If no language is explicitly specified we default to the current URL
+    // language. If we used a language different from the one conveyed by the
+    // requested URL, we might end up being unable to check if there is a path
+    // alias matching the URL path.
+    if (!$langcode) {
+      $langcode = language(LANGUAGE_TYPE_URL)->langcode;
+    }
+
+    if ($action == 'wipe') {
+      $this->lookup_cache = array();
+      $this->lookup_cache['whitelist'] = $this->pathAliasWhitelistRebuild();
+    }
+    elseif ($this->lookup_cache['whitelist'] && $path != '') {
+      if ($action == 'alias') {
+        // During the first call to this function per language, load the expected
+        // system paths for the page from cache.
+        if (!empty($this->lookup_cache['first_call'])) {
+          $this->lookup_cache['first_call'] = FALSE;
+
+          $this->lookup_cache['map'][$langcode] = array();
+          // Load system paths from cache.
+          if (!empty($this->request_paths) && $cached = cache('path')->get(end($this->request_paths))) {
+            $this->lookup_cache['system_paths'] = $cached->data;
+            // Now fetch the aliases corresponding to these system paths.
+            $args = array(
+              ':system' => $this->lookup_cache['system_paths'],
+              ':langcode' => $langcode,
+              ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED,
+            );
+            // Always get the language-specific alias before the language-neutral
+            // one. For example 'de' is less than 'und' so the order needs to be
+            // ASC, while 'xx-lolspeak' is more than 'und' so the order needs to
+            // be DESC. We also order by pid ASC so that fetchAllKeyed() returns
+            // the most recently created alias for each source. Subsequent queries
+            // using fetchField() must use pid DESC to have the same effect.
+            // For performance reasons, the query builder is not used here.
+            if ($langcode == LANGUAGE_NOT_SPECIFIED) {
+              // Prevent PDO from complaining about a token the query doesn't use.
+              unset($args[':langcode']);
+              $result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode = :langcode_undetermined ORDER BY pid ASC', $args);
+            }
+            elseif ($langcode < LANGUAGE_NOT_SPECIFIED) {
+              $result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid ASC', $args);
+            }
+            else {
+              $result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid ASC', $args);
+            }
+            $this->lookup_cache['map'][$langcode] = $result->fetchAllKeyed();
+            // Keep a record of paths with no alias to avoid querying twice.
+            $this->lookup_cache['no_aliases'][$langcode] = array_flip(array_diff_key($this->lookup_cache['system_paths'], array_keys($this->lookup_cache['map'][$langcode])));
+          }
+        }
+        // If the alias has already been loaded, return it.
+        if (isset($this->lookup_cache['map'][$langcode][$path])) {
+          return $this->lookup_cache['map'][$langcode][$path];
+        }
+        // Check the path whitelist, if the top-level part before the first /
+        // is not in the list, then there is no need to do anything further,
+        // it is not in the database.
+        elseif (!isset($this->lookup_cache['whitelist'][strtok($path, '/')])) {
+          return FALSE;
+        }
+        // For system paths which were not cached, query aliases individually.
+        elseif (!isset($this->lookup_cache['no_aliases'][$langcode][$path])) {
+          $args = array(
+            ':source' => $path,
+            ':langcode' => $langcode,
+            ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED,
+          );
+          // See the queries above.
+          if ($langcode == LANGUAGE_NOT_SPECIFIED) {
+            unset($args[':langcode']);
+            $alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode = :langcode_undetermined ORDER BY pid DESC", $args)->fetchField();
+          }
+          elseif ($langcode > LANGUAGE_NOT_SPECIFIED) {
+            $alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args)->fetchField();
+          }
+          else {
+            $alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args)->fetchField();
+          }
+          $this->lookup_cache['map'][$langcode][$path] = $alias;
+          return $alias;
+        }
+      }
+      // Check $no_source for this $path in case we've already determined that there
+      // isn't a path that has this alias
+      elseif ($action == 'source' && !isset($this->lookup_cache['no_source'][$langcode][$path])) {
+        // Look for the value $path within the cached $map
+        $source = FALSE;
+        if (!isset($this->lookup_cache['map'][$langcode]) || !($source = array_search($path, $this->lookup_cache['map'][$langcode]))) {
+          $args = array(
+            ':alias' => $path,
+            ':langcode' => $langcode,
+            ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED,
+          );
+          // See the queries above.
+          if ($langcode == LANGUAGE_NOT_SPECIFIED) {
+            unset($args[':langcode']);
+            $result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode = :langcode_undetermined ORDER BY pid DESC", $args);
+          }
+          elseif ($langcode > LANGUAGE_NOT_SPECIFIED) {
+            $result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args);
+          }
+          else {
+            $result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args);
+          }
+          if ($source = $result->fetchField()) {
+            $this->lookup_cache['map'][$langcode][$source] = $path;
+          }
+          else {
+            // We can't record anything into $map because we do not have a valid
+            // index and there is no need because we have not learned anything
+            // about any Drupal path. Thus cache to $no_source.
+            $this->lookup_cache['no_source'][$langcode][$path] = TRUE;
+          }
+        }
+        return $source;
+      }
+    }
+
+    return FALSE;
+  }
+
+  /**
+   * Rebuild the path alias white list.
+   *
+   * @param $source
+   *   An optional system path for which an alias is being inserted.
+   *
+   * @return
+   *   An array containing a white list of path aliases.
+   */
+  protected function pathAliasWhitelistRebuild($source = NULL) {
+    // When paths are inserted, only rebuild the whitelist if the system path
+    // has a top level component which is not already in the whitelist.
+    if (!empty($source)) {
+      $whitelist = variable_get('path_alias_whitelist', NULL);
+      if (isset($whitelist[strtok($source, '/')])) {
+        return $whitelist;
+      }
+    }
+    // For each alias in the database, get the top level component of the system
+    // path it corresponds to. This is the portion of the path before the first
+    // '/', if present, otherwise the whole path itself.
+    $whitelist = array();
+    $result = $this->connection->query("SELECT DISTINCT SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias}");
+    foreach ($result as $row) {
+      $whitelist[$row->path] = TRUE;
+    }
+    variable_set('path_alias_whitelist', $whitelist);
+    return $whitelist;
+  }
+}
diff --git a/core/lib/Drupal/Core/Path/AliasManagerInterface.php b/core/lib/Drupal/Core/Path/AliasManagerInterface.php
new file mode 100644
index 0000000..c4a4b1f
--- /dev/null
+++ b/core/lib/Drupal/Core/Path/AliasManagerInterface.php
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Path\AliasManagerInterface.
+ */
+
+namespace Drupal\Core\Path;
+
+interface AliasManagerInterface {
+
+  /**
+   * Called by the PathSubscriber at the start of a request.
+   *
+   * @param $path
+   *   The system path for the current request.
+   */
+  public function startRequest($path);
+
+  /**
+   * Given a path alias, return the internal path it represents.
+   *
+   * @param $path
+   *   A Drupal path alias.
+   * @param $path_language
+   *   An optional language code to look up the path in.
+   *
+   * @return
+   *   The internal path represented by the alias, or the original alias if no
+   *   internal path was found.
+   */
+  public function getSystemPath($path, $path_language = NULL);
+
+  /**
+   * Given an internal Drupal path, return the alias set by the administrator.
+   *
+   * If no path is provided, the function will return the alias of the current
+   * page.
+   *
+   * @param $path
+   *   An optional internal Drupal path.
+   * @param $path_language
+   *   An optional language code to look up the path in.
+   *
+   * @return
+   *   An aliased path if one was found, or the original path if no alias was
+   *   found.
+   */
+  public function getPathAlias($path = NULL, $path_language = NULL);
+
+  /**
+   * Clear the path cache.
+   *
+   * @param $source
+   *   An optional system path for which an alias is being changed.
+   */
+  public function cacheClear($source = NULL);
+
+  /**
+   * Called by the PathSubscriber at the end of a request.
+   */
+  public function endRequest();
+
+}
diff --git a/core/lib/Drupal/Core/Path/Path.php b/core/lib/Drupal/Core/Path/Path.php
new file mode 100644
index 0000000..8c795d4
--- /dev/null
+++ b/core/lib/Drupal/Core/Path/Path.php
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Path\Path.
+ */
+
+namespace Drupal\Core\Path;
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Database\Connection;
+
+class Path {
+
+  protected $connection;
+
+  public function __construct(Connection $connection, AliasManager $alias_manager) {
+    $this->connection = $connection;
+    $this->alias_manager = $alias_manager;
+  }
+
+  public function save($source, $alias, $langcode = LANGUAGE_NOT_SPECIFIED, $pid = NULL) {
+
+    $fields = array(
+      'source' => $source,
+      'alias' => $alias,
+      'langcode' => $langcode,
+    );
+
+    // Insert or update the alias.
+    if (empty($pid)) {
+      $query = $this->connection->insert('url_alias', array('return' => Database::RETURN_INSERT_ID))
+        ->fields($fields);
+    }
+    else {
+      $fields['pid'] = $pid;
+      $query = $this->connection->update('url_alias')
+        ->fields($fields)
+        ->condition('pid', $pid);
+    }
+    if ($pid = $query->execute()) {
+      $fields['pid'] = $pid;
+      $this->alias_manager->cacheClear();
+      return $fields;
+    }
+    return FALSE;
+  }
+
+  public function load($conditions) {
+    if (is_numeric($conditions)) {
+      $conditions = array('pid' => $conditions);
+    }
+    elseif (is_string($conditions)) {
+      $conditions = array('source' => $conditions);
+    }
+    elseif (!is_array($conditions)) {
+      return FALSE;
+    }
+    $select = $this->connection->select('url_alias');
+    foreach ($conditions as $field => $value) {
+      $select->condition($field, $value);
+    }
+    return $select
+      ->fields('url_alias')
+      ->execute()
+      ->fetchAssoc();
+  }
+
+  public function delete($conditions) {
+    if (!is_array($conditions)) {
+      $conditions = array('pid' => $conditions);
+    }
+    $path = $this->load($conditions);
+    $query = $this->connection->delete('url_alias');
+    foreach ($conditions as $field => $value) {
+      $query->condition($field, $value);
+    }
+    $deleted = $query->execute();
+    $this->alias_manager->cacheClear();
+    // @todo: figure out where we can invoke hook_path_delete()
+    return $deleted;
+  }
+}
+
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 0626c08..8462c11 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -851,7 +851,7 @@ function block_block_list_alter(&$blocks) {
       if ($block->visibility < BLOCK_VISIBILITY_PHP) {
         // Compare the lowercase path alias (if any) and internal path.
         $path = current_path();
-        $path_alias = drupal_strtolower(drupal_get_path_alias($path));
+        $path_alias = drupal_strtolower(drupal_container()->get('path.alias_manager')->getPathAlias($path));
         $page_match = drupal_match_path($path_alias, $pages) || (($path != $path_alias) && drupal_match_path($path, $pages));
         // When $block->visibility has a value of 0 (BLOCK_VISIBILITY_NOTLISTED),
         // the block is displayed on all pages except those listed in $block->pages.
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php
index bafb620..d1ad5f0 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php
@@ -109,13 +109,13 @@ class LocalePathTest extends WebTestBase {
       'alias'    => $custom_path,
       'langcode' => LANGUAGE_NOT_SPECIFIED,
     );
-    path_save($edit);
-    $lookup_path = drupal_lookup_path('alias', 'node/' . $node->nid, 'en');
+    drupal_container()->get('path.crud')->save($edit['source'], $edit['alias'], $edit['langcode']);
+    $lookup_path = drupal_container()->get('path.alias_manager')->getPathAlias('node/' . $node->nid, 'en');
     $this->assertEqual($english_path, $lookup_path, t('English language alias has priority.'));
     // Same check for language 'xx'.
-    $lookup_path = drupal_lookup_path('alias', 'node/' . $node->nid, $prefix);
+    $lookup_path = drupal_container()->get('path.alias_manager')->getPathAlias('node/' . $node->nid, $prefix);
     $this->assertEqual($custom_language_path, $lookup_path, t('Custom language alias has priority.'));
-    path_delete($edit);
+    drupal_container()->get('path.crud')->delete($edit);
 
     // Create language nodes to check priority of aliases.
     $first_node = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1));
@@ -127,7 +127,7 @@ class LocalePathTest extends WebTestBase {
       'alias'    => $custom_path,
       'langcode' => 'en',
     );
-    path_save($edit);
+    drupal_container()->get('path.crud')->save($edit['source'], $edit['alias'], $edit['langcode']);
 
     // Assign a custom path alias to second node with LANGUAGE_NOT_SPECIFIED.
     $edit = array(
@@ -135,7 +135,7 @@ class LocalePathTest extends WebTestBase {
       'alias'    => $custom_path,
       'langcode' => LANGUAGE_NOT_SPECIFIED,
     );
-    path_save($edit);
+    drupal_container()->get('path.crud')->save($edit['source'], $edit['alias'], $edit['langcode']);
 
     // Test that both node titles link to our path alias.
     $this->drupalGet('<front>');
diff --git a/core/modules/menu/menu.admin.inc b/core/modules/menu/menu.admin.inc
index fc38caa..3e168dc 100644
--- a/core/modules/menu/menu.admin.inc
+++ b/core/modules/menu/menu.admin.inc
@@ -392,7 +392,7 @@ function menu_edit_item($form, &$form_state, $type, $item, $menu) {
  */
 function menu_edit_item_validate($form, &$form_state) {
   $item = &$form_state['values'];
-  $normal_path = drupal_get_normal_path($item['link_path']);
+  $normal_path = drupal_container()->get('path.alias_manager')->getSystemPath($item['link_path']);
   if ($item['link_path'] != $normal_path) {
     drupal_set_message(t('The menu system stores system paths only, but will use the URL alias for display. %link_path has been stored as %normal_path', array('%link_path' => $item['link_path'], '%normal_path' => $normal_path)));
     $item['link_path'] = $normal_path;
diff --git a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php
index dcaf945..1be60d4 100644
--- a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php
+++ b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php
@@ -57,9 +57,7 @@ class PathAliasTest extends PathTestBase {
     // Visit the alias for the node and confirm a cache entry is created.
     cache('path')->flush();
     $this->drupalGet($edit['alias']);
-    // @todo The alias should actually have been cached with the system path as
-    // the key, see the todo in drupal_cache_system_paths() in path.inc.
-    $this->assertTrue(cache('path')->get($edit['alias']), t('Cache entry was created.'));
+    $this->assertTrue(cache('path')->get($edit['source']), t('Cache entry was created.'));
   }
 
   /**
@@ -94,7 +92,7 @@ class PathAliasTest extends PathTestBase {
     $this->assertText($node1->label(), 'Changed alias works.');
     $this->assertResponse(200);
 
-    drupal_static_reset('drupal_lookup_path');
+    drupal_container()->get('path.alias_manager')->cacheClear();
     // Confirm that previous alias no longer works.
     $this->drupalGet($previous);
     $this->assertNoText($node1->label(), 'Previous alias no longer works.');
diff --git a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php
index f9aa0de..36c284c 100644
--- a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php
+++ b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php
@@ -78,7 +78,7 @@ class PathLanguageTest extends PathTestBase {
     $this->drupalPost(NULL, $edit, t('Save'));
 
     // Clear the path lookup cache.
-    drupal_lookup_path('wipe');
+    drupal_container()->get('path.alias_manager')->cacheClear();
 
     // Ensure the node was created.
     $french_node = $this->drupalGetNodeByTitle($edit["title"]);
@@ -117,7 +117,7 @@ class PathLanguageTest extends PathTestBase {
     // We need to ensure that the user language preference is not taken into
     // account while determining the path alias language, because if this
     // happens we have no way to check that the path alias is valid: there is no
-    // path alias for French matching the english alias. So drupal_lookup_path()
+    // path alias for French matching the english alias. So the alias manager
     // needs to use the URL language to check whether the alias is valid.
     $this->drupalGet($english_alias);
     $this->assertText($english_node->label(), 'Alias for English translation works.');
@@ -141,20 +141,20 @@ class PathLanguageTest extends PathTestBase {
     $this->drupalGet($french_alias);
     $this->assertResponse(404, t('Alias for French translation is unavailable when URL language negotiation is disabled.'));
 
-    // drupal_lookup_path() has an internal static cache. Check to see that
+    // The alias manager has an internal path lookup cache. Check to see that
     // it has the appropriate contents at this point.
-    drupal_lookup_path('wipe');
-    $french_node_path = drupal_lookup_path('source', $french_alias, $french_node->langcode);
+    drupal_container()->get('path.alias_manager')->cacheClear();
+    $french_node_path = drupal_container()->get('path.alias_manager')->getSystemPath($french_alias, $french_node->langcode);
     $this->assertEqual($french_node_path, 'node/' . $french_node->nid, t('Normal path works.'));
     // Second call should return the same path.
-    $french_node_path = drupal_lookup_path('source', $french_alias, $french_node->langcode);
+    $french_node_path = drupal_container()->get('path.alias_manager')->getSystemPath($french_alias, $french_node->langcode);
     $this->assertEqual($french_node_path, 'node/' . $french_node->nid, t('Normal path is the same.'));
 
     // Confirm that the alias works.
-    $french_node_alias = drupal_lookup_path('alias', 'node/' . $french_node->nid, $french_node->langcode);
+    $french_node_alias = drupal_container()->get('path.alias_manager')->getPathAlias('node/' . $french_node->nid, $french_node->langcode);
     $this->assertEqual($french_node_alias, $french_alias, t('Alias works.'));
     // Second call should return the same alias.
-    $french_node_alias = drupal_lookup_path('alias', 'node/' . $french_node->nid, $french_node->langcode);
+    $french_node_alias = drupal_container()->get('path.alias_manager')->getPathAlias('node/' . $french_node->nid, $french_node->langcode);
     $this->assertEqual($french_node_alias, $french_alias, t('Alias is the same.'));
   }
 }
diff --git a/core/modules/path/path.admin.inc b/core/modules/path/path.admin.inc
index 4188eff..9cccd67 100644
--- a/core/modules/path/path.admin.inc
+++ b/core/modules/path/path.admin.inc
@@ -76,7 +76,7 @@ function path_admin_overview($keys = NULL) {
 
     // If the system path maps to a different URL alias, highlight this table
     // row to let the user know of old aliases.
-    if ($data->alias != drupal_get_path_alias($data->source, $data->langcode)) {
+    if ($data->alias != drupal_container()->get('path.alias_manager')->getPathAlias($data->source, $data->langcode)) {
       $row['class'] = array('warning');
     }
 
@@ -218,7 +218,7 @@ function path_admin_form_delete_submit($form, &$form_state) {
  */
 function path_admin_form_validate($form, &$form_state) {
   $source = &$form_state['values']['source'];
-  $source = drupal_get_normal_path($source);
+  $source = drupal_container()->get('path.alias_manager')->getSystemPath($source);
   $alias = $form_state['values']['alias'];
   $pid = isset($form_state['values']['pid']) ? $form_state['values']['pid'] : 0;
   // Language is only set if language.module is enabled, otherwise save for all
@@ -250,7 +250,15 @@ function path_admin_form_submit($form, &$form_state) {
   // Remove unnecessary values.
   form_state_values_clean($form_state);
 
-  path_save($form_state['values']);
+  $pid = isset($form_state['values']['pid']) ? $form_state['values']['pid'] : 0;
+  $source = &$form_state['values']['source'];
+  $source = drupal_container()->get('path.alias_manager')->getSystemPath($source);
+  $alias = $form_state['values']['alias'];
+  // Language is only set if language.module is enabled, otherwise save for all
+  // languages.
+  $langcode = isset($form_state['values']['langcode']) ? $form_state['values']['langcode'] : LANGUAGE_NOT_SPECIFIED;
+
+  drupal_container()->get('path.crud')->save($source, $alias, $langcode, $pid);
 
   drupal_set_message(t('The alias has been saved.'));
   $form_state['redirect'] = 'admin/config/search/path';
@@ -282,7 +290,7 @@ function path_admin_delete_confirm($form, &$form_state, $path) {
  */
 function path_admin_delete_confirm_submit($form, &$form_state) {
   if ($form_state['values']['confirm']) {
-    path_delete($form_state['path']['pid']);
+    drupal_container()->get('path.crud')->delete($form_state['path']['pid']);
     $form_state['redirect'] = 'admin/config/search/path';
   }
 }
diff --git a/core/modules/path/path.api.php b/core/modules/path/path.api.php
index f2c5ece..c69b97d 100644
--- a/core/modules/path/path.api.php
+++ b/core/modules/path/path.api.php
@@ -20,7 +20,7 @@
  *   - pid: Unique path alias identifier.
  *   - langcode: The language code of the alias.
  *
- * @see path_save()
+ * @see \Drupal\Core\Path\Path::save()
  */
 function hook_path_insert($path) {
   db_insert('mytable')
@@ -41,7 +41,7 @@ function hook_path_insert($path) {
  *   - pid: Unique path alias identifier.
  *   - langcode: The language code of the alias.
  *
- * @see path_save()
+ * @see \Drupal\Core\Path\Path::save()
  */
 function hook_path_update($path) {
   db_update('mytable')
@@ -60,7 +60,7 @@ function hook_path_update($path) {
  *   - pid: Unique path alias identifier.
  *   - langcode: The language code of the alias.
  *
- * @see path_delete()
+ * @see \Drupal\Core\Path\Path::delete()
  */
 function hook_path_delete($path) {
   db_delete('mytable')
diff --git a/core/modules/path/path.module b/core/modules/path/path.module
index 6a69c13..32c0dfb 100644
--- a/core/modules/path/path.module
+++ b/core/modules/path/path.module
@@ -107,7 +107,7 @@ function path_form_node_form_alter(&$form, $form_state) {
     if ($node->langcode != LANGUAGE_NOT_SPECIFIED) {
       $conditions['langcode'] = $node->langcode;
     }
-    $path = path_load($conditions);
+    $path = drupal_container()->get('path.crud')->load($conditions);
     if ($path === FALSE) {
       $path = array();
     }
@@ -190,14 +190,13 @@ function path_form_element_validate($element, &$form_state, $complete_form) {
  */
 function path_node_insert(Node $node) {
   if (isset($node->path)) {
-    $path = $node->path;
-    $path['alias'] = trim($path['alias']);
+    $alias = trim($node->path['alias']);
     // Only save a non-empty alias.
-    if (!empty($path['alias'])) {
+    if (!empty($alias)) {
       // Ensure fields for programmatic executions.
-      $path['source'] = 'node/' . $node->nid;
-      $path['langcode'] = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED;
-      path_save($path);
+      $source = 'node/' . $node->nid;
+      $langcode = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED;
+      drupal_container()->get('path.crud')->save($source, $alias, $langcode);
     }
   }
 }
@@ -208,17 +207,17 @@ function path_node_insert(Node $node) {
 function path_node_update(Node $node) {
   if (isset($node->path)) {
     $path = $node->path;
-    $path['alias'] = trim($path['alias']);
+    $alias = trim($path['alias']);
     // Delete old alias if user erased it.
     if (!empty($path['pid']) && empty($path['alias'])) {
-      path_delete($path['pid']);
+      drupal_container()->get('path.crud')->delete($path['pid']);
     }
     // Only save a non-empty alias.
     if (!empty($path['alias'])) {
       // Ensure fields for programmatic executions.
-      $path['source'] = 'node/' . $node->nid;
-      $path['langcode'] = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED;
-      path_save($path);
+      $source = 'node/' . $node->nid;
+      $langcode = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED;
+      drupal_container()->get('path.crud')->save($source, $alias, $langcode, $path['pid']);
     }
   }
 }
@@ -228,7 +227,7 @@ function path_node_update(Node $node) {
  */
 function path_node_predelete(Node $node) {
   // Delete all aliases associated with this node.
-  path_delete(array('source' => 'node/' . $node->nid));
+  drupal_container()->get('path.crud')->delete(array('source' => 'node/' . $node->nid));
 }
 
 /**
@@ -238,7 +237,7 @@ function path_form_taxonomy_term_form_alter(&$form, $form_state) {
   // Make sure this does not show up on the delete confirmation form.
   if (empty($form_state['confirm_delete'])) {
     $term = $form_state['controller']->getEntity($form_state);
-    $path = (isset($term->tid) ? path_load('taxonomy/term/' . $term->tid) : array());
+    $path = (isset($term->tid) ? drupal_container()->get('path.crud')->load('taxonomy/term/' . $term->tid) : array());
     if ($path === FALSE) {
       $path = array();
     }
@@ -279,7 +278,7 @@ function path_taxonomy_term_insert(Term $term) {
       // Ensure fields for programmatic executions.
       $path['source'] = 'taxonomy/term/' . $term->tid;
       $path['langcode'] = LANGUAGE_NOT_SPECIFIED;
-      path_save($path);
+      drupal_container()->get('path.crud')->save($path['source'], $path['alias'], $path['langcode']);
     }
   }
 }
@@ -293,14 +292,14 @@ function path_taxonomy_term_update(Term $term) {
     $path['alias'] = trim($path['alias']);
     // Delete old alias if user erased it.
     if (!empty($path['pid']) && empty($path['alias'])) {
-      path_delete($path['pid']);
+      drupal_container()->get('path.crud')->delete($path['pid']);
     }
     // Only save a non-empty alias.
     if (!empty($path['alias'])) {
       // Ensure fields for programmatic executions.
       $path['source'] = 'taxonomy/term/' . $term->tid;
       $path['langcode'] = LANGUAGE_NOT_SPECIFIED;
-      path_save($path);
+      drupal_container()->get('path.crud')->save($path['source'], $path['alias'], $path['langcode']);
     }
   }
 }
@@ -310,7 +309,7 @@ function path_taxonomy_term_update(Term $term) {
  */
 function path_taxonomy_term_delete(Term $term) {
   // Delete all aliases associated with this term.
-  path_delete(array('source' => 'taxonomy/term/' . $term->tid));
+  drupal_container()->get('path.crud')->delete(array('source' => 'taxonomy/term/' . $term->tid));
 }
 
 /**
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index 315ae7a..723e75d 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -643,7 +643,7 @@ function search_index($sid, $module, $text, $langcode) {
         if ($tagname == 'a') {
           // Check if link points to a node on this site
           if (preg_match($node_regexp, $value, $match)) {
-            $path = drupal_get_normal_path($match[1]);
+            $path = drupal_container()->get('path.alias_manager')->getSystemPath($match[1]);
             if (preg_match('!(?:node|book)/(?:view/)?([0-9]+)!i', $path, $match)) {
               $linknid = $match[1];
               if ($linknid > 0) {
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php
index 9ee094b..937074b 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php
@@ -31,7 +31,7 @@ class ShortcutLinksTest extends ShortcutTestBase {
       'source' => 'node/' . $this->node->nid,
       'alias' => $this->randomName(8),
     );
-    path_save($path);
+    drupal_container()->get('path.crud')->save($path['source'], $path['alias']);
 
     // Create some paths to test.
     $test_cases = array(
@@ -54,7 +54,7 @@ class ShortcutLinksTest extends ShortcutTestBase {
       $saved_set = shortcut_set_load($set->set_name);
       $paths = $this->getShortcutInformation($saved_set, 'link_path');
       $test_path = empty($test['path']) ? '<front>' : $test['path'];
-      $this->assertTrue(in_array(drupal_get_normal_path($test_path), $paths), 'Shortcut created: '. $test['path']);
+      $this->assertTrue(in_array(drupal_container()->get('path.alias_manager')->getSystemPath($test_path), $paths), 'Shortcut created: '. $test['path']);
       $this->assertLink($title, 0, 'Shortcut link found on the page.');
     }
   }
diff --git a/core/modules/shortcut/shortcut.admin.inc b/core/modules/shortcut/shortcut.admin.inc
index ca5d936..c79b68d 100644
--- a/core/modules/shortcut/shortcut.admin.inc
+++ b/core/modules/shortcut/shortcut.admin.inc
@@ -409,7 +409,7 @@ function _shortcut_link_form_elements($shortcut_link = NULL) {
     );
   }
   else {
-    $shortcut_link['link_path'] = ($shortcut_link['link_path'] == '<front>') ? '' : drupal_get_path_alias($shortcut_link['link_path']);
+    $shortcut_link['link_path'] = ($shortcut_link['link_path'] == '<front>') ? '' : drupal_container()->get('path.alias_manager')->getPathAlias($shortcut_link['link_path']);
   }
 
   $form['shortcut_link']['#tree'] = TRUE;
@@ -456,7 +456,7 @@ function shortcut_link_edit_validate($form, &$form_state) {
  */
 function shortcut_link_edit_submit($form, &$form_state) {
   // Normalize the path in case it is an alias.
-  $shortcut_path = drupal_get_normal_path($form_state['values']['shortcut_link']['link_path']);
+  $shortcut_path = drupal_container()->get('path.alias_manager')->getSystemPath($form_state['values']['shortcut_link']['link_path']);
   if (empty($shortcut_path)) {
     $shortcut_path = '<front>';
   }
@@ -496,7 +496,7 @@ function shortcut_link_add_submit($form, &$form_state) {
  */
 function shortcut_admin_add_link($shortcut_link, &$shortcut_set) {
   // Normalize the path in case it is an alias.
-  $shortcut_link['link_path'] = drupal_get_normal_path($shortcut_link['link_path']);
+  $shortcut_link['link_path'] = drupal_container()->get('path.alias_manager')->getSystemPath($shortcut_link['link_path']);
   if (empty($shortcut_link['link_path'])) {
     $shortcut_link['link_path'] = '<front>';
   }
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index 9bbb12a..2a07989 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -616,7 +616,7 @@ function shortcut_set_title_exists($title) {
  */
 function shortcut_valid_link($path) {
   // Do not use URL aliases.
-  $normal_path = drupal_get_normal_path($path);
+  $normal_path = drupal_container()->get('path.alias_manager')->getSystemPath($path);
   if ($path != $normal_path) {
     $path = $normal_path;
   }
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module
index c07a1c8..b663024 100644
--- a/core/modules/statistics/statistics.module
+++ b/core/modules/statistics/statistics.module
@@ -388,7 +388,7 @@ function statistics_block_view($delta = '') {
  *   A string as a link, truncated to the width, linked to the given $path.
  */
 function _statistics_link($path, $width = 35) {
-  $title = drupal_get_path_alias($path);
+  $title = drupal_container()->get('path.alias_manager')->getPathAlias($path);
   $title = truncate_utf8($title, $width, FALSE, TRUE);
   return l($title, $path);
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Path/LookupTest.php b/core/modules/system/lib/Drupal/system/Tests/Path/LookupTest.php
index a90b5f4..2b5e128 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Path/LookupTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Path/LookupTest.php
@@ -2,27 +2,27 @@
 
 /**
  * @file
- * Definition of Drupal\system\Tests\Path\LookupTest.
+ * Definition of Drupal\path\Tests\Path\LookupTest.
  */
 
-namespace Drupal\system\Tests\Path;
+namespace Drupal\path\Tests\Path;
 
 use Drupal\simpletest\WebTestBase;
 
 /**
- * Unit test for drupal_lookup_path().
+ * Tests for the alias manager.
  */
 class LookupTest extends WebTestBase {
   public static function getInfo() {
     return array(
       'name' => t('Path lookup'),
-      'description' => t('Tests that drupal_lookup_path() returns correct paths.'),
+      'description' => t('Tests that the alias manager returns correct paths.'),
       'group' => t('Path API'),
     );
   }
 
   /**
-   * Test that drupal_lookup_path() returns the correct path.
+   * Test that the alias manager returns the correct path.
    */
   function testDrupalLookupPath() {
     $account = $this->drupalCreateUser();
@@ -35,9 +35,9 @@ class LookupTest extends WebTestBase {
       'source' => "user/$uid",
       'alias' => 'foo',
     );
-    path_save($path);
-    $this->assertEqual(drupal_lookup_path('alias', $path['source']), $path['alias'], t('Basic alias lookup works.'));
-    $this->assertEqual(drupal_lookup_path('source', $path['alias']), $path['source'], t('Basic source lookup works.'));
+    drupal_container()->get('path.crud')->save($path['source'], $path['alias']);
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getPathAlias($path['source']), $path['alias'], t('Basic alias lookup works.'));
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getSystemPath($path['alias']), $path['source'], t('Basic source lookup works.'));
 
     // Create a language specific alias for the default language (English).
     $path = array(
@@ -45,17 +45,17 @@ class LookupTest extends WebTestBase {
       'alias' => "users/$name",
       'langcode' => 'en',
     );
-    path_save($path);
-    $this->assertEqual(drupal_lookup_path('alias', $path['source']), $path['alias'], t('English alias overrides language-neutral alias.'));
-    $this->assertEqual(drupal_lookup_path('source', $path['alias']), $path['source'], t('English source overrides language-neutral source.'));
+    drupal_container()->get('path.crud')->save($path['source'], $path['alias'], $path['langcode']);
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getPathAlias($path['source']), $path['alias'], t('English alias overrides language-neutral alias.'));
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getSystemPath($path['alias']), $path['source'], t('English source overrides language-neutral source.'));
 
     // Create a language-neutral alias for the same path, again.
     $path = array(
       'source' => "user/$uid",
       'alias' => 'bar',
     );
-    path_save($path);
-    $this->assertEqual(drupal_lookup_path('alias', $path['source']), "users/$name", t('English alias still returned after entering a language-neutral alias.'));
+    drupal_container()->get('path.crud')->save($path['source'], $path['alias']);
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getPathAlias($path['source']), "users/$name", t('English alias still returned after entering a language-neutral alias.'));
 
     // Create a language-specific (xx-lolspeak) alias for the same path.
     $path = array(
@@ -63,10 +63,10 @@ class LookupTest extends WebTestBase {
       'alias' => 'LOL',
       'langcode' => 'xx-lolspeak',
     );
-    path_save($path);
-    $this->assertEqual(drupal_lookup_path('alias', $path['source']), "users/$name", t('English alias still returned after entering a LOLspeak alias.'));
+    drupal_container()->get('path.crud')->save($path['source'], $path['alias'], $path['langcode']);
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getPathAlias($path['source']), "users/$name", t('English alias still returned after entering a LOLspeak alias.'));
     // The LOLspeak alias should be returned if we really want LOLspeak.
-    $this->assertEqual(drupal_lookup_path('alias', $path['source'], 'xx-lolspeak'), 'LOL', t('LOLspeak alias returned if we specify xx-lolspeak to drupal_lookup_path().'));
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getPathAlias($path['source'], 'xx-lolspeak'), 'LOL', t('LOLspeak alias returned if we specify xx-lolspeak to the alias manager.'));
 
     // Create a new alias for this path in English, which should override the
     // previous alias for "user/$uid".
@@ -75,26 +75,22 @@ class LookupTest extends WebTestBase {
       'alias' => 'users/my-new-path',
       'langcode' => 'en',
     );
-    path_save($path);
-    $this->assertEqual(drupal_lookup_path('alias', $path['source']), $path['alias'], t('Recently created English alias returned.'));
-    $this->assertEqual(drupal_lookup_path('source', $path['alias']), $path['source'], t('Recently created English source returned.'));
+    drupal_container()->get('path.crud')->save($path['source'], $path['alias'], $path['langcode']);
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getPathAlias($path['source']), $path['alias'], t('Recently created English alias returned.'));
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getSystemPath($path['alias']), $path['source'], t('Recently created English source returned.'));
 
     // Remove the English aliases, which should cause a fallback to the most
     // recently created language-neutral alias, 'bar'.
     db_delete('url_alias')
       ->condition('langcode', 'en')
       ->execute();
-    drupal_clear_path_cache();
-    $this->assertEqual(drupal_lookup_path('alias', $path['source']), 'bar', t('Path lookup falls back to recently created language-neutral alias.'));
+    drupal_container()->get('path.alias_manager')->cacheClear();
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getPathAlias($path['source']), 'bar', t('Path lookup falls back to recently created language-neutral alias.'));
 
     // Test the situation where the alias and language are the same, but
     // the source differs. The newer alias record should be returned.
     $account2 = $this->drupalCreateUser();
-    $path = array(
-      'source' => 'user/' . $account2->uid,
-      'alias' => 'bar',
-    );
-    path_save($path);
-    $this->assertEqual(drupal_lookup_path('source', $path['alias']), $path['source'], t('Newer alias record is returned when comparing two LANGUAGE_NOT_SPECIFIED paths with the same alias.'));
+    drupal_container()->get('path.crud')->save('user/' . $account2->uid, 'bar');
+    $this->assertEqual(drupal_container()->get('path.alias_manager')->getPathAlias('source', 'bar'), 'user/' . $account2->uid, t('Newer alias record is returned when comparing two LANGUAGE_NOT_SPECIFIED paths with the same alias.'));
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Path/SaveTest.php b/core/modules/system/lib/Drupal/system/Tests/Path/SaveTest.php
index f017230..b2eed0c 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Path/SaveTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Path/SaveTest.php
@@ -10,7 +10,7 @@ namespace Drupal\system\Tests\Path;
 use Drupal\simpletest\WebTestBase;
 
 /**
- * Tests the path_save() function.
+ * Tests the drupal_container()->get('path.crud')->save() function. 
  */
 class SaveTest extends WebTestBase {
 
@@ -24,7 +24,7 @@ class SaveTest extends WebTestBase {
   public static function getInfo() {
     return array(
       'name' => t('Path save'),
-      'description' => t('Tests that path_save() exposes the previous alias value.'),
+      'description' => t('Tests that saving the path alias exposes the previous alias value.'),
       'group' => t('Path API'),
     );
   }
@@ -35,7 +35,8 @@ class SaveTest extends WebTestBase {
   }
 
   /**
-   * Tests that path_save() makes the original path available to modules.
+   * Tests that drupal_container()->get('path.crud')->save($path) makes the
+   * original path available to modules.
    */
   function testDrupalSaveOriginalPath() {
     $account = $this->drupalCreateUser();
@@ -48,11 +49,11 @@ class SaveTest extends WebTestBase {
       'alias' => 'foo',
     );
     $path_original = $path;
-    path_save($path);
+    drupal_container()->get('path.crud')->save($path['source'], $path['alias']);
 
     // Alter the path.
     $path['alias'] = 'bar';
-    path_save($path);
+    drupal_container()->get('path.crud')->save($path['source'], $path['alias']);
 
     // Test to see if the original alias is available to modules during
     // hook_path_update().
diff --git a/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php b/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php
index 6bcbca8..6165806 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php
@@ -45,7 +45,7 @@ class UrlAlterFunctionalTest extends WebTestBase {
 
     // Test that a path always uses its alias.
     $path = array('source' => "user/$uid/test1", 'alias' => 'alias/test1');
-    path_save($path);
+    drupal_container()->get('path.crud')->save($$path['source'], $path['alias']);
     $this->assertUrlInboundAlter('alias/test1', "user/$uid/test1");
     $this->assertUrlOutboundAlter("user/$uid/test1", 'alias/test1');
 
@@ -118,7 +118,7 @@ class UrlAlterFunctionalTest extends WebTestBase {
    *
    * @param $original
    *   A string with the aliased or un-normal path that is run through
-   *   drupal_get_normal_path().
+   *   drupal_container()->get('path.alias_manager')->getSystemPath().
    * @param $final
    *   A string with the expected result after url().
    * @return
@@ -126,7 +126,7 @@ class UrlAlterFunctionalTest extends WebTestBase {
    */
   protected function assertUrlInboundAlter($original, $final) {
     // Test inbound altering.
-    $result = drupal_get_normal_path($original);
+    $result = drupal_container()->get('path.alias_manager')->getSystemPath($original);
     $this->assertIdentical($result, $final, t('Altered inbound URL %original, expected %final, and got %result.', array('%original' => $original, '%final' => $final, '%result' => $result)));
   }
 }
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 2bf4343..d1140a5 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -1516,10 +1516,11 @@ function system_site_information_settings($form, &$form_state) {
     '#type' => 'fieldset',
     '#title' => t('Front page'),
   );
+  $front_page = $site_config->get('page.front') != 'user' ? drupal_container()->get('path.alias_manager')->getPathAlias($site_config->get('page.front')) : '';
   $form['front_page']['site_frontpage'] = array(
     '#type' => 'textfield',
     '#title' => t('Default front page'),
-    '#default_value' => ($site_config->get('page.front') != 'user' ? drupal_get_path_alias($site_config->get('page.front')) : ''),
+    '#default_value' => $front_page,
     '#size' => 40,
     '#description' => t('Optionally, specify a relative URL to display as the front page.  Leave blank to display the default content feed.'),
     '#field_prefix' => url(NULL, array('absolute' => TRUE)),
@@ -1561,7 +1562,7 @@ function system_site_information_settings_validate($form, &$form_state) {
   }
   else {
     // Get the normal path of the front page.
-    form_set_value($form['front_page']['site_frontpage'], drupal_get_normal_path($form_state['values']['site_frontpage']), $form_state);
+    form_set_value($form['front_page']['site_frontpage'], drupal_container()->get('path.alias_manager')->getSystemPath($form_state['values']['site_frontpage']), $form_state);
   }
   // Validate front page path.
   if (!drupal_valid_path($form_state['values']['site_frontpage'])) {
@@ -1569,10 +1570,10 @@ function system_site_information_settings_validate($form, &$form_state) {
   }
   // Get the normal paths of both error pages.
   if (!empty($form_state['values']['site_403'])) {
-    form_set_value($form['error_page']['site_403'], drupal_get_normal_path($form_state['values']['site_403']), $form_state);
+    form_set_value($form['error_page']['site_403'], drupal_container()->get('path.alias_manager')->getSystemPath($form_state['values']['site_403']), $form_state);
   }
   if (!empty($form_state['values']['site_404'])) {
-    form_set_value($form['error_page']['site_404'], drupal_get_normal_path($form_state['values']['site_404']), $form_state);
+    form_set_value($form['error_page']['site_404'], drupal_container()->get('path.alias_manager')->getSystemPath($form_state['values']['site_404']), $form_state);
   }
   // Validate 403 error path.
   if (!empty($form_state['values']['site_403']) && !drupal_valid_path($form_state['values']['site_403'])) {
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index c7343ba..5d03688 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -3468,7 +3468,7 @@ function hook_system_themes_page_alter(&$theme_groups) {
  * @param $path_language
  *   The language of the path.
  *
- * @see drupal_get_normal_path()
+ * @see \Drupal\Core\Path\AliasManager::getSystemPath()
  */
 function hook_url_inbound_alter(&$path, $original_path, $path_language) {
   // Create the path user/me/edit, which allows a user to edit their account.
diff --git a/core/scripts/generate-d7-content.sh b/core/scripts/generate-d7-content.sh
index 7f03846..c997160 100644
--- a/core/scripts/generate-d7-content.sh
+++ b/core/scripts/generate-d7-content.sh
@@ -253,7 +253,7 @@ for ($i = 0; $i < 12; $i++) {
     'alias' => "content/poll/$i/results",
     'source' => "node/$node->nid/results",
   );
-  path_save($path);
+  drupal_container()->get('path.crud')->save($path['source'], $path['alias']);
 
   // Add some votes
   $node = node_load($node->nid);
