reference_table.cc revision b726dcb581bf72da46527378ccb6889020f0e6e9
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
196c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes#include "indirect_reference_table.h"
206c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes
2111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes#include "object.h"
2211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
2311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughesnamespace art {
2411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
25bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott HughesReferenceTable::ReferenceTable(const char* name, size_t initial_size, size_t max_size)
26bb1e8f0a07c12a8b0a2dd3cab6a1a7e825a54c6fElliott Hughes    : name_(name), max_size_(max_size) {
2711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  CHECK_LE(initial_size, max_size);
2811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  entries_.reserve(initial_size);
2911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
3011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
31c1674ed06662420213441ff2b818f2f71f9098dcElliott HughesReferenceTable::~ReferenceTable() {
32c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
33c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
347577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughesvoid ReferenceTable::Add(const Object* obj) {
3511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  DCHECK(obj != NULL);
3611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (entries_.size() == max_size_) {
3711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    LOG(FATAL) << "ReferenceTable '" << name_ << "' "
3811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes               << "overflowed (" << max_size_ << " entries)";
3911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
4011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  entries_.push_back(obj);
4111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
4211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
437577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughesvoid ReferenceTable::Remove(const Object* obj) {
4411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // We iterate backwards on the assumption that references are LIFO.
4511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  for (int i = entries_.size() - 1; i >= 0; --i) {
4611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (entries_[i] == obj) {
4711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      entries_.erase(entries_.begin() + i);
4811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return;
4911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
5011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
5111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
5211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
535b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// If "obj" is an array, return the number of elements in the array.
545b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// Otherwise, return zero.
5573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughesstatic size_t GetElementCount(const Object* obj) {
56b63ec393a5c4ba2be1d34dd871cda811eaa803c7Brian Carlstrom  if (obj == NULL || obj == kClearedJniWeakGlobal || !obj->IsArrayInstance()) {
5711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return 0;
5811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
5911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  return obj->AsArray()->GetLength();
6011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
6111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
6211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughesstruct ObjectComparator {
6300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  bool operator()(const Object* obj1, const Object* obj2)
6400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // TODO: enable analysis when analysis can work with the STL.
6500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      NO_THREAD_SAFETY_ANALYSIS {
66b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    Locks::mutator_lock_->AssertSharedHeld();
6711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // Ensure null references and cleared jweaks appear at the end.
6811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (obj1 == NULL) {
6911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return true;
7011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else if (obj2 == NULL) {
7111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return false;
7211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
7311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (obj1 == kClearedJniWeakGlobal) {
7411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return true;
7511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else if (obj2 == kClearedJniWeakGlobal) {
7611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return false;
7711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
7811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
7911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // Sort by class...
8011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (obj1->GetClass() != obj2->GetClass()) {
8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      return obj1->GetClass()->IdentityHashCode() < obj2->IdentityHashCode();
8211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else {
8311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // ...then by size...
8411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t count1 = obj1->SizeOf();
8511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t count2 = obj2->SizeOf();
8611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      if (count1 != count2) {
8711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes        return count1 < count2;
8811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      } else {
8900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers        // ...and finally by identity hash code.
9000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers        return obj1->IdentityHashCode() < obj2->IdentityHashCode();
9111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      }
9211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
9311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
9411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes};
9511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
965b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// Log an object with some additional info.
975b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro//
985b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// Pass in the number of elements in the array (or 0 if this is not an
995b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// array object), and the number of additional objects that are identical
1005b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// or equivalent to the original.
10100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersstatic void DumpSummaryLine(std::ostream& os, const Object* obj, size_t element_count,
10200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                            int identical, int equiv)
103b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
10411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (obj == NULL) {
10573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    os << "    NULL reference (count=" << equiv << ")\n";
10611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
10711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
10811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (obj == kClearedJniWeakGlobal) {
10973e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    os << "    cleared jweak (count=" << equiv << ")\n";
11011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
11111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
11211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
11354e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes  std::string className(PrettyTypeOf(obj));
11411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (obj->IsClass()) {
11511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // We're summarizing multiple instances, so using the exemplar
11611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // Class' type parameter here would be misleading.
11711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    className = "java.lang.Class";
11811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
11973e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  if (element_count != 0) {
12073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    StringAppendF(&className, " (%zd elements)", element_count);
12111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
12211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
12311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  size_t total = identical + equiv + 1;
124215f3144be114ac27002059330d903bf1ff5a592Elliott Hughes  std::string msg(StringPrintf("%5zd of %s", total, className.c_str()));
12511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (identical + equiv != 0) {
12611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    StringAppendF(&msg, " (%d unique instances)", equiv + 1);
12711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
12873e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  os << "    " << msg << "\n";
12911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
13011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
13111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughessize_t ReferenceTable::Size() const {
13211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  return entries_.size();
13311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
13411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
13573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughesvoid ReferenceTable::Dump(std::ostream& os) const {
13673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  os << name_ << " reference table dump:\n";
13773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  Dump(os, entries_);
1386c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes}
13911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
14073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughesvoid ReferenceTable::Dump(std::ostream& os, const Table& entries) {
1416c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  if (entries.empty()) {
14273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    os << "  (empty)\n";
14311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
14411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
14511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
14611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Dump the most recent N entries.
14711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  const size_t kLast = 10;
1486c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  size_t count = entries.size();
14911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  int first = count - kLast;
15011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (first < 0) {
15111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    first = 0;
15211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
15373e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  os << "  Last " << (count - first) << " entries (of " << count << "):\n";
15411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  for (int idx = count - 1; idx >= first; --idx) {
1556c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes    const Object* ref = entries[idx];
15611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (ref == NULL) {
15711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      continue;
15811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
15911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (ref == kClearedJniWeakGlobal) {
16073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      os << StringPrintf("    %5d: cleared jweak\n", idx);
16111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      continue;
16211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
16311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (ref->GetClass() == NULL) {
16411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // should only be possible right after a plain dvmMalloc().
16511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t size = ref->SizeOf();
16673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      os << StringPrintf("    %5d: %p (raw) (%zd bytes)\n", idx, ref, size);
16711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      continue;
16811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
16911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
17054e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes    std::string className(PrettyTypeOf(ref));
17111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
17211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    std::string extras;
17373e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    size_t element_count = GetElementCount(ref);
17473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    if (element_count != 0) {
17573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      StringAppendF(&extras, " (%zd elements)", element_count);
17673e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    } else if (ref->GetClass()->IsStringClass()) {
17773e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      String* s = const_cast<Object*>(ref)->AsString();
17873e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      std::string utf8(s->ToModifiedUtf8());
17973e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      if (s->GetLength() <= 16) {
18073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes        StringAppendF(&extras, " \"%s\"", utf8.c_str());
18111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      } else {
18273e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes        StringAppendF(&extras, " \"%.16s... (%d chars)", utf8.c_str(), s->GetLength());
18311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      }
18411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
18573e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    os << StringPrintf("    %5d: ", idx) << ref << " " << className << extras << "\n";
18611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
18711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
18811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Make a copy of the table and sort it.
189410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  Table sorted_entries(entries.begin(), entries.end());
19011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  std::sort(sorted_entries.begin(), sorted_entries.end(), ObjectComparator());
19111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
19211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Remove any uninteresting stuff from the list. The sort moved them all to the end.
19311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  while (!sorted_entries.empty() && sorted_entries.back() == NULL) {
19411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    sorted_entries.pop_back();
19511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
19611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  while (!sorted_entries.empty() && sorted_entries.back() == kClearedJniWeakGlobal) {
19711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    sorted_entries.pop_back();
19811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
19911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (sorted_entries.empty()) {
20011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
20111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
20211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
20311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Dump a summary of the whole table.
20473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  os << "  Summary:\n";
20511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  size_t equiv = 0;
20611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  size_t identical = 0;
20711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  for (size_t idx = 1; idx < count; idx++) {
2087577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes    const Object* prev = sorted_entries[idx-1];
2097577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes    const Object* current = sorted_entries[idx];
21073e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    size_t element_count = GetElementCount(prev);
21111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (current == prev) {
21211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // Same reference, added more than once.
21311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      identical++;
21473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes    } else if (current->GetClass() == prev->GetClass() && GetElementCount(current) == element_count) {
21511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // Same class / element count, different object.
21611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      equiv++;
21711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else {
21811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // Different class.
21973e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes      DumpSummaryLine(os, prev, element_count, identical, equiv);
22011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      equiv = identical = 0;
22111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
22211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
22311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Handle the last entry.
22473e66f73f5093b64f2b023ebbb85916a13d5c937Elliott Hughes  DumpSummaryLine(os, sorted_entries.back(), GetElementCount(sorted_entries.back()), identical, equiv);
22511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
22611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
227410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughesvoid ReferenceTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
228410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  typedef Table::const_iterator It; // TODO: C++0x auto
229410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  for (It it = entries_.begin(), end = entries_.end(); it != end; ++it) {
230410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes    visitor(*it, arg);
231410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  }
232410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes}
233410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
23411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}  // namespace art
235