// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifdef LIVE_OBJECT_LIST

#include <ctype.h>
#include <stdlib.h>

#include "v8.h"

#include "checks.h"
#include "global-handles.h"
#include "heap.h"
#include "inspector.h"
#include "isolate.h"
#include "list-inl.h"
#include "liveobjectlist-inl.h"
#include "string-stream.h"
#include "v8utils.h"
#include "v8conversions.h"

namespace v8 {
namespace internal {


typedef int (*RawComparer)(const void*, const void*);


#ifdef CHECK_ALL_OBJECT_TYPES

#define DEBUG_LIVE_OBJECT_TYPES(v) \
  v(Smi, "unexpected: Smi") \
  \
  v(CodeCache, "unexpected: CodeCache") \
  v(BreakPointInfo, "unexpected: BreakPointInfo") \
  v(DebugInfo, "unexpected: DebugInfo") \
  v(TypeSwitchInfo, "unexpected: TypeSwitchInfo") \
  v(SignatureInfo, "unexpected: SignatureInfo") \
  v(Script, "unexpected: Script") \
  v(ObjectTemplateInfo, "unexpected: ObjectTemplateInfo") \
  v(FunctionTemplateInfo, "unexpected: FunctionTemplateInfo") \
  v(CallHandlerInfo, "unexpected: CallHandlerInfo") \
  v(InterceptorInfo, "unexpected: InterceptorInfo") \
  v(AccessCheckInfo, "unexpected: AccessCheckInfo") \
  v(AccessorInfo, "unexpected: AccessorInfo") \
  v(ExternalTwoByteString, "unexpected: ExternalTwoByteString") \
  v(ExternalAsciiString, "unexpected: ExternalAsciiString") \
  v(ExternalString, "unexpected: ExternalString") \
  v(SeqTwoByteString, "unexpected: SeqTwoByteString") \
  v(SeqAsciiString, "unexpected: SeqAsciiString") \
  v(SeqString, "unexpected: SeqString") \
  v(JSFunctionResultCache, "unexpected: JSFunctionResultCache") \
  v(GlobalContext, "unexpected: GlobalContext") \
  v(MapCache, "unexpected: MapCache") \
  v(CodeCacheHashTable, "unexpected: CodeCacheHashTable") \
  v(CompilationCacheTable, "unexpected: CompilationCacheTable") \
  v(SymbolTable, "unexpected: SymbolTable") \
  v(Dictionary, "unexpected: Dictionary") \
  v(HashTable, "unexpected: HashTable") \
  v(DescriptorArray, "unexpected: DescriptorArray") \
  v(ExternalFloatArray, "unexpected: ExternalFloatArray") \
  v(ExternalUnsignedIntArray, "unexpected: ExternalUnsignedIntArray") \
  v(ExternalIntArray, "unexpected: ExternalIntArray") \
  v(ExternalUnsignedShortArray, "unexpected: ExternalUnsignedShortArray") \
  v(ExternalShortArray, "unexpected: ExternalShortArray") \
  v(ExternalUnsignedByteArray, "unexpected: ExternalUnsignedByteArray") \
  v(ExternalByteArray, "unexpected: ExternalByteArray") \
  v(JSValue, "unexpected: JSValue")

#else
#define DEBUG_LIVE_OBJECT_TYPES(v)
#endif


#define FOR_EACH_LIVE_OBJECT_TYPE(v) \
  DEBUG_LIVE_OBJECT_TYPES(v) \
  \
  v(JSArray, "JSArray") \
  v(JSRegExp, "JSRegExp") \
  v(JSFunction, "JSFunction") \
  v(JSGlobalObject, "JSGlobal") \
  v(JSBuiltinsObject, "JSBuiltins") \
  v(GlobalObject, "Global") \
  v(JSGlobalProxy, "JSGlobalProxy") \
  v(JSObject, "JSObject") \
  \
  v(Context, "meta: Context") \
  v(ByteArray, "meta: ByteArray") \
  v(ExternalPixelArray, "meta: PixelArray") \
  v(ExternalArray, "meta: ExternalArray") \
  v(FixedArray, "meta: FixedArray") \
  v(String, "String") \
  v(HeapNumber, "HeapNumber") \
  \
  v(Code, "meta: Code") \
  v(Map, "meta: Map") \
  v(Oddball, "Oddball") \
  v(Foreign, "meta: Foreign") \
  v(SharedFunctionInfo, "meta: SharedFunctionInfo") \
  v(Struct, "meta: Struct") \
  \
  v(HeapObject, "HeapObject")


enum /* LiveObjectType */ {
#define DECLARE_OBJECT_TYPE_ENUM(type, name) kType##type,
  FOR_EACH_LIVE_OBJECT_TYPE(DECLARE_OBJECT_TYPE_ENUM)
  kInvalidLiveObjType,
  kNumberOfTypes
#undef DECLARE_OBJECT_TYPE_ENUM
};


LiveObjectType GetObjectType(HeapObject* heap_obj) {
  // TODO(mlam): investigate usint Map::instance_type() instead.
#define CHECK_FOR_OBJECT_TYPE(type, name) \
  if (heap_obj->Is##type()) return kType##type;
  FOR_EACH_LIVE_OBJECT_TYPE(CHECK_FOR_OBJECT_TYPE)
#undef CHECK_FOR_OBJECT_TYPE

  UNREACHABLE();
  return kInvalidLiveObjType;
}


inline const char* GetObjectTypeDesc(LiveObjectType type) {
  static const char* const name[kNumberOfTypes] = {
  #define DEFINE_OBJECT_TYPE_NAME(type, name) name,
    FOR_EACH_LIVE_OBJECT_TYPE(DEFINE_OBJECT_TYPE_NAME)
    "invalid"
  #undef DEFINE_OBJECT_TYPE_NAME
  };
  ASSERT(type < kNumberOfTypes);
  return name[type];
}


const char* GetObjectTypeDesc(HeapObject* heap_obj) {
  LiveObjectType type = GetObjectType(heap_obj);
  return GetObjectTypeDesc(type);
}


bool IsOfType(LiveObjectType type, HeapObject *obj) {
  // Note: there are types that are more general (e.g. JSObject) that would
  // have passed the Is##type_() test for more specialized types (e.g.
  // JSFunction).  If we find a more specialized match but we're looking for
  // the general type, then we should reject the ones that matches the
  // specialized type.
#define CHECK_OBJECT_TYPE(type_, name) \
  if (obj->Is##type_()) return (type == kType##type_);

  FOR_EACH_LIVE_OBJECT_TYPE(CHECK_OBJECT_TYPE)
#undef CHECK_OBJECT_TYPE

  return false;
}


const AllocationSpace kInvalidSpace = static_cast<AllocationSpace>(-1);

static AllocationSpace FindSpaceFor(String* space_str) {
  SmartPointer<char> s =
      space_str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);

  const char* key_str = *s;
  switch (key_str[0]) {
    case 'c':
      if (strcmp(key_str, "cell") == 0) return CELL_SPACE;
      if (strcmp(key_str, "code") == 0) return CODE_SPACE;
      break;
    case 'l':
      if (strcmp(key_str, "lo") == 0) return LO_SPACE;
      break;
    case 'm':
      if (strcmp(key_str, "map") == 0) return MAP_SPACE;
      break;
    case 'n':
      if (strcmp(key_str, "new") == 0) return NEW_SPACE;
      break;
    case 'o':
      if (strcmp(key_str, "old-pointer") == 0) return OLD_POINTER_SPACE;
      if (strcmp(key_str, "old-data") == 0) return OLD_DATA_SPACE;
      break;
  }
  return kInvalidSpace;
}


static bool InSpace(AllocationSpace space, HeapObject *heap_obj) {
  Heap* heap = ISOLATE->heap();
  if (space != LO_SPACE) {
    return heap->InSpace(heap_obj, space);
  }

  // This is an optimization to speed up the check for an object in the LO
  // space by exclusion because we know that all object pointers passed in
  // here are guaranteed to be in the heap.  Hence, it is safe to infer
  // using an exclusion test.
  // Note: calling Heap::InSpace(heap_obj, LO_SPACE) is too slow for our
  // filters.
  int first_space = static_cast<int>(FIRST_SPACE);
  int last_space = static_cast<int>(LO_SPACE);
  for (int sp = first_space; sp < last_space; sp++) {
    if (heap->InSpace(heap_obj, static_cast<AllocationSpace>(sp))) {
      return false;
    }
  }
  SLOW_ASSERT(heap->InSpace(heap_obj, LO_SPACE));
  return true;
}


static LiveObjectType FindTypeFor(String* type_str) {
  SmartPointer<char> s =
      type_str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);

#define CHECK_OBJECT_TYPE(type_, name) { \
    const char* type_desc = GetObjectTypeDesc(kType##type_); \
    const char* key_str = *s; \
    if (strstr(type_desc, key_str) != NULL) return kType##type_; \
  }
  FOR_EACH_LIVE_OBJECT_TYPE(CHECK_OBJECT_TYPE)
#undef CHECK_OBJECT_TYPE

  return kInvalidLiveObjType;
}


class LolFilter {
 public:
  explicit LolFilter(Handle<JSObject> filter_obj);

  inline bool is_active() const { return is_active_; }
  inline bool Matches(HeapObject* obj) {
    return !is_active() || MatchesSlow(obj);
  }

 private:
  void InitTypeFilter(Handle<JSObject> filter_obj);
  void InitSpaceFilter(Handle<JSObject> filter_obj);
  void InitPropertyFilter(Handle<JSObject> filter_obj);
  bool MatchesSlow(HeapObject* obj);

