diff --git a/includes/module.inc b/includes/module.inc
index 779b668..714957a 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -425,6 +425,8 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
       registry_update();
       // Refresh the schema to include it.
       drupal_get_schema(NULL, TRUE);
+      // Update the theme registry to include it.
+      drupal_theme_rebuild();
       // Clear entity cache.
       entity_info_cache_clear();
 
@@ -545,6 +547,8 @@ function module_disable($module_list, $disable_dependents = TRUE) {
     // Update the registry to remove the newly-disabled module.
     registry_update();
     _system_update_bootstrap_status();
+    // Update the theme registry to remove the newly-disabled module.
+    drupal_theme_rebuild();
   }
 
   // If there remains no more node_access module, rebuilding will be
diff --git a/includes/theme.inc b/includes/theme.inc
index 3ae5000..e156ccc 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -241,7 +241,7 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
  *   The theme registry array if it has been stored in memory, NULL otherwise.
  */
 function theme_get_registry() {
-  static $theme_registry = NULL;
+  $theme_registry = &drupal_static(__FUNCTION__);
 
   if (!isset($theme_registry)) {
     list($callback, $arguments) = _theme_registry_callback();
@@ -310,6 +310,7 @@ function _theme_save_registry($theme, $registry) {
  */
 function drupal_theme_rebuild() {
   cache_clear_all('theme_registry', 'cache', TRUE);
+  drupal_static_reset('theme_get_registry');
 }
 
 /**
@@ -749,7 +750,12 @@ function list_themes($refresh = FALSE) {
  *   An HTML string representing the themed output.
  */
 function theme($hook, $variables = array()) {
-  static $hooks = NULL;
+  // Use the advanced drupal_static() pattern, since this is called very often.
+  static $drupal_static_fast;
+  if (!isset($drupal_static_fast)) {
+    $drupal_static_fast['hooks'] = &drupal_static('theme_get_registry');
+  }
+  $hooks = &$drupal_static_fast['hooks'];
 
   // If called before all modules are loaded, we do not necessarily have a full
   // theme registry to work with, and therefore cannot process the theme
diff --git a/modules/simpletest/tests/theme.test b/modules/simpletest/tests/theme.test
index f1e1bd5..26fa35f 100644
--- a/modules/simpletest/tests/theme.test
+++ b/modules/simpletest/tests/theme.test
@@ -101,6 +101,17 @@ class ThemeUnitTest extends DrupalWebTestCase {
     $this->drupalGet('theme-test/suggestion');
     variable_set('preprocess_css', 0);
   }
+
+  /**
+   * Ensures the theme registry is rebuilt when modules are disabled/enabled.
+   */
+  function testRegistryRebuild() {
+    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'a')), 'a', t('The theme registry contains theme_test_foo.'));
+    module_disable(array('theme_test'), FALSE);
+    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'b')), '', t('The theme registry does not contain theme_test_foo, because the module is disabled.'));
+    module_enable(array('theme_test'), FALSE);
+    $this->assertIdentical(theme('theme_test_foo', array('foo' => 'c')), 'c', t('The theme registry contains theme_test_foo again after re-enabling the module.'));
+  }
 }
 
 /**
diff --git a/modules/simpletest/tests/theme_test.module b/modules/simpletest/tests/theme_test.module
index 160d192..f8cb6a5 100644
--- a/modules/simpletest/tests/theme_test.module
+++ b/modules/simpletest/tests/theme_test.module
@@ -1,6 +1,24 @@
 <?php
 
 /**
+ * Implements hook_theme().
+ */
+function theme_test_theme() {
+  return array(
+    'theme_test_foo' => array(
+      'variables' => array('foo' => NULL),
+    ),
+  );
+}
+
+/**
+ * Theme function for testing theme('theme_test_foo').
+ */
+function theme_theme_test_foo($variables) {
+  return $variables['foo'];
+}
+
+/**
  * Implements hook_menu().
  */
 function theme_test_menu() {
