Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.246
diff -u -p -r1.246 bootstrap.inc
--- includes/bootstrap.inc	7 Nov 2008 17:21:53 -0000	1.246
+++ includes/bootstrap.inc	9 Nov 2008 06:54:34 -0000
@@ -207,6 +207,16 @@ define('CHECK_PLAIN', 0);
 define('PASS_THROUGH', -1);
 
 /**
+ * Signals that the registry lookup cache should be reset. 
+ */
+define('REGISTRY_RESET_LOOKUP_CACHE', 1);
+
+/**
+ * Signals that the registry lookup cache should be written to storage. 
+ */
+define('REGISTRY_WRITE_LOOKUP_CACHE', 2);
+
+/**
  * @} End of "Title text filtering flags".
  */
 
@@ -1412,7 +1422,6 @@ function drupal_function_exists($functio
   $checked[$function] = FALSE;
 
   if (function_exists($function)) {
-    registry_mark_code('function', $function);
     $checked[$function] = TRUE;
     return TRUE;
   }
@@ -1457,7 +1466,40 @@ function drupal_autoload_class($class) {
 /**
  * Helper to check for a resource in the registry.
  */
-function _registry_check_code($type, $name) {
+function _registry_check_code($type, $name = NULL) {
+  static $lookup_cache, $cache_update_needed;
+
+  if ($lookup_cache === NULL) {
+    $lookup_cache = array();
+    if ($cache = cache_get('lookup_cache', 'cache_registry')) {
+      $lookup_cache = $cache->data;
+    }
+  }
+  
+  // When we rebuild the registry, we need to reset this cache so that it
+  // only contains resources that we know haven't changed during the rebuild.
+  if ($type === REGISTRY_RESET_LOOKUP_CACHE) {
+    $cache_update_needed = TRUE;
+    $lookup_cache = $name;
+    return;
+  }
+
+  if ($type === REGISTRY_WRITE_LOOKUP_CACHE) {
+    if ($cache_update_needed) {
+      cache_set('lookup_cache', $lookup_cache, 'cache_registry');
+    }
+    // Always return, even if we don't write to the cache.
+    return;
+  }
+  
+  $cache_key = $type{0} . $name;
+  if (isset($lookup_cache[$cache_key])) {
+    if ($lookup_cache[$cache_key]) {
+      require_once DRUPAL_ROOT . '/' . $lookup_cache[$cache_key];
+    }
+    return $lookup_cache[$cache_key];
+  }
+  
   // This function may get called when the default database is not active, but
   // there is no reason we'd ever want to not use the default database for
   // this query.
@@ -1466,38 +1508,20 @@ function _registry_check_code($type, $na
       ':type' => $type,
     ))
     ->fetchField();
+
+  // Flag that we've run a lookup query and need to update the cache.
+  $cache_update_needed = TRUE;
+
+  // Misses are valuable information worth caching, so cache even if
+  // $file is FALSE.
+  $lookup_cache[$cache_key] = $file;
+
   if ($file) {
     require_once DRUPAL_ROOT . '/' . $file;
-    registry_mark_code($type, $name);
     return TRUE;
   }
-  return FALSE;
-}
-
-/**
- * Collect the resources used for this request.
- *
- * @param $type
- *   The type of resource.
- * @param $name
- *   The name of the resource.
- * @param $return
- *   Boolean flag to indicate whether to return the resources.
- */
-function registry_mark_code($type, $name, $return = FALSE) {
-  static $resources = array();
-
-  if ($type && $name) {
-    if (!isset($resources[$type])) {
-      $resources[$type] = array();
-    }
-    if (!in_array($name, $resources[$type])) {
-      $resources[$type][] = $name;
-    }
-  }
-
-  if ($return) {
-    return $resources;
+  else {
+    return FALSE;
   }
 }
 
@@ -1513,62 +1537,5 @@ function registry_rebuild() {
 }
 
 /**
- * Save the files required by the registry for this path.
- */
-function registry_cache_path_files() {
-  if ($used_code = registry_mark_code(NULL, NULL, TRUE)) {
-    $files = array();
-    $type_sql = array();
-    $params = array();
-
-    // This function may get called when the default database is not active, but
-    // there is no reason we'd ever want to not use the default database for
-    // this query.
-    $select = Database::getConnection('default')->select('registry')->distinct();
-    $select->addField('registry', 'filename');
-
-    // This creates a series of 2-clause AND conditions that are then ORed together.
-    $ors = db_or();
-    foreach ($used_code as $type => $names) {
-      $and = db_and()
-        ->condition('name', $names, 'IN')
-        ->condition('type', $type);
-      $ors->condition($and);
-    }
-    $select->condition($ors);
-    $files = $select->execute()->fetchCol();
-
-    if ($files) {
-      sort($files);
-      // Only write this to cache if the file list we are going to cache
-      // is different to what we loaded earlier in the request.
-      if ($files != registry_load_path_files(TRUE)) {
-        $menu = menu_get_item();
-        cache_set('registry:' . $menu['path'], implode(';', $files), 'cache_registry');
-      }
-    }
-  }
-}
-
-/**
- * registry_load_path_files
- */
-function registry_load_path_files($return = FALSE) {
-  static $file_cache_data = array();
-  if ($return) {
-    sort($file_cache_data);
-    return $file_cache_data;
-  }
-  $menu = menu_get_item();
-  $cache = cache_get('registry:' . $menu['path'], 'cache_registry');
-  if (!empty($cache->data)) {
-    foreach(explode(';', $cache->data) as $file) {
-      require_once DRUPAL_ROOT . '/' . $file;
-      $file_cache_data[] = $file;
-    }
-  }
-}
-
-/**
  * @} End of "ingroup registry".
  */
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.822
diff -u -p -r1.822 common.inc
--- includes/common.inc	8 Nov 2008 22:04:03 -0000	1.822
+++ includes/common.inc	9 Nov 2008 06:54:52 -0000
@@ -1625,7 +1625,7 @@ function drupal_page_footer() {
   module_invoke_all('exit');
 
   module_implements(MODULE_IMPLEMENTS_WRITE_CACHE);
-  registry_cache_path_files();
+  _registry_check_code(REGISTRY_WRITE_LOOKUP_CACHE);
 }
 
 /**
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.300
diff -u -p -r1.300 menu.inc
--- includes/menu.inc	8 Nov 2008 04:13:10 -0000	1.300
+++ includes/menu.inc	9 Nov 2008 06:55:03 -0000
@@ -393,7 +393,6 @@ function menu_execute_active_handler($pa
     menu_rebuild();
   }
   if ($router_item = menu_get_item($path)) {
-    registry_load_path_files();
     if ($router_item['access']) {
       if (drupal_function_exists($router_item['page_callback'])) {
         return call_user_func_array($router_item['page_callback'], $router_item['page_arguments']);
Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.132
diff -u -p -r1.132 module.inc
--- includes/module.inc	31 Oct 2008 02:18:22 -0000	1.132
+++ includes/module.inc	9 Nov 2008 06:55:06 -0000
@@ -90,7 +90,7 @@ function module_list($refresh = FALSE, $
  *   The array of filesystem objects used to rebuild the cache.
  */
 function module_rebuild_cache() {
-  // Get current list of modules
+  // Get current list of modules, including uninstalled modules.
   $files = drupal_system_listing('/\.module$/', 'modules', 'name', 0);
 
   // Extract current files from database.
@@ -108,7 +108,7 @@ function module_rebuild_cache() {
     'php' => DRUPAL_MINIMUM_PHP,
     'files' => array(),
   );
-
+  
   foreach ($files as $filename => $file) {
     // Look for the info file.
     $file->info = drupal_parse_info_file(dirname($file->filename) . '/' . $file->name . '.info');
@@ -128,7 +128,8 @@ function module_rebuild_cache() {
     // Log the critical hooks implemented by this module.
     $bootstrap = 0;
     foreach (bootstrap_hooks() as $hook) {
-      if (module_hook($file->name, $hook)) {
+      // Only look for hooks in installed modules.
+      if ((isset($file->status) && $file->status) && module_hook($file->name, $hook)) {
         $bootstrap = 1;
         break;
       }
@@ -394,7 +395,7 @@ function module_hook($module, $hook) {
     return function_exists($function);
   }
   else {
-    return drupal_function_exists($function);
+    return in_array($module, module_implements($hook));
   }
 }
 
Index: includes/registry.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/registry.inc,v
retrieving revision 1.7
diff -u -p -r1.7 registry.inc
--- includes/registry.inc	31 Oct 2008 02:18:22 -0000	1.7
+++ includes/registry.inc	9 Nov 2008 06:55:07 -0000
@@ -69,10 +69,23 @@ function _registry_rebuild() {
         ->execute();
     }
   }
-  _registry_parse_files($files);
+  $parsed_files = _registry_parse_files($files);
 
+  $unchanged_resources = array();
+  if ($lookup_cache = cache_get('lookup_cache', 'cache_registry')) {
+    foreach ($lookup_cache->data as $key => $file) {
+      // If the file for this cached resource is carried over unchanged from 
+      // the last registry build, then we can safely re-cache it.
+      if ($file && in_array($file, array_keys($files)) && !in_array($file, $parsed_files)) {
+        $unchanged_resources[$key] = $file;
+      }
+    }
+  }
   module_implements(MODULE_IMPLEMENTS_CLEAR_CACHE);
   cache_clear_all('*', 'cache_registry', TRUE);
+  if (count($unchanged_resources) > 0) {
+    _registry_check_code(REGISTRY_RESET_LOOKUP_CACHE, $unchanged_resources);
+  }
 }
 
 /**
@@ -92,12 +105,13 @@ function registry_get_parsed_files() {
  *  The list of files to check and parse.
  */
 function _registry_parse_files($files) {
-  $changed_files = array();
+  $parsed_files = array();
   foreach ($files as $filename => $file) {
     $contents = file_get_contents($filename);
     $md5 = md5($contents);
     $new_file = !isset($file['md5']);
     if ($new_file || $md5 != $file['md5']) {
+      $parsed_files[] = $filename;
       // We update the md5 after we've saved the files resources rather than here, so if we
       // don't make it through this rebuild, the next run will reparse the file.
       _registry_parse_file($filename, $contents, $file['module'], $file['weight']);
@@ -108,6 +122,7 @@ function _registry_parse_files($files) {
         ->execute();
     }
   }
+  return $parsed_files;
 }
 
 /**
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.102
diff -u -p -r1.102 system.admin.inc
--- modules/system/system.admin.inc	16 Oct 2008 20:23:08 -0000	1.102
+++ modules/system/system.admin.inc	9 Nov 2008 06:55:21 -0000
@@ -657,7 +657,7 @@ function system_modules($form_state = ar
       }
     }
     // Generate link for module's help page, if there is one.
-    if ($help_arg && module_hook($filename, 'help')) {
+    if ($help_arg && $module->status && module_hook($filename, 'help')) {
       if (module_invoke($filename, 'help', "admin/help#$filename", $help_arg)) {
         // Module has a help page.
         $extra['help'] = theme('more_help_link', url("admin/help/$filename"));
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.635
diff -u -p -r1.635 system.module
--- modules/system/system.module	31 Oct 2008 02:18:22 -0000	1.635
+++ modules/system/system.module	9 Nov 2008 06:55:32 -0000
@@ -1380,7 +1380,7 @@ function system_admin_compact_page($mode
  */
 function system_get_module_admin_tasks($module) {
   static $items;
-
+  
   if (!isset($items)) {
     $result = db_query("
        SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, ml.*
