Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1174
diff -u -p -r1.1174 common.inc
--- includes/common.inc	26 May 2010 19:51:01 -0000	1.1174
+++ includes/common.inc	29 May 2010 02:04:58 -0000
@@ -4890,6 +4890,13 @@ function drupal_pre_render_markup($eleme
 function drupal_render_page($page) {
   $main_content_display = &drupal_static('system_main_content_added', FALSE);
 
+  // menu_execute_active_handler() initializes the theme before invoking the
+  // page callback, but it's possible that drupal_render_page() is called for
+  // an error page (MENU_NOT_FOUND, MENU_ACCESS_DENIED) or during hook_init().
+  // Even in these situations, the theme may implement hook_page_alter() and
+  // other alter hooks that get called during hook_page_build().
+  drupal_theme_initialize();
+
   // Allow menu callbacks to return strings or arbitrary arrays to render.
   // If the array returned is not of #type page directly, we need to fill
   // in the page with defaults.
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.394
diff -u -p -r1.394 menu.inc
--- includes/menu.inc	28 May 2010 10:18:57 -0000	1.394
+++ includes/menu.inc	29 May 2010 02:04:59 -0000
@@ -466,6 +466,12 @@ function menu_execute_active_handler($pa
         if ($router_item['include_file']) {
           require_once DRUPAL_ROOT . '/' . $router_item['include_file'];
         }
+        // Initialize the theme so that its hook_*_alter() implementations get
+        // called during page callback execution, even ahead of when rendering
+        // starts. Retrieving the theme registry, even from cache, is slow, so
+        // we delay that until it is needed, so that pages that don't require
+        // anything to be themed (e.g., */autocomplete) are served faster.
+        drupal_theme_initialize(FALSE);
         $page_callback_result = call_user_func_array($router_item['page_callback'], $router_item['page_arguments']);
       }
       else {
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.598
diff -u -p -r1.598 theme.inc
--- includes/theme.inc	19 May 2010 19:22:24 -0000	1.598
+++ includes/theme.inc	29 May 2010 02:04:59 -0000
@@ -68,11 +68,20 @@ function _drupal_theme_access($theme) {
 /**
  * Initialize the theme system by loading the theme.
  */
-function drupal_theme_initialize() {
+function drupal_theme_initialize($load_registry = TRUE) {
   global $theme, $user, $theme_key;
 
+  // Not drupal_static(), because the theme system does not support
+  // uninitializing an initialized theme or initializing a second theme during
+  // the same page request.
+  static $registry_loaded = FALSE;
+
   // If $theme is already set, assume the others are set, too, and do nothing
   if (isset($theme)) {
+    if (!$registry_loaded && $load_registry) {
+      $registry_loaded = TRUE;
+      _theme_load_registry($GLOBALS['theme_info'], $GLOBALS['base_theme_info'], $GLOBALS['theme_engine']);
+    }
     return;
   }
 
@@ -98,7 +107,17 @@ function drupal_theme_initialize() {
     $base_theme[] = $new_base_theme = $themes[$themes[$ancestor]->base_theme];
     $ancestor = $themes[$ancestor]->base_theme;
   }
-  _drupal_theme_initialize($themes[$theme], array_reverse($base_theme));
+
+  // Allow the loading of the registry to be delayed.
+  if (!$registry_loaded && $load_registry) {
+    $registry_loaded = TRUE;
+    $registry_callback = '_theme_load_registry';
+  }
+  else {
+    $registry_callback = NULL;
+  }
+
+  _drupal_theme_initialize($themes[$theme], array_reverse($base_theme), $registry_callback);
 
   // Themes can have alter functions, so reset the drupal_alter() cache.
   drupal_static_reset('drupal_alter');