  bool is_active_;
  LiveObjectType type_;
  AllocationSpace space_;
  Handle<String> prop_;
};


LolFilter::LolFilter(Handle<JSObject> filter_obj)
    : is_active_(false),
      type_(kInvalidLiveObjType),
      space_(kInvalidSpace),
      prop_() {
  if (filter_obj.is_null()) return;

  InitTypeFilter(filter_obj);
  InitSpaceFilter(filter_obj);
  InitPropertyFilter(filter_obj);
}


void LolFilter::InitTypeFilter(Handle<JSObject> filter_obj) {
  Handle<String> type_sym = FACTORY->LookupAsciiSymbol("type");
  MaybeObject* maybe_result = filter_obj->GetProperty(*type_sym);
  Object* type_obj;
  if (maybe_result->ToObject(&type_obj)) {
    if (type_obj->IsString()) {
      String* type_str = String::cast(type_obj);
      type_ = FindTypeFor(type_str);
      if (type_ != kInvalidLiveObjType) {
        is_active_ = true;
      }
    }
  }
}


void LolFilter::InitSpaceFilter(Handle<JSObject> filter_obj) {
  Handle<String> space_sym = FACTORY->LookupAsciiSymbol("space");
  MaybeObject* maybe_result = filter_obj->GetProperty(*space_sym);
  Object* space_obj;
  if (maybe_result->ToObject(&space_obj)) {
    if (space_obj->IsString()) {
      String* space_str = String::cast(space_obj);
      space_ = FindSpaceFor(space_str);
      if (space_ != kInvalidSpace) {
        is_active_ = true;
      }
    }
  }
}


void LolFilter::InitPropertyFilter(Handle<JSObject> filter_obj) {
  Handle<String> prop_sym = FACTORY->LookupAsciiSymbol("prop");
  MaybeObject* maybe_result = filter_obj->GetProperty(*prop_sym);
  Object* prop_obj;
  if (maybe_result->ToObject(&prop_obj)) {
    if (prop_obj->IsString()) {
      prop_ = Handle<String>(String::cast(prop_obj));
      is_active_ = true;
    }
  }
}


bool LolFilter::MatchesSlow(HeapObject* obj) {
  if ((type_ != kInvalidLiveObjType) && !IsOfType(type_, obj)) {
    return false;  // Fail because obj is not of the type of interest.
  }
  if ((space_ != kInvalidSpace) && !InSpace(space_, obj)) {
    return false;  // Fail because obj is not in the space of interest.
  }
  if (!prop_.is_null() && obj->IsJSObject()) {
    LookupResult result;
    obj->Lookup(*prop_, &result);
    if (!result.IsProperty()) {
      return false;  // Fail because obj does not have the property of interest.
    }
  }
  return true;
}


class LolIterator {
 public:
  LolIterator(LiveObjectList* older, LiveObjectList* newer)
      : older_(older),
        newer_(newer),
        curr_(0),
        elements_(0),
        count_(0),
        index_(0) { }

  inline void Init() {
    SetCurrent(newer_);
    // If the elements_ list is empty, then move on to the next list as long
    // as we're not at the last list (indicated by done()).
    while ((elements_ == NULL) && !Done()) {
      SetCurrent(curr_->prev_);
    }
  }

  inline bool Done() const {
    return (curr_ == older_);
  }

  // Object level iteration.
  inline void Next() {
    index_++;
    if (index_ >= count_) {
      // Iterate backwards until we get to the oldest list.
      while (!Done()) {
        SetCurrent(curr_->prev_);
        // If we have elements to process, we're good to go.
        if (elements_ != NULL) break;

        // Else, we should advance to the next older list.
      }
    }
  }

  inline int Id() const {
    return elements_[index_].id_;
  }
  inline HeapObject* Obj() const {
    return elements_[index_].obj_;
  }

  inline int LolObjCount() const {
    if (curr_ != NULL) return curr_->obj_count_;
    return 0;
  }

 protected:
  inline void SetCurrent(LiveObjectList* new_curr) {
    curr_ = new_curr;
    if (curr_ != NULL) {
      elements_ = curr_->elements_;
      count_ = curr_->obj_count_;
      index_ = 0;
    }
  }

  LiveObjectList* older_;
  LiveObjectList* newer_;
  LiveObjectList* curr_;
  LiveObjectList::Element* elements_;
  int count_;
  int index_;
};


class LolForwardIterator : public LolIterator {
 public:
  LolForwardIterator(LiveObjectList* first, LiveObjectList* last)
      : LolIterator(first, last) {
  }

  inline void Init() {
    SetCurrent(older_);
    // If the elements_ list is empty, then move on to the next list as long
    // as we're not at the last list (indicated by Done()).
    while ((elements_ == NULL) && !Done()) {
      SetCurrent(curr_->next_);
    }
  }

  inline bool Done() const {
    return (curr_ == newer_);
  }

  // Object level iteration.
  inline void Next() {
    index_++;
    if (index_ >= count_) {
      // Done with current list.  Move on to the next.
      while (!Done()) {  // If not at the last list already, ...
        SetCurrent(curr_->next_);
        // If we have elements to process, we're good to go.
        if (elements_ != NULL) break;

        // Else, we should advance to the next list.
      }
    }
  }
};


// Minimizes the white space in a string.  Tabs and newlines are replaced
// with a space where appropriate.
static int CompactString(char* str) {
  char* src = str;
  char* dst = str;
  char prev_ch = 0;
  while (*dst != '\0') {
    char ch = *src++;
    // We will treat non-ascii chars as '?'.
    if ((ch & 0x80) != 0) {
      ch = '?';
    }
    // Compact contiguous whitespace chars into a single ' '.
    if (isspace(ch)) {
      if (prev_ch != ' ') *dst++ = ' ';
      prev_ch = ' ';
      continue;
    }
    *dst++ = ch;
    prev_ch = ch;
  }
  return (dst - str);
}


// Generates a custom description based on the specific type of
// object we're looking at.  We only generate specialized
// descriptions where we can.  In all other cases, we emit the
// generic info.
static void GenerateObjectDesc(HeapObject* obj,
                               char* buffer,
                               int buffer_size) {
  Vector<char> buffer_v(buffer, buffer_size);
  ASSERT(obj != NULL);
  if (obj->IsJSArray()) {
    JSArray* jsarray = JSArray::cast(obj);
    double length = jsarray->length()->Number();
    OS::SNPrintF(buffer_v,
                 "%p <%s> len %g",
                 reinterpret_cast<void*>(obj),
                 GetObjectTypeDesc(obj),
                 length);

  } else if (obj->IsString()) {
    String *str = String::cast(obj);
    // Only grab up to 160 chars in case they are double byte.
    // We'll only dump 80 of them after we compact them.
    const int kMaxCharToDump = 80;
    const int kMaxBufferSize = kMaxCharToDump * 2;
    SmartPointer<char> str_sp = str->ToCString(DISALLOW_NULLS,
                                               ROBUST_STRING_TRAVERSAL,
                                               0,
                                               kMaxBufferSize);
    char* str_cstr = *str_sp;
    int length = CompactString(str_cstr);
    OS::SNPrintF(buffer_v,
                 "%p <%s> '%.80s%s'",
                 reinterpret_cast<void*>(obj),
                 GetObjectTypeDesc(obj),
                 str_cstr,
                 (length > kMaxCharToDump) ? "..." : "");

  } else if (obj->IsJSFunction() || obj->IsSharedFunctionInfo()) {
    SharedFunctionInfo* sinfo;
    if (obj->IsJSFunction()) {
      JSFunction* func = JSFunction::cast(obj);
      sinfo = func->shared();
    } else {
      sinfo = SharedFunctionInfo::cast(obj);
    }

    String* name = sinfo->DebugName();
    SmartPointer<char> name_sp =
        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
    char* name_cstr = *name_sp;

    HeapStringAllocator string_allocator;
    StringStream stream(&string_allocator);
    sinfo->SourceCodePrint(&stream, 50);
    SmartPointer<const char> source_sp = stream.ToCString();
    const char* source_cstr = *source_sp;

    OS::SNPrintF(buffer_v,
                 "%p <%s> '%s' %s",
                 reinterpret_cast<void*>(obj),
                 GetObjectTypeDesc(obj),
                 name_cstr,
                 source_cstr);

  } else if (obj->IsFixedArray()) {
    FixedArray* fixed = FixedArray::cast(obj);

    OS::SNPrintF(buffer_v,
                 "%p <%s> len %d",
                 reinterpret_cast<void*>(obj),
                 GetObjectTypeDesc(obj),
                 fixed->length());

  } else {
    OS::SNPrintF(buffer_v,
                 "%p <%s>",
                 reinterpret_cast<void*>(obj),
                 GetObjectTypeDesc(obj));
  }
}


// Utility function for filling in a line of detail in a verbose dump.
static bool AddObjDetail(Handle<FixedArray> arr,
                         int index,
                         int obj_id,
                         Handle<HeapObject> target,
                         const char* desc_str,
                         Handle<String> id_sym,
                         Handle<String> desc_sym,
                         Handle<String> size_sym,
                         Handle<JSObject> detail,
                         Handle<String> desc,
                         Handle<Object> error) {
  Isolate* isolate = Isolate::Current();
  Factory* factory = isolate->factory();
  detail = factory->NewJSObject(isolate->object_function());
  if (detail->IsFailure()) {
    error = detail;
    return false;
  }

  int size = 0;
  char buffer[512];
  if (desc_str == NULL) {
    ASSERT(!target.is_null());
    HeapObject* obj = *target;
    GenerateObjectDesc(obj, buffer, sizeof(buffer));
    desc_str = buffer;
    size = obj->Size();
  }
  desc = factory->NewStringFromAscii(CStrVector(desc_str));
  if (desc->IsFailure()) {
    error = desc;
    return false;
  }

  { MaybeObject* maybe_result = detail->SetProperty(*id_sym,
                                                    Smi::FromInt(obj_id),
                                                    NONE,
                                                    kNonStrictMode);
    if (maybe_result->IsFailure()) return false;
  }
  { MaybeObject* maybe_result = detail->SetProperty(*desc_sym,
                                                    *desc,
                                                    NONE,
                                                    kNonStrictMode);
    if (maybe_result->IsFailure()) return false;
  }
  { MaybeObject* maybe_result = detail->SetProperty(*size_sym,
                                                    Smi::FromInt(size),
                                                    NONE,
                                                    kNonStrictMode);
    if (maybe_result->IsFailure()) return false;
  }

  arr->set(index, *detail);
  return true;
}


class DumpWriter {
 public:
  virtual ~DumpWriter() {}

  virtual void ComputeTotalCountAndSize(LolFilter* filter,
                                        int* count,
                                        int* size) = 0;
  virtual bool Write(Handle<FixedArray> elements_arr,
                     int start,
                     int dump_limit,
                     LolFilter* filter,
                     Handle<Object> error) = 0;
};


class LolDumpWriter: public DumpWriter {
 public:
  LolDumpWriter(LiveObjectList* older, LiveObjectList* newer)
      : older_(older), newer_(newer) {
  }

