diff --git includes/menu.inc includes/menu.inc
index dfc5d32..d4cc81c 100644
--- includes/menu.inc
+++ includes/menu.inc
@@ -370,6 +370,7 @@ function menu_get_item($path = NULL, $router_item = NULL) {
       ->execute()->fetchAssoc();
     if ($router_item) {
       $map = _menu_translate($router_item, $original_map);
+      $router_item['original_map'] = $original_map;
       if ($map === FALSE) {
         $router_items[$path] = FALSE;
         return FALSE;
@@ -843,13 +844,16 @@ function menu_tree_output($tree) {
  * @return
  *   An tree of menu links in an array, in the order they should be rendered.
  */
-function menu_tree_all_data($menu_name, $item = NULL) {
+function menu_tree_all_data($menu_name, $item = NULL, $max_depth = NULL) {
   $tree = &drupal_static(__FUNCTION__, array());
 
   // Use $mlid as a flag for whether the data being loaded is for the whole tree.
   $mlid = isset($item['mlid']) ? $item['mlid'] : 0;
+  if (isset($max_depth)) {
+    $max_depth = min($max_depth, MENU_MAX_DEPTH);
+  }
   // Generate a cache ID (cid) specific for this $menu_name and $item.
-  $cid = 'links:' . $menu_name . ':all-cid:' . $mlid;
+  $cid = 'links:' . $menu_name . ':all-cid:' . $mlid . ':' . (int)$max_depth;
 
   if (!isset($tree[$cid])) {
     // If the static variable doesn't have the data, check {cache_menu}.
@@ -885,7 +889,9 @@ function menu_tree_all_data($menu_name, $item = NULL) {
         $query->orderBy('p' . $i, 'ASC');
       }
       $query->condition('ml.menu_name', $menu_name);
-
+      if (isset($max_depth)) {
+        $query->condition('ml.depth', $max_depth, '<=');
+      }
       if ($mlid) {
         // The tree is for a single item, so we need to match the values in its
         // p columns and 0 (the top level) with the plid values of other links.
@@ -905,7 +911,8 @@ function menu_tree_all_data($menu_name, $item = NULL) {
       // Select the links from the table, and recursively build the tree. We
       // LEFT JOIN since there is no match in {menu_router} for an external
       // link.
-      $data['tree'] = menu_tree_data($query->execute(), $parents);
+      $result = $query->execute()->fetchAllAssoc();
+      $data['tree'] = menu_tree_data($result, $parents);
       $data['node_links'] = array();
       menu_tree_collect_node_links($data['tree'], $data['node_links']);
       // Cache the data, if it is not already in the cache.
@@ -939,13 +946,16 @@ function menu_tree_all_data($menu_name, $item = NULL) {
  *   submenu below the link if there is one, and it is a subtree that has the
  *   same structure described for the top-level array.
  */
-function menu_tree_page_data($menu_name) {
+function menu_tree_page_data($menu_name, $max_depth = NULL) {
   $tree = &drupal_static(__FUNCTION__, array());
 
   // Load the menu item corresponding to the current page.
   if ($item = menu_get_item()) {
+    if (isset($max_depth)) {
+      $max_depth = min($max_depth, MENU_MAX_DEPTH);
+    }
     // Generate a cache ID (cid) specific for this page.
-    $cid = 'links:' . $menu_name . ':page-cid:' . $item['href'] . ':' . (int)$item['access'];
+    $cid = 'links:' . $menu_name . ':page-cid:' . $item['href'] . ':' . (int)$item['access'] . ':' . (int)$max_depth;
 
     if (!isset($tree[$cid])) {
       // If the static variable doesn't have the data, check {cache_menu}.
@@ -1056,7 +1066,11 @@ function menu_tree_page_data($menu_name) {
         }
         $query->condition('ml.menu_name', $menu_name);
         $query->condition('ml.plid', $args, 'IN');
-        $data['tree'] = menu_tree_data($query->execute(), $parents);
+        if (isset($max_depth)) {
+          $query->condition('ml.depth', $max_depth, '<=');
+        }
+        $result = $query->execute()->fetchAllAssoc();
+        $data['tree'] = menu_tree_data($result, $parents);
         $data['node_links'] = array();
         menu_tree_collect_node_links($data['tree'], $data['node_links']);
         // Cache the data, if it is not already in the cache.
@@ -1163,7 +1177,7 @@ function _menu_tree_check_access(&$tree) {
  * Build the data representing a menu tree.
  *
  * @param $result
- *   The database result.
+ *   An array of links (associative arrays) ordered by p1..p9.
  * @param $parents
  *   An array of the plid values that represent the path from the current page
  *   to the root of the menu tree.
@@ -1172,7 +1186,8 @@ function _menu_tree_check_access(&$tree) {
  * @return
  *   See menu_tree_page_data for a description of the data structure.
  */
-function menu_tree_data($result = NULL, $parents = array(), $depth = 1) {
+function menu_tree_data($result = array(), $parents = array(), $depth = 1) {
+  $result = array_reverse($result);
   list(, $tree) = _menu_tree_data($result, $parents, $depth);
   return $tree;
 }
@@ -1184,11 +1199,10 @@ function menu_tree_data($result = NULL, $parents = array(), $depth = 1) {
  * the next menu item. So we are always rendering the element previously
  * processed not the current one.
  */
-function _menu_tree_data($result, $parents, $depth, $previous_element = '') {
+function _menu_tree_data(&$result, $parents, $depth, $previous_element = '') {
   $remnant = NULL;
   $tree = array();
-  foreach ($result as $item) {
-    $item = is_object($item) ? get_object_vars($item) : $item;
+  while ($item = array_pop($result)) {
     // We need to determine if we're on the path to root so we can later build
     // the correct active trail and breadcrumb.
     $item['in_active_trail'] = in_array($item['mlid'], $parents);
@@ -1405,7 +1419,7 @@ function menu_navigation_links($menu_name, $level = 0) {
   }
 
   // Get the menu hierarchy for the current page.
-  $tree = menu_tree_page_data($menu_name);
+  $tree = menu_tree_page_data($menu_name, $level + 1);
 
   // Go down the active trail until the right level is reached.
   while ($level-- > 0 && $tree) {
