diff --git a/core/includes/module.inc b/core/includes/module.inc
index 215d165..c202b8e 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -498,6 +498,7 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
       }
 
       // Allow modules to react prior to the enabling of a module.
+      entity_info_cache_clear();
       module_invoke_all('modules_preenable', array($module));
 
       // Enable the module.
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index a1c93de..b05f4d9 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -1576,6 +1576,11 @@ function hook_field_storage_details_alter(&$details, $field) {
  * Modules implementing this hook should load field values and add them to
  * objects in $entities. Fields with no values should be added as empty arrays.
  *
+ * By the time this hook runs, the relevant field definitions have been
+ * populated and cached in FieldInfo, so calling field_info_field_by_id() on
+ * each field individually is more efficient than loading all fields in memory
+ * upfront with field_info_field_by_ids() (which is uncached).
+ *
  * @param $entity_type
  *   The type of entity, such as 'node' or 'user'.
  * @param $entities
@@ -1593,11 +1598,10 @@ function hook_field_storage_details_alter(&$details, $field) {
  *     fields. If unset or FALSE, only non-deleted fields should be loaded.
  */
 function hook_field_storage_load($entity_type, $entities, $age, $fields, $options) {
-  $field_info = field_info_field_by_ids();
   $load_current = $age == FIELD_LOAD_CURRENT;
 
   foreach ($fields as $field_id => $ids) {
-    $field = $field_info[$field_id];
+    $field = field_info_field_by_id($field_id);
     $field_name = $field['field_name'];
     $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
 
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index 2579126..2278826 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -349,7 +349,6 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
     'langcode' => NULL,
   );
   $options += $default_options;
-  $field_info = field_info_field_by_ids();
 
   $fields = array();
   $grouped_instances = array();
@@ -373,7 +372,7 @@ function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b =
     foreach ($instances as $instance) {
       $field_id = $instance['field_id'];
       $field_name = $instance['field_name'];
-      $field = $field_info[$field_id];
+      $field = field_info_field_by_id($field_id);
       $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op;
       if (function_exists($function)) {
         // Add the field to the list of fields to invoke the hook on.
@@ -736,7 +735,6 @@ function field_attach_form($entity_type, EntityInterface $entity, &$form, &$form
  *     operated on.
  */
 function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $options = array()) {
-  $field_info = field_info_field_by_ids();
   $load_current = $age == FIELD_LOAD_CURRENT;
 
   // Merge default options.
@@ -814,7 +812,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $
         }
         // Collect the storage backend if the field has not been loaded yet.
         if (!isset($skip_fields[$field_id])) {
-          $field = $field_info[$field_id];
+          $field = field_info_field_by_id($field_id);
           $storages[$field['storage']['type']][$field_id][] = $load_current ? $id : $vid;
         }
       }
diff --git a/core/modules/field/field.crud.inc b/core/modules/field/field.crud.inc
index 2b28a56..ba2f09e 100644
--- a/core/modules/field/field.crud.inc
+++ b/core/modules/field/field.crud.inc
@@ -322,7 +322,11 @@ function field_read_field($field_name, $include_additional = array()) {
  * Reads in fields that match an array of conditions.
  *
  * @param array $params
- *   An array of conditions to match against.
+ *   An array of conditions to match against. Keys are columns from the
+ *   'field_config' table, values are conditions to match. Additionally,
+ *   conditions on the 'entity_type' and 'bundle' columns from the
+ *   'field_config_instance' table are supported (select fields having an
+ *   instance on a given bundle).
  * @param array $include_additional
  *   The default behavior of this function is to not return fields that are
  *   inactive or have been deleted. Setting
@@ -340,8 +344,18 @@ function field_read_fields($params = array(), $include_additional = array()) {
 
   // Turn the conditions into a query.
   foreach ($params as $key => $value) {
+    // Allow filtering on the 'entity_type' and 'bundle' columns of the
+    // field_config_instance table.
+    if ($key == 'entity_type' || $key == 'bundle') {
+      if (empty($fci_join)) {
+        $fci_join = $query->join('field_config_instance', 'fci', 'fc.id = fci.field_id');
+      }
+      $key = 'fci.' . $key;
+    }
+
     $query->condition($key, $value);
   }
+
   if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) {
     $query
       ->condition('fc.active', 1)
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index 50b270f..2c610a1 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -6,6 +6,29 @@
  */
 
 use Drupal\field\FieldInstance;
+use Drupal\field\FieldInfo;
+
+/**
+ * Retrieves the Drupal\field\FieldInfo object for the current request.
+ *
+ * @return Drupal\field\FieldInfo
+ *   An instance of the Drupal\field\FieldInfo class.
+ */
+function _field_info_field_cache() {
+  // Use the advanced drupal_static() pattern, since this is called very often.
+  static $drupal_static_fast;
+
+  if (!isset($drupal_static_fast)) {
+    $drupal_static_fast['field_info_field_cache'] = &drupal_static(__FUNCTION__);
+  }
+  $info = &$drupal_static_fast['field_info_field_cache'];
+
+  if (!isset($info)) {
+    $info = new FieldInfo();
+  }
+
+  return $info;
+}
 
 /**
  * @defgroup field_info Field Info API
@@ -35,7 +58,7 @@ function field_info_cache_clear() {
   entity_info_cache_clear();
 
   _field_info_collate_types_reset();
-  _field_info_collate_fields_reset();
+  _field_info_field_cache()->flush();
 }
 
 /**
@@ -153,265 +176,6 @@ function _field_info_collate_types_reset() {
 }
 
 /**
- * Collates all information on existing fields and instances.
- *
- * @return
- *   An associative array containing:
- *   - fields: Array of existing fields, keyed by field ID. This element lists
- *     deleted and non-deleted fields, but not inactive ones. Each field has an
- *     additional element, 'bundles', which is an array of all non-deleted
- *     instances of that field.
- *   - field_ids: Array of field IDs, keyed by field name. This element only
- *     lists non-deleted, active fields.
- *   - instances: Array of existing instances, keyed by entity type, bundle name
- *     and field name. This element only lists non-deleted instances whose field
- *     is active.
- *
- * @see _field_info_collate_fields_reset()
- */
-function _field_info_collate_fields() {
-  // Use the advanced drupal_static() pattern, since this is called very often.
-  static $drupal_static_fast;
-
-  if (!isset($drupal_static_fast)) {
-    $drupal_static_fast['field_info_collate_fields'] = &drupal_static(__FUNCTION__);
-  }
-  $info = &$drupal_static_fast['field_info_collate_fields'];
-
-  if (!isset($info)) {
-    if ($cached = cache('field')->get('field_info_fields')) {
-      $info = $cached->data;
-    }
-    else {
-      $definitions = array(
-        'field_ids' => field_read_fields(array(), array('include_deleted' => 1)),
-        'instances' => field_read_instances(),
-      );
-
-      // Populate 'fields' with all fields, keyed by ID.
-      $info['fields'] = array();
-      foreach ($definitions['field_ids'] as $key => $field) {
-        $info['fields'][$key] = $definitions['field_ids'][$key] = _field_info_prepare_field($field);
-      }
-
-      // Build an array of field IDs for non-deleted fields, keyed by name.
-      $info['field_ids'] = array();
-      foreach ($info['fields'] as $key => $field) {
-        if (!$field['deleted']) {
-          $info['field_ids'][$field['field_name']] = $key;
-        }
-      }
-
-      // Populate 'instances'. Only non-deleted instances are considered.
-      $info['instances'] = array();
-      foreach (field_info_bundles() as $entity_type => $bundles) {
-        foreach ($bundles as $bundle => $bundle_info) {
-          $info['instances'][$entity_type][$bundle] = array();
-        }
-      }
-      foreach ($definitions['instances'] as $instance) {
-        $field = $info['fields'][$instance['field_id']];
-        $instance = _field_info_prepare_instance($instance, $field);
-        $info['instances'][$instance['entity_type']][$instance['bundle']][$instance['field_name']] = new FieldInstance($instance);
-        // Enrich field definitions with the list of bundles where they have
-        // instances. NOTE: Deleted fields in $info['field_ids'] are not
-        // enriched because all of their instances are deleted, too, and
-        // are thus not in $definitions['instances'].
-        $info['fields'][$instance['field_id']]['bundles'][$instance['entity_type']][] = $instance['bundle'];
-      }
-
-      // Populate 'extra_fields'.
-      $extra = module_invoke_all('field_extra_fields');
-      drupal_alter('field_extra_fields', $extra);
-      // Merge in saved settings.
-      foreach ($extra as $entity_type => $bundles) {
-        foreach ($bundles as $bundle => $extra_fields) {
-          $extra_fields = _field_info_prepare_extra_fields($extra_fields, $entity_type, $bundle);
-          $info['extra_fields'][$entity_type][$bundle] = $extra_fields;
-        }
-      }
-
-      cache('field')->set('field_info_fields', $info);
-    }
-  }
-
-  return $info;
-}
-
-/**
- * Clears collated information on existing fields and instances.
- */
-function _field_info_collate_fields_reset() {
-  drupal_static_reset('_field_info_collate_fields');
-  cache('field')->delete('field_info_fields');
-}
-
-/**
- * Prepares a field definition for the current run-time context.
- *
- * Since the field was last saved or updated, new field settings can be
- * expected.
- *
- * @param $field
- *   The raw field structure as read from the database.
- *
- * @return
- *   The field array with storage and settings data added.
- */
-function _field_info_prepare_field($field) {
-  // Make sure all expected field settings are present.
-  $field['settings'] += field_info_field_settings($field['type']);
-  $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
-
-  // Add storage details.
-  $details = (array) module_invoke($field['storage']['module'], 'field_storage_details', $field);
-  drupal_alter('field_storage_details', $details, $field, $instance);
-  $field['storage']['details'] = $details;
-
-  // Initialize the 'bundles' list.
-  $field['bundles'] = array();
-
-  return $field;
-}
-
-/**
- * Prepares an instance definition for the current run-time context.
- *
- * Since the instance was last saved or updated, a number of things might have
- * changed: widgets or formatters disabled, new settings expected, new view
- * modes added, etc.
- *
- * @param $instance
- *   The raw instance structure as read from the database.
- * @param $field
- *   The field structure for the instance.
- *
- * @return
- *   Field instance array.
- */
-function _field_info_prepare_instance($instance, $field) {
-  // Make sure all expected instance settings are present.
-  $instance['settings'] += field_info_instance_settings($field['type']);
-
-  // Set a default value for the instance.
-  if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance['default_value'])) {
-    $instance['default_value'] = NULL;
-  }
-
-  foreach ($instance['display'] as $view_mode => $display) {
-    $instance['display'][$view_mode] = _field_info_prepare_instance_display($field, $display);
-  }
-
-  // Fallback to 'hidden' for view modes configured to use custom display
-  // settings, and for which the instance has no explicit settings.
-  $entity_info = entity_get_info($instance['entity_type']);
-  $view_modes = array_merge(array('default'), array_keys($entity_info['view modes']));
-  $view_mode_settings = field_view_mode_settings($instance['entity_type'], $instance['bundle']);
-  foreach ($view_modes as $view_mode) {
-    if ($view_mode == 'default' || !empty($view_mode_settings[$view_mode]['custom_settings'])) {
-      if (!isset($instance['display'][$view_mode])) {
-        $instance['display'][$view_mode] = array(
-          'type' => 'hidden',
-          'label' => 'above',
-          'settings' => array(),
-          'weight' => 0,
-        );
-      }
-    }
-  }
-
-  return $instance;
-}
-
-/**
- * Adapts display specifications to the current run-time context.
- *
- * @param $field
- *   The field structure for the instance.
- * @param $display
- *   Display specifications as found in $instance['display']['some_view_mode'].
- *
- * @return
- *   The modified $display array.
- */
-function _field_info_prepare_instance_display($field, $display) {
-  $field_type = field_info_field_types($field['type']);
-
-  // Fill in default values.
-  $display += array(
-    'label' => 'above',
-    'type' => $field_type['default_formatter'],
-    'settings' => array(),
-    'weight' => 0,
-  );
-  if ($display['type'] != 'hidden') {
-    $formatter_type = field_info_formatter_types($display['type']);
-    // Fallback to default formatter if formatter type is not available.
-    if (!$formatter_type) {
-      $display['type'] = $field_type['default_formatter'];
-      $formatter_type = field_info_formatter_types($display['type']);
-    }
-    $display['module'] = $formatter_type['module'];
-    // Fill in default settings for the formatter.
-    $display['settings'] += field_info_formatter_settings($display['type']);
-  }
-
-  return $display;
-}
-
-/**
- * Prepares 'extra fields' for the current run-time context.
- *
- * @param $extra_fields
- *   The array of extra fields, as collected in hook_field_extra_fields().
- * @param $entity_type
- *   The entity type.
- * @param $bundle
- *   The bundle name.
- *
- * @return
- *   An array of data about extra fields.
- */
-function _field_info_prepare_extra_fields($extra_fields, $entity_type, $bundle) {
-  $entity_type_info = entity_get_info($entity_type);
-  $bundle_settings = field_bundle_settings($entity_type, $bundle);
-  $extra_fields += array('form' => array(), 'display' => array());
-
-  $result = array();
-  // Extra fields in forms.
-  foreach ($extra_fields['form'] as $name => $field_data) {
-    $settings = isset($bundle_settings['extra_fields']['form'][$name]) ? $bundle_settings['extra_fields']['form'][$name] : array();
-    if (isset($settings['weight'])) {
-      $field_data['weight'] = $settings['weight'];
-    }
-    $result['form'][$name] = $field_data;
-  }
-
-  // Extra fields in displayed entities.
-  $data = $extra_fields['display'];
-  foreach ($extra_fields['display'] as $name => $field_data) {
-    $settings = isset($bundle_settings['extra_fields']['display'][$name]) ? $bundle_settings['extra_fields']['display'][$name] : array();
-    $field_data['visible'] = isset($field_data['visible']) ? $field_data['visible'] : TRUE;
-    $view_modes = array_merge(array('default'), array_keys($entity_type_info['view modes']));
-    foreach ($view_modes as $view_mode) {
-      if (isset($settings[$view_mode])) {
-        $field_data['display'][$view_mode] = $settings[$view_mode];
-      }
-      else {
-        $field_data['display'][$view_mode] = array(
-          'weight' => $field_data['weight'],
-          'visible' => $field_data['visible'],
-        );
-      }
-    }
-    unset($field_data['weight']);
-    $result['display'][$name] = $field_data;
-  }
-
-  return $result;
-}
-
-/**
  * Determines the behavior of a widget with respect to an operation.
  *
  * @param $op
@@ -432,6 +196,22 @@ function field_behaviors_widget($op, $instance) {
 }
 
 /**
+ * Returns a lightweight map of fields across bundles.
+ *
+ * The function only returns active, non deleted fields.
+ *
+ * @return
+ *   An array keyed by field name. Each value is an array with two entries:
+ *   - type: The field type.
+ *   - bundles: The bundles in which the field appears, as an array with entity
+ *     types as keys and the array of bundle names as values.
+ */
+function field_info_field_map() {
+  $cache = _field_info_field_cache();
+  return $cache->getFieldMap();
+}
+
+/**
  * Returns information about field types from hook_field_info().
  *
  * @param $field_type
@@ -552,19 +332,32 @@ function field_info_bundles($entity_type = NULL) {
 /**
  * Returns all field definitions.
  *
+ * Use of this function should be avoided when possible, since it loads and
+ * statically caches a potentially large array of information. Use
+ * field_info_field_map() instead.
+ *
+ * When iterating over the fields present in a given bundle after a call to
+ * field_info_instances($entity_type, $bundle), it is recommended to use
+ * field_info_field() on each individual field instead.
+ *
  * @return
  *   An array of field definitions, keyed by field name. Each field has an
  *   additional property, 'bundles', which is an array of all the bundles to
  *   which this field belongs, keyed by entity type.
+ *
+ * @see field_info_field_map()
  */
 function field_info_fields() {
+  $cache = _field_info_field_cache();
+  $info = $cache->getFields();
+
   $fields = array();
-  $info = _field_info_collate_fields();
-  foreach ($info['fields'] as $key => $field) {
+  foreach ($info as $key => $field) {
     if (!$field['deleted']) {
       $fields[$field['field_name']] = $field;
     }
   }
+
   return $fields;
 }
 
@@ -586,10 +379,8 @@ function field_info_fields() {
  * @see field_info_field_by_id()
  */
 function field_info_field($field_name) {
-  $info = _field_info_collate_fields();
-  if (isset($info['field_ids'][$field_name])) {
-    return $info['fields'][$info['field_ids'][$field_name]];
-  }
+  $cache = _field_info_field_cache();
+  return $cache->getField($field_name);
 }
 
 /**
@@ -607,17 +398,19 @@ function field_info_field($field_name) {
  * @see field_info_field()
  */
 function field_info_field_by_id($field_id) {
-  $info = _field_info_collate_fields();
-  if (isset($info['fields'][$field_id])) {
-    return $info['fields'][$field_id];
-  }
+  $cache = _field_info_field_cache();
+  return $cache->getFieldById($field_id);
 }
 
 /**
  * Returns the same data as field_info_field_by_id() for every field.
  *
- * This function is typically used when handling all fields of some entities
- * to avoid thousands of calls to field_info_field_by_id().
+ * Use of this function should be avoided when possible, since it loads and
+ * statically caches a potentially large array of information.
+ *
+ * When iterating over the fields present in a given bundle after a call to
+ * field_info_instances($entity_type, $bundle), it is recommended to use
+ * field_info_field() on each individual field instead.
  *
  * @return
  *   An array, each key is a field ID and the values are field arrays as
@@ -628,17 +421,28 @@ function field_info_field_by_id($field_id) {
  * @see field_info_field_by_id()
  */
 function field_info_field_by_ids() {
-  $info = _field_info_collate_fields();
-  return $info['fields'];
+  $cache = _field_info_field_cache();
+  return $cache->getFields();
 }
 
 /**
  * Retrieves information about field instances.
  *
+ * Use of this function to retriev instances across separate bundles (i.e. when
+ * the $bundle parameter is NULL) should be avoided when possible, since it
+ * loads and  statically caches a potentially large array of information. Use
+ * field_info_field_map() instead.
+ *
+ * When retrieving the instances of a specific bundle (i.e. when both
+ * $entity_type and $bundle_name are provided, the function also populates a
+ * static cache with the corresponding field definitions, allowing fast
+ * retrieval of field_info_field() later in the request.
+ *
  * @param $entity_type
- *   The entity type for which to return instances.
+ *   (optional) The entity type for which to return instances.
  * @param $bundle_name
- *   The bundle name for which to return instances.
+ *   (optional) The bundle name for which to return instances. If $entity_type
+ *   is NULL, the $bundle_name parameter is ignored.
  *
  * @return
  *   If $entity_type is not set, return all instances keyed by entity type and
@@ -647,22 +451,26 @@ function field_info_field_by_ids() {
  *   return all instances for that bundle.
  */
 function field_info_instances($entity_type = NULL, $bundle_name = NULL) {
-  $info = _field_info_collate_fields();
+  $cache = _field_info_field_cache();
 
-  if (isset($entity_type) && isset($bundle_name)) {
-    return isset($info['instances'][$entity_type][$bundle_name]) ? $info['instances'][$entity_type][$bundle_name] : array();
-  }
-  elseif (isset($entity_type)) {
-    return isset($info['instances'][$entity_type]) ? $info['instances'][$entity_type] : array();
+  if (!isset($entity_type)) {
+    return $cache->getInstances();
   }
-  else {
-    return $info['instances'];
+
+  if (!isset($bundle_name)) {
+    return $cache->getInstances($entity_type);
   }
+
+  return $cache->getBundleInstances($entity_type, $bundle_name);
 }
 
 /**
  * Returns an array of instance data for a specific field and bundle.
  *
+ * The function populates a static cache with all fields and instances used in
+ * the bundle, allowing fast retrieval of field_info_field() or
+ * field_info_instance() later in the request.
+ *
  * @param $entity_type
  *   The entity type for the instance.
  * @param $field_name
@@ -675,9 +483,10 @@ function field_info_instances($entity_type = NULL, $bundle_name = NULL) {
  *   NULL if the instance does not exist.
  */
 function field_info_instance($entity_type, $field_name, $bundle_name) {
-  $info = _field_info_collate_fields();
-  if (isset($info['instances'][$entity_type][$bundle_name][$field_name])) {
-    return $info['instances'][$entity_type][$bundle_name][$field_name];
+  $cache = _field_info_field_cache();
+  $info = $cache->getBundleInstances($entity_type, $bundle_name);
+  if (isset($info[$field_name])) {
+    return $info[$field_name];
   }
 }
 
@@ -735,11 +544,10 @@ function field_info_instance($entity_type, $field_name, $bundle_name) {
  *   The array of pseudo-field elements in the bundle.
  */
 function field_info_extra_fields($entity_type, $bundle, $context) {
-  $info = _field_info_collate_fields();
-  if (isset($info['extra_fields'][$entity_type][$bundle][$context])) {
-    return $info['extra_fields'][$entity_type][$bundle][$context];
-  }
-  return array();
+  $cache = _field_info_field_cache();
+  $info = $cache->getBundleExtraFields($entity_type, $bundle);
+
+  return isset($info[$context]) ? $info[$context] : array();
 }
 
 /**
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index f42df5f..2274b93 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -1001,7 +1001,8 @@ function field_view_field($entity_type, $entity, $field_name, $display = array()
   if ($field = field_info_field($field_name)) {
     if (is_array($display)) {
       // When using custom display settings, fill in default values.
-      $display = _field_info_prepare_instance_display($field, $display);
+      $cache = _field_info_field_cache();
+      $display = $cache->prepareInstanceDisplay($display, $field["type"]);
     }
 
     // Hook invocations are done through the _field_invoke() functions in
diff --git a/core/modules/field/lib/Drupal/field/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php
new file mode 100644
index 0000000..db5dd45
--- /dev/null
+++ b/core/modules/field/lib/Drupal/field/FieldInfo.php
@@ -0,0 +1,628 @@
+<?php
+
+/*
+ * @file
+ * Definition of Drupal\field\FieldInfo.
+ */
+
+namespace Drupal\field;
+
+/**
+ * Provides field and instance definitions for the current runtime environment.
+ *
+ * A Drupal\field\FieldInfo object is created and statically persisted through
+ * the request by the field_info_cache() function. The object properties act as
+ * a "static cache" of fields and instances definitions.
+ *
+ * The preferred way to access definitions is through the getBundleInstances()
+ * method, which keeps cache entries per bundle, storing both fields and
+ * instances for a given bundle. Fields used in multiple bundles are duplicated
+ * in several cache entries, and are merged into a single list in the memory
+ * cache. Cache entries are loaded for bundles as a whole, optimizing memory
+ * and CPU usage for the most common pattern of iterating over all instances of
+ * a bundle rather than accessing a single instance.
+ *
+ * The getFields() and getInstances() methods, which return all existing field
+ * and instance definitions, are kept mainly for backwards compatibility, and
+ * should be avoided when possible, since they load and persist in memory a
+ * potentially large array of information. In many cases, the lightweight
+ * getFieldMap() method should be preferred.
+ */
+class FieldInfo {
+
+  /**
+   * Lightweight map of fields across entity types and bundles.
+   *
+   * @var array
+   */
+  protected $fieldMap;
+
+  /**
+   * List of $field structures keyed by ID. Includes deleted fields.
+   *
+   * @var array
+   */
+  protected $fieldsById = array();
+
+  /**
+   * Mapping of field names to the ID of the corresponding non-deleted field.
+   *
+   * @var array
+   */
+  protected $fieldIdsByName = array();
+
+  /**
+   * Whether $fieldsById contains all field definitions or a subset.
+   *
+   * @var bool
+   */
+  protected $loadedAllFields = FALSE;
+
+  /**
+   * Separately tracks requested field names or IDs that do not exists.
+   *
+   * @var array
+   */
+  protected $unknownFields = array();
+
+  /**
+   * Instance definitions by bundle.
+   *
+   * @var array
+   */
+  protected $bundleInstances = array();
+
+  /**
+   * Whether $bundleInstances contains all instances definitions or a subset.
+   *
+   * @var bool
+   */
+  protected $loadedAllInstances = FALSE;
+
+  /**
+   * Separately tracks requested bundles that are empty (or do not exist).
+   *
+   * @var array
+   */
+  protected $emptyBundles = array();
+
+  /**
+   * Extra fields by bundle.
+   *
+   * @var array
+   */
+  protected $bundleExtraFields = array();
+
+  /**
+   * Clears the "static" and persistent caches.
+   */
+  public function flush() {
+    $this->fieldMap = NULL;
+
+    $this->fieldsById = array();
+    $this->fieldIdsByName = array();
+    $this->loadedAllFields = FALSE;
+    $this->unknownFields = array();
+
+    $this->bundleInstances = array();
+    $this->loadedAllInstances = FALSE;
+    $this->emptyBundles = array();
+
+    $this->bundleExtraFields = array();
+
+    cache('field')->deletePrefix('field_info:');
+  }
+
+  /**
+   * Collects a lightweight map of fields across bundles.
+   *
+   * @return
+   *   An array keyed by field name. Each value is an array with two entries:
+   *   - type: The field type.
+   *   - bundles: The bundles in which the field appears, as an array with
+   *     entity types as keys and the array of bundle names as values.
+   */
+  public function getFieldMap() {
+    // Read from the "static" cache.
+    if ($this->fieldMap !== NULL) {
+      return $this->fieldMap;
+    }
+
+    // Read from persistent cache.
+    if ($cached = cache('field')->get('field_info:field_map')) {
+      $map = $cached->data;
+
+      // Save in "static" cache.
+      $this->fieldMap = $map;
+
+      return $map;
+    }
+
+    $map = array();
+
+    $query = db_select('field_config_instance', 'fci');
+    $query->join('field_config', 'fc', 'fc.id = fci.field_id');
+    $query->fields('fc', array('type'));
+    $query->fields('fci', array('field_name', 'entity_type', 'bundle'))
+      ->condition('fc.active', 1)
+      ->condition('fc.storage_active', 1)
+      ->condition('fc.deleted', 0)
+      ->condition('fci.deleted', 0);
+    foreach ($query->execute() as $row) {
+      $map[$row->field_name]['bundles'][$row->entity_type][] = $row->bundle;
+      $map[$row->field_name]['type'] = $row->type;
+    }
+
+    // Save in "static" and persistent caches.
+    $this->fieldMap = $map;
+    cache('field')->set('field_info:field_map', $map);
+
+    return $map;
+  }
+
+  /**
+   * Returns all active fields, including deleted ones.
+   *
+   * @return
+   *   An array of field definitions, keyed by field ID.
+   */
+  public function getFields() {
+    // Read from the "static" cache.
+    if ($this->loadedAllFields) {
+      return $this->fieldsById;
+    }
+
+    // Read from persistent cache.
+    if ($cached = cache('field')->get('field_info:fields')) {
+      $this->fieldsById = $cached->data;
+    }
+    else {
+      // Collect and prepare fields.
+      foreach (field_read_fields(array(), array('include_deleted' => TRUE)) as $field) {
+        $this->fieldsById[$field['id']] = $this->prepareField($field);
+      }
+
+      // Store in persistent cache.
+      cache('field')->set('field_info:fields', $this->fieldsById);
+    }
+
+    // Fill the name/ID map.
+    foreach ($this->fieldsById as $field) {
+      if (!$field['deleted']) {
+        $this->fieldIdsByName[$field['field_name']] = $field['id'];
+      }
+    }
+
+    $this->loadedAllFields = TRUE;
+
+    return $this->fieldsById;
+  }
+
+  /**
+   * Retrieves all active, non-deleted instances definitions.
+   *
+   * This method does not read from nor populate the "static" and persistent
+   * caches.
+   *
+   * @param $entity_type
+   *   (optional) The entity type.
+   *
+   * @return
+   *   If $entity_type is not set, all instances keyed by entity type and bundle
+   *   name. If $entity_type is set, all instances for that entity type, keyed
+   *   by bundle name.
+   */
+  public function getInstances($entity_type = NULL) {
+    // If the full list is not present in "static" cache yet.
+    if (!$this->loadedAllInstances) {
+
+      // Read from persistent cache.
+      if ($cached = cache('field')->get('field_info:instances')) {
+        $this->bundleInstances = $cached->data;
+      }
+      else {
+        // Collect and prepare instances.
+
+        // We also need to populate the static field cache, since it will not
+        // be set by subsequent getBundleInstances() calls.
+        $this->getFields();
+
+        foreach (field_read_instances() as $instance) {
+          $field = $this->getField($instance['field_name']);
+          $instance = $this->prepareInstance($instance, $field['type']);
+          $this->bundleInstances[$instance['entity_type']][$instance['bundle']][$instance['field_name']] = new FieldInstance($instance);
+        }
+
+        // Store in persistent cache.
+        cache('field')->set('field_info:instances', $this->bundleInstances);
+      }
+
+      $this->loadedAllInstances = TRUE;
+    }
+
+    if (isset($entity_type)) {
+      return isset($this->bundleInstances[$entity_type]) ? $this->bundleInstances[$entity_type] : array();
+    }
+    else {
+      return $this->bundleInstances;
+    }
+  }
+
+  /**
+   * Returns a field definition from a field name.
+   *
+   * This method only retrieves active, non-deleted fields.
+   *
+   * @param $field_name
+   *   The field name.
+   *
+   * @return
+   *   The field definition, or NULL if no field was found.
+   */
+  public function getField($field_name) {
+    // Read from the "static" cache.
+    if (isset($this->fieldIdsByName[$field_name])) {
+      $field_id = $this->fieldIdsByName[$field_name];
+      return $this->fieldsById[$field_id];
+    }
+    if (isset($this->unknownFields[$field_name])) {
+      return;
+    }
+
+    // Do not check the (large) persistent cache, but read the definition.
+
+    // Cache miss: read from definition.
+    if ($field = field_read_field(array('field_name' => $field_name))) {
+      $field = $this->prepareField($field);
+
+      // Save in the "static" cache.
+      $this->fieldsById[$field['id']] = $field;
+      $this->fieldIdsByName[$field['field_name']] = $field['id'];
+
+      return $field;
+    }
+    else {
+      $this->unknownFields[$field_name] = TRUE;
+    }
+  }
+
+  /**
+   * Returns a field definition from a field ID.
+   *
+   * This method only retrieves active fields, deleted or not.
+   *
+   * @param $field_id
+   *   The field ID.
+   *
+   * @return
+   *   The field definition, or NULL if no field was found.
+   */
+  public function getFieldById($field_id) {
+    // Read from the "static" cache.
+    if (isset($this->fieldsById[$field_id])) {
+      return $this->fieldsById[$field_id];
+    }
+    if (isset($this->unknownFields[$field_id])) {
+      return;
+    }
+
+    // No persistent cache, fields are only persistently cached as part of a
+    // bundle.
+
+    // Cache miss: read from definition.
+    if ($fields = field_read_fields(array('id' => $field_id), array('include_deleted' => TRUE))) {
+      $field = current($fields);
+      $field = $this->prepareField($field);
+
+      // Store in the static cache.
+      $this->fieldsById[$field['id']] = $field;
+      if (!$field['deleted']) {
+        $this->fieldIdsByName[$field['field_name']] = $field['id'];
+      }
+
+      return $field;
+    }
+    else {
+      $this->unknownFields[$field_id] = TRUE;
+    }
+  }
+
+  /**
+   * Retrieves the instances for a bundle.
+   *
+   * The function also populates the corresponding field definitions in the
+   * "static" cache.
+   *
+   * @param $entity_type
+   *   The entity type.
+   * @param $bundle
+   *   The bundle name.
+   *
+   * @return
+   *   The array of instance definitions, keyed by field name.
+   */
+  public function getBundleInstances($entity_type, $bundle) {
+    // Read from the "static" cache.
+    if (isset($this->bundleInstances[$entity_type][$bundle])) {
+      return $this->bundleInstances[$entity_type][$bundle];
+    }
+    if (isset($this->emptyBundles[$entity_type][$bundle])) {
+      return array();
+    }
+
+    // Read from the persistent cache.
+    if ($cached = cache('field')->get("field_info:bundle:$entity_type:$bundle")) {
+      $info = $cached->data;
+
+      // Extract the field definitions and save them in the "static" cache.
+      foreach ($info['fields'] as $field) {
+        if (!isset($this->fieldsById[$field['id']])) {
+          $this->fieldsById[$field['id']] = $field;
+          if (!$field['deleted']) {
+            $this->fieldIdsByName[$field['field_name']] = $field['id'];
+          }
+        }
+      }
+      unset($info['fields']);
+
+      // Save in the "static" cache.
+      $this->bundleInstances[$entity_type][$bundle] = $info['instances'];
+
+      return $info['instances'];
+    }
+
+    // Cache miss: collect from the definitions.
+
+    $instances = array();
+
+    // Collect the fields in the bundle.
+    $params = array('entity_type' => $entity_type, 'bundle' => $bundle);
+    $fields = field_read_fields($params);
+
+    // This iterates on non-deleted instances, so deleted fields are kept out of
+    // the persistent caches.
+    foreach (field_read_instances($params) as $instance) {
+      $field = $fields[$instance['field_name']];
+
+      $instance = $this->prepareInstance($instance, $field['type']);
+      $instances[$field['field_name']] = new FieldInstance($instance);
+
+      // If the field is not in our global "static" list yet, add it.
+      if (!isset($this->fieldsById[$field['id']])) {
+        $field = $this->prepareField($field);
+
+        $this->fieldsById[$field['id']] = $field;
+        $this->fieldIdsByName[$field['field_name']] = $field['id'];
+      }
+    }
+
+    // Store in the 'static' cache'. Empty (or non-existent) bundles are stored
+    // separately, so that they do not pollute the global list returned by
+    // getInstances().
+    if ($instances) {
+      $this->bundleInstances[$entity_type][$bundle] = $instances;
+    }
+    else {
+      $this->emptyBundles[$entity_type][$bundle] = TRUE;
+    }
+
+    // The persistent cache additionally contains the definitions of the fields
+    // involved in the bundle.
+    $cache = array(
+      'instances' => $instances,
+      'fields' => array()
+    );
+    foreach ($instances as $instance) {
+      $cache['fields'][] = $this->fieldsById[$instance['field_id']];
+    }
+    cache('field')->set("field_info:bundle:$entity_type:$bundle", $cache);
+
+    return $instances;
+  }
+
+  /**
+   * Retrieves the "extra fields" for a bundle.
+   *
+   * @param $entity_type
+   *   The entity type.
+   * @param $bundle
+   *   The bundle name.
+   *
+   * @return
+   *   The array of extra fields.
+   */
+  public function getBundleExtraFields($entity_type, $bundle) {
+    // Read from the "static" cache.
+    if (isset($this->bundleExtraFields[$entity_type][$bundle])) {
+      return $this->bundleExtraFields[$entity_type][$bundle];
+    }
+
+    // Read from the persistent cache.
+    if ($cached = cache('field')->get("field_info:bundle_extra:$entity_type:$bundle")) {
+      $this->bundleExtraFields[$entity_type][$bundle] = $cached->data;
+      return $this->bundleExtraFields[$entity_type][$bundle];
+    }
+
+    // Cache miss: read from hook_field_extra_fields(). Note: given the current
+    // shape of the hook, we have no other way than collecting extra fields on
+    // all bundles.
+    $info = array();
+    $extra = module_invoke_all('field_extra_fields');
+    drupal_alter('field_extra_fields', $extra);
+    // Merge in saved settings.
+    if (isset($extra[$entity_type][$bundle])) {
+      $info = $this->prepareExtraFields($extra[$entity_type][$bundle], $entity_type, $bundle);
+    }
+
+    // Store in the 'static' and persistent caches.
+    $this->bundleExtraFields[$entity_type][$bundle] = $info;
+    cache('field')->set("field_info:bundle_extra:$entity_type:$bundle", $info);
+
+    return $this->bundleExtraFields[$entity_type][$bundle];
+  }
+
+  /**
+   * Prepares a field definition for the current run-time context.
+   *
+   * @param $field
+   *   The raw field structure as read from the database.
+   *
+   * @return
+   *   The field definition completed for the current runtime context.
+   */
+  public function prepareField($field) {
+    // Make sure all expected field settings are present.
+    $field['settings'] += field_info_field_settings($field['type']);
+    $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
+
+    // Add storage details.
+    $details = (array) module_invoke($field['storage']['module'], 'field_storage_details', $field);
+    drupal_alter('field_storage_details', $details, $field);
+    $field['storage']['details'] = $details;
+
+    // Populate the list of bundles using the field.
+    $field['bundles'] = array();
+    if (!$field['deleted']) {
+      $map = $this->getFieldMap();
+      if (isset($map[$field['field_name']])) {
+        $field['bundles'] = $map[$field['field_name']]['bundles'];
+      }
+    }
+
+    return $field;
+  }
+
+  /**
+   * Prepares an instance definition for the current run-time context.
+   *
+   * @param $instance
+   *   The raw instance structure as read from the database.
+   * @param $field_type
+   *   The field type.
+   *
+   * @return
+   *   The field instance array completed for the current runtime context.
+   */
+  public function prepareInstance($instance, $field_type) {
+    // Make sure all expected instance settings are present.
+    $instance['settings'] += field_info_instance_settings($field_type);
+
+    // Set a default value for the instance.
+    if (field_behaviors_widget('default value', $instance) == FIELD_BEHAVIOR_DEFAULT && !isset($instance['default_value'])) {
+      $instance['default_value'] = NULL;
+    }
+
+    // Prepare display settings.
+    foreach ($instance['display'] as $view_mode => $display) {
+      $instance['display'][$view_mode] = $this->prepareInstanceDisplay($display, $field_type);
+    }
+
+    // Fall back to 'hidden' for view modes configured to use custom display
+    // settings, and for which the instance has no explicit settings.
+    $entity_info = entity_get_info($instance['entity_type']);
+    $view_modes = array_merge(array('default'), array_keys($entity_info['view modes']));
+    $view_mode_settings = field_view_mode_settings($instance['entity_type'], $instance['bundle']);
+    foreach ($view_modes as $view_mode) {
+      if ($view_mode == 'default' || !empty($view_mode_settings[$view_mode]['custom_settings'])) {
+        if (!isset($instance['display'][$view_mode])) {
+          $instance['display'][$view_mode] = array(
+            'type' => 'hidden',
+            'label' => 'above',
+            'settings' => array(),
+            'weight' => 0,
+          );
+        }
+      }
+    }
+
+    return $instance;
+  }
+
+  /**
+   * Adapts display specifications to the current run-time context.
+   *
+   * @param $display
+   *   Display specifications as found in $instance['display']['a_view_mode'].
+   * @param $field_type
+   *   The field type.
+   *
+   * @return
+   *   The display properties completed for the current runtime context.
+   */
+  public function prepareInstanceDisplay($display, $field_type) {
+    $field_type_info = field_info_field_types($field_type);
+
+    // Fill in default values.
+    $display += array(
+      'label' => 'above',
+      'type' => $field_type_info['default_formatter'],
+      'settings' => array(),
+      'weight' => 0,
+    );
+    if ($display['type'] != 'hidden') {
+      $formatter_type_info = field_info_formatter_types($display['type']);
+      // Fall back to default formatter if formatter type is not available.
+      if (!$formatter_type_info) {
+        $display['type'] = $field_type_info['default_formatter'];
+        $formatter_type_info = field_info_formatter_types($display['type']);
+      }
+      $display['module'] = $formatter_type_info['module'];
+      // Fill in default settings for the formatter.
+      $display['settings'] += field_info_formatter_settings($display['type']);
+    }
+
+    return $display;
+  }
+
+  /**
+   * Prepares 'extra fields' for the current run-time context.
+   *
+   * @param $extra_fields
+   *   The array of extra fields, as collected in hook_field_extra_fields().
+   * @param $entity_type
+   *   The entity type.
+   * @param $bundle
+   *   The bundle name.
+   *
+   * @return
+   *   The list of extra fields completed for the current runtime context.
+   */
+  public function prepareExtraFields($extra_fields, $entity_type, $bundle) {
+    $entity_type_info = entity_get_info($entity_type);
+    $bundle_settings = field_bundle_settings($entity_type, $bundle);
+    $extra_fields += array('form' => array(), 'display' => array());
+
+    $result = array();
+    // Extra fields in forms.
+    foreach ($extra_fields['form'] as $name => $field_data) {
+      $settings = isset($bundle_settings['extra_fields']['form'][$name]) ? $bundle_settings['extra_fields']['form'][$name] : array();
+      if (isset($settings['weight'])) {
+        $field_data['weight'] = $settings['weight'];
+      }
+      $result['form'][$name] = $field_data;
+    }
+
+    // Extra fields in displayed entities.
+    $data = $extra_fields['display'];
+    foreach ($extra_fields['display'] as $name => $field_data) {
+      $settings = isset($bundle_settings['extra_fields']['display'][$name]) ? $bundle_settings['extra_fields']['display'][$name] : array();
+      $view_modes = array_merge(array('default'), array_keys($entity_type_info['view modes']));
+      foreach ($view_modes as $view_mode) {
+        if (isset($settings[$view_mode])) {
+          $field_data['display'][$view_mode] = $settings[$view_mode];
+        }
+        else {
+          $field_data['display'][$view_mode] = array(
+            'weight' => $field_data['weight'],
+            'visible' => isset($field_data['visible']) ? $field_data['visible'] : TRUE,
+          );
+        }
+      }
+      unset($field_data['weight']);
+      unset($field_data['visible']);
+      $result['display'][$name] = $field_data;
+    }
+
+    return $result;
+  }
+}
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
index 6f43f55..a55ab14 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php
@@ -63,7 +63,7 @@ class FieldInfoTest extends FieldTestBase {
 
     // Verify that no unexpected instances exist.
     $instances = field_info_instances('test_entity');
-    $expected = array('test_bundle' => array());
+    $expected = array();
     $this->assertIdentical($instances, $expected, "field_info_instances('test_entity') returns " . var_export($expected, TRUE) . '.');
     $instances = field_info_instances('test_entity', 'test_bundle');
     $this->assertIdentical($instances, array(), "field_info_instances('test_entity', 'test_bundle') returns an empty array.");
@@ -120,7 +120,7 @@ class FieldInfoTest extends FieldTestBase {
 
     // Test with an entity type that has no bundles.
     $instances = field_info_instances('user');
-    $expected = array('user' => array());
+    $expected = array();
     $this->assertIdentical($instances, $expected, "field_info_instances('user') returns " . var_export($expected, TRUE) . '.');
     $instances = field_info_instances('user', 'user');
     $this->assertIdentical($instances, array(), "field_info_instances('user', 'user') returns an empty array.");
@@ -235,6 +235,81 @@ class FieldInfoTest extends FieldTestBase {
   }
 
   /**
+   * Test field_info_field_map().
+   */
+  function testFieldMap() {
+    // We will overlook fields created by the 'standard' install profile.
+    $exclude = field_info_field_map();
+
+    // Create a new bundle for 'test_entity' entity type.
+    field_test_create_bundle('test_bundle_2');
+
+    // Create a couple fields.
+    $fields  = array(
+      array(
+        'field_name' => 'field_1',
+        'type' => 'test_field',
+      ),
+      array(
+        'field_name' => 'field_2',
+        'type' => 'hidden_test_field',
+      ),
+    );
+    foreach ($fields as $field) {
+      field_create_field($field);
+    }
+
+    // Create a couple instances.
+    $instances = array(
+      array(
+        'field_name' => 'field_1',
+        'entity_type' => 'test_entity',
+        'bundle' => 'test_bundle',
+      ),
+      array(
+        'field_name' => 'field_1',
+        'entity_type' => 'test_entity',
+        'bundle' => 'test_bundle_2',
+      ),
+      array(
+        'field_name' => 'field_2',
+        'entity_type' => 'test_entity',
+        'bundle' => 'test_bundle',
+      ),
+      array(
+        'field_name' => 'field_2',
+        'entity_type' => 'test_cacheable_entity',
+        'bundle' => 'test_bundle',
+      ),
+    );
+    foreach ($instances as $instance) {
+      field_create_instance($instance);
+    }
+
+    $expected = array(
+      'field_1' => array(
+        'type' => 'test_field',
+        'bundles' => array(
+          'test_entity' => array('test_bundle', 'test_bundle_2'),
+        ),
+      ),
+      'field_2' => array(
+        'type' => 'hidden_test_field',
+        'bundles' => array(
+          'test_entity' => array('test_bundle'),
+          'test_cacheable_entity' => array('test_bundle'),
+        ),
+      ),
+    );
+
+    // Check that the field map is correct.
+    $map = field_info_field_map();
+    $map = array_diff_key($map, $exclude);
+    $this->assertEqual($map, $expected);
+  }
+
+
+  /**
    * Test that the field_info settings convenience functions work.
    */
   function testSettingsInfo() {
diff --git a/core/modules/field/modules/field_sql_storage/field_sql_storage.module b/core/modules/field/modules/field_sql_storage/field_sql_storage.module
index 310cf6c..26b2ba8 100644
--- a/core/modules/field/modules/field_sql_storage/field_sql_storage.module
+++ b/core/modules/field/modules/field_sql_storage/field_sql_storage.module
@@ -335,11 +335,10 @@ function field_sql_storage_field_storage_delete_field($field) {
  * Implements hook_field_storage_load().
  */
 function field_sql_storage_field_storage_load($entity_type, $entities, $age, $fields, $options) {
-  $field_info = field_info_field_by_ids();
   $load_current = $age == FIELD_LOAD_CURRENT;
 
   foreach ($fields as $field_id => $ids) {
-    $field = $field_info[$field_id];
+    $field = field_info_field_by_id($field_id);
     $field_name = $field['field_name'];
     $table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field);
 
diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module
index 2efc07c..e984b87 100644
--- a/core/modules/field_ui/field_ui.module
+++ b/core/modules/field_ui/field_ui.module
@@ -327,23 +327,30 @@ function _field_ui_bundle_admin_path($entity_type, $bundle_name) {
  * Identifies inactive fields within a bundle.
  */
 function field_ui_inactive_instances($entity_type, $bundle_name = NULL) {
-  if (!empty($bundle_name)) {
-    $inactive = array($bundle_name => array());
-    $params = array('bundle' => $bundle_name);
+  $params = array('entity_type' => $entity_type);
+
+  if (empty($bundle_name)) {
+    $active = field_info_instances($entity_type);
+    $inactive = array();
   }
   else {
-    $inactive = array();
-    $params = array();
+    // Restrict to the specified bundle. For consistency with the case where
+    // $bundle_name is NULL, the $active and  $inactive arrays are keyed by
+    // bundle name first.
+    $params['bundle'] = $bundle_name;
+    $active = array($bundle_name => field_info_instances($entity_type, $bundle_name));
+    $inactive = array($bundle_name => array());
   }
-  $params['entity_type'] = $entity_type;
 
-  $active_instances = field_info_instances($entity_type);
+  // Iterate on existing definitions, and spot those that do not appear in the
+  // $active list collected earlier.
   $all_instances = field_read_instances($params, array('include_inactive' => TRUE));
   foreach ($all_instances as $instance) {
-    if (!isset($active_instances[$instance['bundle']][$instance['field_name']])) {
+    if (!isset($active[$instance['bundle']][$instance['field_name']])) {
       $inactive[$instance['bundle']][$instance['field_name']] = $instance;
     }
   }
+
   if (!empty($bundle_name)) {
     return $inactive[$bundle_name];
   }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
index 8783fc8..b5f3714 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
@@ -172,7 +172,7 @@ class ManageFieldsTest extends FieldUiTestBase {
    */
   function assertFieldSettings($bundle, $field_name, $string = 'dummy test string', $entity_type = 'node') {
     // Reset the fields info.
-    _field_info_collate_fields_reset();
+    field_info_cache_clear();
     // Assert field settings.
     $field = field_info_field($field_name);
     $this->assertTrue($field['settings']['test_field_setting'] == $string, 'Field settings were found.');
@@ -262,7 +262,7 @@ class ManageFieldsTest extends FieldUiTestBase {
     $this->fieldUIDeleteField($bundle_path1, $this->field_name, $this->field_label, $this->type);
 
     // Reset the fields info.
-    _field_info_collate_fields_reset();
+    field_info_cache_clear();
     // Check that the field instance was deleted.
     $this->assertNull(field_info_instance('node', $this->field_name, $this->type), 'Field instance was deleted.');
     // Check that the field was not deleted
@@ -272,7 +272,7 @@ class ManageFieldsTest extends FieldUiTestBase {
     $this->fieldUIDeleteField($bundle_path2, $this->field_name, $this->field_label, $type_name2);
 
     // Reset the fields info.
-    _field_info_collate_fields_reset();
+    field_info_cache_clear();
     // Check that the field instance was deleted.
     $this->assertNull(field_info_instance('node', $this->field_name, $type_name2), 'Field instance was deleted.');
     // Check that the field was deleted too.