  void ComputeTotalCountAndSize(LolFilter* filter, int* count, int* size) {
    *count = 0;
    *size = 0;

    LolIterator it(older_, newer_);
    for (it.Init(); !it.Done(); it.Next()) {
      HeapObject* heap_obj = it.Obj();
      if (!filter->Matches(heap_obj)) {
        continue;
      }

      *size += heap_obj->Size();
      (*count)++;
    }
  }

  bool Write(Handle<FixedArray> elements_arr,
             int start,
             int dump_limit,
             LolFilter* filter,
             Handle<Object> error) {
    // The lols are listed in latest to earliest.  We want to dump from
    // earliest to latest.  So, compute the last element to start with.
    int index = 0;
    int count = 0;

    Isolate* isolate = Isolate::Current();
    Factory* factory = isolate->factory();

    // Prefetch some needed symbols.
    Handle<String> id_sym = factory->LookupAsciiSymbol("id");
    Handle<String> desc_sym = factory->LookupAsciiSymbol("desc");
    Handle<String> size_sym = factory->LookupAsciiSymbol("size");

    // Fill the array with the lol object details.
    Handle<JSObject> detail;
    Handle<String> desc;
    Handle<HeapObject> target;

    LiveObjectList* first_lol = (older_ != NULL) ?
                                older_->next_ : LiveObjectList::first_;
    LiveObjectList* last_lol = (newer_ != NULL) ? newer_->next_ : NULL;

    LolForwardIterator it(first_lol, last_lol);
    for (it.Init(); !it.Done() && (index < dump_limit); it.Next()) {
      HeapObject* heap_obj = it.Obj();

      // Skip objects that have been filtered out.
      if (!filter->Matches(heap_obj)) {
        continue;
      }

      // Only report objects that are in the section of interest.
      if (count >= start) {
        target = Handle<HeapObject>(heap_obj);
        bool success = AddObjDetail(elements_arr,
                                    index++,
                                    it.Id(),
                                    target,
                                    NULL,
                                    id_sym,
                                    desc_sym,
                                    size_sym,
                                    detail,
                                    desc,
                                    error);
        if (!success) return false;
      }
      count++;
    }
    return true;
  }

 private:
  LiveObjectList* older_;
  LiveObjectList* newer_;
};


class RetainersDumpWriter: public DumpWriter {
 public:
  RetainersDumpWriter(Handle<HeapObject> target,
                      Handle<JSObject> instance_filter,
                      Handle<JSFunction> args_function)
      : target_(target),
        instance_filter_(instance_filter),
        args_function_(args_function) {
  }

  void ComputeTotalCountAndSize(LolFilter* filter, int* count, int* size) {
    Handle<FixedArray> retainers_arr;
    Handle<Object> error;

    *size = -1;
    LiveObjectList::GetRetainers(target_,
                                 instance_filter_,
                                 retainers_arr,
                                 0,
                                 Smi::kMaxValue,
                                 count,
                                 filter,
                                 NULL,
                                 *args_function_,
                                 error);
  }

  bool Write(Handle<FixedArray> elements_arr,
             int start,
             int dump_limit,
             LolFilter* filter,
             Handle<Object> error) {
    int dummy;
    int count;

    // Fill the retainer objects.
    count = LiveObjectList::GetRetainers(target_,
                                         instance_filter_,
                                         elements_arr,
                                         start,
                                         dump_limit,
                                         &dummy,
                                         filter,
                                         NULL,
                                         *args_function_,
                                         error);
    if (count < 0) {
        return false;
    }
    return true;
  }

 private:
  Handle<HeapObject> target_;
  Handle<JSObject> instance_filter_;
  Handle<JSFunction> args_function_;
};


class LiveObjectSummary {
 public:
  explicit LiveObjectSummary(LolFilter* filter)
      : total_count_(0),
        total_size_(0),
        found_root_(false),
        found_weak_root_(false),
        filter_(filter) {
    memset(counts_, 0, sizeof(counts_[0]) * kNumberOfEntries);
    memset(sizes_, 0, sizeof(sizes_[0]) * kNumberOfEntries);
  }

  void Add(HeapObject* heap_obj) {
    int size = heap_obj->Size();
    LiveObjectType type = GetObjectType(heap_obj);
    ASSERT(type != kInvalidLiveObjType);
    counts_[type]++;
    sizes_[type] += size;
    total_count_++;
    total_size_ += size;
  }

  void set_found_root() { found_root_ = true; }
  void set_found_weak_root() { found_weak_root_ = true; }

  inline int Count(LiveObjectType type) {
    return counts_[type];
  }
  inline int Size(LiveObjectType type) {
    return sizes_[type];
  }
  inline int total_count() {
    return total_count_;
  }
  inline int total_size() {
    return total_size_;
  }
  inline bool found_root() {
    return found_root_;
  }
  inline bool found_weak_root() {
    return found_weak_root_;
  }
  int GetNumberOfEntries() {
    int entries = 0;
    for (int i = 0; i < kNumberOfEntries; i++) {
      if (counts_[i]) entries++;
    }
    return entries;
  }

  inline LolFilter* filter() { return filter_; }

  static const int kNumberOfEntries = kNumberOfTypes;

 private:
  int counts_[kNumberOfEntries];
  int sizes_[kNumberOfEntries];
  int total_count_;
  int total_size_;
  bool found_root_;
  bool found_weak_root_;

  LolFilter *filter_;
};


// Abstraction for a summary writer.
class SummaryWriter {
 public:
  virtual ~SummaryWriter() {}
  virtual void Write(LiveObjectSummary* summary) = 0;
};


// A summary writer for filling in a summary of lol lists and diffs.
class LolSummaryWriter: public SummaryWriter {
 public:
  LolSummaryWriter(LiveObjectList *older_lol,
                   LiveObjectList *newer_lol)
      : older_(older_lol), newer_(newer_lol) {
  }

  void Write(LiveObjectSummary* summary) {
    LolFilter* filter = summary->filter();

    // Fill the summary with the lol object details.
    LolIterator it(older_, newer_);
    for (it.Init(); !it.Done(); it.Next()) {
      HeapObject* heap_obj = it.Obj();
      if (!filter->Matches(heap_obj)) {
        continue;
      }
      summary->Add(heap_obj);
    }
  }

 private:
  LiveObjectList* older_;
  LiveObjectList* newer_;
};


// A summary writer for filling in a retainers list.
class RetainersSummaryWriter: public SummaryWriter {
 public:
  RetainersSummaryWriter(Handle<HeapObject> target,
                         Handle<JSObject> instance_filter,
                         Handle<JSFunction> args_function)
      : target_(target),
        instance_filter_(instance_filter),
        args_function_(args_function) {
  }

  void Write(LiveObjectSummary* summary) {
    Handle<FixedArray> retainers_arr;
    Handle<Object> error;
    int dummy_total_count;
    LiveObjectList::GetRetainers(target_,
                                 instance_filter_,
                                 retainers_arr,
                                 0,
                                 Smi::kMaxValue,
                                 &dummy_total_count,
                                 summary->filter(),
                                 summary,
                                 *args_function_,
                                 error);
  }

