Index: update.php
===================================================================
RCS file: /cvs/drupal/drupal/update.php,v
retrieving revision 1.302
diff -u -p -r1.302 update.php
--- update.php	7 Sep 2009 15:43:54 -0000	1.302
+++ update.php	9 Sep 2009 09:05:07 -0000
@@ -291,6 +291,9 @@ if (empty($op) && $update_access_allowed
   drupal_load('module', 'system');
   drupal_load('module', 'filter');
 
+  // Reset the module_implements() cache.
+  module_implements('', FALSE, TRUE);
+
   // Set up $language, since the installer components require it.
   drupal_language_initialize();
 
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.984
diff -u -p -r1.984 common.inc
--- includes/common.inc	5 Sep 2009 15:05:01 -0000	1.984
+++ includes/common.inc	9 Sep 2009 09:05:08 -0000
@@ -2403,6 +2402,7 @@ function drupal_page_footer() {
 
   _registry_check_code(REGISTRY_WRITE_LOOKUP_CACHE);
   drupal_cache_system_paths();
+  module_implements_write_cache();
 }
 
 /**
Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.157
diff -u -p -r1.157 module.inc
--- includes/module.inc	24 Aug 2009 00:14:18 -0000	1.157
+++ includes/module.inc	9 Sep 2009 09:05:08 -0000
@@ -14,7 +14,6 @@ function module_load_all($bootstrap = FA
   foreach (module_list(TRUE, $bootstrap) as $module) {
     drupal_load('module', $module);
   }
-  module_implements('', FALSE, TRUE);
 }
 
 /**
@@ -344,19 +343,37 @@ function module_hook($module, $hook) {
  *   An array with the names of the modules which are implementing this hook.
  */
 function module_implements($hook, $sort = FALSE, $refresh = FALSE) {
-  static $implementations;
+  $implementations = &drupal_static(__FUNCTION__, array());
 
   if ($refresh) {
     $implementations = array();
+    variable_set('module_implements', array());
     return;
   }
+  if (empty($implementations)) {
+    // Since the size of the module_implements() cache is relatively small
+    // and is needed on every page, we store the information in a variable
+    // rather than using cache_set() and cache_get().
+    $implementations = variable_get('module_implements', array());
+  }
 
   if (!isset($implementations[$hook])) {
     $implementations[$hook] = array();
     $list = module_list(FALSE, FALSE, $sort);
     foreach ($list as $module) {
       if (module_hook($module, $hook)) {
-        $implementations[$hook][] = $module;
+        $implementations[$hook][$module] = $module;
+      }
+    }
+  }
+  else {
+    foreach ($implementations[$hook] as $module) {
+      if (!module_hook($hook, $module)) {
+        // Ensure no undefined function errors for calling functions.
+        unset($implementations[$hook][$module]);
+        // Set the module_implements cache to an empty array, this will
+        // force a fresh rebuild in module_implements_write_cache().
+        variable_set('module_implements', array());
       }
     }
   }
@@ -371,6 +388,21 @@ function module_implements($hook, $sort 
 }
 
 /**
+ * Write to the module_implements() cache.
+ */
+function module_implements_write_cache() {
+  $cached_implementations = variable_get('module_implements', array());
+  $implementations = &drupal_static('module_implements');
+  // Determine whether any hooks have been invoked this request, which had
+  // not previously been cached.
+  $new_hooks = array_diff_key($implementations, $cached_implementations);
+  if (!empty($new_hooks)) {
+    $implementations = $cached_implementations += $implementations;
+    variable_set('module_implements', $implementations);
+  }
+}
+
+/**
  * Invoke a hook in a particular module.
  *
  * @param $module
