/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "reference_table.h"

#include "indirect_reference_table.h"

#include "object.h"

namespace art {

ReferenceTable::ReferenceTable(const char* name, size_t initial_size, size_t max_size)
    : name_(name), max_size_(max_size) {
  CHECK_LE(initial_size, max_size);
  entries_.reserve(initial_size);
}

ReferenceTable::~ReferenceTable() {
}

void ReferenceTable::Add(const Object* obj) {
  DCHECK(obj != NULL);
  if (entries_.size() == max_size_) {
    LOG(FATAL) << "ReferenceTable '" << name_ << "' "
               << "overflowed (" << max_size_ << " entries)";
  }
  entries_.push_back(obj);
}

void ReferenceTable::Remove(const Object* obj) {
  // We iterate backwards on the assumption that references are LIFO.
  for (int i = entries_.size() - 1; i >= 0; --i) {
    if (entries_[i] == obj) {
      entries_.erase(entries_.begin() + i);
      return;
    }
  }
}

// If "obj" is an array, return the number of elements in the array.
// Otherwise, return zero.
size_t GetElementCount(const Object* obj) {
  if (obj == NULL || obj == kClearedJniWeakGlobal || !obj->IsArrayInstance()) {
    return 0;
  }
  return obj->AsArray()->GetLength();
}

struct ObjectComparator {
  bool operator()(const Object* obj1, const Object* obj2) {
    // Ensure null references and cleared jweaks appear at the end.
    if (obj1 == NULL) {
      return true;
    } else if (obj2 == NULL) {
      return false;
    }
    if (obj1 == kClearedJniWeakGlobal) {
      return true;
    } else if (obj2 == kClearedJniWeakGlobal) {
      return false;
    }

    // Sort by class...
    if (obj1->GetClass() != obj2->GetClass()) {
      return reinterpret_cast<uintptr_t>(obj1->GetClass()) <
          reinterpret_cast<uintptr_t>(obj2->GetClass());
    } else {
      // ...then by size...
      size_t count1 = obj1->SizeOf();
      size_t count2 = obj2->SizeOf();
      if (count1 != count2) {
        return count1 < count2;
      } else {
        // ...and finally by address.
        return reinterpret_cast<uintptr_t>(obj1) <
            reinterpret_cast<uintptr_t>(obj2);
      }
    }
  }
};

// Log an object with some additional info.
//
// Pass in the number of elements in the array (or 0 if this is not an
// array object), and the number of additional objects that are identical
// or equivalent to the original.
void LogSummaryLine(const Object* obj, size_t elems, int identical, int equiv) {
  if (obj == NULL) {
    LOG(WARNING) << "    NULL reference (count=" << equiv << ")";
    return;
  }
  if (obj == kClearedJniWeakGlobal) {
    LOG(WARNING) << "    cleared jweak (count=" << equiv << ")";
    return;
  }

  std::string className(PrettyTypeOf(obj));
  if (obj->IsClass()) {
    // We're summarizing multiple instances, so using the exemplar
    // Class' type parameter here would be misleading.
    className = "java.lang.Class";
  }
  if (elems != 0) {
    StringAppendF(&className, " (%zd elements)", elems);
  }

  size_t total = identical + equiv + 1;
  std::string msg(StringPrintf("%5zd of %s", total, className.c_str()));
  if (identical + equiv != 0) {
    StringAppendF(&msg, " (%d unique instances)", equiv + 1);
  }
  LOG(WARNING) << "    " << msg;
}

size_t ReferenceTable::Size() const {
  return entries_.size();
}

void ReferenceTable::Dump() const {
  LOG(WARNING) << name_ << " reference table dump:";
  Dump(entries_);
}

void ReferenceTable::Dump(const Table& entries) {
  if (entries.empty()) {
    LOG(WARNING) << "  (empty)";
    return;
  }

  // Dump the most recent N entries.
  const size_t kLast = 10;
  size_t count = entries.size();
  int first = count - kLast;
  if (first < 0) {
    first = 0;
  }
  LOG(WARNING) << "  Last " << (count - first) << " entries (of " << count << "):";
  for (int idx = count - 1; idx >= first; --idx) {
    const Object* ref = entries[idx];
    if (ref == NULL) {
      continue;
    }
    if (ref == kClearedJniWeakGlobal) {
      LOG(WARNING) << StringPrintf("    %5d: cleared jweak", idx);
      continue;
    }
    if (ref->GetClass() == NULL) {
      // should only be possible right after a plain dvmMalloc().
      size_t size = ref->SizeOf();
      LOG(WARNING) << StringPrintf("    %5d: %p (raw) (%zd bytes)", idx, ref, size);
      continue;
    }

    std::string className(PrettyTypeOf(ref));

    std::string extras;
    size_t elems = GetElementCount(ref);
    if (elems != 0) {
      StringAppendF(&extras, " (%zd elements)", elems);
    }
#if 0
    // TODO: support dumping string data.
    else if (ref->GetClass() == gDvm.classJavaLangString) {
      const StringObject* str = reinterpret_cast<const StringObject*>(ref);
      extras += " \"";
      size_t count = 0;
      char* s = dvmCreateCstrFromString(str);
      char* p = s;
      for (; *p && count < 16; ++p, ++count) {
        extras += *p;
      }
      if (*p == 0) {
        extras += "\"";
      } else {
        StringAppendF(&extras, "... (%d chars)", str->length());
      }
      free(s);
    }
#endif
    LOG(WARNING) << StringPrintf("    %5d: ", idx) << ref << " " << className << extras;
  }

  // Make a copy of the table and sort it.
  Table sorted_entries(entries.begin(), entries.end());
  std::sort(sorted_entries.begin(), sorted_entries.end(), ObjectComparator());

  // Remove any uninteresting stuff from the list. The sort moved them all to the end.
  while (!sorted_entries.empty() && sorted_entries.back() == NULL) {
    sorted_entries.pop_back();
  }
  while (!sorted_entries.empty() && sorted_entries.back() == kClearedJniWeakGlobal) {
    sorted_entries.pop_back();
  }
  if (sorted_entries.empty()) {
    return;
  }

  // Dump a summary of the whole table.
  LOG(WARNING) << "  Summary:";
  size_t equiv = 0;
  size_t identical = 0;
  for (size_t idx = 1; idx < count; idx++) {
    const Object* prev = sorted_entries[idx-1];
    const Object* current = sorted_entries[idx];
    size_t elems = GetElementCount(prev);
    if (current == prev) {
      // Same reference, added more than once.
      identical++;
    } else if (current->GetClass() == prev->GetClass() && GetElementCount(current) == elems) {
      // Same class / element count, different object.
      equiv++;
    } else {
      // Different class.
      LogSummaryLine(prev, elems, identical, equiv);
      equiv = identical = 0;
    }
  }
  // Handle the last entry.
  LogSummaryLine(sorted_entries.back(), GetElementCount(sorted_entries.back()), identical, equiv);
}

void ReferenceTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
  typedef Table::const_iterator It; // TODO: C++0x auto
  for (It it = entries_.begin(), end = entries_.end(); it != end; ++it) {
    visitor(*it, arg);
  }
}

}  // namespace art