 private:
  Handle<HeapObject> target_;
  Handle<JSObject> instance_filter_;
  Handle<JSFunction> args_function_;
};


uint32_t LiveObjectList::next_element_id_ = 1;
int LiveObjectList::list_count_ = 0;
int LiveObjectList::last_id_ = 0;
LiveObjectList* LiveObjectList::first_ = NULL;
LiveObjectList* LiveObjectList::last_ = NULL;


LiveObjectList::LiveObjectList(LiveObjectList* prev, int capacity)
    : prev_(prev),
      next_(NULL),
      capacity_(capacity),
      obj_count_(0) {
  elements_ = NewArray<Element>(capacity);
  id_ = ++last_id_;

  list_count_++;
}


LiveObjectList::~LiveObjectList() {
  DeleteArray<Element>(elements_);
  delete prev_;
}


int LiveObjectList::GetTotalObjCountAndSize(int* size_p) {
  int size = 0;
  int count = 0;
  LiveObjectList *lol = this;
  do {
    // Only compute total size if requested i.e. when size_p is not null.
    if (size_p != NULL) {
      Element* elements = lol->elements_;
      for (int i = 0; i < lol->obj_count_; i++) {
        HeapObject* heap_obj = elements[i].obj_;
        size += heap_obj->Size();
      }
    }
    count += lol->obj_count_;
    lol = lol->prev_;
  } while (lol != NULL);

  if (size_p != NULL) {
    *size_p = size;
  }
  return count;
}


// Adds an object to the lol.
// Returns true if successful, else returns false.
bool LiveObjectList::Add(HeapObject* obj) {
  // If the object is already accounted for in the prev list which we inherit
  // from, then no need to add it to this list.
  if ((prev() != NULL) && (prev()->Find(obj) != NULL)) {
    return true;
  }
  ASSERT(obj_count_ <= capacity_);
  if (obj_count_ == capacity_) {
    // The heap must have grown and we have more objects than capacity to store
    // them.
    return false;  // Fail this addition.
  }
  Element& element = elements_[obj_count_++];
  element.id_ = next_element_id_++;
  element.obj_ = obj;
  return true;
}


// Comparator used for sorting and searching the lol.
int LiveObjectList::CompareElement(const Element* a, const Element* b) {
  const HeapObject* obj1 = a->obj_;
  const HeapObject* obj2 = b->obj_;
  // For lol elements, it doesn't matter which comes first if 2 elements point
  // to the same object (which gets culled later).  Hence, we only care about
  // the the greater than / less than relationships.
  return (obj1 > obj2) ? 1 : (obj1 == obj2) ? 0 : -1;
}


// Looks for the specified object in the lol, and returns its element if found.
LiveObjectList::Element* LiveObjectList::Find(HeapObject* obj) {
  LiveObjectList* lol = this;
  Element key;
  Element* result = NULL;

  key.obj_ = obj;
  // Iterate through the chain of lol's to look for the object.
  while ((result == NULL) && (lol != NULL)) {
    result = reinterpret_cast<Element*>(
        bsearch(&key, lol->elements_, lol->obj_count_,
                sizeof(Element),
                reinterpret_cast<RawComparer>(CompareElement)));
    lol = lol->prev_;
  }
  return result;
}


// "Nullifies" (convert the HeapObject* into an SMI) so that it will get cleaned
// up in the GCEpilogue, while preserving the sort order of the lol.
// NOTE: the lols need to be already sorted before NullifyMostRecent() is
// called.
void LiveObjectList::NullifyMostRecent(HeapObject* obj) {
  LiveObjectList* lol = last();
  Element key;
  Element* result = NULL;

  key.obj_ = obj;
  // Iterate through the chain of lol's to look for the object.
  while (lol != NULL) {
    result = reinterpret_cast<Element*>(
        bsearch(&key, lol->elements_, lol->obj_count_,
                sizeof(Element),
                reinterpret_cast<RawComparer>(CompareElement)));
    if (result != NULL) {
      // Since there may be more than one (we are nullifying dup's after all),
      // find the first in the current lol, and nullify that.  The lol should
      // be sorted already to make this easy (see the use of SortAll()).
      int i = result - lol->elements_;

      // NOTE: we sort the lol in increasing order.  So, if an object has been
      // "nullified" (its lowest bit will be cleared to make it look like an
      // SMI), it would/should show up before the equivalent dups that have not
      // yet been "nullified".  Hence, we should be searching backwards for the
      // first occurence of a matching object and nullify that instance.  This
      // will ensure that we preserve the expected sorting order.
      for (i--; i > 0; i--) {
        Element* element = &lol->elements_[i];
        HeapObject* curr_obj = element->obj_;
        if (curr_obj != obj) {
            break;  // No more matches.  Let's move on.
        }
        result = element;  // Let this earlier match be the result.
      }

      // Nullify the object.
      NullifyNonLivePointer(&result->obj_);
      return;
    }
    lol = lol->prev_;
  }
}


// Sorts the lol.
void LiveObjectList::Sort() {
  if (obj_count_ > 0) {
    Vector<Element> elements_v(elements_, obj_count_);
    elements_v.Sort(CompareElement);
  }
}


// Sorts all captured lols starting from the latest.
void LiveObjectList::SortAll() {
  LiveObjectList* lol = last();
  while (lol != NULL) {
    lol->Sort();
    lol = lol->prev_;
  }
}


// Counts the number of objects in the heap.
static int CountHeapObjects() {
  int count = 0;
  // Iterate over all the heap spaces and count the number of objects.
  HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
  HeapObject* heap_obj = NULL;
  while ((heap_obj = iterator.next()) != NULL) {
    count++;
  }
  return count;
}


// Captures a current snapshot of all objects in the heap.
MaybeObject* LiveObjectList::Capture() {
  Isolate* isolate = Isolate::Current();
  Factory* factory = isolate->factory();
  HandleScope scope(isolate);

  // Count the number of objects in the heap.
  int total_count = CountHeapObjects();
  int count = total_count;
  int size = 0;

  LiveObjectList* last_lol = last();
  if (last_lol != NULL) {
    count -= last_lol->TotalObjCount();
  }

  LiveObjectList* lol;

  // Create a lol large enough to track all the objects.
  lol = new LiveObjectList(last_lol, count);
  if (lol == NULL) {
    return NULL;  // No memory to proceed.
  }

  // The HeapIterator needs to be in its own scope because it disables
  // allocation, and we need allocate below.
  {
    // Iterate over all the heap spaces and add the objects.
    HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
    HeapObject* heap_obj = NULL;
    bool failed = false;
    while (!failed && (heap_obj = iterator.next()) != NULL) {
      failed = !lol->Add(heap_obj);
      size += heap_obj->Size();
    }
    ASSERT(!failed);

    lol->Sort();

    // Add the current lol to the list of lols.
    if (last_ != NULL) {
      last_->next_ = lol;
    } else {
      first_ = lol;
    }
    last_ = lol;

#ifdef VERIFY_LOL
    if (FLAG_verify_lol) {
      Verify(true);
    }
#endif
  }

  Handle<String> id_sym = factory->LookupAsciiSymbol("id");
  Handle<String> count_sym = factory->LookupAsciiSymbol("count");
  Handle<String> size_sym = factory->LookupAsciiSymbol("size");

  Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
  if (result->IsFailure()) return Object::cast(*result);

  { MaybeObject* maybe_result = result->SetProperty(*id_sym,
                                                    Smi::FromInt(lol->id()),
                                                    NONE,
                                                    kNonStrictMode);
    if (maybe_result->IsFailure()) return maybe_result;
  }
  { MaybeObject* maybe_result = result->SetProperty(*count_sym,
                                                    Smi::FromInt(total_count),
                                                    NONE,
                                                    kNonStrictMode);
    if (maybe_result->IsFailure()) return maybe_result;
  }
  { MaybeObject* maybe_result = result->SetProperty(*size_sym,
                                                    Smi::FromInt(size),
                                                    NONE,
                                                    kNonStrictMode);
    if (maybe_result->IsFailure()) return maybe_result;
  }

  return *result;
}


// Delete doesn't actually deletes an lol.  It just marks it as invisible since
// its contents are considered to be part of subsequent lists as well.  The
// only time we'll actually delete the lol is when we Reset() or if the lol is
// invisible, and its element count reaches 0.
bool LiveObjectList::Delete(int id) {
  LiveObjectList *lol = last();
  while (lol != NULL) {
    if (lol->id() == id) {
      break;
    }
    lol = lol->prev_;
  }

  // If no lol is found for this id, then we fail to delete.
  if (lol == NULL) return false;

  // Else, mark the lol as invisible i.e. id == 0.
  lol->id_ = 0;
  list_count_--;
  ASSERT(list_count_ >= 0);
  if (lol->obj_count_ == 0) {
    // Point the next lol's prev to this lol's prev.
    LiveObjectList* next = lol->next_;
    LiveObjectList* prev = lol->prev_;
    // Point next's prev to prev.
    if (next != NULL) {
      next->prev_ = lol->prev_;
    } else {
      last_ = lol->prev_;
    }
    // Point prev's next to next.
    if (prev != NULL) {
      prev->next_ = lol->next_;
    } else {
      first_ = lol->next_;
    }

    lol->prev_ = NULL;
    lol->next_ = NULL;

    // Delete this now empty and invisible lol.
    delete lol;
  }

  // Just in case we've marked everything invisible, then clean up completely.
  if (list_count_ == 0) {
    Reset();
  }

  return true;
}


MaybeObject* LiveObjectList::Dump(int older_id,
                                  int newer_id,
                                  int start_idx,
                                  int dump_limit,
                                  Handle<JSObject> filter_obj) {
  if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) {
    return Failure::Exception();  // Fail: 0 is not a valid lol id.
  }
  if (newer_id < older_id) {
    // They are not in the expected order.  Swap them.
    int temp = older_id;
    older_id = newer_id;
    newer_id = temp;
  }

  LiveObjectList *newer_lol = FindLolForId(newer_id, last());
  LiveObjectList *older_lol = FindLolForId(older_id, newer_lol);

  // If the id is defined, and we can't find a LOL for it, then we have an
  // invalid id.
  if ((newer_id != 0) && (newer_lol == NULL)) {
    return Failure::Exception();  // Fail: the newer lol id is invalid.
  }
  if ((older_id != 0) && (older_lol == NULL)) {
    return Failure::Exception();  // Fail: the older lol id is invalid.
  }

  LolFilter filter(filter_obj);
  LolDumpWriter writer(older_lol, newer_lol);
  return DumpPrivate(&writer, start_idx, dump_limit, &filter);
}


MaybeObject* LiveObjectList::DumpPrivate(DumpWriter* writer,
                                         int start,
                                         int dump_limit,
                                         LolFilter* filter) {
  Isolate* isolate = Isolate::Current();
  Factory* factory = isolate->factory();

  HandleScope scope(isolate);

  // Calculate the number of entries of the dump.
  int count = -1;
  int size = -1;
  writer->ComputeTotalCountAndSize(filter, &count, &size);

  // Adjust for where to start the dump.
  if ((start < 0) || (start >= count)) {
    return Failure::Exception();  // invalid start.
  }

  int remaining_count = count - start;
  if (dump_limit > remaining_count) {
    dump_limit = remaining_count;
  }

  // Allocate an array to hold the result.
  Handle<FixedArray> elements_arr = factory->NewFixedArray(dump_limit);
  if (elements_arr->IsFailure()) return Object::cast(*elements_arr);

  // Fill in the dump.
  Handle<Object> error;
  bool success = writer->Write(elements_arr,
                               start,
                               dump_limit,
                               filter,
                               error);
  if (!success) return Object::cast(*error);

  MaybeObject* maybe_result;

  // Allocate the result body.
  Handle<JSObject> body = factory->NewJSObject(isolate->object_function());
  if (body->IsFailure()) return Object::cast(*body);

  // Set the updated body.count.
  Handle<String> count_sym = factory->LookupAsciiSymbol("count");
  maybe_result = body->SetProperty(*count_sym,
                                   Smi::FromInt(count),
                                   NONE,
                                   kNonStrictMode);
  if (maybe_result->IsFailure()) return maybe_result;

  // Set the updated body.size if appropriate.
  if (size >= 0) {
    Handle<String> size_sym = factory->LookupAsciiSymbol("size");
    maybe_result = body->SetProperty(*size_sym,
                                     Smi::FromInt(size),
                                     NONE,
                                     kNonStrictMode);
    if (maybe_result->IsFailure()) return maybe_result;
  }

  // Set body.first_index.
  Handle<String> first_sym = factory->LookupAsciiSymbol("first_index");
  maybe_result = body->SetProperty(*first_sym,
                                   Smi::FromInt(start),
                                   NONE,
                                   kNonStrictMode);
  if (maybe_result->IsFailure()) return maybe_result;

  // Allocate the JSArray of the elements.
  Handle<JSObject> elements = factory->NewJSObject(isolate->array_function());
  if (elements->IsFailure()) return Object::cast(*elements);
  Handle<JSArray>::cast(elements)->SetContent(*elements_arr);

  // Set body.elements.
  Handle<String> elements_sym = factory->LookupAsciiSymbol("elements");
  maybe_result = body->SetProperty(*elements_sym,
                                   *elements,
                                   NONE,
                                   kNonStrictMode);
  if (maybe_result->IsFailure()) return maybe_result;

  return *body;
}


MaybeObject* LiveObjectList::Summarize(int older_id,
                                       int newer_id,
                                       Handle<JSObject> filter_obj) {
  if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) {
    return Failure::Exception();  // Fail: 0 is not a valid lol id.
  }
  if (newer_id < older_id) {
    // They are not in the expected order.  Swap them.
    int temp = older_id;
    older_id = newer_id;
    newer_id = temp;
  }

