Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.408
diff -u -p -r1.408 menu.inc
--- includes/menu.inc	1 Sep 2010 02:59:04 -0000	1.408
+++ includes/menu.inc	14 Sep 2010 00:57:58 -0000
@@ -1946,48 +1946,65 @@ function menu_local_tasks($level = 0) {
  * @see contextual_links_preprocess()
  */
 function menu_contextual_links($module, $parent_path, $args) {
-  static $path_empty = array();
+  // Use the advanced drupal_static() pattern, since this is called very often.
+  static $drupal_static_fast;
+  if (!isset($drupal_static_fast)) {
+    $drupal_static_fast['data'] = &drupal_static(__FUNCTION__, array(
+      'empty' => array(),
+      'items' => array(),
+    ));
+  }
+  $items = &$drupal_static_fast['data']['items'];
+  $empty_parent_paths = &$drupal_static_fast['data']['empty'];
 
-  $links = array();
-  // Performance: In case a previous invocation for the same parent path did not
-  // return any links, we immediately return here.
-  if (isset($path_empty[$parent_path])) {
-    return $links;
+  // In case a previous invocation for the same parent path did not return any
+  // links, immediately return here.
+  if (isset($empty_parent_paths[$parent_path])) {
+    return array();
   }
-  // Construct the item-specific parent path.
+  // Construct the parent link path specific to the element.
   $path = $parent_path . '/' . implode('/', $args);
 
   // Get the router item for the given parent link path.
   $router_item = menu_get_item($path);
-  if (!$router_item || !$router_item['access']) {
-    $path_empty[$parent_path] = TRUE;
-    return $links;
+  if (empty($router_item['access'])) {
+    $empty_parent_paths[$parent_path] = TRUE;
+    return array();
   }
-  $data = &drupal_static(__FUNCTION__, array());
   $root_path = $router_item['path'];
+  $tab_root = $router_item['tab_root'];
 
   // Performance: For a single, normalized path (such as 'node/%') we only query
   // available tasks once per request.
-  if (!isset($data[$root_path])) {
-    // Get all contextual links that are direct children of the router item and
-    // not of the tab type 'view'.
-    $data[$root_path] = db_select('menu_router', 'm')
-      ->fields('m')
-      ->condition('tab_parent', $router_item['tab_root'])
-      ->condition('context', MENU_CONTEXT_NONE, '<>')
-      ->condition('context', MENU_CONTEXT_PAGE, '<>')
-      ->orderBy('weight')
-      ->orderBy('title')
-      ->execute()
-      ->fetchAllAssoc('path', PDO::FETCH_ASSOC);
+  if (!isset($items[$tab_root])) {
+    $cid = 'contextual-links:' . $tab_root;
+    if ($cache = cache_get($cid, 'cache_menu')) {
+      $items[$tab_root] = $cache->data;
+    }
+    else {
+      // Get all contextual links that are direct children of the router item
+      // and not of the tab type 'view'.
+      $items[$tab_root] = db_select('menu_router', 'm')
+        ->fields('m')
+        ->condition('tab_parent', $router_item['tab_root'])
+        ->condition('context', MENU_CONTEXT_NONE, '<>')
+        ->condition('context', MENU_CONTEXT_PAGE, '<>')
+        ->orderBy('weight')
+        ->orderBy('title')
+        ->execute()
+        ->fetchAllAssoc('path', PDO::FETCH_ASSOC);
+
+      cache_set($cid, $items[$tab_root], 'cache_menu');
+    }
   }
-  $parent_length = drupal_strlen($root_path) + 1;
+  $parent_length = drupal_strlen($tab_root) + 1;
   $map = $router_item['original_map'];
-  foreach ($data[$root_path] as $item) {
+  $links = array();
+  foreach ($items[$tab_root] as $item) {
     // Extract the actual "task" string from the path argument.
     $key = drupal_substr($item['path'], $parent_length);
 
-    // Denormalize and translate the contextual link.
+    // Try to translate the router item into a contextual link.
     _menu_translate($item, $map, TRUE);
     if (!$item['access']) {
       continue;
@@ -2000,11 +2017,11 @@ function menu_contextual_links($module, 
   // Allow modules to alter contextual links.
   drupal_alter('menu_contextual_links', $links, $router_item, $root_path);
 
-  // Performance: If the current user does not have access to any links for this
-  // router path and no other module added further links, we assign FALSE here
-  // to skip the entire process the next time the same router path is requested.
+  // If the current user does not have access to any links for this router path
+  // and no other module added further links, we assign FALSE here to skip the
+  // entire process the next time the same router path is requested.
   if (empty($links)) {
-    $path_empty[$parent_path] = TRUE;
+    $empty_parent_paths[$parent_path] = TRUE;
   }
 
   return $links;
