diff --git a/core/includes/common.inc b/core/includes/common.inc
index 2f14740..7f8a787 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -7428,46 +7428,67 @@ 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.
+ * Clears static caches, 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.
+ * Note that after clearing all static caches also the theme is not initialized
+ * any more and any possible previously added Javascript or CSS is gone.
  */
 function drupal_flush_all_caches() {
-  // Change query-strings on css/js files to enforce reload for all users.
-  _drupal_flush_css_js();
-
+  // We start rebuilding foundational data ("prepare phase"), then flush all
+  // caches so that any foundational changes take affect in afterwards
+  // initialized caches. Then, go in rebuild phase to allow modules to rebuild
+  // data based upon fresh caches.
+
+  // Rebuild the registry, module and theme data. Note that the module data is
+  // rebuilt as part of registry_rebuild().
+  module_list(TRUE);
+  module_implements_reset();
   registry_rebuild();
-  drupal_clear_css_cache();
-  drupal_clear_js_cache();
-
-  // Rebuild the theme data. Note that the module data is rebuilt above, as
-  // part of registry_rebuild().
   system_rebuild_theme_data();
-  drupal_theme_rebuild();
 
-  // @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 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();
 
   // Synchronize to catch any actions that were added or removed.
   actions_synchronize();
 
+  // Allow modules to prepare re-initializing caches, i.e. prepare data required
+  // by caches. E.g. this hook could be used to process configuration provided
+  // by modules, so that those configuration is reflected in the refreshed
+  // caches afterwards.
+  module_invoke_all('flush_caches_prepare');
+
+  // Now start flushing all static and permanent caches.
+  drupal_static_reset();
+
   // 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');
+  // Postpone clearing page cache to the end to keep serving from cache in the
+  // meanwhile.
+  $core = array('cache', 'path', 'filter', 'bootstrap');
   $cache_bins = array_merge(module_invoke_all('flush_caches'), $core);
   foreach ($cache_bins as $bin) {
     cache($bin)->flush();
   }
 
-  // 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();
+  // Clear the static schema cache as well.
+  // @todo: Fix to not rebuild the schema immediately.
+  drupal_get_schema(NULL, TRUE);
+
+  // Rebuild phase. Allow modules to rebuild data based upon caches.
+  module_invoke_all('rebuild');
+
+  // Now rebuild the menu based upon re-freshed caches. Thus, this will
+  // re-initialize lots of caches.
+  menu_rebuild();
+
+  // Now clear page, CSS and JS caches.
+  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 3f5eb2e..f430015 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1532,6 +1532,10 @@ function install_finished(&$install_state) {
   // registered by the install profile are registered correctly.
   drupal_flush_all_caches();
 
+  // Re-initialize the maintenance theme.
+  unset($GLOBALS['theme']);
+  drupal_maintenance_theme();
+
   // Remember the profile which was used.
   variable_set('install_profile', drupal_get_profile());
 
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 4d942ed..142f186 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -918,9 +918,9 @@ function _block_get_renderable_block($element) {
 }
 
 /**
- * Implements hook_flush_caches().
+ * Implements hook_rebuild().
  */
-function block_flush_caches() {
+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.
@@ -928,8 +928,7 @@ function block_flush_caches() {
   foreach ($themes as $theme) {
     _block_rehash($theme->name);
   }
-
-  return array('block');
+  cache('block')->flush();
 }
 
 /**
diff --git a/core/modules/comment/comment.test b/core/modules/comment/comment.test
index 9a77853..86986f2 100644
--- a/core/modules/comment/comment.test
+++ b/core/modules/comment/comment.test
@@ -1961,12 +1961,13 @@ 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();
     $edit['modules[Core][comment][enable]'] = 'comment';
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
+    // Be sure to load the newly enabled modules and reset all.
+    module_load_all();
     $this->resetAll();
     $this->assertTrue(module_exists('comment'), t('Comment module enabled.'));
 
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 9129fd5..8a2761a 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -409,10 +409,16 @@ function field_system_info_alter(&$info, $file, $type) {
 }
 
 /**
+ * Implements hook_flush_caches_prepare().
+ */
+function field_flush_caches_prepare() {
+  field_sync_field_status();
+}
+
+/**
  * Implements hook_flush_caches().
  */
 function field_flush_caches() {
-  field_sync_field_status();
   return array('field');
 }
 
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 3b8942f..975a8fb 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -772,6 +772,13 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE)
 }
 
 /**
+ * Implements hook_flush_caches().
+ */
+function filter_flush_caches() {
+  return array('filter');
+}
+
+/**
  * Expands an element into a base element with text format selector attached.
  *
  * The form element will be expanded into two separate form elements, one
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index c7be759..cc183f3 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -765,6 +765,13 @@ function node_type_cache_reset() {
 }
 
 /**
+ * Implements hook_flush_caches_prepare().
+ */
+function node_flush_caches_prepare() {
+  node_types_rebuild();
+}
+
+/**
  * Sets the default values for a node type.
  *
  * The defaults are appropriate for a type defined through hook_node_info(),
@@ -2063,9 +2070,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 cdab966..f9ea24d 100644
--- a/core/modules/simpletest/drupal_web_test_case.php
+++ b/core/modules/simpletest/drupal_web_test_case.php
@@ -1472,17 +1472,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.
+    // Perform rebuilds and flush caches.
     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 27c79c7..887f47e 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -2058,22 +2058,83 @@ function hook_mail($key, &$message, $params) {
 }
 
 /**
- * Add a list of cache tables to be cleared.
+ * Flush all 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 allows your module to clear its caches. It should not be used for
+ * rebuilding information though, just flush caches and re-initialize caches
+ * upon request. For that the hook allows your module to return an array of
+ * cache bins to be cleared. Also, any static variables that are not implemented
+ * with drupal_static() should be cleared using this hook.
+ *
+ * This hook is invoked by drupal_flush_all_caches or the Clear button on the
+ * Performance page. It runs after hook_flush_caches_prepare() and before
+ * hook_rebuild(). hook_flush_caches_prepare() should be used for rebuilding any
+ * foundational data, which should be reflected in refreshed caches. Rebuild
+ * operations that require already refreshed caches to run should be implemented
+ * using hook_rebuild().
  *
  * @return
- *   An array of cache bins.
+ *   An array of cache bins to be flushed.
  *
  * @see drupal_flush_all_caches()
+ * @see hook_flush_caches_prepare()
+ * @see hook_rebuild()
  */
 function hook_flush_caches() {
   return array('example');
 }
 
 /**
+ * Prepare flushing all caches.
+ *
+ * This hook runs before hook_flush_caches(). It allows modules to rebuild
+ * any foundational data, which should be reflected in refreshed caches. For
+ * example, it could be used to sync configuration provided by modules to the
+ * database.
+ *
+ * When this hook is invoked, no caches have been flushed yet, however the
+ * registry as well as module and theme data has been already rebuilt. Rebuild
+ * operations which require refreshed caches should be implemented using
+ * hook_rebuild().
+ *
+ * @see drupal_flush_all_caches()
+ * @see hook_flush_caches()
+ * @see hook_rebuild()
+ */
+function hook_flush_caches_prepare() {
+  node_types_rebuild();
+}
+
+/**
+ * Rebuild data based upon refreshed caches.
+ *
+ * This hook runs after hook_flush_caches_prepare() and hook_flush_caches().
+ * It allows modules to implement final rebuild operations which require
+ * refreshed caches, like rebuilding the menu.
+ * Any caches that need to be flushed for the changes to take effect should be
+ * flushed once the rebuild operation is complete.
+ *
+ * When this hook is invoked, all caches have been flushed so fresh caches are
+ * available. However, data which is required by other modules and should be
+ * reflected in their caches should be rebuilt using
+ * hook_flush_caches_prepare().
+ *
+ * @see drupal_flush_all_caches()
+ * @see hook_flush_caches_prepare()
+ * @see hook_rebuild()
+ */
+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);
+  }
+  cache('block')->flush();
+}
+
+/**
  * 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 20607d4..05db191 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -3072,13 +3072,11 @@ function system_cron() {
 }
 
 /**
- * Implements hook_flush_caches().
+ * Implements hook_flush_caches_prepare().
  */
-function system_flush_caches() {
+function system_flush_caches_prepare() {
   // Rebuild list of date formats.
   system_date_formats_rebuild();
-  // Reset the menu static caches.
-  menu_reset_static_cache();
 }
 
 /**