  LiveObjectList *newer_lol = FindLolForId(newer_id, last());
  LiveObjectList *older_lol = FindLolForId(older_id, newer_lol);

  // If the id is defined, and we can't find a LOL for it, then we have an
  // invalid id.
  if ((newer_id != 0) && (newer_lol == NULL)) {
    return Failure::Exception();  // Fail: the newer lol id is invalid.
  }
  if ((older_id != 0) && (older_lol == NULL)) {
    return Failure::Exception();  // Fail: the older lol id is invalid.
  }

  LolFilter filter(filter_obj);
  LolSummaryWriter writer(older_lol, newer_lol);
  return SummarizePrivate(&writer, &filter, false);
}


// Creates a summary report for the debugger.
// Note: the SummaryWriter takes care of iterating over objects and filling in
// the summary.
MaybeObject* LiveObjectList::SummarizePrivate(SummaryWriter* writer,
                                              LolFilter* filter,
                                              bool is_tracking_roots) {
  HandleScope scope;
  MaybeObject* maybe_result;

  LiveObjectSummary summary(filter);
  writer->Write(&summary);

  Isolate* isolate = Isolate::Current();
  Factory* factory = isolate->factory();

  // The result body will look like this:
  // body: {
  //   count: <total_count>,
  //   size: <total_size>,
  //   found_root: <boolean>,       // optional.
  //   found_weak_root: <boolean>,  // optional.
  //   summary: [
  //     {
  //       desc: "<object type name>",
  //       count: <count>,
  //       size: size
  //     },
  //     ...
  //   ]
  // }

  // Prefetch some needed symbols.
  Handle<String> desc_sym = factory->LookupAsciiSymbol("desc");
  Handle<String> count_sym = factory->LookupAsciiSymbol("count");
  Handle<String> size_sym = factory->LookupAsciiSymbol("size");
  Handle<String> summary_sym = factory->LookupAsciiSymbol("summary");

  // Allocate the summary array.
  int entries_count = summary.GetNumberOfEntries();
  Handle<FixedArray> summary_arr =
      factory->NewFixedArray(entries_count);
  if (summary_arr->IsFailure()) return Object::cast(*summary_arr);

  int idx = 0;
  for (int i = 0; i < LiveObjectSummary::kNumberOfEntries; i++) {
    // Allocate the summary record.
    Handle<JSObject> detail = factory->NewJSObject(isolate->object_function());
    if (detail->IsFailure()) return Object::cast(*detail);

    // Fill in the summary record.
    LiveObjectType type = static_cast<LiveObjectType>(i);
    int count = summary.Count(type);
    if (count) {
      const char* desc_cstr = GetObjectTypeDesc(type);
      Handle<String> desc = factory->LookupAsciiSymbol(desc_cstr);
      int size = summary.Size(type);

      maybe_result = detail->SetProperty(*desc_sym,
                                         *desc,
                                         NONE,
                                         kNonStrictMode);
      if (maybe_result->IsFailure()) return maybe_result;
      maybe_result = detail->SetProperty(*count_sym,
                                         Smi::FromInt(count),
                                         NONE,
                                         kNonStrictMode);
      if (maybe_result->IsFailure()) return maybe_result;
      maybe_result = detail->SetProperty(*size_sym,
                                         Smi::FromInt(size),
                                         NONE,
                                         kNonStrictMode);
      if (maybe_result->IsFailure()) return maybe_result;

      summary_arr->set(idx++, *detail);
    }
  }

  // Wrap the summary fixed array in a JS array.
  Handle<JSObject> summary_obj =
    factory->NewJSObject(isolate->array_function());
  if (summary_obj->IsFailure()) return Object::cast(*summary_obj);
  Handle<JSArray>::cast(summary_obj)->SetContent(*summary_arr);

  // Create the body object.
  Handle<JSObject> body = factory->NewJSObject(isolate->object_function());
  if (body->IsFailure()) return Object::cast(*body);

  // Fill out the body object.
  int total_count = summary.total_count();
  int total_size = summary.total_size();
  maybe_result = body->SetProperty(*count_sym,
                                   Smi::FromInt(total_count),
                                   NONE,
                                   kNonStrictMode);
  if (maybe_result->IsFailure()) return maybe_result;

  maybe_result = body->SetProperty(*size_sym,
                                   Smi::FromInt(total_size),
                                   NONE,
                                   kNonStrictMode);
  if (maybe_result->IsFailure()) return maybe_result;

  if (is_tracking_roots) {
    int found_root = summary.found_root();
    int found_weak_root = summary.found_weak_root();
    Handle<String> root_sym = factory->LookupAsciiSymbol("found_root");
    Handle<String> weak_root_sym =
        factory->LookupAsciiSymbol("found_weak_root");
    maybe_result = body->SetProperty(*root_sym,
                                     Smi::FromInt(found_root),
                                     NONE,
                                     kNonStrictMode);
    if (maybe_result->IsFailure()) return maybe_result;
    maybe_result = body->SetProperty(*weak_root_sym,
                                     Smi::FromInt(found_weak_root),
                                     NONE,
                                     kNonStrictMode);
    if (maybe_result->IsFailure()) return maybe_result;
  }

  maybe_result = body->SetProperty(*summary_sym,
                                   *summary_obj,
                                   NONE,
                                   kNonStrictMode);
  if (maybe_result->IsFailure()) return maybe_result;

  return *body;
}


// Returns an array listing the captured lols.
// Note: only dumps the section starting at start_idx and only up to
// dump_limit entries.
MaybeObject* LiveObjectList::Info(int start_idx, int dump_limit) {
  Isolate* isolate = Isolate::Current();
  Factory* factory = isolate->factory();

  HandleScope scope(isolate);
  MaybeObject* maybe_result;

  int total_count = LiveObjectList::list_count();
  int dump_count = total_count;

  // Adjust for where to start the dump.
  if (total_count == 0) {
      start_idx = 0;  // Ensure this to get an empty list.
  } else if ((start_idx < 0) || (start_idx >= total_count)) {
    return Failure::Exception();  // invalid start.
  }
  dump_count -= start_idx;

  // Adjust for the dump limit.
  if (dump_count > dump_limit) {
    dump_count = dump_limit;
  }

  // Allocate an array to hold the result.
  Handle<FixedArray> list = factory->NewFixedArray(dump_count);
  if (list->IsFailure()) return Object::cast(*list);

  // Prefetch some needed symbols.
  Handle<String> id_sym = factory->LookupAsciiSymbol("id");
  Handle<String> count_sym = factory->LookupAsciiSymbol("count");
  Handle<String> size_sym = factory->LookupAsciiSymbol("size");

  // Fill the array with the lol details.
  int idx = 0;
  LiveObjectList* lol = first_;
  while ((lol != NULL) && (idx < start_idx)) {  // Skip tail entries.
    if (lol->id() != 0) {
      idx++;
    }
    lol = lol->next();
  }
  idx = 0;
  while ((lol != NULL) && (dump_limit != 0)) {
    if (lol->id() != 0) {
      int count;
      int size;
      count = lol->GetTotalObjCountAndSize(&size);

      Handle<JSObject> detail =
          factory->NewJSObject(isolate->object_function());
      if (detail->IsFailure()) return Object::cast(*detail);

      maybe_result = detail->SetProperty(*id_sym,
                                         Smi::FromInt(lol->id()),
                                         NONE,
                                         kNonStrictMode);
      if (maybe_result->IsFailure()) return maybe_result;
      maybe_result = detail->SetProperty(*count_sym,
                                         Smi::FromInt(count),
                                         NONE,
                                         kNonStrictMode);
      if (maybe_result->IsFailure()) return maybe_result;
      maybe_result = detail->SetProperty(*size_sym,
                                         Smi::FromInt(size),
                                         NONE,
                                         kNonStrictMode);
      if (maybe_result->IsFailure()) return maybe_result;
      list->set(idx++, *detail);
      dump_limit--;
    }
    lol = lol->next();
  }

  // Return the result as a JS array.
  Handle<JSObject> lols = factory->NewJSObject(isolate->array_function());
  Handle<JSArray>::cast(lols)->SetContent(*list);

  Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
  if (result->IsFailure()) return Object::cast(*result);

  maybe_result = result->SetProperty(*count_sym,
                                     Smi::FromInt(total_count),
                                     NONE,
                                     kNonStrictMode);
  if (maybe_result->IsFailure()) return maybe_result;

  Handle<String> first_sym = factory->LookupAsciiSymbol("first_index");
  maybe_result = result->SetProperty(*first_sym,
                                     Smi::FromInt(start_idx),
                                     NONE,
                                     kNonStrictMode);
  if (maybe_result->IsFailure()) return maybe_result;

  Handle<String> lists_sym = factory->LookupAsciiSymbol("lists");
  maybe_result = result->SetProperty(*lists_sym,
                                     *lols,
                                     NONE,
                                     kNonStrictMode);
  if (maybe_result->IsFailure()) return maybe_result;

  return *result;
}


// Deletes all captured lols.
void LiveObjectList::Reset() {
  LiveObjectList *lol = last();
  // Just delete the last.  Each lol will delete it's prev automatically.
  delete lol;

  next_element_id_ = 1;
  list_count_ = 0;
  last_id_ = 0;
  first_ = NULL;
  last_ = NULL;
}


// Gets the object for the specified obj id.
Object* LiveObjectList::GetObj(int obj_id) {
  Element* element = FindElementFor<int>(GetElementId, obj_id);
  if (element != NULL) {
    return Object::cast(element->obj_);
  }
  return HEAP->undefined_value();
}


