11e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Copyright 2011 the V8 project authors. All rights reserved.
21e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Redistribution and use in source and binary forms, with or without
31e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// modification, are permitted provided that the following conditions are
41e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// met:
51e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//
61e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//     * Redistributions of source code must retain the above copyright
71e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//       notice, this list of conditions and the following disclaimer.
81e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//     * Redistributions in binary form must reproduce the above
91e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//       copyright notice, this list of conditions and the following
101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//       disclaimer in the documentation and/or other materials provided
111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//       with the distribution.
121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//     * Neither the name of Google Inc. nor the names of its
131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//       contributors may be used to endorse or promote products derived
141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//       from this software without specific prior written permission.
151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block//
161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef LIVE_OBJECT_LIST
291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include <ctype.h>
311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include <stdlib.h>
321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "v8.h"
341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "checks.h"
361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "global-handles.h"
371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "heap.h"
381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "inspector.h"
3969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#include "isolate.h"
401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "list-inl.h"
41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "liveobjectlist-inl.h"
421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "string-stream.h"
431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "v8utils.h"
4469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#include "v8conversions.h"
451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace v8 {
471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace internal {
481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
50e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochtypedef int (*RawComparer)(const void*, const void*);
51e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
52e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
53e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef CHECK_ALL_OBJECT_TYPES
54e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
55e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define DEBUG_LIVE_OBJECT_TYPES(v) \
56e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(Smi, "unexpected: Smi") \
57e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  \
58e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(CodeCache, "unexpected: CodeCache") \
59e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(BreakPointInfo, "unexpected: BreakPointInfo") \
60e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(DebugInfo, "unexpected: DebugInfo") \
61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(TypeSwitchInfo, "unexpected: TypeSwitchInfo") \
62e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(SignatureInfo, "unexpected: SignatureInfo") \
63e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(Script, "unexpected: Script") \
64e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ObjectTemplateInfo, "unexpected: ObjectTemplateInfo") \
65e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(FunctionTemplateInfo, "unexpected: FunctionTemplateInfo") \
66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(CallHandlerInfo, "unexpected: CallHandlerInfo") \
67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(InterceptorInfo, "unexpected: InterceptorInfo") \
68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(AccessCheckInfo, "unexpected: AccessCheckInfo") \
69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(AccessorInfo, "unexpected: AccessorInfo") \
70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalTwoByteString, "unexpected: ExternalTwoByteString") \
71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalAsciiString, "unexpected: ExternalAsciiString") \
72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalString, "unexpected: ExternalString") \
73e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(SeqTwoByteString, "unexpected: SeqTwoByteString") \
74e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(SeqAsciiString, "unexpected: SeqAsciiString") \
75e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(SeqString, "unexpected: SeqString") \
76e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(JSFunctionResultCache, "unexpected: JSFunctionResultCache") \
77e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(GlobalContext, "unexpected: GlobalContext") \
78e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(MapCache, "unexpected: MapCache") \
79e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(CodeCacheHashTable, "unexpected: CodeCacheHashTable") \
80e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(CompilationCacheTable, "unexpected: CompilationCacheTable") \
81e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(SymbolTable, "unexpected: SymbolTable") \
82e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(Dictionary, "unexpected: Dictionary") \
83e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(HashTable, "unexpected: HashTable") \
84e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(DescriptorArray, "unexpected: DescriptorArray") \
85e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalFloatArray, "unexpected: ExternalFloatArray") \
86e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalUnsignedIntArray, "unexpected: ExternalUnsignedIntArray") \
87e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalIntArray, "unexpected: ExternalIntArray") \
88e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalUnsignedShortArray, "unexpected: ExternalUnsignedShortArray") \
89e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalShortArray, "unexpected: ExternalShortArray") \
90e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalUnsignedByteArray, "unexpected: ExternalUnsignedByteArray") \
91e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalByteArray, "unexpected: ExternalByteArray") \
92e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(JSValue, "unexpected: JSValue")
93e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
94e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#else
95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define DEBUG_LIVE_OBJECT_TYPES(v)
96e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif
97e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
98e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
99e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define FOR_EACH_LIVE_OBJECT_TYPE(v) \
100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  DEBUG_LIVE_OBJECT_TYPES(v) \
101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  \
102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(JSArray, "JSArray") \
103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(JSRegExp, "JSRegExp") \
104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(JSFunction, "JSFunction") \
105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(JSGlobalObject, "JSGlobal") \
106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(JSBuiltinsObject, "JSBuiltins") \
107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(GlobalObject, "Global") \
108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(JSGlobalProxy, "JSGlobalProxy") \
109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(JSObject, "JSObject") \
110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  \
111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(Context, "meta: Context") \
112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ByteArray, "meta: ByteArray") \
11369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v(ExternalPixelArray, "meta: PixelArray") \
114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(ExternalArray, "meta: ExternalArray") \
115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(FixedArray, "meta: FixedArray") \
116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(String, "String") \
117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(HeapNumber, "HeapNumber") \
118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  \
119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(Code, "meta: Code") \
120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(Map, "meta: Map") \
121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(Oddball, "Oddball") \
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  v(Foreign, "meta: Foreign") \
123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(SharedFunctionInfo, "meta: SharedFunctionInfo") \
124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(Struct, "meta: Struct") \
125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  \
126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  v(HeapObject, "HeapObject")
127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochenum /* LiveObjectType */ {
130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define DECLARE_OBJECT_TYPE_ENUM(type, name) kType##type,
131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FOR_EACH_LIVE_OBJECT_TYPE(DECLARE_OBJECT_TYPE_ENUM)
132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  kInvalidLiveObjType,
133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  kNumberOfTypes
134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#undef DECLARE_OBJECT_TYPE_ENUM
135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLiveObjectType GetObjectType(HeapObject* heap_obj) {
139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // TODO(mlam): investigate usint Map::instance_type() instead.
140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define CHECK_FOR_OBJECT_TYPE(type, name) \
141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (heap_obj->Is##type()) return kType##type;
142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FOR_EACH_LIVE_OBJECT_TYPE(CHECK_FOR_OBJECT_TYPE)
143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#undef CHECK_FOR_OBJECT_TYPE
144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  UNREACHABLE();
146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return kInvalidLiveObjType;
147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochinline const char* GetObjectTypeDesc(LiveObjectType type) {
151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static const char* const name[kNumberOfTypes] = {
152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  #define DEFINE_OBJECT_TYPE_NAME(type, name) name,
153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    FOR_EACH_LIVE_OBJECT_TYPE(DEFINE_OBJECT_TYPE_NAME)
154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "invalid"
155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  #undef DEFINE_OBJECT_TYPE_NAME
156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  };
157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(type < kNumberOfTypes);
158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return name[type];
159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochconst char* GetObjectTypeDesc(HeapObject* heap_obj) {
163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectType type = GetObjectType(heap_obj);
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return GetObjectTypeDesc(type);
165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool IsOfType(LiveObjectType type, HeapObject* obj) {
169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Note: there are types that are more general (e.g. JSObject) that would
170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // have passed the Is##type_() test for more specialized types (e.g.
171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // JSFunction).  If we find a more specialized match but we're looking for
172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the general type, then we should reject the ones that matches the
173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // specialized type.
174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define CHECK_OBJECT_TYPE(type_, name) \
175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (obj->Is##type_()) return (type == kType##type_);
176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FOR_EACH_LIVE_OBJECT_TYPE(CHECK_OBJECT_TYPE)
178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#undef CHECK_OBJECT_TYPE
179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return false;
181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochconst AllocationSpace kInvalidSpace = static_cast<AllocationSpace>(-1);
185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic AllocationSpace FindSpaceFor(String* space_str) {
187589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  SmartArrayPointer<char> s =
188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      space_str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const char* key_str = *s;
191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  switch (key_str[0]) {
192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case 'c':
193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (strcmp(key_str, "cell") == 0) return CELL_SPACE;
194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (strcmp(key_str, "code") == 0) return CODE_SPACE;
195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case 'l':
197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (strcmp(key_str, "lo") == 0) return LO_SPACE;
198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case 'm':
200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (strcmp(key_str, "map") == 0) return MAP_SPACE;
201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case 'n':
203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (strcmp(key_str, "new") == 0) return NEW_SPACE;
204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case 'o':
206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (strcmp(key_str, "old-pointer") == 0) return OLD_POINTER_SPACE;
207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (strcmp(key_str, "old-data") == 0) return OLD_DATA_SPACE;
208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return kInvalidSpace;
211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool InSpace(AllocationSpace space, HeapObject* heap_obj) {
21569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Heap* heap = ISOLATE->heap();
216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (space != LO_SPACE) {
21769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return heap->InSpace(heap_obj, space);
218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // This is an optimization to speed up the check for an object in the LO
221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // space by exclusion because we know that all object pointers passed in
222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // here are guaranteed to be in the heap.  Hence, it is safe to infer
223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // using an exclusion test.
224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Note: calling Heap::InSpace(heap_obj, LO_SPACE) is too slow for our
225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // filters.
226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int first_space = static_cast<int>(FIRST_SPACE);
227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int last_space = static_cast<int>(LO_SPACE);
228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int sp = first_space; sp < last_space; sp++) {
22969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (heap->InSpace(heap_obj, static_cast<AllocationSpace>(sp))) {
230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return false;
231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
23369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  SLOW_ASSERT(heap->InSpace(heap_obj, LO_SPACE));
234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return true;
235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic LiveObjectType FindTypeFor(String* type_str) {
239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  SmartArrayPointer<char> s =
240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      type_str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define CHECK_OBJECT_TYPE(type_, name) { \
243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    const char* type_desc = GetObjectTypeDesc(kType##type_); \
244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    const char* key_str = *s; \
245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (strstr(type_desc, key_str) != NULL) return kType##type_; \
246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FOR_EACH_LIVE_OBJECT_TYPE(CHECK_OBJECT_TYPE)
248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#undef CHECK_OBJECT_TYPE
249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return kInvalidLiveObjType;
251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass LolFilter {
255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  explicit LolFilter(Handle<JSObject> filter_obj);
257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline bool is_active() const { return is_active_; }
259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline bool Matches(HeapObject* obj) {
260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return !is_active() || MatchesSlow(obj);
261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private:
264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void InitTypeFilter(Handle<JSObject> filter_obj);
265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void InitSpaceFilter(Handle<JSObject> filter_obj);
266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void InitPropertyFilter(Handle<JSObject> filter_obj);
267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool MatchesSlow(HeapObject* obj);
268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool is_active_;
270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectType type_;
271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AllocationSpace space_;
272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<String> prop_;
273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLolFilter::LolFilter(Handle<JSObject> filter_obj)
277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    : is_active_(false),
278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      type_(kInvalidLiveObjType),
279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      space_(kInvalidSpace),
280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      prop_() {
281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (filter_obj.is_null()) return;
282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  InitTypeFilter(filter_obj);
284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  InitSpaceFilter(filter_obj);
285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  InitPropertyFilter(filter_obj);
286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LolFilter::InitTypeFilter(Handle<JSObject> filter_obj) {
29069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> type_sym = FACTORY->LookupAsciiSymbol("type");
291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MaybeObject* maybe_result = filter_obj->GetProperty(*type_sym);
292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Object* type_obj;
293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->ToObject(&type_obj)) {
294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (type_obj->IsString()) {
295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      String* type_str = String::cast(type_obj);
296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      type_ = FindTypeFor(type_str);
297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (type_ != kInvalidLiveObjType) {
298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        is_active_ = true;
299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LolFilter::InitSpaceFilter(Handle<JSObject> filter_obj) {
30669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> space_sym = FACTORY->LookupAsciiSymbol("space");
307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MaybeObject* maybe_result = filter_obj->GetProperty(*space_sym);
308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Object* space_obj;
309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->ToObject(&space_obj)) {
310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (space_obj->IsString()) {
311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      String* space_str = String::cast(space_obj);
312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      space_ = FindSpaceFor(space_str);
313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (space_ != kInvalidSpace) {
314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        is_active_ = true;
315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LolFilter::InitPropertyFilter(Handle<JSObject> filter_obj) {
32269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> prop_sym = FACTORY->LookupAsciiSymbol("prop");
323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MaybeObject* maybe_result = filter_obj->GetProperty(*prop_sym);
324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Object* prop_obj;
325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->ToObject(&prop_obj)) {
326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (prop_obj->IsString()) {
327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      prop_ = Handle<String>(String::cast(prop_obj));
328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      is_active_ = true;
329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool LolFilter::MatchesSlow(HeapObject* obj) {
335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((type_ != kInvalidLiveObjType) && !IsOfType(type_, obj)) {
336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;  // Fail because obj is not of the type of interest.
337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((space_ != kInvalidSpace) && !InSpace(space_, obj)) {
339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;  // Fail because obj is not in the space of interest.
340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!prop_.is_null() && obj->IsJSObject()) {
342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LookupResult result;
343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    obj->Lookup(*prop_, &result);
344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!result.IsProperty()) {
345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return false;  // Fail because obj does not have the property of interest.
346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return true;
349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass LolIterator {
353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolIterator(LiveObjectList* older, LiveObjectList* newer)
355e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : older_(older),
356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        newer_(newer),
357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        curr_(0),
358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        elements_(0),
359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        count_(0),
360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        index_(0) { }
361e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline void Init() {
363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    SetCurrent(newer_);
364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // If the elements_ list is empty, then move on to the next list as long
365e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // as we're not at the last list (indicated by done()).
366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while ((elements_ == NULL) && !Done()) {
367e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      SetCurrent(curr_->prev_);
368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
369e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
370e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline bool Done() const {
372e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return (curr_ == older_);
373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Object level iteration.
376e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline void Next() {
377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    index_++;
378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (index_ >= count_) {
379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Iterate backwards until we get to the oldest list.
380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      while (!Done()) {
381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        SetCurrent(curr_->prev_);
382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // If we have elements to process, we're good to go.
383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (elements_ != NULL) break;
384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Else, we should advance to the next older list.
386e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
387e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
388e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
390e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline int Id() const {
391e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return elements_[index_].id_;
392e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
393e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline HeapObject* Obj() const {
394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return elements_[index_].obj_;
395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline int LolObjCount() const {
398e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (curr_ != NULL) return curr_->obj_count_;
399e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return 0;
400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
402e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch protected:
403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline void SetCurrent(LiveObjectList* new_curr) {
404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    curr_ = new_curr;
405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (curr_ != NULL) {
406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      elements_ = curr_->elements_;
407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      count_ = curr_->obj_count_;
408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      index_ = 0;
409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* older_;
413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* newer_;
414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* curr_;
415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList::Element* elements_;
416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count_;
417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int index_;
418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass LolForwardIterator : public LolIterator {
422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolForwardIterator(LiveObjectList* first, LiveObjectList* last)
424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : LolIterator(first, last) {
425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline void Init() {
428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    SetCurrent(older_);
429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // If the elements_ list is empty, then move on to the next list as long
430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // as we're not at the last list (indicated by Done()).
431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while ((elements_ == NULL) && !Done()) {
432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      SetCurrent(curr_->next_);
433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline bool Done() const {
437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return (curr_ == newer_);
438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Object level iteration.
441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline void Next() {
442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    index_++;
443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (index_ >= count_) {
444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Done with current list.  Move on to the next.
445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      while (!Done()) {  // If not at the last list already, ...
446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        SetCurrent(curr_->next_);
447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // If we have elements to process, we're good to go.
448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (elements_ != NULL) break;
449e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Else, we should advance to the next list.
451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Minimizes the white space in a string.  Tabs and newlines are replaced
458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// with a space where appropriate.
459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic int CompactString(char* str) {
460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  char* src = str;
461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  char* dst = str;
462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  char prev_ch = 0;
463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (*dst != '\0') {
464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    char ch = *src++;
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We will treat non-ASCII chars as '?'.
466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if ((ch & 0x80) != 0) {
467e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ch = '?';
468e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Compact contiguous whitespace chars into a single ' '.
470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (isspace(ch)) {
471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (prev_ch != ' ') *dst++ = ' ';
472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      prev_ch = ' ';
473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      continue;
474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    *dst++ = ch;
476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    prev_ch = ch;
477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return (dst - str);
479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Generates a custom description based on the specific type of
483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// object we're looking at.  We only generate specialized
484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// descriptions where we can.  In all other cases, we emit the
485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// generic info.
486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic void GenerateObjectDesc(HeapObject* obj,
487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               char* buffer,
488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               int buffer_size) {
489e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Vector<char> buffer_v(buffer, buffer_size);
490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(obj != NULL);
491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (obj->IsJSArray()) {
492e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    JSArray* jsarray = JSArray::cast(obj);
493e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    double length = jsarray->length()->Number();
494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    OS::SNPrintF(buffer_v,
495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 "%p <%s> len %g",
496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 reinterpret_cast<void*>(obj),
497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 GetObjectTypeDesc(obj),
498e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 length);
499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (obj->IsString()) {
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    String* str = String::cast(obj);
502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Only grab up to 160 chars in case they are double byte.
503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // We'll only dump 80 of them after we compact them.
504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    const int kMaxCharToDump = 80;
505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    const int kMaxBufferSize = kMaxCharToDump * 2;
506589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> str_sp = str->ToCString(DISALLOW_NULLS,
507589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                    ROBUST_STRING_TRAVERSAL,
508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                    0,
509589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                                                    kMaxBufferSize);
510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    char* str_cstr = *str_sp;
511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int length = CompactString(str_cstr);
512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    OS::SNPrintF(buffer_v,
513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 "%p <%s> '%.80s%s'",
514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 reinterpret_cast<void*>(obj),
515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 GetObjectTypeDesc(obj),
516e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 str_cstr,
517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 (length > kMaxCharToDump) ? "..." : "");
518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
519e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (obj->IsJSFunction() || obj->IsSharedFunctionInfo()) {
520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    SharedFunctionInfo* sinfo;
521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (obj->IsJSFunction()) {
522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JSFunction* func = JSFunction::cast(obj);
523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sinfo = func->shared();
524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      sinfo = SharedFunctionInfo::cast(obj);
526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    String* name = sinfo->DebugName();
529589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> name_sp =
530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    char* name_cstr = *name_sp;
532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapStringAllocator string_allocator;
534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    StringStream stream(&string_allocator);
535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    sinfo->SourceCodePrint(&stream, 50);
536589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<const char> source_sp = stream.ToCString();
537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    const char* source_cstr = *source_sp;
538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    OS::SNPrintF(buffer_v,
540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 "%p <%s> '%s' %s",
541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 reinterpret_cast<void*>(obj),
542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 GetObjectTypeDesc(obj),
543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 name_cstr,
544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 source_cstr);
545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if (obj->IsFixedArray()) {
547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    FixedArray* fixed = FixedArray::cast(obj);
548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    OS::SNPrintF(buffer_v,
550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 "%p <%s> len %d",
551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 reinterpret_cast<void*>(obj),
552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 GetObjectTypeDesc(obj),
553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 fixed->length());
554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    OS::SNPrintF(buffer_v,
557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 "%p <%s>",
558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 reinterpret_cast<void*>(obj),
559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 GetObjectTypeDesc(obj));
560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Utility function for filling in a line of detail in a verbose dump.
565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic bool AddObjDetail(Handle<FixedArray> arr,
566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         int index,
567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         int obj_id,
568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Handle<HeapObject> target,
569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         const char* desc_str,
570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Handle<String> id_sym,
571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Handle<String> desc_sym,
572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Handle<String> size_sym,
573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Handle<JSObject> detail,
574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Handle<String> desc,
575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Handle<Object> error) {
57669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
57769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Factory* factory = isolate->factory();
57869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  detail = factory->NewJSObject(isolate->object_function());
579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (detail->IsFailure()) {
580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    error = detail;
581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;
582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int size = 0;
585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  char buffer[512];
586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (desc_str == NULL) {
587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!target.is_null());
588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject* obj = *target;
589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    GenerateObjectDesc(obj, buffer, sizeof(buffer));
590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    desc_str = buffer;
591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    size = obj->Size();
592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
59369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  desc = factory->NewStringFromAscii(CStrVector(desc_str));
594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (desc->IsFailure()) {
595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    error = desc;
596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;
597e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { MaybeObject* maybe_result = detail->SetProperty(*id_sym,
600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    Smi::FromInt(obj_id),
601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    NONE,
602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    kNonStrictMode);
603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return false;
604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { MaybeObject* maybe_result = detail->SetProperty(*desc_sym,
606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    *desc,
607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    NONE,
608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    kNonStrictMode);
609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return false;
610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { MaybeObject* maybe_result = detail->SetProperty(*size_sym,
612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    Smi::FromInt(size),
613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    NONE,
614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    kNonStrictMode);
615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return false;
616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  arr->set(index, *detail);
619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return true;
620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass DumpWriter {
624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  virtual ~DumpWriter() {}
626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  virtual void ComputeTotalCountAndSize(LolFilter* filter,
628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                        int* count,
629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                        int* size) = 0;
630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  virtual bool Write(Handle<FixedArray> elements_arr,
631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     int start,
632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     int dump_limit,
633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     LolFilter* filter,
634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                     Handle<Object> error) = 0;
635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
637e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass LolDumpWriter: public DumpWriter {
639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolDumpWriter(LiveObjectList* older, LiveObjectList* newer)
641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : older_(older), newer_(newer) {
642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
644e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void ComputeTotalCountAndSize(LolFilter* filter, int* count, int* size) {
645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    *count = 0;
646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    *size = 0;
647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LolIterator it(older_, newer_);
649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (it.Init(); !it.Done(); it.Next()) {
650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HeapObject* heap_obj = it.Obj();
651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!filter->Matches(heap_obj)) {
652e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        continue;
653e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      *size += heap_obj->Size();
656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (*count)++;
657e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
659e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool Write(Handle<FixedArray> elements_arr,
661e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             int start,
662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             int dump_limit,
663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             LolFilter* filter,
664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             Handle<Object> error) {
665e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // The lols are listed in latest to earliest.  We want to dump from
666e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // earliest to latest.  So, compute the last element to start with.
667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int index = 0;
668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int count = 0;
669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
67069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Isolate* isolate = Isolate::Current();
67169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Factory* factory = isolate->factory();
67269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Prefetch some needed symbols.
67469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Handle<String> id_sym = factory->LookupAsciiSymbol("id");
67569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Handle<String> desc_sym = factory->LookupAsciiSymbol("desc");
67669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Handle<String> size_sym = factory->LookupAsciiSymbol("size");
677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Fill the array with the lol object details.
679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<JSObject> detail;
680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<String> desc;
681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<HeapObject> target;
682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LiveObjectList* first_lol = (older_ != NULL) ?
684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                older_->next_ : LiveObjectList::first_;
685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LiveObjectList* last_lol = (newer_ != NULL) ? newer_->next_ : NULL;
686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LolForwardIterator it(first_lol, last_lol);
688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (it.Init(); !it.Done() && (index < dump_limit); it.Next()) {
689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HeapObject* heap_obj = it.Obj();
690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Skip objects that have been filtered out.
692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!filter->Matches(heap_obj)) {
693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        continue;
694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Only report objects that are in the section of interest.
697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (count >= start) {
698e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        target = Handle<HeapObject>(heap_obj);
699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        bool success = AddObjDetail(elements_arr,
700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    index++,
701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    it.Id(),
702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    target,
703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    NULL,
704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    id_sym,
705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    desc_sym,
706e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    size_sym,
707e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    detail,
708e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    desc,
709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                    error);
710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (!success) return false;
711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      count++;
713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return true;
715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private:
718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* older_;
719e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* newer_;
720e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
721e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass RetainersDumpWriter: public DumpWriter {
724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
725e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  RetainersDumpWriter(Handle<HeapObject> target,
726e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      Handle<JSObject> instance_filter,
727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                      Handle<JSFunction> args_function)
728e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : target_(target),
729e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        instance_filter_(instance_filter),
730e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        args_function_(args_function) {
731e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
733e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void ComputeTotalCountAndSize(LolFilter* filter, int* count, int* size) {
734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<FixedArray> retainers_arr;
735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<Object> error;
736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    *size = -1;
738e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LiveObjectList::GetRetainers(target_,
739e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 instance_filter_,
740e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 retainers_arr,
741e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 0,
742e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 Smi::kMaxValue,
743e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 count,
744e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 filter,
745e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 NULL,
746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 *args_function_,
747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 error);
748e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
749e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
750e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool Write(Handle<FixedArray> elements_arr,
751e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             int start,
752e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             int dump_limit,
753e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             LolFilter* filter,
754e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             Handle<Object> error) {
755e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int dummy;
756e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int count;
757e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
758e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Fill the retainer objects.
759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    count = LiveObjectList::GetRetainers(target_,
760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         instance_filter_,
761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         elements_arr,
762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         start,
763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         dump_limit,
764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         &dummy,
765e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         filter,
766e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         NULL,
767e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         *args_function_,
768e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         error);
769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (count < 0) {
770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        return false;
771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return true;
773e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private:
776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<HeapObject> target_;
777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<JSObject> instance_filter_;
778e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<JSFunction> args_function_;
779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass LiveObjectSummary {
783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  explicit LiveObjectSummary(LolFilter* filter)
785e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : total_count_(0),
786e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        total_size_(0),
787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        found_root_(false),
788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        found_weak_root_(false),
789e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        filter_(filter) {
790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    memset(counts_, 0, sizeof(counts_[0]) * kNumberOfEntries);
791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    memset(sizes_, 0, sizeof(sizes_[0]) * kNumberOfEntries);
792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Add(HeapObject* heap_obj) {
795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int size = heap_obj->Size();
796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LiveObjectType type = GetObjectType(heap_obj);
797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(type != kInvalidLiveObjType);
798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    counts_[type]++;
799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    sizes_[type] += size;
800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    total_count_++;
801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    total_size_ += size;
802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
804e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void set_found_root() { found_root_ = true; }
805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void set_found_weak_root() { found_weak_root_ = true; }
806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline int Count(LiveObjectType type) {
808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return counts_[type];
809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline int Size(LiveObjectType type) {
811e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return sizes_[type];
812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
813e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline int total_count() {
814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return total_count_;
815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline int total_size() {
817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return total_size_;
818e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline bool found_root() {
820e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return found_root_;
821e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline bool found_weak_root() {
823e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return found_weak_root_;
824e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int GetNumberOfEntries() {
826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int entries = 0;
827e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (int i = 0; i < kNumberOfEntries; i++) {
828e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (counts_[i]) entries++;
829e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
830e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return entries;
831e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
832e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline LolFilter* filter() { return filter_; }
834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static const int kNumberOfEntries = kNumberOfTypes;
836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private:
838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int counts_[kNumberOfEntries];
839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int sizes_[kNumberOfEntries];
840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int total_count_;
841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int total_size_;
842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool found_root_;
843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool found_weak_root_;
844e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LolFilter* filter_;
846e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Abstraction for a summary writer.
850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass SummaryWriter {
851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
852e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  virtual ~SummaryWriter() {}
853e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  virtual void Write(LiveObjectSummary* summary) = 0;
854e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// A summary writer for filling in a summary of lol lists and diffs.
858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass LolSummaryWriter: public SummaryWriter {
859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LolSummaryWriter(LiveObjectList* older_lol,
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   LiveObjectList* newer_lol)
862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : older_(older_lol), newer_(newer_lol) {
863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Write(LiveObjectSummary* summary) {
866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LolFilter* filter = summary->filter();
867e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
868e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Fill the summary with the lol object details.
869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LolIterator it(older_, newer_);
870e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (it.Init(); !it.Done(); it.Next()) {
871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HeapObject* heap_obj = it.Obj();
872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!filter->Matches(heap_obj)) {
873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        continue;
874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
875e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      summary->Add(heap_obj);
876e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
879e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private:
880e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* older_;
881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* newer_;
882e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
883e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
884e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
885e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// A summary writer for filling in a retainers list.
886e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass RetainersSummaryWriter: public SummaryWriter {
887e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  RetainersSummaryWriter(Handle<HeapObject> target,
889e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Handle<JSObject> instance_filter,
890e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                         Handle<JSFunction> args_function)
891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : target_(target),
892e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        instance_filter_(instance_filter),
893e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        args_function_(args_function) {
894e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
895e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
896e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Write(LiveObjectSummary* summary) {
897e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<FixedArray> retainers_arr;
898e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<Object> error;
899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int dummy_total_count;
900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LiveObjectList::GetRetainers(target_,
901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 instance_filter_,
902e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 retainers_arr,
903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 0,
904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 Smi::kMaxValue,
905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 &dummy_total_count,
906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 summary->filter(),
907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 summary,
908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 *args_function_,
909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 error);
910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private:
913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<HeapObject> target_;
914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<JSObject> instance_filter_;
915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<JSFunction> args_function_;
916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
917e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
919e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochuint32_t LiveObjectList::next_element_id_ = 1;
920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint LiveObjectList::list_count_ = 0;
921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint LiveObjectList::last_id_ = 0;
922e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLiveObjectList* LiveObjectList::first_ = NULL;
923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLiveObjectList* LiveObjectList::last_ = NULL;
924e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
925e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
926e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLiveObjectList::LiveObjectList(LiveObjectList* prev, int capacity)
927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    : prev_(prev),
928e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      next_(NULL),
929e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      capacity_(capacity),
930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      obj_count_(0) {
931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  elements_ = NewArray<Element>(capacity);
932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  id_ = ++last_id_;
933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  list_count_++;
935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLiveObjectList::~LiveObjectList() {
939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  DeleteArray<Element>(elements_);
940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  delete prev_;
941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
942e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint LiveObjectList::GetTotalObjCountAndSize(int* size_p) {
945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int size = 0;
946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = 0;
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LiveObjectList* lol = this;
948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  do {
949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Only compute total size if requested i.e. when size_p is not null.
950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (size_p != NULL) {
951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Element* elements = lol->elements_;
952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      for (int i = 0; i < lol->obj_count_; i++) {
953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        HeapObject* heap_obj = elements[i].obj_;
954e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        size += heap_obj->Size();
955e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
957e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    count += lol->obj_count_;
958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->prev_;
959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } while (lol != NULL);
960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (size_p != NULL) {
962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    *size_p = size;
963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
964e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return count;
965e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
967e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Adds an object to the lol.
969e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Returns true if successful, else returns false.
970e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool LiveObjectList::Add(HeapObject* obj) {
971e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If the object is already accounted for in the prev list which we inherit
972e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // from, then no need to add it to this list.
973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((prev() != NULL) && (prev()->Find(obj) != NULL)) {
974e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return true;
975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
976e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(obj_count_ <= capacity_);
977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (obj_count_ == capacity_) {
978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // The heap must have grown and we have more objects than capacity to store
979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // them.
980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return false;  // Fail this addition.
981e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
982e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element& element = elements_[obj_count_++];
983e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  element.id_ = next_element_id_++;
984e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  element.obj_ = obj;
985e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return true;
986e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
987e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
988e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
989e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Comparator used for sorting and searching the lol.
990e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint LiveObjectList::CompareElement(const Element* a, const Element* b) {
991e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const HeapObject* obj1 = a->obj_;
992e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const HeapObject* obj2 = b->obj_;
993e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // For lol elements, it doesn't matter which comes first if 2 elements point
994e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // to the same object (which gets culled later).  Hence, we only care about
995e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the the greater than / less than relationships.
996e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return (obj1 > obj2) ? 1 : (obj1 == obj2) ? 0 : -1;
997e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
998e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
999e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1000e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Looks for the specified object in the lol, and returns its element if found.
1001e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLiveObjectList::Element* LiveObjectList::Find(HeapObject* obj) {
1002e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* lol = this;
1003e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element key;
1004e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element* result = NULL;
1005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1006e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  key.obj_ = obj;
1007e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Iterate through the chain of lol's to look for the object.
1008e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while ((result == NULL) && (lol != NULL)) {
1009e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    result = reinterpret_cast<Element*>(
1010e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        bsearch(&key, lol->elements_, lol->obj_count_,
1011e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                sizeof(Element),
1012e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                reinterpret_cast<RawComparer>(CompareElement)));
1013e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->prev_;
1014e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1015e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return result;
1016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1018e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// "Nullifies" (convert the HeapObject* into an SMI) so that it will get cleaned
1020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// up in the GCEpilogue, while preserving the sort order of the lol.
1021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// NOTE: the lols need to be already sorted before NullifyMostRecent() is
1022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// called.
1023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LiveObjectList::NullifyMostRecent(HeapObject* obj) {
1024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* lol = last();
1025e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element key;
1026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element* result = NULL;
1027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  key.obj_ = obj;
1029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Iterate through the chain of lol's to look for the object.
1030e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (lol != NULL) {
1031e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    result = reinterpret_cast<Element*>(
1032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        bsearch(&key, lol->elements_, lol->obj_count_,
1033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                sizeof(Element),
1034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                reinterpret_cast<RawComparer>(CompareElement)));
1035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (result != NULL) {
1036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Since there may be more than one (we are nullifying dup's after all),
1037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // find the first in the current lol, and nullify that.  The lol should
1038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // be sorted already to make this easy (see the use of SortAll()).
1039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      int i = result - lol->elements_;
1040e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // NOTE: we sort the lol in increasing order.  So, if an object has been
1042e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // "nullified" (its lowest bit will be cleared to make it look like an
1043e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // SMI), it would/should show up before the equivalent dups that have not
1044e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // yet been "nullified".  Hence, we should be searching backwards for the
1045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // first occurence of a matching object and nullify that instance.  This
1046e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // will ensure that we preserve the expected sorting order.
1047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      for (i--; i > 0; i--) {
1048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Element* element = &lol->elements_[i];
1049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        HeapObject* curr_obj = element->obj_;
1050e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (curr_obj != obj) {
1051e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            break;  // No more matches.  Let's move on.
1052e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
1053e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        result = element;  // Let this earlier match be the result.
1054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
1055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Nullify the object.
1057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      NullifyNonLivePointer(&result->obj_);
1058e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return;
1059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->prev_;
1061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Sorts the lol.
1066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LiveObjectList::Sort() {
1067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (obj_count_ > 0) {
1068e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Vector<Element> elements_v(elements_, obj_count_);
1069e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    elements_v.Sort(CompareElement);
1070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Sorts all captured lols starting from the latest.
1075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LiveObjectList::SortAll() {
1076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* lol = last();
1077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (lol != NULL) {
1078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol->Sort();
1079e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->prev_;
1080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Counts the number of objects in the heap.
1085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic int CountHeapObjects() {
1086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = 0;
1087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Iterate over all the heap spaces and count the number of objects.
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HeapIterator iterator;
1089e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapObject* heap_obj = NULL;
1090e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while ((heap_obj = iterator.next()) != NULL) {
1091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    count++;
1092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return count;
1094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Captures a current snapshot of all objects in the heap.
1098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMaybeObject* LiveObjectList::Capture() {
109969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
110069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Factory* factory = isolate->factory();
110169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HandleScope scope(isolate);
1102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Count the number of objects in the heap.
1104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int total_count = CountHeapObjects();
1105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = total_count;
1106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int size = 0;
1107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* last_lol = last();
1109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (last_lol != NULL) {
1110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    count -= last_lol->TotalObjCount();
1111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* lol;
1114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Create a lol large enough to track all the objects.
1116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  lol = new LiveObjectList(last_lol, count);
1117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (lol == NULL) {
1118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return NULL;  // No memory to proceed.
1119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The HeapIterator needs to be in its own scope because it disables
1122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // allocation, and we need allocate below.
1123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  {
1124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Iterate over all the heap spaces and add the objects.
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HeapIterator iterator;
1126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject* heap_obj = NULL;
1127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    bool failed = false;
1128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (!failed && (heap_obj = iterator.next()) != NULL) {
1129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      failed = !lol->Add(heap_obj);
1130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      size += heap_obj->Size();
1131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!failed);
1133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol->Sort();
1135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Add the current lol to the list of lols.
1137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (last_ != NULL) {
1138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      last_->next_ = lol;
1139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      first_ = lol;
1141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    last_ = lol;
1143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef VERIFY_LOL
1145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (FLAG_verify_lol) {
1146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Verify(true);
1147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif
1149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
115169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> id_sym = factory->LookupAsciiSymbol("id");
115269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> count_sym = factory->LookupAsciiSymbol("count");
115369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> size_sym = factory->LookupAsciiSymbol("size");
1154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
115569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
1156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (result->IsFailure()) return Object::cast(*result);
1157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { MaybeObject* maybe_result = result->SetProperty(*id_sym,
1159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    Smi::FromInt(lol->id()),
1160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    NONE,
1161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    kNonStrictMode);
1162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return maybe_result;
1163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { MaybeObject* maybe_result = result->SetProperty(*count_sym,
1165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    Smi::FromInt(total_count),
1166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    NONE,
1167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    kNonStrictMode);
1168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return maybe_result;
1169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  { MaybeObject* maybe_result = result->SetProperty(*size_sym,
1171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    Smi::FromInt(size),
1172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    NONE,
1173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                                    kNonStrictMode);
1174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return maybe_result;
1175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return *result;
1178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Delete doesn't actually deletes an lol.  It just marks it as invisible since
1182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// its contents are considered to be part of subsequent lists as well.  The
1183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// only time we'll actually delete the lol is when we Reset() or if the lol is
1184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// invisible, and its element count reaches 0.
1185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool LiveObjectList::Delete(int id) {
11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LiveObjectList* lol = last();
1187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (lol != NULL) {
1188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (lol->id() == id) {
1189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      break;
1190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->prev_;
1192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If no lol is found for this id, then we fail to delete.
1195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (lol == NULL) return false;
1196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Else, mark the lol as invisible i.e. id == 0.
1198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  lol->id_ = 0;
1199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  list_count_--;
1200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(list_count_ >= 0);
1201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (lol->obj_count_ == 0) {
1202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Point the next lol's prev to this lol's prev.
1203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LiveObjectList* next = lol->next_;
1204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LiveObjectList* prev = lol->prev_;
1205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Point next's prev to prev.
1206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (next != NULL) {
1207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      next->prev_ = lol->prev_;
1208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      last_ = lol->prev_;
1210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Point prev's next to next.
1212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (prev != NULL) {
1213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      prev->next_ = lol->next_;
1214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
1215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      first_ = lol->next_;
1216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol->prev_ = NULL;
1219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol->next_ = NULL;
1220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Delete this now empty and invisible lol.
1222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    delete lol;
1223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Just in case we've marked everything invisible, then clean up completely.
1226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (list_count_ == 0) {
1227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Reset();
1228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return true;
1231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMaybeObject* LiveObjectList::Dump(int older_id,
1235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  int newer_id,
1236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  int start_idx,
1237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  int dump_limit,
1238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                  Handle<JSObject> filter_obj) {
1239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) {
1240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Failure::Exception();  // Fail: 0 is not a valid lol id.
1241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (newer_id < older_id) {
1243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // They are not in the expected order.  Swap them.
1244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int temp = older_id;
1245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    older_id = newer_id;
1246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    newer_id = temp;
1247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LiveObjectList* newer_lol = FindLolForId(newer_id, last());
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LiveObjectList* older_lol = FindLolForId(older_id, newer_lol);
1251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If the id is defined, and we can't find a LOL for it, then we have an
1253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // invalid id.
1254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((newer_id != 0) && (newer_lol == NULL)) {
1255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Failure::Exception();  // Fail: the newer lol id is invalid.
1256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((older_id != 0) && (older_lol == NULL)) {
1258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Failure::Exception();  // Fail: the older lol id is invalid.
1259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolFilter filter(filter_obj);
1262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolDumpWriter writer(older_lol, newer_lol);
1263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return DumpPrivate(&writer, start_idx, dump_limit, &filter);
1264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMaybeObject* LiveObjectList::DumpPrivate(DumpWriter* writer,
1268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         int start,
1269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         int dump_limit,
1270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         LolFilter* filter) {
127169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
127269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Factory* factory = isolate->factory();
127369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
127469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HandleScope scope(isolate);
1275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Calculate the number of entries of the dump.
1277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = -1;
1278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int size = -1;
1279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  writer->ComputeTotalCountAndSize(filter, &count, &size);
1280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Adjust for where to start the dump.
1282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((start < 0) || (start >= count)) {
1283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Failure::Exception();  // invalid start.
1284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int remaining_count = count - start;
1287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (dump_limit > remaining_count) {
1288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    dump_limit = remaining_count;
1289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Allocate an array to hold the result.
129269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<FixedArray> elements_arr = factory->NewFixedArray(dump_limit);
1293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (elements_arr->IsFailure()) return Object::cast(*elements_arr);
1294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Fill in the dump.
1296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<Object> error;
1297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool success = writer->Write(elements_arr,
1298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               start,
1299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               dump_limit,
1300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               filter,
1301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               error);
1302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!success) return Object::cast(*error);
1303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MaybeObject* maybe_result;
1305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Allocate the result body.
130769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<JSObject> body = factory->NewJSObject(isolate->object_function());
1308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (body->IsFailure()) return Object::cast(*body);
1309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set the updated body.count.
131169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> count_sym = factory->LookupAsciiSymbol("count");
1312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  maybe_result = body->SetProperty(*count_sym,
1313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   Smi::FromInt(count),
1314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   NONE,
1315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   kNonStrictMode);
1316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set the updated body.size if appropriate.
1319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (size >= 0) {
132069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Handle<String> size_sym = factory->LookupAsciiSymbol("size");
1321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    maybe_result = body->SetProperty(*size_sym,
1322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Smi::FromInt(size),
1323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     NONE,
1324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     kNonStrictMode);
1325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return maybe_result;
1326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set body.first_index.
132969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> first_sym = factory->LookupAsciiSymbol("first_index");
1330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  maybe_result = body->SetProperty(*first_sym,
1331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   Smi::FromInt(start),
1332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   NONE,
1333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   kNonStrictMode);
1334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Allocate the JSArray of the elements.
133769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<JSObject> elements = factory->NewJSObject(isolate->array_function());
1338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (elements->IsFailure()) return Object::cast(*elements);
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  maybe_result = Handle<JSArray>::cast(elements)->SetContent(*elements_arr);
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Set body.elements.
134469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> elements_sym = factory->LookupAsciiSymbol("elements");
1345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  maybe_result = body->SetProperty(*elements_sym,
1346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   *elements,
1347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   NONE,
1348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   kNonStrictMode);
1349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return *body;
1352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1355e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMaybeObject* LiveObjectList::Summarize(int older_id,
1356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       int newer_id,
1357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       Handle<JSObject> filter_obj) {
1358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) {
1359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Failure::Exception();  // Fail: 0 is not a valid lol id.
1360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1361e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (newer_id < older_id) {
1362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // They are not in the expected order.  Swap them.
1363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int temp = older_id;
1364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    older_id = newer_id;
1365e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    newer_id = temp;
1366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1367e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LiveObjectList* newer_lol = FindLolForId(newer_id, last());
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LiveObjectList* older_lol = FindLolForId(older_id, newer_lol);
1370e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If the id is defined, and we can't find a LOL for it, then we have an
1372e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // invalid id.
1373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((newer_id != 0) && (newer_lol == NULL)) {
1374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Failure::Exception();  // Fail: the newer lol id is invalid.
1375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1376e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if ((older_id != 0) && (older_lol == NULL)) {
1377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Failure::Exception();  // Fail: the older lol id is invalid.
1378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolFilter filter(filter_obj);
1381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolSummaryWriter writer(older_lol, newer_lol);
1382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return SummarizePrivate(&writer, &filter, false);
1383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1386e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Creates a summary report for the debugger.
1387e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Note: the SummaryWriter takes care of iterating over objects and filling in
1388e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// the summary.
1389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMaybeObject* LiveObjectList::SummarizePrivate(SummaryWriter* writer,
1390e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              LolFilter* filter,
1391e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                              bool is_tracking_roots) {
1392e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HandleScope scope;
1393e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MaybeObject* maybe_result;
1394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectSummary summary(filter);
1396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  writer->Write(&summary);
1397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
139869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
139969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Factory* factory = isolate->factory();
140069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The result body will look like this:
1402e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // body: {
1403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   count: <total_count>,
1404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   size: <total_size>,
1405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   found_root: <boolean>,       // optional.
1406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   found_weak_root: <boolean>,  // optional.
1407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   summary: [
1408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     {
1409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //       desc: "<object type name>",
1410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //       count: <count>,
1411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //       size: size
1412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     },
1413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     ...
1414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //   ]
1415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // }
1416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Prefetch some needed symbols.
141869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> desc_sym = factory->LookupAsciiSymbol("desc");
141969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> count_sym = factory->LookupAsciiSymbol("count");
142069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> size_sym = factory->LookupAsciiSymbol("size");
142169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> summary_sym = factory->LookupAsciiSymbol("summary");
1422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Allocate the summary array.
1424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int entries_count = summary.GetNumberOfEntries();
1425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<FixedArray> summary_arr =
142669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      factory->NewFixedArray(entries_count);
1427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (summary_arr->IsFailure()) return Object::cast(*summary_arr);
1428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int idx = 0;
1430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < LiveObjectSummary::kNumberOfEntries; i++) {
1431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Allocate the summary record.
143269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Handle<JSObject> detail = factory->NewJSObject(isolate->object_function());
1433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (detail->IsFailure()) return Object::cast(*detail);
1434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Fill in the summary record.
1436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LiveObjectType type = static_cast<LiveObjectType>(i);
1437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int count = summary.Count(type);
1438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (count) {
1439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      const char* desc_cstr = GetObjectTypeDesc(type);
144069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Handle<String> desc = factory->LookupAsciiSymbol(desc_cstr);
1441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      int size = summary.Size(type);
1442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      maybe_result = detail->SetProperty(*desc_sym,
1444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         *desc,
1445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         NONE,
1446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         kNonStrictMode);
1447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (maybe_result->IsFailure()) return maybe_result;
1448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      maybe_result = detail->SetProperty(*count_sym,
1449e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         Smi::FromInt(count),
1450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         NONE,
1451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         kNonStrictMode);
1452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (maybe_result->IsFailure()) return maybe_result;
1453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      maybe_result = detail->SetProperty(*size_sym,
1454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         Smi::FromInt(size),
1455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         NONE,
1456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         kNonStrictMode);
1457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (maybe_result->IsFailure()) return maybe_result;
1458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      summary_arr->set(idx++, *detail);
1460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Wrap the summary fixed array in a JS array.
146469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<JSObject> summary_obj =
146569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    factory->NewJSObject(isolate->array_function());
1466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (summary_obj->IsFailure()) return Object::cast(*summary_obj);
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  maybe_result = Handle<JSArray>::cast(summary_obj)->SetContent(*summary_arr);
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Create the body object.
147269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<JSObject> body = factory->NewJSObject(isolate->object_function());
1473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (body->IsFailure()) return Object::cast(*body);
1474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Fill out the body object.
1476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int total_count = summary.total_count();
1477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int total_size = summary.total_size();
1478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  maybe_result = body->SetProperty(*count_sym,
1479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   Smi::FromInt(total_count),
1480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   NONE,
1481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   kNonStrictMode);
1482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  maybe_result = body->SetProperty(*size_sym,
1485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   Smi::FromInt(total_size),
1486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   NONE,
1487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   kNonStrictMode);
1488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1489e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (is_tracking_roots) {
1491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int found_root = summary.found_root();
1492e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int found_weak_root = summary.found_weak_root();
149369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Handle<String> root_sym = factory->LookupAsciiSymbol("found_root");
1494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<String> weak_root_sym =
149569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        factory->LookupAsciiSymbol("found_weak_root");
1496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    maybe_result = body->SetProperty(*root_sym,
1497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Smi::FromInt(found_root),
1498e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     NONE,
1499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     kNonStrictMode);
1500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return maybe_result;
1501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    maybe_result = body->SetProperty(*weak_root_sym,
1502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Smi::FromInt(found_weak_root),
1503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     NONE,
1504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     kNonStrictMode);
1505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return maybe_result;
1506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  maybe_result = body->SetProperty(*summary_sym,
1509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   *summary_obj,
1510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   NONE,
1511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   kNonStrictMode);
1512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return *body;
1515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1516e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Returns an array listing the captured lols.
1519e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Note: only dumps the section starting at start_idx and only up to
1520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// dump_limit entries.
1521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMaybeObject* LiveObjectList::Info(int start_idx, int dump_limit) {
152269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
152369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Factory* factory = isolate->factory();
152469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
152569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HandleScope scope(isolate);
1526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MaybeObject* maybe_result;
1527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int total_count = LiveObjectList::list_count();
1529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int dump_count = total_count;
1530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Adjust for where to start the dump.
1532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (total_count == 0) {
1533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      start_idx = 0;  // Ensure this to get an empty list.
1534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else if ((start_idx < 0) || (start_idx >= total_count)) {
1535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Failure::Exception();  // invalid start.
1536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  dump_count -= start_idx;
1538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Adjust for the dump limit.
1540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (dump_count > dump_limit) {
1541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    dump_count = dump_limit;
1542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Allocate an array to hold the result.
154569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<FixedArray> list = factory->NewFixedArray(dump_count);
1546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (list->IsFailure()) return Object::cast(*list);
1547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Prefetch some needed symbols.
154969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> id_sym = factory->LookupAsciiSymbol("id");
155069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> count_sym = factory->LookupAsciiSymbol("count");
155169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> size_sym = factory->LookupAsciiSymbol("size");
1552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Fill the array with the lol details.
1554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int idx = 0;
1555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* lol = first_;
1556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while ((lol != NULL) && (idx < start_idx)) {  // Skip tail entries.
1557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (lol->id() != 0) {
1558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      idx++;
1559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->next();
1561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  idx = 0;
1563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while ((lol != NULL) && (dump_limit != 0)) {
1564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (lol->id() != 0) {
1565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      int count;
1566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      int size;
1567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      count = lol->GetTotalObjCountAndSize(&size);
1568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
156969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Handle<JSObject> detail =
157069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          factory->NewJSObject(isolate->object_function());
1571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (detail->IsFailure()) return Object::cast(*detail);
1572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      maybe_result = detail->SetProperty(*id_sym,
1574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         Smi::FromInt(lol->id()),
1575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         NONE,
1576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         kNonStrictMode);
1577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (maybe_result->IsFailure()) return maybe_result;
1578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      maybe_result = detail->SetProperty(*count_sym,
1579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         Smi::FromInt(count),
1580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         NONE,
1581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         kNonStrictMode);
1582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (maybe_result->IsFailure()) return maybe_result;
1583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      maybe_result = detail->SetProperty(*size_sym,
1584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         Smi::FromInt(size),
1585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         NONE,
1586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                         kNonStrictMode);
1587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (maybe_result->IsFailure()) return maybe_result;
1588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      list->set(idx++, *detail);
1589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      dump_limit--;
1590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->next();
1592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Return the result as a JS array.
159569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<JSObject> lols = factory->NewJSObject(isolate->array_function());
15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  maybe_result = Handle<JSArray>::cast(lols)->SetContent(*list);
15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
160069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
1601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (result->IsFailure()) return Object::cast(*result);
1602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  maybe_result = result->SetProperty(*count_sym,
1604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Smi::FromInt(total_count),
1605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     NONE,
1606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     kNonStrictMode);
1607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
160969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> first_sym = factory->LookupAsciiSymbol("first_index");
1610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  maybe_result = result->SetProperty(*first_sym,
1611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Smi::FromInt(start_idx),
1612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     NONE,
1613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     kNonStrictMode);
1614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
161669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> lists_sym = factory->LookupAsciiSymbol("lists");
1617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  maybe_result = result->SetProperty(*lists_sym,
1618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     *lols,
1619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     NONE,
1620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     kNonStrictMode);
1621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (maybe_result->IsFailure()) return maybe_result;
1622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return *result;
1624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Deletes all captured lols.
1628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LiveObjectList::Reset() {
16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LiveObjectList* lol = last();
1630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Just delete the last.  Each lol will delete it's prev automatically.
1631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  delete lol;
1632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  next_element_id_ = 1;
1634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  list_count_ = 0;
1635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  last_id_ = 0;
1636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  first_ = NULL;
1637e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  last_ = NULL;
1638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Gets the object for the specified obj id.
1642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochObject* LiveObjectList::GetObj(int obj_id) {
1643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element* element = FindElementFor<int>(GetElementId, obj_id);
1644e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (element != NULL) {
1645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Object::cast(element->obj_);
1646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
164769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return HEAP->undefined_value();
1648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Gets the obj id for the specified address if valid.
1652e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint LiveObjectList::GetObjId(Object* obj) {
1653e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Make a heap object pointer from the address.
1654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapObject* hobj = HeapObject::cast(obj);
1655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element* element = FindElementFor<HeapObject*>(GetElementObj, hobj);
1656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (element != NULL) {
1657e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return element->id_;
1658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1659e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return 0;  // Invalid address.
1660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1661e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Gets the obj id for the specified address if valid.
1664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochObject* LiveObjectList::GetObjId(Handle<String> address) {
1665589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  SmartArrayPointer<char> addr_str =
1666e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      address->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
166869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
166969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Extract the address value from the string.
167169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int value =
167269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      static_cast<int>(StringToInt(isolate->unicode_cache(), *address, 16));
1673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Object* obj = reinterpret_cast<Object*>(value);
1674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return Smi::FromInt(GetObjId(obj));
1675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Helper class for copying HeapObjects.
1679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass LolVisitor: public ObjectVisitor {
1680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
1681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolVisitor(HeapObject* target, Handle<HeapObject> handle_to_skip)
1682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : target_(target), handle_to_skip_(handle_to_skip), found_(false) {}
1683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void VisitPointer(Object** p) { CheckPointer(p); }
1685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void VisitPointers(Object** start, Object** end) {
1687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Check all HeapObject pointers in [start, end).
1688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (Object** p = start; !found() && p < end; p++) CheckPointer(p);
1689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline bool found() const { return found_; }
1692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline bool reset() { return found_ = false; }
1693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private:
1695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline void CheckPointer(Object** p) {
1696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Object* object = *p;
1697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (HeapObject::cast(object) == target_) {
1698e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // We may want to skip this handle because the handle may be a local
1699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // handle in a handle scope in one of our callers.  Once we return,
1700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // that handle will be popped.  Hence, we don't want to count it as
1701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // a root that would have kept the target object alive.
1702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!handle_to_skip_.is_null() &&
1703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          handle_to_skip_.location() == reinterpret_cast<HeapObject**>(p)) {
1704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        return;  // Skip this handle.
1705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
1706e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      found_ = true;
1707e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1708e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapObject* target_;
1711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<HeapObject> handle_to_skip_;
1712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool found_;
1713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
1714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochinline bool AddRootRetainerIfFound(const LolVisitor& visitor,
1717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   LolFilter* filter,
17183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   LiveObjectSummary* summary,
17193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   void (*SetRootFound)(LiveObjectSummary* s),
1720e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   int start,
1721e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   int dump_limit,
1722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   int* total_count,
1723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   Handle<FixedArray> retainers_arr,
1724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   int* count,
1725e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   int* index,
1726e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   const char* root_name,
1727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   Handle<String> id_sym,
1728e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   Handle<String> desc_sym,
1729e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   Handle<String> size_sym,
1730e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   Handle<Object> error) {
1731e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HandleScope scope;
1732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1733e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Scratch handles.
1734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<JSObject> detail;
1735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<String> desc;
1736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<HeapObject> retainer;
1737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1738e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (visitor.found()) {
1739e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!filter->is_active()) {
1740e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      (*total_count)++;
1741e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (summary) {
1742e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        SetRootFound(summary);
1743e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else if ((*total_count > start) && ((*index) < dump_limit)) {
1744e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        (*count)++;
1745e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (!retainers_arr.is_null()) {
1746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          return AddObjDetail(retainers_arr,
1747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              (*index)++,
1748e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              0,
1749e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              retainer,
1750e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              root_name,
1751e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              id_sym,
1752e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              desc_sym,
1753e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              size_sym,
1754e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              detail,
1755e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              desc,
1756e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              error);
1757e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
1758e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
1759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return true;
1762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
17653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline void SetFoundRoot(LiveObjectSummary* summary) {
1766e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  summary->set_found_root();
1767e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1768e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochinline void SetFoundWeakRoot(LiveObjectSummary* summary) {
1771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  summary->set_found_weak_root();
1772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1773e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint LiveObjectList::GetRetainers(Handle<HeapObject> target,
1776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 Handle<JSObject> instance_filter,
1777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 Handle<FixedArray> retainers_arr,
1778e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 int start,
1779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 int dump_limit,
1780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 int* total_count,
1781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 LolFilter* filter,
17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 LiveObjectSummary* summary,
1783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 JSFunction* arguments_function,
1784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 Handle<Object> error) {
1785e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HandleScope scope;
1786e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Scratch handles.
1788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<JSObject> detail;
1789e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<String> desc;
1790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<HeapObject> retainer;
1791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
179269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
179369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Factory* factory = isolate->factory();
179469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Prefetch some needed symbols.
179669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> id_sym = factory->LookupAsciiSymbol("id");
179769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> desc_sym = factory->LookupAsciiSymbol("desc");
179869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Handle<String> size_sym = factory->LookupAsciiSymbol("size");
1799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  NoHandleAllocation ha;
1801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = 0;
1802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int index = 0;
1803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<JSObject> last_obj;
1804e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  *total_count = 0;
1806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Iterate roots.
1808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolVisitor lol_visitor(*target, target);
180969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  isolate->heap()->IterateStrongRoots(&lol_visitor, VISIT_ALL);
1810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!AddRootRetainerIfFound(lol_visitor,
1811e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              filter,
1812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              summary,
1813e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              SetFoundRoot,
1814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              start,
1815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              dump_limit,
1816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              total_count,
1817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              retainers_arr,
1818e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              &count,
1819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              &index,
1820e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              "<root>",
1821e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              id_sym,
1822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              desc_sym,
1823e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              size_sym,
1824e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              error)) {
1825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return -1;
1826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1827e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1828e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  lol_visitor.reset();
182969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  isolate->heap()->IterateWeakRoots(&lol_visitor, VISIT_ALL);
1830e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!AddRootRetainerIfFound(lol_visitor,
1831e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              filter,
1832e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              summary,
1833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              SetFoundWeakRoot,
1834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              start,
1835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              dump_limit,
1836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              total_count,
1837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              retainers_arr,
1838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              &count,
1839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              &index,
1840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              "<weak root>",
1841e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              id_sym,
1842e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              desc_sym,
1843e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              size_sym,
1844e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              error)) {
1845e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return -1;
1846e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1847e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1848e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Iterate the live object lists.
1849e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolIterator it(NULL, last());
1850e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (it.Init(); !it.Done() && (index < dump_limit); it.Next()) {
1851e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject* heap_obj = it.Obj();
1852e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1853e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Only look at all JSObjects.
1854e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (heap_obj->IsJSObject()) {
1855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Skip context extension objects and argument arrays as these are
1856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // checked in the context of functions using them.
1857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JSObject* obj = JSObject::cast(heap_obj);
1858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (obj->IsJSContextExtensionObject() ||
1859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          obj->map()->constructor() == arguments_function) {
1860e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        continue;
1861e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
1862e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1863e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Check if the JS object has a reference to the object looked for.
1864e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (obj->ReferencesObject(*target)) {
1865e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Check instance filter if supplied. This is normally used to avoid
1866e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // references from mirror objects (see Runtime_IsInPrototypeChain).
1867e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (!instance_filter->IsUndefined()) {
1868e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          Object* V = obj;
1869e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          while (true) {
1870e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            Object* prototype = V->GetPrototype();
1871e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            if (prototype->IsNull()) {
1872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              break;
1873e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            }
1874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            if (*instance_filter == prototype) {
1875e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              obj = NULL;  // Don't add this object.
1876e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              break;
1877e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            }
1878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            V = prototype;
1879e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          }
1880e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
1881e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1882e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (obj != NULL) {
1883e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Skip objects that have been filtered out.
1884e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          if (filter->Matches(heap_obj)) {
1885e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            continue;
1886e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          }
1887e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Valid reference found add to instance array if supplied an update
1889e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // count.
1890e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          last_obj = Handle<JSObject>(obj);
1891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          (*total_count)++;
1892e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1893e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          if (summary != NULL) {
1894e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            summary->Add(heap_obj);
1895e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          } else if ((*total_count > start) && (index < dump_limit)) {
1896e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            count++;
1897e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            if (!retainers_arr.is_null()) {
1898e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              retainer = Handle<HeapObject>(heap_obj);
1899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              bool success = AddObjDetail(retainers_arr,
1900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          index++,
1901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          it.Id(),
1902e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          retainer,
1903e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          NULL,
1904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          id_sym,
1905e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          desc_sym,
1906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          size_sym,
1907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          detail,
1908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          desc,
1909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                          error);
1910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              if (!success) return -1;
1911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            }
1912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          }
1913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
1914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
1915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1917e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Check for circular reference only. This can happen when the object is only
1919e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // referenced from mirrors and has a circular reference in which case the
1920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // object is not really alive and would have been garbage collected if not
1921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // referenced from the mirror.
1922e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (*total_count == 1 && !last_obj.is_null() && *last_obj == *target) {
1924e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    count = 0;
1925e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    *total_count = 0;
1926e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1928e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return count;
1929e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1930e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1931e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMaybeObject* LiveObjectList::GetObjRetainers(int obj_id,
1933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                             Handle<JSObject> instance_filter,
1934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                             bool verbose,
1935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                             int start,
1936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                             int dump_limit,
1937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                             Handle<JSObject> filter_obj) {
193869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
193969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Factory* factory = isolate->factory();
194069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Heap* heap = isolate->heap();
194169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
194269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  HandleScope scope(isolate);
1943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Get the target object.
1945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapObject* heap_obj = HeapObject::cast(GetObj(obj_id));
194669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (heap_obj == heap->undefined_value()) {
1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return heap_obj;
1948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<HeapObject> target = Handle<HeapObject>(heap_obj);
1951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Get the constructor function for context extension and arguments array.
1953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  JSObject* arguments_boilerplate =
195469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      isolate->context()->global_context()->arguments_boilerplate();
1955e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  JSFunction* arguments_function =
1956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      JSFunction::cast(arguments_boilerplate->map()->constructor());
1957e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Handle<JSFunction> args_function = Handle<JSFunction>(arguments_function);
1959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolFilter filter(filter_obj);
1960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!verbose) {
1962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    RetainersSummaryWriter writer(target, instance_filter, args_function);
1963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return SummarizePrivate(&writer, &filter, true);
1964e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1965e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
1966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    RetainersDumpWriter writer(target, instance_filter, args_function);
1967e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Object* body_obj;
1968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    MaybeObject* maybe_result =
1969e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        DumpPrivate(&writer, start, dump_limit, &filter);
1970e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!maybe_result->ToObject(&body_obj)) {
1971e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return maybe_result;
1972e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1974e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Set body.id.
1975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<JSObject> body = Handle<JSObject>(JSObject::cast(body_obj));
197669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Handle<String> id_sym = factory->LookupAsciiSymbol("id");
1977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    maybe_result = body->SetProperty(*id_sym,
1978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     Smi::FromInt(obj_id),
1979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     NONE,
1980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                     kNonStrictMode);
1981e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (maybe_result->IsFailure()) return maybe_result;
1982e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1983e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return *body;
1984e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1985e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
1986e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1987e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1988e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochObject* LiveObjectList::PrintObj(int obj_id) {
1989e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Object* obj = GetObj(obj_id);
1990e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!obj) {
199169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return HEAP->undefined_value();
1992e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1993e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1994e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  EmbeddedVector<char, 128> temp_filename;
1995e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static int temp_count = 0;
1996e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const char* path_prefix = ".";
1997e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
199869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
199969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Factory* factory = isolate->factory();
200069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Heap* heap = isolate->heap();
200169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2002e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_lol_workdir) {
2003e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    path_prefix = FLAG_lol_workdir;
2004e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::SNPrintF(temp_filename, "%s/lol-print-%d", path_prefix, ++temp_count);
2006e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2007e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FILE* f = OS::FOpen(temp_filename.start(), "w+");
2008e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2009e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  PrintF(f, "@%d ", LiveObjectList::GetObjId(obj));
2010e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef OBJECT_PRINT
2011e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef INSPECTOR
2012e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Inspector::DumpObjectType(f, obj);
2013e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif  // INSPECTOR
2014e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  PrintF(f, "\n");
2015e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->Print(f);
2016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#else  // !OBJECT_PRINT
2017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  obj->ShortPrint(f);
2018e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif  // !OBJECT_PRINT
2019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  PrintF(f, "\n");
2020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Flush(f);
2021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  fclose(f);
2022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Create a string from the temp_file.
2024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Note: the mmapped resource will take care of closing the file.
2025e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MemoryMappedExternalResource* resource =
2026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      new MemoryMappedExternalResource(temp_filename.start(), true);
2027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (resource->exists() && !resource->is_empty()) {
2028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(resource->IsAscii());
2029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<String> dump_string =
203069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        factory->NewExternalStringFromAscii(resource);
203169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    heap->external_string_table()->AddString(*dump_string);
2032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return *dump_string;
2033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    delete resource;
2035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
203669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return HEAP->undefined_value();
2037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2040e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass LolPathTracer: public PathTracer {
2041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public:
2042e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolPathTracer(FILE* out,
2043e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                Object* search_target,
2044e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                WhatToFind what_to_find)
2045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : PathTracer(search_target, what_to_find, VISIT_ONLY_STRONG), out_(out) {}
2046e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private:
2048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void ProcessResults();
2049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2050e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FILE* out_;
2051e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch};
2052e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2053e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LolPathTracer::ProcessResults() {
2055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (found_target_) {
2056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF(out_, "=====================================\n");
2057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF(out_, "====        Path to object       ====\n");
2058e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF(out_, "=====================================\n\n");
2059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(!object_stack_.is_empty());
2061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Object* prev = NULL;
2062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (int i = 0, index = 0; i < object_stack_.length(); i++) {
2063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Object* obj = object_stack_[i];
2064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Skip this object if it is basically the internals of the
2066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // previous object (which would have dumped its details already).
2067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (prev && prev->IsJSObject() &&
2068e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          (obj != search_target_)) {
2069e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        JSObject* jsobj = JSObject::cast(prev);
2070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (obj->IsFixedArray() &&
2071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            jsobj->properties() == FixedArray::cast(obj)) {
2072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Skip this one because it would have been printed as the
2073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // properties of the last object already.
2074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          continue;
2075e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else if (obj->IsHeapObject() &&
2076e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                   jsobj->elements() == HeapObject::cast(obj)) {
2077e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Skip this one because it would have been printed as the
2078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // elements of the last object already.
2079e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          continue;
2080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
2081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Print a connecting arrow.
2084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (i > 0) PrintF(out_, "\n     |\n     |\n     V\n\n");
2085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2086e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Print the object index.
2087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF(out_, "[%d] ", ++index);
2088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2089e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Print the LOL object ID:
2090e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      int id = LiveObjectList::GetObjId(obj);
2091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (id > 0) PrintF(out_, "@%d ", id);
2092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef OBJECT_PRINT
2094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef INSPECTOR
2095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Inspector::DumpObjectType(out_, obj);
2096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif  // INSPECTOR
2097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF(out_, "\n");
2098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      obj->Print(out_);
2099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#else  // !OBJECT_PRINT
2100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      obj->ShortPrint(out_);
2101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF(out_, "\n");
2102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif  // !OBJECT_PRINT
2103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Flush(out_);
2104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF(out_, "\n");
2106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF(out_, "=====================================\n\n");
2107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Flush(out_);
2108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochObject* LiveObjectList::GetPathPrivate(HeapObject* obj1, HeapObject* obj2) {
2113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  EmbeddedVector<char, 128> temp_filename;
2114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static int temp_count = 0;
2115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  const char* path_prefix = ".";
2116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_lol_workdir) {
2118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    path_prefix = FLAG_lol_workdir;
2119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::SNPrintF(temp_filename, "%s/lol-getpath-%d", path_prefix, ++temp_count);
2121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FILE* f = OS::FOpen(temp_filename.start(), "w+");
2123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
212469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Isolate* isolate = Isolate::Current();
212569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Factory* factory = isolate->factory();
212669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Heap* heap = isolate->heap();
212769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Save the previous verbosity.
2129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool prev_verbosity = FLAG_use_verbose_printer;
2130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FLAG_use_verbose_printer = false;
2131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Dump the paths.
2133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  {
2134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // The tracer needs to be scoped because its usage asserts no allocation,
2135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // and we need to allocate the result string below.
2136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    LolPathTracer tracer(f, obj2, LolPathTracer::FIND_FIRST);
2137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    bool found = false;
2139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (obj1 == NULL) {
2140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Check for ObjectGroups that references this object.
2141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // TODO(mlam): refactor this to be more modular.
2142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      {
214369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        List<ObjectGroup*>* groups = isolate->global_handles()->object_groups();
2144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        for (int i = 0; i < groups->length(); i++) {
2145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          ObjectGroup* group = groups->at(i);
2146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          if (group == NULL) continue;
2147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          bool found_group = false;
214969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          for (size_t j = 0; j < group->length_; j++) {
215069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            Object* object = *(group->objects_[j]);
2151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            HeapObject* hobj = HeapObject::cast(object);
2152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            if (obj2 == hobj) {
2153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              found_group = true;
2154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              break;
2155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            }
2156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          }
2157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          if (found_group) {
2159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            PrintF(f,
2160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                   "obj %p is a member of object group %p {\n",
2161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                   reinterpret_cast<void*>(obj2),
2162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                   reinterpret_cast<void*>(group));
216369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            for (size_t j = 0; j < group->length_; j++) {
216469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch              Object* object = *(group->objects_[j]);
2165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              if (!object->IsHeapObject()) continue;
2166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              HeapObject* hobj = HeapObject::cast(object);
2168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              int id = GetObjId(hobj);
2169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              if (id != 0) {
2170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                PrintF(f, "  @%d:", id);
2171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              } else {
2172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                PrintF(f, "  <no id>:");
2173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              }
2174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              char buffer[512];
2176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              GenerateObjectDesc(hobj, buffer, sizeof(buffer));
2177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              PrintF(f, " %s", buffer);
2178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              if (hobj == obj2) {
2179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                PrintF(f, " <===");
2180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              }
2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              PrintF(f, "\n");
2182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            }
2183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            PrintF(f, "}\n");
2184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          }
2185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
2186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF(f, "path from roots to obj %p\n", reinterpret_cast<void*>(obj2));
218969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      heap->IterateRoots(&tracer, VISIT_ONLY_STRONG);
2190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      found = tracer.found();
2191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!found) {
2193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        PrintF(f, "  No paths found. Checking symbol tables ...\n");
219469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        SymbolTable* symbol_table = HEAP->raw_unchecked_symbol_table();
2195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        tracer.VisitPointers(reinterpret_cast<Object**>(&symbol_table),
2196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                             reinterpret_cast<Object**>(&symbol_table)+1);
2197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        found = tracer.found();
2198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (!found) {
2199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          symbol_table->IteratePrefix(&tracer);
2200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          found = tracer.found();
2201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
2202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!found) {
2205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        PrintF(f, "  No paths found. Checking weak roots ...\n");
2206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Check weak refs next.
220769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        isolate->global_handles()->IterateWeakRoots(&tracer);
2208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        found = tracer.found();
2209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
2212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF(f, "path from obj %p to obj %p:\n",
2213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             reinterpret_cast<void*>(obj1), reinterpret_cast<void*>(obj2));
2214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      tracer.TracePathFrom(reinterpret_cast<Object**>(&obj1));
2215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      found = tracer.found();
2216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!found) {
2219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      PrintF(f, "  No paths found\n\n");
2220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Flush and clean up the dumped file.
2224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Flush(f);
2225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  fclose(f);
2226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Restore the previous verbosity.
2228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FLAG_use_verbose_printer = prev_verbosity;
2229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Create a string from the temp_file.
2231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Note: the mmapped resource will take care of closing the file.
2232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  MemoryMappedExternalResource* resource =
2233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      new MemoryMappedExternalResource(temp_filename.start(), true);
2234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (resource->exists() && !resource->is_empty()) {
2235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(resource->IsAscii());
2236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Handle<String> path_string =
223769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        factory->NewExternalStringFromAscii(resource);
223869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    heap->external_string_table()->AddString(*path_string);
2239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return *path_string;
2240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
2241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    delete resource;
2242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
224369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return heap->undefined_value();
2244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochObject* LiveObjectList::GetPath(int obj_id1,
2248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                int obj_id2,
2249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                Handle<JSObject> instance_filter) {
2250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HandleScope scope;
2251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Get the target object.
2253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapObject* obj1 = NULL;
2254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (obj_id1 != 0) {
2255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    obj1 = HeapObject::cast(GetObj(obj_id1));
225669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (obj1 == HEAP->undefined_value()) {
2257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return obj1;
2258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapObject* obj2 = HeapObject::cast(GetObj(obj_id2));
226269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (obj2 == HEAP->undefined_value()) {
2263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return obj2;
2264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return GetPathPrivate(obj1, obj2);
2267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid LiveObjectList::DoProcessNonLive(HeapObject* obj) {
2271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // We should only be called if we have at least one lol to search.
2272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(last() != NULL);
2273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element* element = last()->Find(obj);
2274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (element != NULL) {
2275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    NullifyNonLivePointer(&element->obj_);
2276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LiveObjectList::IterateElementsPrivate(ObjectVisitor* v) {
2281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* lol = last();
2282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (lol != NULL) {
2283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Element* elements = lol->elements_;
2284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int count = lol->obj_count_;
2285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (int i = 0; i < count; i++) {
2286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HeapObject** p = &elements[i].obj_;
22873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v->VisitPointer(reinterpret_cast<Object** >(p));
2288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->prev_;
2290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Purpose: Called by GCEpilogue to purge duplicates.  Not to be called by
2295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// anyone else.
2296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LiveObjectList::PurgeDuplicates() {
2297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool is_sorted = false;
2298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* lol = last();
2299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!lol) {
2300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return;  // Nothing to purge.
2301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int total_count = lol->TotalObjCount();
2304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!total_count) {
2305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return;  // Nothing to purge.
2306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element* elements = NewArray<Element>(total_count);
2309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = 0;
2310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy all the object elements into a consecutive array.
2312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (lol) {
2313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    memcpy(&elements[count], lol->elements_, lol->obj_count_ * sizeof(Element));
2314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    count += lol->obj_count_;
2315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->prev_;
2316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  qsort(elements, total_count, sizeof(Element),
2318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        reinterpret_cast<RawComparer>(CompareElement));
2319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(count == total_count);
2321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Iterate over all objects in the consolidated list and check for dups.
2323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  total_count--;
2324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < total_count; ) {
2325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Element* curr = &elements[i];
2326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject* curr_obj = curr->obj_;
2327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int j = i+1;
2328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    bool done = false;
2329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (!done && (j < total_count)) {
2331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Process if the element's object is still live after the current GC.
2332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Non-live objects will be converted to SMIs i.e. not HeapObjects.
2333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (curr_obj->IsHeapObject()) {
2334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        Element* next = &elements[j];
2335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        HeapObject* next_obj = next->obj_;
2336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (next_obj->IsHeapObject()) {
2337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          if (curr_obj != next_obj) {
2338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            done = true;
2339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            continue;  // Live object but no match.  Move on.
2340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          }
2341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // NOTE: we've just GCed the LOLs.  Hence, they are no longer sorted.
2343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Since we detected at least one need to search for entries, we'll
2344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // sort it to enable the use of NullifyMostRecent() below.  We only
2345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // need to sort it once (except for one exception ... see below).
2346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          if (!is_sorted) {
2347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            SortAll();
2348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            is_sorted = true;
2349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          }
2350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // We have a match.  Need to nullify the most recent ref to this
2352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // object.  We'll keep the oldest ref:
2353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // Note: we will nullify the element record in the LOL
2354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          // database, not in the local sorted copy of the elements.
2355e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          NullifyMostRecent(curr_obj);
2356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
2357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Either the object was already marked for purging, or we just marked
2359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // it.  Either way, if there's more than one dup, then we need to check
2360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // the next element for another possible dup against the current as well
2361e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // before we move on.  So, here we go.
2362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      j++;
2363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2365e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // We can move on to checking the match on the next element.
2366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    i = j;
2367e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2369e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  DeleteArray<Element>(elements);
2370e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2372e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Purpose: Purges dead objects and resorts the LOLs.
2374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LiveObjectList::GCEpiloguePrivate() {
2375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Note: During the GC, ConsStrings may be collected and pointers may be
2376e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // forwarded to its constituent string.  As a result, we may find dupes of
2377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // objects references in the LOL list.
2378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Another common way we get dups is that free chunks that have been swept
2379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // in the oldGen heap may be kept as ByteArray objects in a free list.
2380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //
2381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // When we promote live objects from the youngGen, the object may be moved
2382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // to the start of these free chunks.  Since there is no free or move event
2383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // for the free chunks, their addresses will show up 2 times: once for their
2384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // original free ByteArray selves, and once for the newly promoted youngGen
2385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // object.  Hence, we can get a duplicate address in the LOL again.
2386e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //
2387e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // We need to eliminate these dups because the LOL implementation expects to
2388e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // only have at most one unique LOL reference to any object at any time.
2389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  PurgeDuplicates();
2390e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2391e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // After the GC, sweep away all free'd Elements and compact.
23923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LiveObjectList* prev = NULL;
23933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LiveObjectList* next = NULL;
2394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Iterating from the youngest lol to the oldest lol.
23963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (LiveObjectList* lol = last(); lol; lol = prev) {
2397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Element* elements = lol->elements_;
2398e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    prev = lol->prev();  // Save the prev.
2399e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Remove any references to collected objects.
2401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int i = 0;
2402e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (i < lol->obj_count_) {
2403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Element& element = elements[i];
2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (!element.obj_->IsHeapObject()) {
2405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // If the HeapObject address was converted into a SMI, then this
2406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // is a dead object.  Copy the last element over this one.
2407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        element = elements[lol->obj_count_ - 1];
2408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        lol->obj_count_--;
2409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // We've just moved the last element into this index.  We'll revisit
2410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // this index again.  Hence, no need to increment the iterator.
2411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
2412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        i++;  // Look at the next element next.
2413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int new_count = lol->obj_count_;
2417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Check if there are any more elements to keep after purging the dead ones.
2419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (new_count == 0) {
2420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      DeleteArray<Element>(elements);
2421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      lol->elements_ = NULL;
2422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      lol->capacity_ = 0;
2423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(lol->obj_count_ == 0);
2424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // If the list is also invisible, the clean up the list as well.
2426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (lol->id_ == 0) {
2427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Point the next lol's prev to this lol's prev.
2428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (next) {
2429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          next->prev_ = lol->prev_;
2430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        } else {
2431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          last_ = lol->prev_;
2432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
2433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Delete this now empty and invisible lol.
2435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        delete lol;
2436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Don't point the next to this lol since it is now deleted.
2438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Leave the next pointer pointing to the current lol.
2439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        continue;
2440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
2443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // If the obj_count_ is less than the capacity and the difference is
2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // greater than a specified threshold, then we should shrink the list.
2445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      int diff = lol->capacity_ - new_count;
2446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      const int kMaxUnusedSpace = 64;
2447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (diff > kMaxUnusedSpace) {  // Threshold for shrinking.
2448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Shrink the list.
24493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Element* new_elements = NewArray<Element>(new_count);
2450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        memcpy(new_elements, elements, new_count * sizeof(Element));
2451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        DeleteArray<Element>(elements);
2453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        lol->elements_ = new_elements;
2454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        lol->capacity_ = new_count;
2455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(lol->obj_count_ == new_count);
2457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      lol->Sort();  // We've moved objects.  Re-sort in case.
2459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Save the next (for the previous link) in case we need it later.
2462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    next = lol;
2463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef VERIFY_LOL
2466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_verify_lol) {
2467e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Verify();
2468e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif
2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef VERIFY_LOL
2474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LiveObjectList::Verify(bool match_heap_exactly) {
2475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("Verifying the LiveObjectList database:\n");
2476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LiveObjectList* lol = last();
2478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (lol == NULL) {
2479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    OS::Print("  No lol database to verify\n");
2480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return;
2481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("  Preparing the lol database ...\n");
2484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int total_count = lol->TotalObjCount();
2485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Element* elements = NewArray<Element>(total_count);
2487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = 0;
2488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2489e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Copy all the object elements into a consecutive array.
2490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("  Copying the lol database ...\n");
2491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (lol != NULL) {
2492e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    memcpy(&elements[count], lol->elements_, lol->obj_count_ * sizeof(Element));
2493e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    count += lol->obj_count_;
2494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->prev_;
2495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  qsort(elements, total_count, sizeof(Element),
2497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        reinterpret_cast<RawComparer>(CompareElement));
2498e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(count == total_count);
2500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Iterate over all objects in the heap and check for:
2502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // 1. object in LOL but not in heap i.e. error.
2503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // 2. object in heap but not in LOL (possibly not an error).  Usually
2504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //    just means that we don't have the a capture of the latest heap.
2505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //    That is unless we did this verify immediately after a capture,
2506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //    and specified match_heap_exactly = true.
2507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int number_of_heap_objects = 0;
2509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int number_of_matches = 0;
2510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int number_not_in_heap = total_count;
2511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int number_not_in_lol = 0;
2512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("  Start verify ...\n");
2514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("  Verifying ...");
2515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Flush();
25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HeapIterator iterator;
2517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapObject* heap_obj = NULL;
2518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while ((heap_obj = iterator.next()) != NULL) {
2519e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    number_of_heap_objects++;
2520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Check if the heap_obj is in the lol.
2522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Element key;
2523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    key.obj_ = heap_obj;
2524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Element* result = reinterpret_cast<Element*>(
2526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        bsearch(&key, elements, total_count, sizeof(Element),
2527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                reinterpret_cast<RawComparer>(CompareElement)));
2528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (result != NULL) {
2530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      number_of_matches++;
2531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      number_not_in_heap--;
2532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Mark it as found by changing it into a SMI (mask off low bit).
2533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Note: we cannot use HeapObject::cast() here because it asserts that
2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // the HeapObject bit is set on the address, but we're unsetting it on
2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // purpose here for our marking.
2536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      result->obj_ = reinterpret_cast<HeapObject*>(heap_obj->address());
2537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    } else {
2539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      number_not_in_lol++;
2540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (match_heap_exactly) {
2541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        OS::Print("heap object %p NOT in lol database\n", heap_obj);
2542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Show some sign of life.
2545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (number_of_heap_objects % 1000 == 0) {
2546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      OS::Print(".");
2547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      fflush(stdout);
2548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("\n");
2551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Reporting lol objects not found in the heap.
2553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (number_not_in_heap) {
2554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int found = 0;
2555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (int i = 0; (i < total_count) && (found < number_not_in_heap); i++) {
2556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      Element& element = elements[i];
2557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (element.obj_->IsHeapObject()) {
2558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        OS::Print("lol database object [%d of %d] %p NOT in heap\n",
2559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                  i, total_count, element.obj_);
2560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        found++;
2561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  DeleteArray<Element>(elements);
2566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("number of objects in lol database %d\n", total_count);
2568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("number of heap objects .......... %d\n", number_of_heap_objects);
2569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("number of matches ............... %d\n", number_of_matches);
2570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("number NOT in heap .............. %d\n", number_not_in_heap);
2571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("number NOT in lol database ...... %d\n", number_not_in_lol);
2572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (number_of_matches != total_count) {
2574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    OS::Print("  *** ERROR: "
2575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              "NOT all lol database objects match heap objects.\n");
2576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (number_not_in_heap != 0) {
2578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    OS::Print("  *** ERROR: %d lol database objects not found in heap.\n",
2579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch              number_not_in_heap);
2580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (match_heap_exactly) {
2582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (!(number_not_in_lol == 0)) {
2583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      OS::Print("  *** ERROR: %d heap objects NOT found in lol database.\n",
2584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                number_not_in_lol);
2585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(number_of_matches == total_count);
2589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(number_not_in_heap == 0);
2590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(number_not_in_lol == (number_of_heap_objects - total_count));
2591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (match_heap_exactly) {
2592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(total_count == number_of_heap_objects);
2593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ASSERT(number_not_in_lol == 0);
2594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("  Verify the lol database is sorted ...\n");
2597e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  lol = last();
2598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (lol != NULL) {
2599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    Element* elements = lol->elements_;
2600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (int i = 0; i < lol->obj_count_ - 1; i++) {
2601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (elements[i].obj_ >= elements[i+1].obj_) {
2602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        OS::Print("  *** ERROR: lol %p obj[%d] %p > obj[%d] %p\n",
2603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                  lol, i, elements[i].obj_, i+1, elements[i+1].obj_);
2604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
2605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lol = lol->prev_;
2607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("  DONE verifying.\n\n\n");
2610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LiveObjectList::VerifyNotInFromSpace() {
2614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  OS::Print("VerifyNotInFromSpace() ...\n");
2615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  LolIterator it(NULL, last());
261669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Heap* heap = ISOLATE->heap();
2617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int i = 0;
2618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (it.Init(); !it.Done(); it.Next()) {
2619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject* heap_obj = it.Obj();
262069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (heap->InFromSpace(heap_obj)) {
2621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      OS::Print(" ERROR: VerifyNotInFromSpace: [%d] obj %p in From space %p\n",
26223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                i++, heap_obj, Heap::new_space()->FromSpaceStart());
2623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
2625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
2626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif  // VERIFY_LOL
2627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
26281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
26291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} }  // namespace v8::internal
26301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
26311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif  // LIVE_OBJECT_LIST
2632