Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.352
diff -u -p -r1.352 bootstrap.inc
--- includes/bootstrap.inc	17 Feb 2010 22:44:51 -0000	1.352
+++ includes/bootstrap.inc	20 Feb 2010 04:56:45 -0000
@@ -847,6 +847,84 @@ function drupal_page_is_cacheable($allow
     && !drupal_is_cli();
 }
 
+
+/**
+ * Return additional information cached along with a cached page.
+ *
+ * Modules can implement hook_cached_page_info() and
+ * hook_cached_page_info_alter() in order to provide information about a page
+ * for Drupal to cache alongside the page content and HTTP headers. This
+ * function is called to retrieve that information.
+ *
+ * Example:
+ * @code
+ * function system_cached_page_info() {
+ *   // The normalized Drupal path and page title are not available until after
+ *   // a full bootstrap. For modules to have access to this information when
+ *   // a cached page is being served, they must be cached along with the page.
+ *   return array(
+ *     'path' => $_GET['q'],
+ *     'title' => drupal_get_title(),
+ *   );
+ * }
+ * function statistics_exit() {
+ *   // The statistics module records information in the db for every time a
+ *   // page is accessed, whether cached or not. If a full bootstrap has taken
+ *   // place, then the path and title can be determined normally. Otherwise,
+ *   // this is likely a cached page request, so the path needs to be retrieved
+ *   // from cache.
+ *   if ((drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL)) {
+ *     $path = $_GET['q'];
+ *     $title = drupal_get_title();
+ *   }
+ *   elseif ($cached_page_info = drupal_get_cached_page_info()) {
+ *     $path = $cached_page_info['path'];
+ *     $title = $cached_page_info['title'];
+ *   }
+ *   ...
+ * }
+ * @endcode
+ *
+ * @param $url
+ *   The full URL of the cached page for which to retrieve information. If NULL,
+ *   information is retrieved for the currently requested page.
+ * @param $key
+ *   This can be set to return information for a single key. If NULL, the entire
+ *   info array is returned.
+ *
+ * @return
+ *   Either the full array of information that modules provided in
+ *   hook_cached_page_info() and hook_cached_page_info_alter() implementations
+ *   that were called when the page was cached, or just the value for $key.
+ *
+ * @see hook_cached_page_info()
+ * @see hook_cached_page_info_alter()
+ */
+function drupal_get_cached_page_info($url = NULL, $key = NULL) {
+  global $base_root;
+  $info = &drupal_static(__FUNCTION__, array());
+
+  // Default to the full url of the currently requested page.
+  if (!isset($url)) {
+    $url = $base_root . request_uri();
+  }
+
+  // Retrieve the cached page info.
+  if (!array_key_exists($url, $info)) {
+    $cache = cache_get('page_info::' . $url, 'cache_page');
+    $info[$url] = is_object($cache) ? $cache->data : NULL;
+  }
+
+  // If $key was passed, return just that information. Otherwise return all the
+  // information.
+  if (isset($key)) {
+    return isset($info[$url][$key]) ? $info[$url][$key] : NULL;
+  }
+  else {
+    return $info[$url];
+  }
+}
+
 /**
  * Call all init or exit hooks without including all modules.
  *
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1113
diff -u -p -r1.1113 common.inc
--- includes/common.inc	18 Feb 2010 06:28:08 -0000	1.1113
+++ includes/common.inc	20 Feb 2010 04:56:46 -0000
@@ -4080,6 +4080,12 @@ function drupal_page_set_cache() {
         $cache->data = gzencode($cache->data, 9, FORCE_GZIP);
       }
       cache_set($cache->cid, $cache->data, 'cache_page', $cache->expire, $cache->headers);
+      // Along with the page content and HTTP headers, cache any additional
+      // information about the page that modules may want available when
+      // processing a cached page request. @see drupal_get_cached_page_info().
+      $info = module_invoke_all('cached_page_info');
+      drupal_alter('cached_page_info', $info);
+      cache_set('page_info::' . $cache->cid, $info, 'cache_page', $cache->expire);
     }
     return $cache;
   }
Index: modules/statistics/statistics.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.module,v
retrieving revision 1.331
diff -u -p -r1.331 statistics.module
--- modules/statistics/statistics.module	7 Feb 2010 17:29:09 -0000	1.331
+++ modules/statistics/statistics.module	20 Feb 2010 04:56:48 -0000
@@ -51,14 +51,33 @@ function statistics_help($path, $arg) {
 function statistics_exit() {
   global $user;
 
-  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+  // Get the normalized Drupal path and page title.
+  if ((drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL)) {
+    // If we're fully boostrapped, chances are this is not a cached page
+    // request, and in any case, we can get the path and title directly.
+    $path = $_GET['q'];
+    $title = drupal_get_title();
+  }
+  elseif ($cached_page_info = drupal_get_cached_page_info()) {
+    // If we're not fully bootstrapped, chances are this is a cached page
+    // request, so try to get the cached information.
+    $path = $cached_page_info['path'];
+    $title = $cached_page_info['title'];
+  }
+  else {
+    // Neither fully bootstrapped nor able to get cached information about
+    // this page.
+    $path = '';
+    $title = '';
+  }
 
+  // Update count of content views.
   if (variable_get('statistics_count_content_views', 0)) {
     // We are counting content views.
-    if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') {
+    if ((arg(0, $path) == 'node') && is_numeric(arg(1, $path)) && arg(2, $path) == '') {
       // A node has been viewed, so update the node's counters.
       db_merge('node_counter')
-        ->key(array('nid' => arg(1)))
+        ->key(array('nid' => arg(1, $path)))
         ->fields(array(
           'daycount' => 1,
           'totalcount' => 1,
@@ -69,12 +88,16 @@ function statistics_exit() {
         ->execute();
     }
   }
+
+  // Log page access.
   if (variable_get('statistics_enable_access_log', 0)) {
-    // Log this page access.
+    // Session information is logged, so the session system needs to be
+    // operational.
+    drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
     db_insert('accesslog')
       ->fields(array(
-        'title' => strip_tags(drupal_get_title()),
-        'path' => $_GET['q'],
+        'title' => strip_tags($title),
+        'path' => $path,
         'url' => $_SERVER['HTTP_REFERER'],
         'hostname' => ip_address(),
         'uid' => $user->uid,
Index: modules/system/system.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v
retrieving revision 1.134
diff -u -p -r1.134 system.api.php
--- modules/system/system.api.php	18 Feb 2010 01:40:46 -0000	1.134
+++ modules/system/system.api.php	20 Feb 2010 04:56:48 -0000
@@ -3221,6 +3221,41 @@ function hook_countries_alter(&$countrie
   // Quebec has seceded from Canada. Add to country list.
   $countries['QC'] = 'Quebec';
 }
+
+/**
+ * Provide information about this page as it is being cached.
+ *
+ * @return
+ *   An associative array of information about the page that may be needed when
+ *   the cached page is requested, but that is too time consuming to determine
+ *   for each request of the cached page.
+ *
+ * @see drupal_get_cached_page_info()
+ * @see hook_cached_page_info_alter()
+ */
+function hook_cached_page_info() {
+  return array(
+    // When serving a cached page, hook_boot() or hook_exit() implementations
+    // may want access to these variables, but be unable to get them without
+    // a time consuming full bootstrap.
+    'path' => $_GET['q'],
+    'title' => drupal_get_title(),
+  );
+}
+
+/**
+ * Alter the information about this page as it being cached.
+ *
+ * @param $info
+ *   The associative array of information from hook_cached_page_info().
+ *
+ * @see drupal_get_cached_page_info()
+ * @see hook_cached_page_info()
+ */
+function hook_cached_page_info_alter(&$info) {
+  // system_cached_page_info() added the incorrect page title. Fix it.
+  $info['title'] = t('SOME OTHER TITLE');
+}
 /**
  * @} End of "addtogroup hooks".
  */
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.890
diff -u -p -r1.890 system.module
--- modules/system/system.module	17 Feb 2010 09:09:30 -0000	1.890
+++ modules/system/system.module	20 Feb 2010 04:56:48 -0000
@@ -3515,3 +3515,13 @@ function system_admin_paths() {
   );
   return $paths;
 }
+
+/**
+ * Implements hook_cached_page_info().
+ */
+function system_cached_page_info() {
+  return array(
+    'path' => $_GET['q'],
+    'title' => drupal_get_title(),
+  );
+}