// Gets the obj id for the specified address if valid.
int LiveObjectList::GetObjId(Object* obj) {
  // Make a heap object pointer from the address.
  HeapObject* hobj = HeapObject::cast(obj);
  Element* element = FindElementFor<HeapObject*>(GetElementObj, hobj);
  if (element != NULL) {
    return element->id_;
  }
  return 0;  // Invalid address.
}


// Gets the obj id for the specified address if valid.
Object* LiveObjectList::GetObjId(Handle<String> address) {
  SmartPointer<char> addr_str =
      address->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);

  Isolate* isolate = Isolate::Current();

  // Extract the address value from the string.
  int value =
      static_cast<int>(StringToInt(isolate->unicode_cache(), *address, 16));
  Object* obj = reinterpret_cast<Object*>(value);
  return Smi::FromInt(GetObjId(obj));
}


// Helper class for copying HeapObjects.
class LolVisitor: public ObjectVisitor {
 public:
  LolVisitor(HeapObject* target, Handle<HeapObject> handle_to_skip)
      : target_(target), handle_to_skip_(handle_to_skip), found_(false) {}

  void VisitPointer(Object** p) { CheckPointer(p); }

  void VisitPointers(Object** start, Object** end) {
    // Check all HeapObject pointers in [start, end).
    for (Object** p = start; !found() && p < end; p++) CheckPointer(p);
  }

  inline bool found() const { return found_; }
  inline bool reset() { return found_ = false; }

 private:
  inline void CheckPointer(Object** p) {
    Object* object = *p;
    if (HeapObject::cast(object) == target_) {
      // We may want to skip this handle because the handle may be a local
      // handle in a handle scope in one of our callers.  Once we return,
      // that handle will be popped.  Hence, we don't want to count it as
      // a root that would have kept the target object alive.
      if (!handle_to_skip_.is_null() &&
          handle_to_skip_.location() == reinterpret_cast<HeapObject**>(p)) {
        return;  // Skip this handle.
      }
      found_ = true;
    }
  }

  HeapObject* target_;
  Handle<HeapObject> handle_to_skip_;
  bool found_;
};


inline bool AddRootRetainerIfFound(const LolVisitor& visitor,
                                   LolFilter* filter,
                                   LiveObjectSummary *summary,
                                   void (*SetRootFound)(LiveObjectSummary *s),
                                   int start,
                                   int dump_limit,
                                   int* total_count,
                                   Handle<FixedArray> retainers_arr,
                                   int* count,
                                   int* index,
                                   const char* root_name,
                                   Handle<String> id_sym,
                                   Handle<String> desc_sym,
                                   Handle<String> size_sym,
                                   Handle<Object> error) {
  HandleScope scope;

  // Scratch handles.
  Handle<JSObject> detail;
  Handle<String> desc;
  Handle<HeapObject> retainer;

  if (visitor.found()) {
    if (!filter->is_active()) {
      (*total_count)++;
      if (summary) {
        SetRootFound(summary);
      } else if ((*total_count > start) && ((*index) < dump_limit)) {
        (*count)++;
        if (!retainers_arr.is_null()) {
          return AddObjDetail(retainers_arr,
                              (*index)++,
                              0,
                              retainer,
                              root_name,
                              id_sym,
                              desc_sym,
                              size_sym,
                              detail,
                              desc,
                              error);
        }
      }
    }
  }
  return true;
}


inline void SetFoundRoot(LiveObjectSummary *summary) {
  summary->set_found_root();
}


inline void SetFoundWeakRoot(LiveObjectSummary *summary) {
  summary->set_found_weak_root();
}


int LiveObjectList::GetRetainers(Handle<HeapObject> target,
                                 Handle<JSObject> instance_filter,
                                 Handle<FixedArray> retainers_arr,
                                 int start,
                                 int dump_limit,
                                 int* total_count,
                                 LolFilter* filter,
                                 LiveObjectSummary *summary,
                                 JSFunction* arguments_function,
                                 Handle<Object> error) {
  HandleScope scope;

  // Scratch handles.
  Handle<JSObject> detail;
  Handle<String> desc;
  Handle<HeapObject> retainer;

  Isolate* isolate = Isolate::Current();
  Factory* factory = isolate->factory();

  // Prefetch some needed symbols.
  Handle<String> id_sym = factory->LookupAsciiSymbol("id");
  Handle<String> desc_sym = factory->LookupAsciiSymbol("desc");
  Handle<String> size_sym = factory->LookupAsciiSymbol("size");

  NoHandleAllocation ha;
  int count = 0;
  int index = 0;
  Handle<JSObject> last_obj;

  *total_count = 0;

  // Iterate roots.
  LolVisitor lol_visitor(*target, target);
  isolate->heap()->IterateStrongRoots(&lol_visitor, VISIT_ALL);
  if (!AddRootRetainerIfFound(lol_visitor,
                              filter,
                              summary,
                              SetFoundRoot,
                              start,
                              dump_limit,
                              total_count,
                              retainers_arr,
                              &count,
                              &index,
                              "<root>",
                              id_sym,
                              desc_sym,
                              size_sym,
                              error)) {
    return -1;
  }

  lol_visitor.reset();
  isolate->heap()->IterateWeakRoots(&lol_visitor, VISIT_ALL);
  if (!AddRootRetainerIfFound(lol_visitor,
                              filter,
                              summary,
                              SetFoundWeakRoot,
                              start,
                              dump_limit,
                              total_count,
                              retainers_arr,
                              &count,
                              &index,
                              "<weak root>",
                              id_sym,
                              desc_sym,
                              size_sym,
                              error)) {
    return -1;
  }

  // Iterate the live object lists.
  LolIterator it(NULL, last());
  for (it.Init(); !it.Done() && (index < dump_limit); it.Next()) {
    HeapObject* heap_obj = it.Obj();

    // Only look at all JSObjects.
    if (heap_obj->IsJSObject()) {
      // Skip context extension objects and argument arrays as these are
      // checked in the context of functions using them.
      JSObject* obj = JSObject::cast(heap_obj);
      if (obj->IsJSContextExtensionObject() ||
          obj->map()->constructor() == arguments_function) {
        continue;
      }

      // Check if the JS object has a reference to the object looked for.
      if (obj->ReferencesObject(*target)) {
        // Check instance filter if supplied. This is normally used to avoid
        // references from mirror objects (see Runtime_IsInPrototypeChain).
        if (!instance_filter->IsUndefined()) {
          Object* V = obj;
          while (true) {
            Object* prototype = V->GetPrototype();
            if (prototype->IsNull()) {
              break;
            }
            if (*instance_filter == prototype) {
              obj = NULL;  // Don't add this object.
              break;
            }
            V = prototype;
          }
        }

        if (obj != NULL) {
          // Skip objects that have been filtered out.
          if (filter->Matches(heap_obj)) {
            continue;
          }

          // Valid reference found add to instance array if supplied an update
          // count.
          last_obj = Handle<JSObject>(obj);
          (*total_count)++;

          if (summary != NULL) {
            summary->Add(heap_obj);
          } else if ((*total_count > start) && (index < dump_limit)) {
            count++;
            if (!retainers_arr.is_null()) {
              retainer = Handle<HeapObject>(heap_obj);
              bool success = AddObjDetail(retainers_arr,
                                          index++,
                                          it.Id(),
                                          retainer,
                                          NULL,
                                          id_sym,
                                          desc_sym,
                                          size_sym,
                                          detail,
                                          desc,
                                          error);
              if (!success) return -1;
            }
          }
        }
      }
    }
  }

  // Check for circular reference only. This can happen when the object is only
  // referenced from mirrors and has a circular reference in which case the
  // object is not really alive and would have been garbage collected if not
  // referenced from the mirror.

  if (*total_count == 1 && !last_obj.is_null() && *last_obj == *target) {
    count = 0;
    *total_count = 0;
  }

  return count;
}


MaybeObject* LiveObjectList::GetObjRetainers(int obj_id,
                                             Handle<JSObject> instance_filter,
                                             bool verbose,
                                             int start,
                                             int dump_limit,
                                             Handle<JSObject> filter_obj) {
  Isolate* isolate = Isolate::Current();
  Factory* factory = isolate->factory();
  Heap* heap = isolate->heap();

  HandleScope scope(isolate);

  // Get the target object.
  HeapObject* heap_obj = HeapObject::cast(GetObj(obj_id));
  if (heap_obj == heap->undefined_value()) {
    return heap_obj;
  }

  Handle<HeapObject> target = Handle<HeapObject>(heap_obj);

  // Get the constructor function for context extension and arguments array.
  JSObject* arguments_boilerplate =
      isolate->context()->global_context()->arguments_boilerplate();
  JSFunction* arguments_function =
      JSFunction::cast(arguments_boilerplate->map()->constructor());

  Handle<JSFunction> args_function = Handle<JSFunction>(arguments_function);
  LolFilter filter(filter_obj);

  if (!verbose) {
    RetainersSummaryWriter writer(target, instance_filter, args_function);
    return SummarizePrivate(&writer, &filter, true);

  } else {
    RetainersDumpWriter writer(target, instance_filter, args_function);
    Object* body_obj;
    MaybeObject* maybe_result =
        DumpPrivate(&writer, start, dump_limit, &filter);
    if (!maybe_result->ToObject(&body_obj)) {
      return maybe_result;
    }

    // Set body.id.
    Handle<JSObject> body = Handle<JSObject>(JSObject::cast(body_obj));
    Handle<String> id_sym = factory->LookupAsciiSymbol("id");
    maybe_result = body->SetProperty(*id_sym,
                                     Smi::FromInt(obj_id),
                                     NONE,
                                     kNonStrictMode);
    if (maybe_result->IsFailure()) return maybe_result;

    return *body;
  }
}


