reference_table.cc revision 410c0c876f326e14c176a39ba21fc4dd3f7db8ab
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
2511e45077acba2e757799a00b3be9d63fec36a7ccElliott HughesReferenceTable::ReferenceTable(const char* name,
2611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    size_t initial_size, size_t max_size)
2711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes        : name_(name), max_size_(max_size) {
2811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  CHECK_LE(initial_size, max_size);
2911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  entries_.reserve(initial_size);
3011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
3111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
32c1674ed06662420213441ff2b818f2f71f9098dcElliott HughesReferenceTable::~ReferenceTable() {
33c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes}
34c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes
357577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughesvoid ReferenceTable::Add(const Object* obj) {
3611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  DCHECK(obj != NULL);
3711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (entries_.size() == max_size_) {
3811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    LOG(FATAL) << "ReferenceTable '" << name_ << "' "
3911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes               << "overflowed (" << max_size_ << " entries)";
4011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
4111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  entries_.push_back(obj);
4211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
4311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
447577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughesvoid ReferenceTable::Remove(const Object* obj) {
4511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // We iterate backwards on the assumption that references are LIFO.
4611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  for (int i = entries_.size() - 1; i >= 0; --i) {
4711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (entries_[i] == obj) {
4811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      entries_.erase(entries_.begin() + i);
4911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return;
5011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
5111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
5211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
5311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
545b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// If "obj" is an array, return the number of elements in the array.
555b1982d2b41ab7a664fb04117539f29eadafa773Carl Shapiro// Otherwise, return zero.
5611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughessize_t GetElementCount(const Object* obj) {
57b63ec393a5c4ba2be1d34dd871cda811eaa803c7Brian Carlstrom  if (obj == NULL || obj == kClearedJniWeakGlobal || !obj->IsArrayInstance()) {
5811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return 0;
5911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
6011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  return obj->AsArray()->GetLength();
6111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
6211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
6311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughesstruct ObjectComparator {
647577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes  bool operator()(const Object* obj1, const Object* obj2){
6511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // Ensure null references and cleared jweaks appear at the end.
6611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (obj1 == NULL) {
6711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return true;
6811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else if (obj2 == NULL) {
6911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return false;
7011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
7111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (obj1 == kClearedJniWeakGlobal) {
7211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return true;
7311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else if (obj2 == kClearedJniWeakGlobal) {
7411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return false;
7511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
7611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
7711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // Sort by class...
7811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (obj1->GetClass() != obj2->GetClass()) {
7911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      return reinterpret_cast<uintptr_t>(obj1->GetClass()) <
8011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes          reinterpret_cast<uintptr_t>(obj2->GetClass());
8111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else {
8211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // ...then by size...
8311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t count1 = obj1->SizeOf();
8411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t count2 = obj2->SizeOf();
8511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      if (count1 != count2) {
8611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes        return count1 < count2;
8711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      } else {
8811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes        // ...and finally by address.
8911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes        return reinterpret_cast<uintptr_t>(obj1) <
9011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes            reinterpret_cast<uintptr_t>(obj2);
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.
10111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughesvoid LogSummaryLine(const Object* obj, size_t elems, int identical, int equiv) {
10211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (obj == NULL) {
10311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    LOG(WARNING) << "    NULL reference (count=" << equiv << ")";
10411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
10511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
10611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (obj == kClearedJniWeakGlobal) {
10711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    LOG(WARNING) << "    cleared jweak (count=" << equiv << ")";
10811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
10911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
11011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
11111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  std::string className(PrettyType(obj));
11211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (obj->IsClass()) {
11311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // We're summarizing multiple instances, so using the exemplar
11411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // Class' type parameter here would be misleading.
11511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    className = "java.lang.Class";
11611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
11711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (elems != 0) {
11811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    StringAppendF(&className, " (%zd elements)", elems);
11911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
12011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
12111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  size_t total = identical + equiv + 1;
12211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  std::string msg(StringPrintf("%5d of %s", total, className.c_str()));
12311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (identical + equiv != 0) {
12411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    StringAppendF(&msg, " (%d unique instances)", equiv + 1);
12511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
12611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  LOG(WARNING) << "    " << msg;
12711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
12811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
12911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughessize_t ReferenceTable::Size() const {
13011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  return entries_.size();
13111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
13211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
13311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughesvoid ReferenceTable::Dump() const {
13411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  LOG(WARNING) << name_ << " reference table dump:";
1356c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  Dump(entries_);
1366c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes}
13711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
138410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughesvoid ReferenceTable::Dump(const Table& entries) {
1396c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  if (entries.empty()) {
14011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    LOG(WARNING) << "  (empty)";
14111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
14211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
14311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
14411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Dump the most recent N entries.
14511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  const size_t kLast = 10;
1466c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes  size_t count = entries.size();
14711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  int first = count - kLast;
14811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (first < 0) {
14911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    first = 0;
15011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
15111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  LOG(WARNING) << "  Last " << (count - first) << " entries (of " << count << "):";
15211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  for (int idx = count - 1; idx >= first; --idx) {
1536c1a394b47c85c8d1723fc3b156a3b1b0b29a757Elliott Hughes    const Object* ref = entries[idx];
15411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (ref == NULL) {
15511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      continue;
15611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
15711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (ref == kClearedJniWeakGlobal) {
15811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      LOG(WARNING) << StringPrintf("    %5d: cleared jweak", idx);
15911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      continue;
16011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
16111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (ref->GetClass() == NULL) {
16211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // should only be possible right after a plain dvmMalloc().
16311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t size = ref->SizeOf();
16411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      LOG(WARNING) << StringPrintf("    %5d: %p (raw) (%zd bytes)", idx, ref, size);
16511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      continue;
16611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
16711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
16811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    std::string className(PrettyType(ref));
16911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
17011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    std::string extras;
17111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    size_t elems = GetElementCount(ref);
17211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (elems != 0) {
17311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      StringAppendF(&extras, " (%zd elements)", elems);
17411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
17511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes#if 0
17611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    // TODO: support dumping string data.
17711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    else if (ref->GetClass() == gDvm.classJavaLangString) {
17811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      const StringObject* str = reinterpret_cast<const StringObject*>(ref);
17911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      extras += " \"";
18011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      size_t count = 0;
18111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      char* s = dvmCreateCstrFromString(str);
18211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      char* p = s;
18311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      for (; *p && count < 16; ++p, ++count) {
18411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes        extras += *p;
18511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      }
18611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      if (*p == 0) {
18711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes        extras += "\"";
18811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      } else {
18911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes        StringAppendF(&extras, "... (%d chars)", str->length());
19011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      }
19111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      free(s);
19211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
19311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes#endif
19411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    LOG(WARNING) << StringPrintf("    %5d: ", idx) << ref << " " << className << extras;
19511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
19611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
19711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Make a copy of the table and sort it.
198410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  Table sorted_entries(entries.begin(), entries.end());
19911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  std::sort(sorted_entries.begin(), sorted_entries.end(), ObjectComparator());
20011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
20111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Remove any uninteresting stuff from the list. The sort moved them all to the end.
20211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  while (!sorted_entries.empty() && sorted_entries.back() == NULL) {
20311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    sorted_entries.pop_back();
20411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
20511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  while (!sorted_entries.empty() && sorted_entries.back() == kClearedJniWeakGlobal) {
20611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    sorted_entries.pop_back();
20711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
20811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  if (sorted_entries.empty()) {
20911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    return;
21011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
21111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
21211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Dump a summary of the whole table.
21311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  LOG(WARNING) << "  Summary:";
21411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  size_t equiv = 0;
21511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  size_t identical = 0;
21611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  for (size_t idx = 1; idx < count; idx++) {
2177577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes    const Object* prev = sorted_entries[idx-1];
2187577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes    const Object* current = sorted_entries[idx];
21911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    size_t elems = GetElementCount(prev);
22011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    if (current == prev) {
22111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // Same reference, added more than once.
22211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      identical++;
22311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else if (current->GetClass() == prev->GetClass() && GetElementCount(current) == elems) {
22411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // Same class / element count, different object.
22511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      equiv++;
22611e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    } else {
22711e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      // Different class.
22811e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      LogSummaryLine(prev, elems, identical, equiv);
22911e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes      equiv = identical = 0;
23011e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes    }
23111e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  }
23211e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  // Handle the last entry.
23311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes  LogSummaryLine(sorted_entries.back(), GetElementCount(sorted_entries.back()), identical, equiv);
23411e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}
23511e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes
236410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughesvoid ReferenceTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
237410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  typedef Table::const_iterator It; // TODO: C++0x auto
238410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  for (It it = entries_.begin(), end = entries_.end(); it != end; ++it) {
239410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes    visitor(*it, arg);
240410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  }
241410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes}
242410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
24311e45077acba2e757799a00b3be9d63fec36a7ccElliott Hughes}  // namespace art
244