diff --git a/core/includes/common.inc b/core/includes/common.inc
index 353a9b5..7c8e2de 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -7289,50 +7289,89 @@ function drupal_implode_tags($tags) {
 }
 
 /**
- * Flushes all cached data on the site.
- *
- * Empties cache tables, rebuilds the menu cache and theme registries, and
- * invokes a hook so that other modules' cache data can be cleared as well.
+ * Flushes and resets all caches, and rebuilds data structures.
+ *
+ * At times, it is necessary to "re-initialize" the entire system due to account
+ * for changed or new code. This function:
+ * - Clears all persistent caches (invoking hook_cache_flush())
+ * - Clears all static caches
+ * - Updates the system with latest extension information
+ * - Rebuilds and synchronizes data structures (invoking hook_rebuild())
+ * - Rebuilds the menu router
+ * - Clears page and asset file caches (last, in order to serve requests from
+ *   cache during re-initialization, if possible)
+ *
+ * All modules need to ensure that all of their caches are flushed in
+ * hook_cache_flush() is invoked, so any previously known information no longer
+ * exists. This is important, since all of the following hook_rebuild()
+ * operations must be based on the current system data and must be able to rely
+ * on this contract.
+ *
+ * @see hook_cache_flush()
+ * @see hook_rebuild()
+ *
+ * @todo This functions resets all static caches. The theme is not initialized
+ *   anymore and all previously added JavaScript and CSS is gone. But since that
+ *   is the whole point of this function, all callers need to take care for
+ *   backing up needed variables and properly re-initializing the theme on their
+ *   own. See install_finished() for an example. Normally, this function is
+ *   called as a end of POST request operation that is followed by a redirect
+ *   though.
  */
 function drupal_flush_all_caches() {
-  // Change query-strings on css/js files to enforce reload for all users.
-  _drupal_flush_css_js();
+  // Flush all persistent caches.
+  // This is executed based on "previously" known information, which is
+  // sufficient, since new extensions cannot have any primed caches yet.
+  // Do NOT flush the 'form' cache bin to retain in-progress form submissions.
+  $core = array('bootstrap', 'cache', 'path');
+  $cache_bins = array_merge(module_invoke_all('cache_flush'), $core);
+  foreach ($cache_bins as $bin) {
+    cache($bin)->flush();
+  }
 
-  registry_rebuild();
-  drupal_clear_css_cache();
-  drupal_clear_js_cache();
+  // Reset all static caches.
+  drupal_static_reset();
+
+  // Clear all non-drupal_static() static caches.
+  // None currently; kept if any static caches need to be reset in the future.
 
-  // Rebuild the theme data. Note that the module data is rebuilt above, as
-  // part of registry_rebuild().
+  // Update and synchronize the class registry and extension information based
+  // on current/actual code.
+  // Module data is rebuilt as part of registry_rebuild().
+  registry_rebuild();
   system_rebuild_theme_data();
-  drupal_theme_rebuild();
 
-  entity_info_cache_clear();
+  // Update the list of bootstrap modules.
+  // Allows developers to get new hook_boot() implementations registered without
+  // having to write a hook_update_N() function.
+  _system_update_bootstrap_status();
+
+  // Rebuild the schema and cache a fully-built schema based on new module data.
+  // This is necessary for any invocation of index.php, because setting cache
+  // table entries requires schema information and that occurs during bootstrap
+  // before any modules are loaded, so if there is no cached schema,
+  // drupal_get_schema() will try to generate one, but with no loaded modules,
+  // it will return nothing.
+  drupal_get_schema(NULL, TRUE);
 
-  // @todo D8: Split cache flushing from rebuilding.
-  // @see http://drupal.org/node/996236
-  if (module_exists('node')) {
-    node_types_rebuild();
-  }
-  // node_menu() defines menu items based on node types so it needs to come
-  // after node types are rebuilt.
-  menu_rebuild();
+  // Rebuild all information based on new module data.
+  module_invoke_all('rebuild');
 
   // Synchronize to catch any actions that were added or removed.
   actions_synchronize();
 
-  // Don't clear cache_form - in-progress form submissions may break.
-  // Ordered so clearing the page cache will always be the last action.
-  $core = array('cache', 'path', 'filter', 'bootstrap', 'page');
-  $cache_bins = array_merge(module_invoke_all('flush_caches'), $core);
-  foreach ($cache_bins as $bin) {
-    cache($bin)->flush();
-  }
+  // Rebuild the menu router based on all rebuilt data.
+  // Important: This rebuild must happen last, so the menu router is guaranteed
+  // to be based on up to date information.
+  menu_rebuild();
 
-  // Rebuild the bootstrap module list. We do this here so that developers
-  // can get new hook_boot() implementations registered without having to
-  // write a hook_update_N() function.
-  _system_update_bootstrap_status();
+  // Flush the page, CSS and JS caches.
+  // These are cleared last, with the idea of possibly serving cached pages
+  // during the possibly long-running drupal_flush_all_caches() operation.
+  drupal_clear_css_cache();
+  drupal_clear_js_cache();
+  _drupal_flush_css_js();
+  cache('page')->flush();
 }
 
 /**
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 125852a..9e896e0 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1571,28 +1571,31 @@ function install_import_translations_remaining(&$install_state) {
  *   A message informing the user that the installation is complete.
  */
 function install_finished(&$install_state) {
-  drupal_set_title(st('@drupal installation complete', array('@drupal' => drupal_install_profile_distribution_name())), PASS_THROUGH);
-  $messages = drupal_set_message();
-  $output = '<p>' . st('Congratulations, you installed @drupal!', array('@drupal' => drupal_install_profile_distribution_name())) . '</p>';
-  $output .= '<p>' . (isset($messages['error']) ? st('Review the messages above before visiting <a href="@url">your new site</a>.', array('@url' => url(''))) : st('<a href="@url">Visit your new site</a>.', array('@url' => url('')))) . '</p>';
-
-  // Flush all caches to ensure that any full bootstraps during the installer
-  // do not leave stale cached data, and that any content types or other items
-  // registered by the install profile are registered correctly.
-  drupal_flush_all_caches();
-
   // Remember the profile which was used.
   variable_set('install_profile', drupal_get_profile());
 
-  // Install profiles are always loaded last
+  // Install profiles are always loaded last.
   db_update('system')
     ->fields(array('weight' => 1000))
     ->condition('type', 'module')
     ->condition('name', drupal_get_profile())
     ->execute();
 
-  // Cache a fully-built schema.
-  drupal_get_schema(NULL, TRUE);
+  // Flush all caches to ensure that any full bootstraps during the installer
+  // do not leave stale cached data, and that any content types or other items
+  // registered by the install profile are registered correctly.
+  drupal_flush_all_caches();
+
+  // Re-initialize the maintenance theme for the final installation page.
+  // @see drupal_flush_all_caches()
+  unset($GLOBALS['theme']);
+  drupal_maintenance_theme();
+
+  drupal_set_title(st('@drupal installation complete', array('@drupal' => drupal_install_profile_distribution_name())), PASS_THROUGH);
+
+  $messages = drupal_set_message();
+  $output = '<p>' . st('Congratulations, you installed @drupal!', array('@drupal' => drupal_install_profile_distribution_name())) . '</p>';
+  $output .= '<p>' . (isset($messages['error']) ? st('Review the messages above before visiting <a href="@url">your new site</a>.', array('@url' => url(''))) : st('<a href="@url">Visit your new site</a>.', array('@url' => url('')))) . '</p>';
 
   // Run cron to populate update status tables (if available) so that users
   // will be warned if they've installed an out of date Drupal version.
diff --git a/core/includes/module.inc b/core/includes/module.inc
index 6192a38..9aed15b 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -444,10 +444,10 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
         ->condition('name', $module)
         ->execute();
       // Refresh the module list to include it.
+      _system_update_bootstrap_status();
       system_list_reset();
       module_list(TRUE);
       module_implements_reset();
-      _system_update_bootstrap_status();
       // Update the registry to include it.
       registry_update();
       // Refresh the schema to include it.
@@ -567,6 +567,7 @@ function module_disable($module_list, $disable_dependents = TRUE) {
 
   if (!empty($invoke_modules)) {
     // Refresh the module list to exclude the disabled modules.
+    _system_update_bootstrap_status();
     system_list_reset();
     module_list(TRUE);
     module_implements_reset();
@@ -575,7 +576,6 @@ function module_disable($module_list, $disable_dependents = TRUE) {
     module_invoke_all('modules_disabled', $invoke_modules);
     // 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();
   }
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 069e879..5a03ce2 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -938,9 +938,16 @@ function _block_get_renderable_block($element) {
 }
 
 /**
- * Implements hook_flush_caches().
+ * Implements hook_cache_flush().
  */
-function block_flush_caches() {
+function block_cache_flush() {
+  return array('block');
+}
+
+/**
+ * Implements hook_rebuild().
+ */
+function block_rebuild() {
   // Rehash blocks for active themes. We don't use list_themes() here,
   // because if MAINTENANCE_MODE is defined it skips reading the database,
   // and we can't tell which themes are active.
@@ -948,8 +955,6 @@ function block_flush_caches() {
   foreach ($themes as $theme) {
     _block_rehash($theme->name);
   }
-
-  return array('block');
 }
 
 /**
diff --git a/core/modules/comment/comment.test b/core/modules/comment/comment.test
index 1fc8297..cabca76 100644
--- a/core/modules/comment/comment.test
+++ b/core/modules/comment/comment.test
@@ -2086,7 +2086,6 @@ class CommentFieldsTest extends CommentHelperCase {
     $edit['modules[Core][book][enable]'] = 'book';
     $edit['modules[Core][poll][enable]'] = 'poll';
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->resetAll();
 
     // Now enable the comment module.
     $edit = array();
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 1e8b7bb..0220a6e 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -380,14 +380,19 @@ function field_system_info_alter(&$info, $file, $type) {
 }
 
 /**
- * Implements hook_flush_caches().
+ * Implements hook_cache_flush().
  */
-function field_flush_caches() {
+function field_cache_flush() {
+  // Request a flush of our cache table.
+  return array('field');
+}
+
+/**
+ * Implements hook_rebuild().
+ */
+function field_rebuild() {
   // Refresh the 'active' status of fields.
   field_sync_field_status();
-
- // Request a flush of our cache table.
-  return array('field');
 }
 
 /**
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 45f5170..9f492fe 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -6,6 +6,13 @@
  */
 
 /**
+ * Implements hook_cache_flush().
+ */
+function filter_cache_flush() {
+  return array('filter');
+}
+
+/**
  * Implements hook_help().
  */
 function filter_help($path, $arg) {
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 5e1c3b3..9e21bfa 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -77,6 +77,13 @@ const NODE_ACCESS_DENY = 'deny';
 const NODE_ACCESS_IGNORE = NULL;
 
 /**
+ * Implements hook_rebuild().
+ */
+function node_rebuild() {
+  node_types_rebuild();
+}
+
+/**
  * Implements hook_help().
  */
 function node_help($path, $arg) {
@@ -1890,9 +1897,6 @@ function node_menu() {
     'type' => MENU_CALLBACK,
   );
   // @todo Remove this loop when we have a 'description callback' property.
-  // Resets the internal static cache of _node_types_build() and forces a
-  // rebuild of the node type information.
-  node_type_cache_reset();
   foreach (node_type_get_types() as $type) {
     $type_url_str = str_replace('_', '-', $type->type);
     $items['node/add/' . $type_url_str] = array(
diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php
index 540dc0e..57e807d 100644
--- a/core/modules/simpletest/drupal_web_test_case.php
+++ b/core/modules/simpletest/drupal_web_test_case.php
@@ -1493,17 +1493,7 @@ class DrupalWebTestCase extends DrupalTestCase {
    * are enabled later.
    */
   protected function resetAll() {
-    // Reset all static variables.
-    drupal_static_reset();
-    // Reset the list of enabled modules.
-    module_list(TRUE);
-
-    // Reset cached schema for new database prefix. This must be done before
-    // drupal_flush_all_caches() so rebuilds can make use of the schema of
-    // modules enabled on the cURL side.
-    drupal_get_schema(NULL, TRUE);
-
-    // Perform rebuilds and flush remaining caches.
+    // Clear all database and static caches and rebuild data structures.
     drupal_flush_all_caches();
 
     // Reload global $conf array and permissions.
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index c6e1288..37782e8 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -2087,22 +2087,58 @@ function hook_mail($key, &$message, $params) {
 }
 
 /**
- * Add a list of cache tables to be cleared.
+ * Flush all persistent and static caches.
  *
- * This hook allows your module to add cache bins to the list of cache bins
- * that will be cleared by the Clear button on the Performance page or
- * whenever drupal_flush_all_caches is invoked.
+ * This hook asks your module to clear all of its persistent (database) and
+ * static caches, in order to ensure a clean environment for subsequently
+ * invoked data rebuilds.
  *
- * @return
- *   An array of cache bins.
+ * Do NOT use this hook for rebuilding information. Only use it to flush custom
+ * caches and return the names of additional cache bins to flush.
+ *
+ * Static caches using drupal_static() do not need to be reset manually.
+ * However, all other static variables that do not use drupal_static() must be
+ * manually reset.
+ *
+ * This hook is invoked by drupal_flush_all_caches(). It runs before module data
+ * is updated and before hook_rebuild().
+ *
+ * @return array
+ *   An array of cache bins to be flushed.
  *
  * @see drupal_flush_all_caches()
+ * @see hook_rebuild()
  */
-function hook_flush_caches() {
+function hook_cache_flush() {
   return array('example');
 }
 
 /**
+ * Rebuild data based upon refreshed caches.
+ *
+ * This hook allows your module to rebuild its data based on the latest/current
+ * module data. It runs after hook_cache_flush() and after all module data has
+ * been updated.
+ *
+ * This hook is only invoked after the system has been completely
+ * "re-initialized"; i.e., all previously cached data is known to be gone and
+ * every API in the system is known to return current information, so your
+ * module can safely rely on all available data to rebuild its own.
+ *
+ * @see hook_cache_flush()
+ * @see drupal_flush_all_caches()
+ */
+function hook_rebuild() {
+  // Rehash blocks for active themes. We don't use list_themes() here,
+  // because if MAINTENANCE_MODE is defined it skips reading the database,
+  // and we can't tell which themes are active.
+  $themes = db_query("SELECT name FROM {system} WHERE type = 'theme' AND status = 1");
+  foreach ($themes as $theme) {
+    _block_rehash($theme->name);
+  }
+}
+
+/**
  * Perform necessary actions before modules are installed.
  *
  * This function allows all modules to react prior to a module being installed.
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index dfb8936..1caadd9 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2530,8 +2530,6 @@ function _system_update_bootstrap_status() {
     $query->condition('name', $bootstrap_modules, 'NOT IN');
   }
   $query->execute();
-  // Reset the cached list of bootstrap modules.
-  system_list_reset();
 }
 
 /**
@@ -3064,8 +3062,8 @@ function system_cron() {
     }
   }
 
-  $core = array('cache', 'path', 'filter', 'page', 'form', 'menu');
-  $cache_bins = array_merge(module_invoke_all('flush_caches'), $core);
+  $core = array('cache', 'path', 'page', 'form', 'menu');
+  $cache_bins = array_merge(module_invoke_all('cache_flush'), $core);
   foreach ($cache_bins as $bin) {
     cache($bin)->expire();
   }
@@ -3091,13 +3089,11 @@ function system_cron() {
 }
 
 /**
- * Implements hook_flush_caches().
+ * Implements hook_rebuild().
  */
-function system_flush_caches() {
+function system_rebuild() {
   // Rebuild list of date formats.
   system_date_formats_rebuild();
-  // Reset the menu static caches.
-  menu_reset_static_cache();
 }
 
 /**
diff --git a/core/modules/system/system.test b/core/modules/system/system.test
index 16348cc..4ec879f 100644
--- a/core/modules/system/system.test
+++ b/core/modules/system/system.test
@@ -2294,7 +2294,7 @@ class UpdateScriptFunctionalTest extends DrupalWebTestCase {
     $this->drupalPost(NULL, array(), t('Continue'));
     $this->assertText(t('No pending updates.'), t('End of update process was reached.'));
     // Confirm that all caches were cleared.
-    $this->assertText(t('hook_flush_caches() invoked for update_script_test.module.'), 'Caches were cleared when there were no requirements warnings or errors.');
+    $this->assertText(t('hook_cache_flush() invoked for update_script_test.module.'), 'Caches were cleared when there were no requirements warnings or errors.');
 
     // If there is a requirements warning, we expect it to be initially
     // displayed, but clicking the link to proceed should allow us to go
@@ -2312,7 +2312,7 @@ class UpdateScriptFunctionalTest extends DrupalWebTestCase {
     $this->drupalPost(NULL, array(), t('Apply pending updates'));
     $this->assertText(t('The update_script_test_update_8000() update was executed successfully.'), t('End of update process was reached.'));
     // Confirm that all caches were cleared.
-    $this->assertText(t('hook_flush_caches() invoked for update_script_test.module.'), 'Caches were cleared after resolving a requirements warning and applying updates.');
+    $this->assertText(t('hook_cache_flush() invoked for update_script_test.module.'), 'Caches were cleared after resolving a requirements warning and applying updates.');
 
     // Now try again without pending updates to make sure that works too.
     $this->drupalGet($this->update_url, array('external' => TRUE));
@@ -2322,7 +2322,7 @@ class UpdateScriptFunctionalTest extends DrupalWebTestCase {
     $this->drupalPost(NULL, array(), t('Continue'));
     $this->assertText(t('No pending updates.'), t('End of update process was reached.'));
     // Confirm that all caches were cleared.
-    $this->assertText(t('hook_flush_caches() invoked for update_script_test.module.'), 'Caches were cleared after applying updates and re-running the script.');
+    $this->assertText(t('hook_cache_flush() invoked for update_script_test.module.'), 'Caches were cleared after applying updates and re-running the script.');
 
     // If there is a requirements error, it should be displayed even after
     // clicking the link to proceed (since the problem that triggered the error
diff --git a/core/modules/system/tests/cache.test b/core/modules/system/tests/cache.test
index e5d4435..82264c2 100644
--- a/core/modules/system/tests/cache.test
+++ b/core/modules/system/tests/cache.test
@@ -321,7 +321,7 @@ class CacheClearCase extends CacheTestCase {
    */
   function testFlushAllCaches() {
     // Create cache entries for each flushed cache bin.
-    $bins = array('cache', 'filter', 'page', 'bootstrap', 'path');
+    $bins = array('bootstrap', 'cache', 'path', 'page', 'menu');
     $bins = array_merge(module_invoke_all('flush_caches'), $bins);
     foreach ($bins as $id => $bin) {
       $cid = 'test_cid_clear' . $id;
diff --git a/core/modules/system/tests/modules/update_script_test/update_script_test.module b/core/modules/system/tests/modules/update_script_test/update_script_test.module
index beb5a71..986dc31 100644
--- a/core/modules/system/tests/modules/update_script_test/update_script_test.module
+++ b/core/modules/system/tests/modules/update_script_test/update_script_test.module
@@ -6,13 +6,13 @@
  */
 
 /**
- * Implements hook_flush_caches().
+ * Implements hook_cache_flush().
  *
  * This sets a message to confirm that all caches are cleared whenever
  * update.php completes.
  *
  * @see UpdateScriptFunctionalTest::testRequirements()
  */
-function update_script_test_flush_caches() {
-  drupal_set_message(t('hook_flush_caches() invoked for update_script_test.module.'));
+function update_script_test_cache_flush() {
+  drupal_set_message(t('hook_cache_flush() invoked for update_script_test.module.'));
 }
diff --git a/core/modules/update/update.module b/core/modules/update/update.module
index 6142a20..a5eed76 100644
--- a/core/modules/update/update.module
+++ b/core/modules/update/update.module
@@ -836,7 +836,7 @@ function _update_cache_clear($cid = NULL, $wildcard = FALSE) {
 }
 
 /**
- * Implements hook_flush_caches().
+ * Implements hook_cache_flush().
  *
  * Called from update.php (among others) to flush the caches.
  * Since we're running update.php, we are likely to install a new version of
@@ -851,7 +851,7 @@ function _update_cache_clear($cid = NULL, $wildcard = FALSE) {
  * check if the site is in MAINTENANCE_MODE == 'update' (which indicates
  * update.php is running, not update module... alas for overloaded names).
  */
-function update_flush_caches() {
+function update_cache_flush() {
   if (defined('MAINTENANCE_MODE') && MAINTENANCE_MODE == 'update') {
     _update_cache_clear();
   }