Object* LiveObjectList::PrintObj(int obj_id) {
  Object* obj = GetObj(obj_id);
  if (!obj) {
    return HEAP->undefined_value();
  }

  EmbeddedVector<char, 128> temp_filename;
  static int temp_count = 0;
  const char* path_prefix = ".";

  Isolate* isolate = Isolate::Current();
  Factory* factory = isolate->factory();
  Heap* heap = isolate->heap();

  if (FLAG_lol_workdir) {
    path_prefix = FLAG_lol_workdir;
  }
  OS::SNPrintF(temp_filename, "%s/lol-print-%d", path_prefix, ++temp_count);

  FILE* f = OS::FOpen(temp_filename.start(), "w+");

  PrintF(f, "@%d ", LiveObjectList::GetObjId(obj));
#ifdef OBJECT_PRINT
#ifdef INSPECTOR
  Inspector::DumpObjectType(f, obj);
#endif  // INSPECTOR
  PrintF(f, "\n");
  obj->Print(f);
#else  // !OBJECT_PRINT
  obj->ShortPrint(f);
#endif  // !OBJECT_PRINT
  PrintF(f, "\n");
  Flush(f);
  fclose(f);

  // Create a string from the temp_file.
  // Note: the mmapped resource will take care of closing the file.
  MemoryMappedExternalResource* resource =
      new MemoryMappedExternalResource(temp_filename.start(), true);
  if (resource->exists() && !resource->is_empty()) {
    ASSERT(resource->IsAscii());
    Handle<String> dump_string =
        factory->NewExternalStringFromAscii(resource);
    heap->external_string_table()->AddString(*dump_string);
    return *dump_string;
  } else {
    delete resource;
  }
  return HEAP->undefined_value();
}


class LolPathTracer: public PathTracer {
 public:
  LolPathTracer(FILE* out,
                Object* search_target,
                WhatToFind what_to_find)
      : PathTracer(search_target, what_to_find, VISIT_ONLY_STRONG), out_(out) {}

 private:
  void ProcessResults();

  FILE* out_;
};


void LolPathTracer::ProcessResults() {
  if (found_target_) {
    PrintF(out_, "=====================================\n");
    PrintF(out_, "====        Path to object       ====\n");
    PrintF(out_, "=====================================\n\n");

    ASSERT(!object_stack_.is_empty());
    Object* prev = NULL;
    for (int i = 0, index = 0; i < object_stack_.length(); i++) {
      Object* obj = object_stack_[i];

      // Skip this object if it is basically the internals of the
      // previous object (which would have dumped its details already).
      if (prev && prev->IsJSObject() &&
          (obj != search_target_)) {
        JSObject* jsobj = JSObject::cast(prev);
        if (obj->IsFixedArray() &&
            jsobj->properties() == FixedArray::cast(obj)) {
          // Skip this one because it would have been printed as the
          // properties of the last object already.
          continue;
        } else if (obj->IsHeapObject() &&
                   jsobj->elements() == HeapObject::cast(obj)) {
          // Skip this one because it would have been printed as the
          // elements of the last object already.
          continue;
        }
      }

      // Print a connecting arrow.
      if (i > 0) PrintF(out_, "\n     |\n     |\n     V\n\n");

      // Print the object index.
      PrintF(out_, "[%d] ", ++index);

      // Print the LOL object ID:
      int id = LiveObjectList::GetObjId(obj);
      if (id > 0) PrintF(out_, "@%d ", id);

#ifdef OBJECT_PRINT
#ifdef INSPECTOR
      Inspector::DumpObjectType(out_, obj);
#endif  // INSPECTOR
      PrintF(out_, "\n");
      obj->Print(out_);
#else  // !OBJECT_PRINT
      obj->ShortPrint(out_);
      PrintF(out_, "\n");
#endif  // !OBJECT_PRINT
      Flush(out_);
    }
    PrintF(out_, "\n");
    PrintF(out_, "=====================================\n\n");
    Flush(out_);
  }
}


Object* LiveObjectList::GetPathPrivate(HeapObject* obj1, HeapObject* obj2) {
  EmbeddedVector<char, 128> temp_filename;
  static int temp_count = 0;
  const char* path_prefix = ".";

  if (FLAG_lol_workdir) {
    path_prefix = FLAG_lol_workdir;
  }
  OS::SNPrintF(temp_filename, "%s/lol-getpath-%d", path_prefix, ++temp_count);

  FILE* f = OS::FOpen(temp_filename.start(), "w+");

  Isolate* isolate = Isolate::Current();
  Factory* factory = isolate->factory();
  Heap* heap = isolate->heap();

  // Save the previous verbosity.
  bool prev_verbosity = FLAG_use_verbose_printer;
  FLAG_use_verbose_printer = false;

  // Dump the paths.
  {
    // The tracer needs to be scoped because its usage asserts no allocation,
    // and we need to allocate the result string below.
    LolPathTracer tracer(f, obj2, LolPathTracer::FIND_FIRST);

    bool found = false;
    if (obj1 == NULL) {
      // Check for ObjectGroups that references this object.
      // TODO(mlam): refactor this to be more modular.
      {
        List<ObjectGroup*>* groups = isolate->global_handles()->object_groups();
        for (int i = 0; i < groups->length(); i++) {
          ObjectGroup* group = groups->at(i);
          if (group == NULL) continue;

          bool found_group = false;
          for (size_t j = 0; j < group->length_; j++) {
            Object* object = *(group->objects_[j]);
            HeapObject* hobj = HeapObject::cast(object);
            if (obj2 == hobj) {
              found_group = true;
              break;
            }
          }

          if (found_group) {
            PrintF(f,
                   "obj %p is a member of object group %p {\n",
                   reinterpret_cast<void*>(obj2),
                   reinterpret_cast<void*>(group));
            for (size_t j = 0; j < group->length_; j++) {
              Object* object = *(group->objects_[j]);
              if (!object->IsHeapObject()) continue;

              HeapObject* hobj = HeapObject::cast(object);
              int id = GetObjId(hobj);
              if (id != 0) {
                PrintF(f, "  @%d:", id);
              } else {
                PrintF(f, "  <no id>:");
              }

              char buffer[512];
              GenerateObjectDesc(hobj, buffer, sizeof(buffer));
              PrintF(f, " %s", buffer);
              if (hobj == obj2) {
                PrintF(f, " <===");
              }
              PrintF(f, "\n");
            }
            PrintF(f, "}\n");
          }
        }
      }

      PrintF(f, "path from roots to obj %p\n", reinterpret_cast<void*>(obj2));
      heap->IterateRoots(&tracer, VISIT_ONLY_STRONG);
      found = tracer.found();

      if (!found) {
        PrintF(f, "  No paths found. Checking symbol tables ...\n");
        SymbolTable* symbol_table = HEAP->raw_unchecked_symbol_table();
        tracer.VisitPointers(reinterpret_cast<Object**>(&symbol_table),
                             reinterpret_cast<Object**>(&symbol_table)+1);
        found = tracer.found();
        if (!found) {
          symbol_table->IteratePrefix(&tracer);
          found = tracer.found();
        }
      }

      if (!found) {
        PrintF(f, "  No paths found. Checking weak roots ...\n");
        // Check weak refs next.
        isolate->global_handles()->IterateWeakRoots(&tracer);
        found = tracer.found();
      }

    } else {
      PrintF(f, "path from obj %p to obj %p:\n",
             reinterpret_cast<void*>(obj1), reinterpret_cast<void*>(obj2));
      tracer.TracePathFrom(reinterpret_cast<Object**>(&obj1));
      found = tracer.found();
    }

    if (!found) {
      PrintF(f, "  No paths found\n\n");
    }
  }

  // Flush and clean up the dumped file.
  Flush(f);
  fclose(f);

  // Restore the previous verbosity.
  FLAG_use_verbose_printer = prev_verbosity;

  // Create a string from the temp_file.
  // Note: the mmapped resource will take care of closing the file.
  MemoryMappedExternalResource* resource =
      new MemoryMappedExternalResource(temp_filename.start(), true);
  if (resource->exists() && !resource->is_empty()) {
    ASSERT(resource->IsAscii());
    Handle<String> path_string =
        factory->NewExternalStringFromAscii(resource);
    heap->external_string_table()->AddString(*path_string);
    return *path_string;
  } else {
    delete resource;
  }
  return heap->undefined_value();
}


Object* LiveObjectList::GetPath(int obj_id1,
                                int obj_id2,
                                Handle<JSObject> instance_filter) {
  HandleScope scope;

  // Get the target object.
  HeapObject* obj1 = NULL;
  if (obj_id1 != 0) {
    obj1 = HeapObject::cast(GetObj(obj_id1));
    if (obj1 == HEAP->undefined_value()) {
      return obj1;
    }
  }

  HeapObject* obj2 = HeapObject::cast(GetObj(obj_id2));
  if (obj2 == HEAP->undefined_value()) {
    return obj2;
  }

  return GetPathPrivate(obj1, obj2);
}


void LiveObjectList::DoProcessNonLive(HeapObject *obj) {
  // We should only be called if we have at least one lol to search.
  ASSERT(last() != NULL);
  Element* element = last()->Find(obj);
  if (element != NULL) {
    NullifyNonLivePointer(&element->obj_);
  }
}


void LiveObjectList::IterateElementsPrivate(ObjectVisitor* v) {
  LiveObjectList* lol = last();
  while (lol != NULL) {
    Element* elements = lol->elements_;
    int count = lol->obj_count_;
    for (int i = 0; i < count; i++) {
      HeapObject** p = &elements[i].obj_;
      v->VisitPointer(reinterpret_cast<Object **>(p));
    }
    lol = lol->prev_;
  }
}


