diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index d3522ac..d68421b 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -41,6 +41,13 @@
 const COMMENT_MODE_THREADED = 1;
 
 /**
+ * All comments are displayed, not only published ones (which is the default).
+ * Some functions accept this mode in addition to (OR-ed with) COMMENT_MODE
+ * constants, but it is not a 'setting' like the other modes.
+ */
+const COMMENT_ACCESS_MODE_ADMIN = 2;
+
+/**
  * Anonymous posters cannot enter their contact information.
  */
 const COMMENT_ANONYMOUS_MAYNOT_CONTACT = 0;
@@ -562,107 +569,17 @@ function comment_add(EntityInterface $entity, $field_name = 'comment', $pid = NU
  * @return int[]
  *   An array of the IDs of the comment to be displayed.
  *
- * To display threaded comments in the correct order we keep a 'thread' field
- * and order by that value. This field keeps this data in
- * a way which is easy to update and convenient to use.
- *
- * A "thread" value starts at "1". If we add a child (A) to this comment,
- * we assign it a "thread" = "1.1". A child of (A) will have "1.1.1". Next
- * brother of (A) will get "1.2". Next brother of the parent of (A) will get
- * "2" and so on.
- *
- * First of all note that the thread field stores the depth of the comment:
- * depth 0 will be "X", depth 1 "X.X", depth 2 "X.X.X", etc.
- *
- * Now to get the ordering right, consider this example:
- *
- * 1
- * 1.1
- * 1.1.1
- * 1.2
- * 2
- *
- * If we "ORDER BY thread ASC" we get the above result, and this is the
- * natural order sorted by time. However, if we "ORDER BY thread DESC"
- * we get:
- *
- * 2
- * 1.2
- * 1.1.1
- * 1.1
- * 1
- *
- * Clearly, this is not a natural way to see a thread, and users will get
- * confused. The natural order to show a thread by time desc would be:
- *
- * 2
- * 1
- * 1.2
- * 1.1
- * 1.1.1
- *
- * which is what we already did before the standard pager patch. To achieve
- * this we simply add a "/" at the end of each "thread" value. This way, the
- * thread fields will look like this:
- *
- * 1/
- * 1.1/
- * 1.1.1/
- * 1.2/
- * 2/
- *
- * we add "/" since this char is, in ASCII, higher than every number, so if
- * now we "ORDER BY thread DESC" we get the correct order. However this would
- * spoil the reverse ordering, "ORDER BY thread ASC" -- here, we do not need
- * to consider the trailing "/" so we use a substring only.
+ * @deprecated Deprecated since Drupal 8.x-dev, to be removed in Drupal 8.0.
+ *   Use \Drupal::entityManager()->getStorage('comment')->loadThread() instead,
+ *   which returns objects instead of IDs, and use COMMENT_ACCESS_MODE_ADMIN
+ *   when necessary.
  */
 function comment_get_thread(EntityInterface $entity, $field_name, $mode, $comments_per_page, $pager_id = 0) {
-  $query = db_select('comment', 'c')
-    ->extend('Drupal\Core\Database\Query\PagerSelectExtender');
-  if ($pager_id) {
-    $query->element($pager_id);
-  }
-  $query->addField('c', 'cid');
-  $query
-    ->condition('c.entity_id', $entity->id())
-    ->condition('c.entity_type', $entity->getEntityTypeId())
-    ->condition('c.field_name', $field_name)
-    ->addTag('entity_access')
-    ->addTag('comment_filter')
-    ->addMetaData('base_table', 'comment')
-    ->addMetaData('entity', $entity)
-    ->addMetaData('field_name', $field_name)
-    ->limit($comments_per_page);
-
-  $count_query = db_select('comment', 'c');
-  $count_query->addExpression('COUNT(*)');
-  $count_query
-    ->condition('c.entity_id', $entity->id())
-    ->condition('c.entity_type', $entity->getEntityTypeId())
-    ->condition('c.field_name', $field_name)
-    ->addTag('entity_access')
-    ->addTag('comment_filter')
-    ->addMetaData('base_table', 'comment')
-    ->addMetaData('entity', $entity)
-    ->addMetaData('field_name', $field_name);
-
-  if (!user_access('administer comments')) {
-    $query->condition('c.status', CommentInterface::PUBLISHED);
-    $count_query->condition('c.status', CommentInterface::PUBLISHED);
+  if (\Drupal::currentUser()->hasPermission('administer comments')) {
+    $mode |= COMMENT_ACCESS_MODE_ADMIN;
   }
-  if ($mode == COMMENT_MODE_FLAT) {
-    $query->orderBy('c.cid', 'ASC');
-  }
-  else {
-    // See comment above. Analysis reveals that this doesn't cost too
-    // much. It scales much much better than having the whole comment
-    // structure.
-    $query->addExpression('SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))', 'torder');
-    $query->orderBy('torder', 'ASC');
-  }
-
-  $query->setCountQuery($count_query);
-  return $query->execute()->fetchCol();
+  $comments = \Drupal::entityManager()->getStorage('comment')->loadThread($entity, $field_name, $mode, $comments_per_page, $pager_id);
+  return array_keys($comments);
 }
 
 /**
@@ -908,11 +825,14 @@ function comment_node_update_index(EntityInterface $node, $langcode) {
       $field_definition = $node->getFieldDefinition($field_name);
       $mode = $field_definition->getSetting('default_mode');
       $comments_per_page = $field_definition->getSetting('per_page');
-      if ($node->get($field_name)->status && $cids = comment_get_thread($node, $field_name, $mode, $comments_per_page)) {
-        $comments = entity_load_multiple('comment', $cids);
-        comment_prepare_thread($comments);
-        $build = comment_view_multiple($comments);
-        $return .= drupal_render($build);
+      if ($node->get($field_name)->status) {
+        $comments = \Drupal::entityManager()->getStorage('comment')
+          ->loadThread($node, $field_name, $mode, $comments_per_page);
+        if ($comments) {
+          comment_prepare_thread($comments);
+          $build = comment_view_multiple($comments);
+          $return .= drupal_render($build);
+        }
       }
     }
   }
diff --git a/core/modules/comment/src/CommentStorage.php b/core/modules/comment/src/CommentStorage.php
index 2cffb5e..77b1706 100644
--- a/core/modules/comment/src/CommentStorage.php
+++ b/core/modules/comment/src/CommentStorage.php
@@ -129,6 +129,121 @@ public function getChildCids(array $comments) {
 
   /**
    * {@inheritdoc}
+   *
+   * To display threaded comments in the correct order we keep a 'thread' field
+   * and order by that value. This field keeps this data in
+   * a way which is easy to update and convenient to use.
+   *
+   * A "thread" value starts at "1". If we add a child (A) to this comment,
+   * we assign it a "thread" = "1.1". A child of (A) will have "1.1.1". Next
+   * brother of (A) will get "1.2". Next brother of the parent of (A) will get
+   * "2" and so on.
+   *
+   * First of all note that the thread field stores the depth of the comment:
+   * depth 0 will be "X", depth 1 "X.X", depth 2 "X.X.X", etc.
+   *
+   * Now to get the ordering right, consider this example:
+   *
+   * 1
+   * 1.1
+   * 1.1.1
+   * 1.2
+   * 2
+   *
+   * If we "ORDER BY thread ASC" we get the above result, and this is the
+   * natural order sorted by time. However, if we "ORDER BY thread DESC"
+   * we get:
+   *
+   * 2
+   * 1.2
+   * 1.1.1
+   * 1.1
+   * 1
+   *
+   * Clearly, this is not a natural way to see a thread, and users will get
+   * confused. The natural order to show a thread by time desc would be:
+   *
+   * 2
+   * 1
+   * 1.2
+   * 1.1
+   * 1.1.1
+   *
+   * which is what we already did before the standard pager patch. To achieve
+   * this we simply add a "/" at the end of each "thread" value. This way, the
+   * thread fields will look like this:
+   *
+   * 1/
+   * 1.1/
+   * 1.1.1/
+   * 1.2/
+   * 2/
+   *
+   * we add "/" since this char is, in ASCII, higher than every number, so if
+   * now we "ORDER BY thread DESC" we get the correct order. However this would
+   * spoil the reverse ordering, "ORDER BY thread ASC" -- here, we do not need
+   * to consider the trailing "/" so we use a substring only.
+   */
+  public function loadThread(EntityInterface $entity, $field_name, $mode, $comments_per_page = 0, $pager_id = 0) {
+    $query = $this->database->select('comment', 'c');
+    if ($comments_per_page > 0) {
+      $query = $query->extend('Drupal\Core\Database\Query\PagerSelectExtender')
+        ->limit($comments_per_page);
+      if ($pager_id) {
+        $query->element($pager_id);
+      }
+    }
+    $query->addField('c', 'cid');
+    $query
+      ->condition('c.entity_id', $entity->id())
+      ->condition('c.entity_type', $entity->getEntityTypeId())
+      ->condition('c.field_name', $field_name)
+      ->addTag('entity_access')
+      ->addTag('comment_filter')
+      ->addMetaData('base_table', 'comment')
+      ->addMetaData('entity', $entity)
+      ->addMetaData('field_name', $field_name);
+
+    $count_query = $this->database->select('comment', 'c');
+    $count_query->addExpression('COUNT(*)');
+    $count_query
+      ->condition('c.entity_id', $entity->id())
+      ->condition('c.entity_type', $entity->getEntityTypeId())
+      ->condition('c.field_name', $field_name)
+      ->addTag('entity_access')
+      ->addTag('comment_filter')
+      ->addMetaData('base_table', 'comment')
+      ->addMetaData('entity', $entity)
+      ->addMetaData('field_name', $field_name);
+
+    if (!($mode & COMMENT_ACCESS_MODE_ADMIN)) {
+      $query->condition('c.status', CommentInterface::PUBLISHED);
+      $count_query->condition('c.status', CommentInterface::PUBLISHED);
+    }
+    if (($mode & COMMENT_MODE_THREADED) == COMMENT_MODE_THREADED) {
+      // See comment above. Analysis reveals that this doesn't cost too
+      // much. It scales much much better than having the whole comment
+      // structure.
+      $query->addExpression('SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))', 'torder');
+      $query->orderBy('torder', 'ASC');
+    }
+    else {
+      $query->orderBy('c.cid', 'ASC');
+    }
+
+    $query->setCountQuery($count_query);
+    $cids = $query->execute()->fetchCol();
+
+    $comments = array();
+    if ($cids) {
+      $comments = $this->loadMultiple($cids);
+    }
+
+    return $comments;
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function getSchema() {
     $schema = parent::getSchema();
diff --git a/core/modules/comment/src/CommentStorageInterface.php b/core/modules/comment/src/CommentStorageInterface.php
index c1587a5..93a09c2 100644
--- a/core/modules/comment/src/CommentStorageInterface.php
+++ b/core/modules/comment/src/CommentStorageInterface.php
@@ -49,6 +49,29 @@ public function getMaxThreadPerThread(EntityInterface $comment);
   public function getChildCids(array $comments);
 
   /**
+   * Retrieves comments for a thread, sorted in an order suitable for display.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity whose comment(s) needs rendering.
+   * @param string $field_name
+   *   The field_name whose comment(s) needs rendering.
+   * @param int $mode
+   *   The comment display mode: COMMENT_MODE_FLAT or COMMENT_MODE_THREADED.
+   *   Add (bitwise OR) COMMENT_ACCESS_MODE_ADMIN if unpublished comments should
+   *   be displayed too.
+   * @param int $comments_per_page
+   *   (optional) The amount of comments to display per page.
+   *   Defaults to 0, which means show all comments.
+   * @param int $pager_id
+   *   (optional) Pager id to use in case of multiple pagers on the one page.
+   *   Defaults to 0; is only used when $comments_per_page is greater than zero.
+   *
+   * @return array
+   *   Ordered array of comment objects.
+   */
+  public function loadThread(EntityInterface $entity, $field_name, $mode, $comments_per_page = 0, $pager_id = 0);
+
+  /**
    * Updates the comment statistics for a given node.
    *
    * The {comment_entity_statistics} table has the following fields:
diff --git a/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php b/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php
index 290a607..9ce3ccc 100644
--- a/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php
+++ b/core/modules/comment/src/Plugin/Field/FieldFormatter/CommentDefaultFormatter.php
@@ -137,8 +137,8 @@ public function viewElements(FieldItemListInterface $items) {
         $this->currentUser->hasPermission('administer comments'))) {
         $mode = $comment_settings['default_mode'];
         $comments_per_page = $comment_settings['per_page'];
-        if ($cids = comment_get_thread($entity, $field_name, $mode, $comments_per_page, $this->getSetting('pager_id'))) {
-          $comments = $this->storage->loadMultiple($cids);
+        $comments = $this->storage->loadThread($entity, $field_name, $mode, $comments_per_page, $this->getSetting('pager_id'));
+        if ($comments) {
           comment_prepare_thread($comments);
           $build = $this->viewBuilder->viewMultiple($comments);
           $build['pager']['#theme'] = 'pager';
