reference_table.cc revision ef7d42fca18c16fbaf103822ad16f23246e2905d
111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes/*
211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes * Copyright (C) 2008 The Android Open Source Project
311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes *
411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes * you may not use this file except in compliance with the License.
611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes * You may obtain a copy of the License at
711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes *
811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes *
1011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes * Unless required by applicable law or agreed to in writing, software
1111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes * See the License for the specific language governing permissions and
1411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes * limitations under the License.
1511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes */
1611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
1711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes#include "reference_table.h"
1811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
1976b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughes#include "base/mutex.h"
206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#include "indirect_reference_table.h"
212dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/array.h"
222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/array-inl.h"
232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
242dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
262dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/string.h"
272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "thread.h"
282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utils.h"
2911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
3011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughesnamespace art {
3111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
32bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott HughesReferenceTable::ReferenceTable(const char* name, size_t initial_size, size_t max_size)
33bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes    : name_(name), max_size_(max_size) {
3411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  CHECK_LE(initial_size, max_size);
3511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  entries_.reserve(initial_size);
3611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
3711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
38c1674ed06662420213441ff2b818f2f71f9098dcElliott HughesReferenceTable::~ReferenceTable() {
39c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
40c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
41423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartiervoid ReferenceTable::Add(mirror::Object* obj) {
4211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  DCHECK(obj != NULL);
43423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  if (entries_.size() >= max_size_) {
4411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    LOG(FATAL) << "ReferenceTable '" << name_ << "' "
4511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes               << "overflowed (" << max_size_ << " entries)";
4611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
4711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  entries_.push_back(obj);
4811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
4911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
50423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartiervoid ReferenceTable::Remove(mirror::Object* obj) {
5111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // We iterate backwards on the assumption that references are LIFO.
5211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  for (int i = entries_.size() - 1; i >= 0; --i) {
5311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (entries_[i] == obj) {
5411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      entries_.erase(entries_.begin() + i);
5511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return;
5611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
5711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
5811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
5911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
605b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// If "obj" is an array, return the number of elements in the array.
615b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// Otherwise, return zero.
62ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersstatic size_t GetElementCount(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
63b63ec393a5c4ba2be1d34dd871cda811eaa803c7Brian Carlstrom  if (obj == NULL || obj == kClearedJniWeakGlobal || !obj->IsArrayInstance()) {
6411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return 0;
6511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
6611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  return obj->AsArray()->GetLength();
6711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
6811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
6911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughesstruct ObjectComparator {
70ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  bool operator()(mirror::Object* obj1, mirror::Object* obj2)
7100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // TODO: enable analysis when analysis can work with the STL.
7200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      NO_THREAD_SAFETY_ANALYSIS {
7381d425b0b232962441616f8b14f73620bffef5e5Ian Rogers    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
7411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // Ensure null references and cleared jweaks appear at the end.
7511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (obj1 == NULL) {
7611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return true;
7711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else if (obj2 == NULL) {
7811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return false;
7911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
8011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (obj1 == kClearedJniWeakGlobal) {
8111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return true;
8211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else if (obj2 == kClearedJniWeakGlobal) {
8311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return false;
8411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
8511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
8611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // Sort by class...
8711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (obj1->GetClass() != obj2->GetClass()) {
8800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      return obj1->GetClass()->IdentityHashCode() < obj2->IdentityHashCode();
8911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else {
9011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // ...then by size...
9111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t count1 = obj1->SizeOf();
9211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t count2 = obj2->SizeOf();
9311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      if (count1 != count2) {
9411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes        return count1 < count2;
9511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      } else {
9600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers        // ...and finally by identity hash code.
9700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers        return obj1->IdentityHashCode() < obj2->IdentityHashCode();
9811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      }
9911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
10011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
10111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes};
10211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
1035b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// Log an object with some additional info.
1045b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro//
1055b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// Pass in the number of elements in the array (or 0 if this is not an
1065b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// array object), and the number of additional objects that are identical
1075b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// or equivalent to the original.
108ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersstatic void DumpSummaryLine(std::ostream& os, mirror::Object* obj, size_t element_count,
10900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                            int identical, int equiv)
110b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
11111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (obj == NULL) {
11273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    os << "    NULL reference (count=" << equiv << ")\n";
11311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
11411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
11511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (obj == kClearedJniWeakGlobal) {
11673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    os << "    cleared jweak (count=" << equiv << ")\n";
11711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
11811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
11911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
12054e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes  std::string className(PrettyTypeOf(obj));
12111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (obj->IsClass()) {
12211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // We're summarizing multiple instances, so using the exemplar
12311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // Class' type parameter here would be misleading.
12411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    className = "java.lang.Class";
12511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
12673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  if (element_count != 0) {
12773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    StringAppendF(&className, " (%zd elements)", element_count);
12811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
12911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
13011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  size_t total = identical + equiv + 1;
131215f3144be114ac27002059330d903bf1ff5a592Elliott Hughes  std::string msg(StringPrintf("%5zd of %s", total, className.c_str()));
13211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (identical + equiv != 0) {
13311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    StringAppendF(&msg, " (%d unique instances)", equiv + 1);
13411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
13573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  os << "    " << msg << "\n";
13611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
13711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
13811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughessize_t ReferenceTable::Size() const {
13911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  return entries_.size();
14011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
14111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
14273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughesvoid ReferenceTable::Dump(std::ostream& os) const {
14373e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  os << name_ << " reference table dump:\n";
14473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  Dump(os, entries_);
1456c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes}
14611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
14773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughesvoid ReferenceTable::Dump(std::ostream& os, const Table& entries) {
1486c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  if (entries.empty()) {
14973e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    os << "  (empty)\n";
15011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
15111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
15211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
15311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Dump the most recent N entries.
15411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  const size_t kLast = 10;
1556c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  size_t count = entries.size();
15611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  int first = count - kLast;
15711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (first < 0) {
15811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    first = 0;
15911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
16073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  os << "  Last " << (count - first) << " entries (of " << count << "):\n";
16111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  for (int idx = count - 1; idx >= first; --idx) {
162ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    mirror::Object* ref = entries[idx];
16311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (ref == NULL) {
16411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      continue;
16511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
16611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (ref == kClearedJniWeakGlobal) {
16773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      os << StringPrintf("    %5d: cleared jweak\n", idx);
16811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      continue;
16911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
17011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (ref->GetClass() == NULL) {
17111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // should only be possible right after a plain dvmMalloc().
17211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t size = ref->SizeOf();
17373e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      os << StringPrintf("    %5d: %p (raw) (%zd bytes)\n", idx, ref, size);
17411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      continue;
17511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
17611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
17754e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes    std::string className(PrettyTypeOf(ref));
17811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
17911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    std::string extras;
18073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    size_t element_count = GetElementCount(ref);
18173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    if (element_count != 0) {
18273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      StringAppendF(&extras, " (%zd elements)", element_count);
18373e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    } else if (ref->GetClass()->IsStringClass()) {
1842dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::String* s = const_cast<mirror::Object*>(ref)->AsString();
18573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      std::string utf8(s->ToModifiedUtf8());
18673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      if (s->GetLength() <= 16) {
18773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes        StringAppendF(&extras, " \"%s\"", utf8.c_str());
18811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      } else {
18973e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes        StringAppendF(&extras, " \"%.16s... (%d chars)", utf8.c_str(), s->GetLength());
19011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      }
19111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
19273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    os << StringPrintf("    %5d: ", idx) << ref << " " << className << extras << "\n";
19311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
19411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
19511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Make a copy of the table and sort it.
196410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  Table sorted_entries(entries.begin(), entries.end());
19711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  std::sort(sorted_entries.begin(), sorted_entries.end(), ObjectComparator());
19811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
19911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Remove any uninteresting stuff from the list. The sort moved them all to the end.
20011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  while (!sorted_entries.empty() && sorted_entries.back() == NULL) {
20111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    sorted_entries.pop_back();
20211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
20311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  while (!sorted_entries.empty() && sorted_entries.back() == kClearedJniWeakGlobal) {
20411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    sorted_entries.pop_back();
20511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
20611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (sorted_entries.empty()) {
20711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
20811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
20911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
21011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Dump a summary of the whole table.
21173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  os << "  Summary:\n";
21211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  size_t equiv = 0;
21311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  size_t identical = 0;
21411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  for (size_t idx = 1; idx < count; idx++) {
215ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    mirror::Object* prev = sorted_entries[idx-1];
216ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    mirror::Object* current = sorted_entries[idx];
21773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    size_t element_count = GetElementCount(prev);
21811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (current == prev) {
21911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // Same reference, added more than once.
22011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      identical++;
22173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    } else if (current->GetClass() == prev->GetClass() && GetElementCount(current) == element_count) {
22211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // Same class / element count, different object.
22311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      equiv++;
22411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else {
22511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // Different class.
22673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      DumpSummaryLine(os, prev, element_count, identical, equiv);
22711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      equiv = identical = 0;
22811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
22911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
23011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Handle the last entry.
23173e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  DumpSummaryLine(os, sorted_entries.back(), GetElementCount(sorted_entries.back()), identical, equiv);
23211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
23311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
2342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersvoid ReferenceTable::VisitRoots(RootVisitor* visitor, void* arg) {
235423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  for (auto& ref : entries_) {
236590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    ref = visitor(ref, arg);
237410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  }
238410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes}
239410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
24011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}  // namespace art
241