// Purpose: Called by GCEpilogue to purge duplicates.  Not to be called by
// anyone else.
void LiveObjectList::PurgeDuplicates() {
  bool is_sorted = false;
  LiveObjectList* lol = last();
  if (!lol) {
    return;  // Nothing to purge.
  }

  int total_count = lol->TotalObjCount();
  if (!total_count) {
    return;  // Nothing to purge.
  }

  Element* elements = NewArray<Element>(total_count);
  int count = 0;

  // Copy all the object elements into a consecutive array.
  while (lol) {
    memcpy(&elements[count], lol->elements_, lol->obj_count_ * sizeof(Element));
    count += lol->obj_count_;
    lol = lol->prev_;
  }
  qsort(elements, total_count, sizeof(Element),
        reinterpret_cast<RawComparer>(CompareElement));

  ASSERT(count == total_count);

  // Iterate over all objects in the consolidated list and check for dups.
  total_count--;
  for (int i = 0; i < total_count; ) {
    Element* curr = &elements[i];
    HeapObject* curr_obj = curr->obj_;
    int j = i+1;
    bool done = false;

    while (!done && (j < total_count)) {
      // Process if the element's object is still live after the current GC.
      // Non-live objects will be converted to SMIs i.e. not HeapObjects.
      if (curr_obj->IsHeapObject()) {
        Element* next = &elements[j];
        HeapObject* next_obj = next->obj_;
        if (next_obj->IsHeapObject()) {
          if (curr_obj != next_obj) {
            done = true;
            continue;  // Live object but no match.  Move on.
          }

          // NOTE: we've just GCed the LOLs.  Hence, they are no longer sorted.
          // Since we detected at least one need to search for entries, we'll
          // sort it to enable the use of NullifyMostRecent() below.  We only
          // need to sort it once (except for one exception ... see below).
          if (!is_sorted) {
            SortAll();
            is_sorted = true;
          }

          // We have a match.  Need to nullify the most recent ref to this
          // object.  We'll keep the oldest ref:
          // Note: we will nullify the element record in the LOL
          // database, not in the local sorted copy of the elements.
          NullifyMostRecent(curr_obj);
        }
      }
      // Either the object was already marked for purging, or we just marked
      // it.  Either way, if there's more than one dup, then we need to check
      // the next element for another possible dup against the current as well
      // before we move on.  So, here we go.
      j++;
    }

    // We can move on to checking the match on the next element.
    i = j;
  }

  DeleteArray<Element>(elements);
}


// Purpose: Purges dead objects and resorts the LOLs.
void LiveObjectList::GCEpiloguePrivate() {
  // Note: During the GC, ConsStrings may be collected and pointers may be
  // forwarded to its constituent string.  As a result, we may find dupes of
  // objects references in the LOL list.
  // Another common way we get dups is that free chunks that have been swept
  // in the oldGen heap may be kept as ByteArray objects in a free list.
  //
  // When we promote live objects from the youngGen, the object may be moved
  // to the start of these free chunks.  Since there is no free or move event
  // for the free chunks, their addresses will show up 2 times: once for their
  // original free ByteArray selves, and once for the newly promoted youngGen
  // object.  Hence, we can get a duplicate address in the LOL again.
  //
  // We need to eliminate these dups because the LOL implementation expects to
  // only have at most one unique LOL reference to any object at any time.
  PurgeDuplicates();

  // After the GC, sweep away all free'd Elements and compact.
  LiveObjectList *prev = NULL;
  LiveObjectList *next = NULL;

  // Iterating from the youngest lol to the oldest lol.
  for (LiveObjectList *lol = last(); lol; lol = prev) {
    Element* elements = lol->elements_;
    prev = lol->prev();  // Save the prev.

    // Remove any references to collected objects.
    int i = 0;
    while (i < lol->obj_count_) {
      Element& element = elements[i];
      if (!element.obj_->IsHeapObject()) {
        // If the HeapObject address was converted into a SMI, then this
        // is a dead object.  Copy the last element over this one.
        element = elements[lol->obj_count_ - 1];
        lol->obj_count_--;
        // We've just moved the last element into this index.  We'll revisit
        // this index again.  Hence, no need to increment the iterator.
      } else {
        i++;  // Look at the next element next.
      }
    }

    int new_count = lol->obj_count_;

    // Check if there are any more elements to keep after purging the dead ones.
    if (new_count == 0) {
      DeleteArray<Element>(elements);
      lol->elements_ = NULL;
      lol->capacity_ = 0;
      ASSERT(lol->obj_count_ == 0);

      // If the list is also invisible, the clean up the list as well.
      if (lol->id_ == 0) {
        // Point the next lol's prev to this lol's prev.
        if (next) {
          next->prev_ = lol->prev_;
        } else {
          last_ = lol->prev_;
        }

        // Delete this now empty and invisible lol.
        delete lol;

        // Don't point the next to this lol since it is now deleted.
        // Leave the next pointer pointing to the current lol.
        continue;
      }

    } else {
      // If the obj_count_ is less than the capacity and the difference is
      // greater than a specified threshold, then we should shrink the list.
      int diff = lol->capacity_ - new_count;
      const int kMaxUnusedSpace = 64;
      if (diff > kMaxUnusedSpace) {  // Threshold for shrinking.
        // Shrink the list.
        Element *new_elements = NewArray<Element>(new_count);
        memcpy(new_elements, elements, new_count * sizeof(Element));

        DeleteArray<Element>(elements);
        lol->elements_ = new_elements;
        lol->capacity_ = new_count;
      }
      ASSERT(lol->obj_count_ == new_count);

      lol->Sort();  // We've moved objects.  Re-sort in case.
    }

    // Save the next (for the previous link) in case we need it later.
    next = lol;
  }

#ifdef VERIFY_LOL
  if (FLAG_verify_lol) {
    Verify();
  }
#endif
}


#ifdef VERIFY_LOL
void LiveObjectList::Verify(bool match_heap_exactly) {
  OS::Print("Verifying the LiveObjectList database:\n");

  LiveObjectList* lol = last();
  if (lol == NULL) {
    OS::Print("  No lol database to verify\n");
    return;
  }

  OS::Print("  Preparing the lol database ...\n");
  int total_count = lol->TotalObjCount();

  Element* elements = NewArray<Element>(total_count);
  int count = 0;

  // Copy all the object elements into a consecutive array.
  OS::Print("  Copying the lol database ...\n");
  while (lol != NULL) {
    memcpy(&elements[count], lol->elements_, lol->obj_count_ * sizeof(Element));
    count += lol->obj_count_;
    lol = lol->prev_;
  }
  qsort(elements, total_count, sizeof(Element),
        reinterpret_cast<RawComparer>(CompareElement));

  ASSERT(count == total_count);

  // Iterate over all objects in the heap and check for:
  // 1. object in LOL but not in heap i.e. error.
  // 2. object in heap but not in LOL (possibly not an error).  Usually
  //    just means that we don't have the a capture of the latest heap.
  //    That is unless we did this verify immediately after a capture,
  //    and specified match_heap_exactly = true.

  int number_of_heap_objects = 0;
  int number_of_matches = 0;
  int number_not_in_heap = total_count;
  int number_not_in_lol = 0;

  OS::Print("  Start verify ...\n");
  OS::Print("  Verifying ...");
  Flush();
  HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
  HeapObject* heap_obj = NULL;
  while ((heap_obj = iterator.next()) != NULL) {
    number_of_heap_objects++;

    // Check if the heap_obj is in the lol.
    Element key;
    key.obj_ = heap_obj;

    Element* result = reinterpret_cast<Element*>(
        bsearch(&key, elements, total_count, sizeof(Element),
                reinterpret_cast<RawComparer>(CompareElement)));

    if (result != NULL) {
      number_of_matches++;
      number_not_in_heap--;
      // Mark it as found by changing it into a SMI (mask off low bit).
      // Note: we cannot use HeapObject::cast() here because it asserts that
      // the HeapObject bit is set on the address, but we're unsetting it on
      // purpose here for our marking.
      result->obj_ = reinterpret_cast<HeapObject*>(heap_obj->address());

    } else {
      number_not_in_lol++;
      if (match_heap_exactly) {
        OS::Print("heap object %p NOT in lol database\n", heap_obj);
      }
    }
    // Show some sign of life.
    if (number_of_heap_objects % 1000 == 0) {
      OS::Print(".");
      fflush(stdout);
    }
  }
  OS::Print("\n");

  // Reporting lol objects not found in the heap.
  if (number_not_in_heap) {
    int found = 0;
    for (int i = 0; (i < total_count) && (found < number_not_in_heap); i++) {
      Element& element = elements[i];
      if (element.obj_->IsHeapObject()) {
        OS::Print("lol database object [%d of %d] %p NOT in heap\n",
                  i, total_count, element.obj_);
        found++;
      }
    }
  }

  DeleteArray<Element>(elements);

  OS::Print("number of objects in lol database %d\n", total_count);
  OS::Print("number of heap objects .......... %d\n", number_of_heap_objects);
  OS::Print("number of matches ............... %d\n", number_of_matches);
  OS::Print("number NOT in heap .............. %d\n", number_not_in_heap);
  OS::Print("number NOT in lol database ...... %d\n", number_not_in_lol);

  if (number_of_matches != total_count) {
    OS::Print("  *** ERROR: "
              "NOT all lol database objects match heap objects.\n");
  }
  if (number_not_in_heap != 0) {
    OS::Print("  *** ERROR: %d lol database objects not found in heap.\n",
              number_not_in_heap);
  }
  if (match_heap_exactly) {
    if (!(number_not_in_lol == 0)) {
      OS::Print("  *** ERROR: %d heap objects NOT found in lol database.\n",
                number_not_in_lol);
    }
  }

  ASSERT(number_of_matches == total_count);
  ASSERT(number_not_in_heap == 0);
  ASSERT(number_not_in_lol == (number_of_heap_objects - total_count));
  if (match_heap_exactly) {
    ASSERT(total_count == number_of_heap_objects);
    ASSERT(number_not_in_lol == 0);
  }

  OS::Print("  Verify the lol database is sorted ...\n");
  lol = last();
  while (lol != NULL) {
    Element* elements = lol->elements_;
    for (int i = 0; i < lol->obj_count_ - 1; i++) {
      if (elements[i].obj_ >= elements[i+1].obj_) {
        OS::Print("  *** ERROR: lol %p obj[%d] %p > obj[%d] %p\n",
                  lol, i, elements[i].obj_, i+1, elements[i+1].obj_);
      }
    }
    lol = lol->prev_;
  }

  OS::Print("  DONE verifying.\n\n\n");
}


void LiveObjectList::VerifyNotInFromSpace() {
  OS::Print("VerifyNotInFromSpace() ...\n");
  LolIterator it(NULL, last());
  Heap* heap = ISOLATE->heap();
  int i = 0;
  for (it.Init(); !it.Done(); it.Next()) {
    HeapObject* heap_obj = it.Obj();
    if (heap->InFromSpace(heap_obj)) {
      OS::Print(" ERROR: VerifyNotInFromSpace: [%d] obj %p in From space %p\n",
                i++, heap_obj, heap->new_space()->FromSpaceLow());
    }
  }
}
#endif  // VERIFY_LOL


} }  // namespace v8::internal

#endif  // LIVE_OBJECT_LIST
