diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
index 43ff5f1..767d3a2 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php
@@ -173,67 +173,6 @@ public function invokeFieldMethod($method, EntityInterface $entity) {
     }
   }
 
-   /**
-   * {@inheritdoc}
-   */
-  public function invokeFieldItemPrepareCache(EntityInterface $entity) {
-    foreach (array_keys($entity->getTranslationLanguages()) as $langcode) {
-      // @todo getTranslation() only works on NG entities. Remove the condition
-      // and the second code branch when all core entity types are converted.
-      if ($translation = $entity->getTranslation($langcode)) {
-        foreach ($translation->getPropertyDefinitions() as $property => $definition) {
-          $type_definition = \Drupal::typedData()->getDefinition($definition['type']);
-          // Only create the item objects if needed.
-          if (is_subclass_of($type_definition['class'], '\Drupal\Core\Entity\Field\PrepareCacheInterface')
-            // Prevent legacy field types from skewing performance too much by
-            // checking the existence of the legacy function directly, instead
-            // of making LegacyConfigFieldItem implement PrepareCacheInterface.
-            // @todo Remove once all core field types have been converted (see
-            // http://drupal.org/node/2014671).
-            || (is_subclass_of($type_definition['class'], '\Drupal\field\Plugin\field\field_type\LegacyConfigFieldItem')
-              && isset($type_definition['provider']) && function_exists($type_definition['provider'] . '_field_load'))) {
-
-            // Call the prepareCache() method directly on each item
-            // individually.
-            foreach ($translation->get($property) as $item) {
-              $item->prepareCache();
-            }
-          }
-        }
-      }
-      else {
-        // For BC entities, iterate through the fields and instantiate NG items
-        // objects manually.
-        $definitions = \Drupal::entityManager()->getFieldDefinitions($entity->entityType(), $entity->bundle());
-        foreach ($definitions as $field_name => $definition) {
-          if (!empty($definition['configurable'])) {
-            $type_definition = \Drupal::typedData()->getDefinition($definition['type']);
-            // Only create the item objects if needed.
-            if (is_subclass_of($type_definition['class'], '\Drupal\Core\Entity\Field\PrepareCacheInterface')
-              // @todo Remove once all core field types have been converted
-              // (see http://drupal.org/node/2014671).
-              || (is_subclass_of($type_definition['class'], '\Drupal\field\Plugin\field\field_type\LegacyConfigFieldItem') && function_exists($type_definition['provider'] . '_field_load'))) {
-
-              // Create the items object.
-              $items = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array();
-              $itemsNG = \Drupal::typedData()->create($definition, $items, $field_name, $entity);
-
-              foreach ($itemsNG as $item) {
-                $item->prepareCache();
-              }
-
-              // Put back the items values in the entity.
-              $items = $itemsNG->getValue(TRUE);
-              if ($items !== array() || isset($entity->{$field_name}[$langcode])) {
-                $entity->{$field_name}[$langcode] = $items;
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
   /**
    * Invokes a hook on behalf of the entity.
    *
diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php
index c7f72f7..63a38bf 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php
@@ -163,12 +163,4 @@ public function getQueryServicename();
    */
   public function invokeFieldMethod($method, EntityInterface $entity);
 
-  /**
-   * Invokes the prepareCache() method on all the relevant FieldItem objects.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity object.
-   */
-  public function invokeFieldItemPrepareCache(EntityInterface $entity);
-
 }
diff --git a/core/lib/Drupal/Core/Entity/Field/PrepareCacheInterface.php b/core/lib/Drupal/Core/Entity/Field/PrepareCacheInterface.php
deleted file mode 100644
index 5701523..0000000
--- a/core/lib/Drupal/Core/Entity/Field/PrepareCacheInterface.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Entity\Field\PrepareCacheInterface.
- */
-
-namespace Drupal\Core\Entity\Field;
-
-/**
- * Interface for preparing field values before they enter cache.
- *
- * If a field type implements this interface, the prepareCache() method will be
- * invoked before field values get cached.
- */
-interface PrepareCacheInterface {
-
-  /**
-   * Massages loaded field values before they enter the field cache.
-   *
-   * You should never load fieldable entities within this method, since this is
-   * likely to cause infinite recursions. Use the prepareView() method instead.
-   *
-   * Also note that the method is not called on field values displayed during
-   * entity preview. If the method adds elements that might be needed during
-   * display, you might want to also use prepareView() to add those elements in
-   * case they are not present.
-   */
-  public function prepareCache();
-
-}
diff --git a/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php
index 87b86c0..b86d067 100644
--- a/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php
+++ b/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php
@@ -9,6 +9,8 @@
 
 use Drupal\field\FieldInterface;
 use Drupal\field\FieldInstanceInterface;
+use Drupal\field\Plugin\Type\FieldType\ConfigFieldInterface;
+use Drupal\field\Plugin\Type\FieldType\ConfigFieldItemInterface;
 use Symfony\Component\DependencyInjection\Container;
 
 abstract class FieldableEntityStorageControllerBase extends EntityStorageControllerBase implements FieldableEntityStorageControllerInterface {
@@ -77,20 +79,20 @@ protected function loadFieldItems(array $entities, $age) {
       // Let the storage controller actually load the values.
       $this->doLoadFieldItems($queried_entities, $age);
 
-      // Invoke the field type's prepareCache() method.
-      foreach ($queried_entities as $entity) {
-        $this->invokeFieldItemPrepareCache($entity);
-      }
-
       // Build cache data.
       if ($use_cache) {
         foreach ($queried_entities as $id => $entity) {
           $data = array();
-          $instances = field_info_instances($this->entityType, $entity->bundle());
           foreach ($entity->getTranslationLanguages() as $langcode => $language) {
             $translation = $entity->getTranslation($langcode);
-            foreach ($instances as $instance) {
-              $data[$langcode][$instance['field_name']] = $translation->{$instance['field_name']}->getValue();
+            foreach ($translation as $field_name => $items) {
+              if (!$items->isEmpty() && $items instanceof ConfigFieldInterface) {
+                foreach ($items as $delta => $item) {
+                  if ($item instanceof ConfigFieldItemInterface) {
+                    $data[$langcode][$field_name][$delta] = $item->prepareCache();
+                  }
+                }
+              }
             }
           }
           $cid = "field:{$this->entityType}:$id";
diff --git a/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php b/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php
new file mode 100644
index 0000000..c0f6123
--- /dev/null
+++ b/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\datetime\DateTimeComputed.
+ */
+
+namespace Drupal\datetime;
+
+use Drupal\Core\Datetime\DrupalDateTime;
+use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\Core\TypedData\TypedData;
+
+/**
+ * A computed property for dates of date time field items.
+ *
+ * Required settings (below the definition's 'settings' key) are:
+ *  - date source: The date property containing the to be computed date.
+ */
+class DateTimeComputed extends TypedData {
+
+  /**
+   * Cached computed date.
+   *
+   * @var \DateTime|null
+   */
+  protected $date = NULL;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $definition, $name = NULL, TypedDataInterface $parent = NULL) {
+    parent::__construct($definition, $name, $parent);
+    if (!isset($definition['settings']['date source'])) {
+      throw new \InvalidArgumentException("The definition's 'date source' key has to specify the name of the date property to be computed.");
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValue($langcode = NULL) {
+    if ($this->date !== NULL) {
+      return $this->date;
+    }
+
+    $item = $this->getParent();
+    $value = $item->{($this->definition['settings']['date source'])};
+
+    $storage_format = $item->getFieldDefinition()->getFieldSetting('datetime_type') == 'date' ? DATETIME_DATE_STORAGE_FORMAT : DATETIME_DATETIME_STORAGE_FORMAT;
+    try {
+      $date = DrupalDateTime::createFromFormat($storage_format, $value, DATETIME_STORAGE_TIMEZONE);
+      if ($date instanceOf DrupalDateTime && !$date->hasErrors()) {
+        $this->date = $date;
+      }
+    }
+    catch (\Exception $e) {
+      // @todo Handle this.
+    }
+    return $this->date;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setValue($value, $notify = TRUE) {
+    $this->date = $value;
+    // Notify the parent of any changes.
+    if ($notify && isset($this->parent)) {
+      $this->parent->onChange($this->name);
+    }
+  }
+
+}
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/field_type/DateTimeItem.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/field_type/DateTimeItem.php
index 558ca47..148d472 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/field_type/DateTimeItem.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/field_type/DateTimeItem.php
@@ -31,7 +31,7 @@
  *   default_formatter = "datetime_default"
  * )
  */
-class DateTimeItem extends ConfigFieldItemBase implements PrepareCacheInterface {
+class DateTimeItem extends ConfigFieldItemBase {
 
   /**
    * Field definitions of the contained properties.
@@ -49,6 +49,16 @@ public function getPropertyDefinitions() {
         'type' => 'datetime_iso8601',
         'label' => t('Date value'),
       );
+      static::$propertyDefinitions['date'] = array(
+        'type' => 'datetime_computed',
+        'label' => t('Computed date'),
+        'description' => t('The computed DateTime object.'),
+        'computed' => TRUE,
+        'class' => '\Drupal\datetime\DateTimeComputed',
+        'settings' => array(
+          'date source' => 'value',
+        ),
+      );
     }
 
     return static::$propertyDefinitions;
@@ -115,23 +125,15 @@ public function instanceSettingsForm(array $form, array &$form_state) {
    * {@inheritdoc}
    */
   public function prepareCache() {
+    $values = parent::prepareCache();
     // The function generates a Date object for each field early so that it is
     // cached in the field cache. This avoids the need to generate the object
     // later. The date will be retrieved in UTC, the local timezone adjustment
     // must be made in real time, based on the preferences of the site and user.
-    $value = $this->get('value')->getValue();
-    if (!empty($value)) {
-      $storage_format = $this->getFieldSetting('datetime_type') == 'date' ? DATETIME_DATE_STORAGE_FORMAT : DATETIME_DATETIME_STORAGE_FORMAT;
-      try {
-        $date = DrupalDateTime::createFromFormat($storage_format, $value, DATETIME_STORAGE_TIMEZONE);
-        if ($date instanceOf DrupalDateTime && !$date->hasErrors()) {
-          $this->set('date', $date);
-        }
-      }
-      catch (\Exception $e) {
-        // @todo Handle this.
-      }
+    if (!empty($values['value'])) {
+      $values['date'] = $this->date;
     }
+    return $values;
   }
 
   /**
@@ -142,4 +144,19 @@ public function isEmpty() {
     return $value === NULL || $value === '';
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function onChange($property_name) {
+    // Notify the parent of changes.
+    if (isset($this->parent)) {
+      $this->parent->onChange($this->name);
+    }
+
+    // Enforce that the computed date is recalculated.
+    if ($property_name == 'value') {
+      $this->date = NULL;
+    }
+  }
+
 }
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
index 03f172f..9b3d257 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
@@ -103,11 +103,8 @@ public function viewElements(FieldInterface $items) {
       $formatted_date = '';
       $iso_date = '';
 
-      if (!empty($item->date)) {
-        // The date was created and verified during field_load(), so it is safe
-        // to use without further inspection.
-        $date = $item->date;
-
+      if ($items[$delta]->date) {
+        $date = $items[$delta]->date;
         // Create the ISO date in Universal Time.
         $iso_date = $date->format("Y-m-d\TH:i:s") . 'Z';
 
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php
index 600092f..a942fa6 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php
@@ -36,10 +36,10 @@ public function viewElements(FieldInterface $items) {
     foreach ($items as $delta => $item) {
 
       $output = '';
-      if (!empty($item->date)) {
+      if ($items[$delta]->date) {
+        $date = $items[$delta]->date;
         // The date was created and verified during field_load(), so it is safe
         // to use without further inspection.
-        $date = $item->date;
         $date->setTimeZone(timezone_open(drupal_get_user_timezone()));
         $format = DATETIME_DATETIME_STORAGE_FORMAT;
         if ($this->getFieldSetting('datetime_type') == 'date') {
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
index 37d2c3b..cb36032 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
@@ -126,7 +126,7 @@ public function formElement(FieldInterface $items, $delta, array $element, array
     // validator will not have access to the field definition.
     $element['value']['#date_storage_format'] = $storage_format;
 
-    if (!empty($items[$delta]->date)) {
+    if ($items[$delta]->date) {
       $date = $items[$delta]->date;
       // The date was created and verified during field_load(), so it is safe to
       // use without further inspection.
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
index 6628dbb..4b747cb 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
@@ -114,8 +114,7 @@ public function formElement(FieldInterface $items, $delta, array $element, array
     // validator will not have access to the field definition.
     $element['value']['#date_element_format'] = $element_format;
     $element['value']['#date_storage_format'] = $storage_format;
-
-    if (!empty($items[$delta]->date)) {
+    if ($items[$delta]->date) {
       $date = $items[$delta]->date;
       // The date was created and verified during field_load(), so it is safe to
       // use without further inspection.
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php
index 6b3c137..7e5399f 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigEntityReferenceItemBase.php
@@ -172,4 +172,11 @@ protected function getLegacyCallback($hook) {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareCache() {
+    return $this->getValue();
+  }
+
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemBase.php
index eb16d87..456d42d 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemBase.php
@@ -28,4 +28,12 @@ public function instanceSettingsForm(array $form, array &$form_state) {
     return array();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareCache() {
+    return $this->getValue();
+  }
+
+
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemInterface.php b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemInterface.php
index 88de2ac..161deeb 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemInterface.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/FieldType/ConfigFieldItemInterface.php
@@ -89,4 +89,20 @@ public function settingsForm(array $form, array &$form_state, $has_data);
    */
   public function instanceSettingsForm(array $form, array &$form_state);
 
+  /**
+   * Massages loaded field values before they enter the field cache.
+   *
+   * You should never load fieldable entities within this method, since this is
+   * likely to cause infinite recursions. Use the prepareView() method instead.
+   *
+   * Also note that the method is not called on field values displayed during
+   * entity preview. If the method adds elements that might be needed during
+   * display, you might want to also use prepareView() to add those elements in
+   * case they are not present.
+   *
+   * @return array
+   *   Array of field item values that should be cached.
+   */
+  public function prepareCache();
+
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItem.php b/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItem.php
index e46622f..39070f9 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItem.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/field/field_type/LegacyConfigFieldItem.php
@@ -26,7 +26,7 @@
  * @todo Remove once all core field types have been converted (see
  * http://drupal.org/node/2014671).
  */
-abstract class LegacyConfigFieldItem extends ConfigFieldItemBase implements PrepareCacheInterface {
+abstract class LegacyConfigFieldItem extends ConfigFieldItemBase {
 
   /**
    * {@inheritdoc}
@@ -105,7 +105,9 @@ public function prepareCache() {
       );
       call_user_func_array($callback, $args);
       $this->setValue($items[$entity_id][0]);
+      return $items[$entity_id][0];
     }
+    return $this->getValue();
   }
 
   /**
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
index 2de2456..7bccfd8 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachStorageTest.php
@@ -90,8 +90,6 @@ function testFieldAttachSaveLoad() {
       for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
         // The field value loaded matches the one inserted or updated.
         $this->assertEqual($entity->{$this->field_name}[$delta]->value, $values[$revision_id][$delta]['value'], format_string('Revision %revision_id: expected value %delta was found.', array('%revision_id' => $revision_id, '%delta' => $delta)));
-        // The value added in hook_field_load() is found.
-        $this->assertEqual($entity->{$this->field_name}[$delta]->additional_key, 'additional_value', format_string('Revision %revision_id: extra information for value %delta was found', array('%revision_id' => $revision_id, '%delta' => $delta)));
       }
     }
   }
@@ -100,7 +98,7 @@ function testFieldAttachSaveLoad() {
    * Test the 'multiple' load feature.
    */
   function testFieldAttachLoadMultiple() {
-    $entity_type = 'entity_test';
+    $entity_type = 'entity_test_rev';
 
     // Define 2 bundles.
     $bundles = array(
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/field_type/FileItem.php b/core/modules/file/lib/Drupal/file/Plugin/field/field_type/FileItem.php
index 2ee23f4..02893e0 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/field_type/FileItem.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/field_type/FileItem.php
@@ -344,4 +344,11 @@ public function getUploadValidators() {
     return $validators;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareCache() {
+    return $this->getValue();
+  }
+
 }
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php
index 54630fd..625d4e8 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php
@@ -13,7 +13,7 @@
 /**
  * Base class for 'text' configurable field types.
  */
-abstract class TextItemBase extends ConfigFieldItemBase implements PrepareCacheInterface {
+abstract class TextItemBase extends ConfigFieldItemBase {
 
   /**
    * Definitions of the contained properties.
@@ -71,6 +71,7 @@ public function isEmpty() {
    * {@inheritdoc}
    */
   public function prepareCache() {
+    $values = parent::prepareCache();
     // Where possible, generate the processed (sanitized) version of each
     // textual property (e.g., 'value', 'summary') within this field item early
     // so that it is cached in the field cache. This avoids the need to look up
@@ -79,10 +80,11 @@ public function prepareCache() {
     if (!$text_processing || filter_format_allowcache($this->get('format')->getValue())) {
       foreach ($this->getPropertyDefinitions() as $property => $definition) {
         if (isset($definition['class']) && ($definition['class'] == '\Drupal\text\TextProcessed')) {
-          $this->get($property)->getValue();
+          $values[$property] = $this->get($property)->getValue();
         }
       }
     }
+    return $values;
   }
 
   /**
diff --git a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
index ef9a7df..f3808c9 100644
--- a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
@@ -119,8 +119,30 @@ function testProcessedCache() {
     $entity->name->value = $this->randomName();
     $entity->save();
 
-    // Inject values into the cache to make sure that these are used as-is and
-    // not re-calculated.
+    // Check that the processed values are correctly computed.
+    $this->assertEqual($entity->summary_field->processed, $value);
+    $this->assertEqual($entity->summary_field->summary_processed, $summary);
+
+    // Load the entity and check that the field cache contains the expected
+    // data.
+    $entity = entity_load($entity_type, $entity->id());
+    $cache = cache('field')->get("field:$entity_type:" . $entity->id());
+    $this->assertEqual($cache->data, array(
+      Language::LANGCODE_DEFAULT => array(
+        'summary_field' => array(
+          0 => array(
+            'value' => $value,
+            'summary' => $summary,
+            'format' => 'plain_text',
+            'processed' => $value,
+            'summary_processed' => $summary,
+          ),
+        ),
+      ),
+    ));
+
+    // Inject fake processed values into the cache to make sure that these are
+    // used as-is and not re-calculated when the entity is loaded.
     $data = array(
       Language::LANGCODE_DEFAULT => array(
         'summary_field' => array(
@@ -135,8 +157,7 @@ function testProcessedCache() {
       ),
     );
     cache('field')->set("field:$entity_type:" . $entity->id(), $data);
-
-    $entity = entity_load($entity_type, $entity->id());
+    $entity = entity_load($entity_type, $entity->id(), TRUE);
     $this->assertEqual($entity->summary_field->processed, 'Cached processed value');
     $this->assertEqual($entity->summary_field->summary_processed, 'Cached summary processed value');
 
diff --git a/core/modules/text/lib/Drupal/text/TextProcessed.php b/core/modules/text/lib/Drupal/text/TextProcessed.php
index f3c65e2..bbf0fd0 100644
--- a/core/modules/text/lib/Drupal/text/TextProcessed.php
+++ b/core/modules/text/lib/Drupal/text/TextProcessed.php
@@ -47,7 +47,12 @@ public function getValue($langcode = NULL) {
 
     $item = $this->getParent();
     $text = $item->{($this->definition['settings']['text source'])};
-    if ($item->getFieldDefinition()->getFieldSetting('text_processing')) {
+
+    // Avoid running check_markup() or check_plain() on empty strings.
+    if (!isset($text) || $text === '') {
+      $this->processed = '';
+    }
+    elseif ($item->getFieldDefinition()->getFieldSetting('text_processing')) {
       $this->processed = check_markup($text, $item->format, $item->getLangcode());
     }
     else {
