diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index eee53b1..554cacc 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -3241,21 +3241,24 @@ function _system_default_theme_features() {
  *   An array of regions in the form $region['name'] = 'description'.
  */
 function system_region_list($theme_key, $show = REGIONS_ALL) {
-  $themes = list_themes();
-  if (!isset($themes[$theme_key])) {
-    return array();
-  }
+  $list = &drupal_static(__FUNCTION__, array());
+  if (!isset($list[$theme_key])) {
+    $list[$theme_key] = array(REGIONS_ALL => array(), REGIONS_VISIBLE => array());
+    $themes = list_themes();
+    if (isset($themes[$theme_key])) {
+      $info = $themes[$theme_key]->info;
+      foreach ($info['regions'] as $name => $label) {
+        $list[$theme_key][REGIONS_ALL][$name] = t($label);
+      }
 
-  $list = array();
-  $info = $themes[$theme_key]->info;
-  // If requested, suppress hidden regions. See block_admin_display_form().
-  foreach ($info['regions'] as $name => $label) {
-    if ($show == REGIONS_ALL || !isset($info['regions_hidden']) || !in_array($name, $info['regions_hidden'])) {
-      $list[$name] = t($label);
+      // Also cache a list with hidden regions suppressed.
+      // See block_admin_display_form().
+      $hidden = isset($info['regions_hidden']) ? array_flip($info['regions_hidden']) : array();
+      $list[$theme_key][REGIONS_VISIBLE] = array_diff_key($list[$theme_key][REGIONS_ALL], $hidden);
     }
   }
 
-  return $list;
+  return $list[$theme_key][$show];
 }
 
 /**
