v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-heap-profiler.cc
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 //
3 // Tests for heap profiler
4 
5 #include <ctype.h>
6 
7 #include "v8.h"
8 
9 #include "cctest.h"
10 #include "hashmap.h"
11 #include "heap-profiler.h"
12 #include "snapshot.h"
13 #include "debug.h"
14 #include "utils-inl.h"
15 #include "../include/v8-profiler.h"
16 
17 namespace {
18 
19 class NamedEntriesDetector {
20  public:
21  NamedEntriesDetector()
22  : has_A2(false), has_B2(false), has_C2(false) {
23  }
24 
25  void CheckEntry(i::HeapEntry* entry) {
26  if (strcmp(entry->name(), "A2") == 0) has_A2 = true;
27  if (strcmp(entry->name(), "B2") == 0) has_B2 = true;
28  if (strcmp(entry->name(), "C2") == 0) has_C2 = true;
29  }
30 
31  static bool AddressesMatch(void* key1, void* key2) {
32  return key1 == key2;
33  }
34 
35  void CheckAllReachables(i::HeapEntry* root) {
36  i::HashMap visited(AddressesMatch);
37  i::List<i::HeapEntry*> list(10);
38  list.Add(root);
39  CheckEntry(root);
40  while (!list.is_empty()) {
41  i::HeapEntry* entry = list.RemoveLast();
42  i::Vector<i::HeapGraphEdge*> children = entry->children();
43  for (int i = 0; i < children.length(); ++i) {
44  if (children[i]->type() == i::HeapGraphEdge::kShortcut) continue;
45  i::HeapEntry* child = children[i]->to();
46  i::HashMap::Entry* entry = visited.Lookup(
47  reinterpret_cast<void*>(child),
48  static_cast<uint32_t>(reinterpret_cast<uintptr_t>(child)),
49  true);
50  if (entry->value)
51  continue;
52  entry->value = reinterpret_cast<void*>(1);
53  list.Add(child);
54  CheckEntry(child);
55  }
56  }
57  }
58 
59  bool has_A2;
60  bool has_B2;
61  bool has_C2;
62 };
63 
64 } // namespace
65 
66 
67 static const v8::HeapGraphNode* GetGlobalObject(
68  const v8::HeapSnapshot* snapshot) {
69  CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount());
70  const v8::HeapGraphNode* global_obj =
71  snapshot->GetRoot()->GetChild(0)->GetToNode();
72  CHECK_EQ(0, strncmp("Object", const_cast<i::HeapEntry*>(
73  reinterpret_cast<const i::HeapEntry*>(global_obj))->name(), 6));
74  return global_obj;
75 }
76 
77 
78 static const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node,
80  const char* name) {
81  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
82  const v8::HeapGraphEdge* prop = node->GetChild(i);
83  v8::String::AsciiValue prop_name(prop->GetName());
84  if (prop->GetType() == type && strcmp(name, *prop_name) == 0)
85  return prop->GetToNode();
86  }
87  return NULL;
88 }
89 
90 
91 static bool HasString(const v8::HeapGraphNode* node, const char* contents) {
92  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
93  const v8::HeapGraphEdge* prop = node->GetChild(i);
94  const v8::HeapGraphNode* node = prop->GetToNode();
95  if (node->GetType() == v8::HeapGraphNode::kString) {
96  v8::String::AsciiValue node_name(node->GetName());
97  if (strcmp(contents, *node_name) == 0) return true;
98  }
99  }
100  return false;
101 }
102 
103 
104 TEST(HeapSnapshot) {
105  v8::HandleScope scope;
106  LocalContext env2;
107 
108  CompileRun(
109  "function A2() {}\n"
110  "function B2(x) { return function() { return typeof x; }; }\n"
111  "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n"
112  "var a2 = new A2();\n"
113  "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n"
114  "var c2 = new C2(a2);");
115  const v8::HeapSnapshot* snapshot_env2 =
116  v8::HeapProfiler::TakeSnapshot(v8_str("env2"));
117  const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2);
118 
119  // Verify, that JS global object of env2 has '..2' properties.
120  const v8::HeapGraphNode* a2_node =
121  GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2");
122  CHECK_NE(NULL, a2_node);
123  CHECK_NE(
124  NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_1"));
125  CHECK_NE(
126  NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_2"));
127  CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c2"));
128 
129  NamedEntriesDetector det;
130  det.CheckAllReachables(const_cast<i::HeapEntry*>(
131  reinterpret_cast<const i::HeapEntry*>(global_env2)));
132  CHECK(det.has_A2);
133  CHECK(det.has_B2);
134  CHECK(det.has_C2);
135 }
136 
137 
138 TEST(HeapSnapshotObjectSizes) {
139  v8::HandleScope scope;
140  LocalContext env;
141 
142  // -a-> X1 --a
143  // x -b-> X2 <-|
144  CompileRun(
145  "function X(a, b) { this.a = a; this.b = b; }\n"
146  "x = new X(new X(), new X());\n"
147  "dummy = new X();\n"
148  "(function() { x.a.a = x.b; })();");
149  const v8::HeapSnapshot* snapshot =
150  v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
151  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
152  const v8::HeapGraphNode* x =
153  GetProperty(global, v8::HeapGraphEdge::kProperty, "x");
154  CHECK_NE(NULL, x);
155  const v8::HeapGraphNode* x1 =
156  GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
157  CHECK_NE(NULL, x1);
158  const v8::HeapGraphNode* x2 =
159  GetProperty(x, v8::HeapGraphEdge::kProperty, "b");
160  CHECK_NE(NULL, x2);
161 
162  // Test sizes.
163  CHECK_NE(0, x->GetSelfSize());
164  CHECK_NE(0, x1->GetSelfSize());
165  CHECK_NE(0, x2->GetSelfSize());
166 }
167 
168 
169 TEST(BoundFunctionInSnapshot) {
170  v8::HandleScope scope;
171  LocalContext env;
172  CompileRun(
173  "function myFunction(a, b) { this.a = a; this.b = b; }\n"
174  "function AAAAA() {}\n"
175  "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n");
176  const v8::HeapSnapshot* snapshot =
177  v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
178  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
179  const v8::HeapGraphNode* f =
180  GetProperty(global, v8::HeapGraphEdge::kProperty, "boundFunction");
181  CHECK(f);
182  CHECK_EQ(v8::String::New("native_bind"), f->GetName());
183  const v8::HeapGraphNode* bindings =
184  GetProperty(f, v8::HeapGraphEdge::kInternal, "bindings");
185  CHECK_NE(NULL, bindings);
186  CHECK_EQ(v8::HeapGraphNode::kArray, bindings->GetType());
187  CHECK_EQ(4, bindings->GetChildrenCount());
188 
189  const v8::HeapGraphNode* bound_this = GetProperty(
190  f, v8::HeapGraphEdge::kShortcut, "bound_this");
191  CHECK(bound_this);
192  CHECK_EQ(v8::HeapGraphNode::kObject, bound_this->GetType());
193 
194  const v8::HeapGraphNode* bound_function = GetProperty(
195  f, v8::HeapGraphEdge::kShortcut, "bound_function");
196  CHECK(bound_function);
197  CHECK_EQ(v8::HeapGraphNode::kClosure, bound_function->GetType());
198 
199  const v8::HeapGraphNode* bound_argument = GetProperty(
200  f, v8::HeapGraphEdge::kShortcut, "bound_argument_1");
201  CHECK(bound_argument);
202  CHECK_EQ(v8::HeapGraphNode::kObject, bound_argument->GetType());
203 }
204 
205 
206 TEST(HeapSnapshotEntryChildren) {
207  v8::HandleScope scope;
208  LocalContext env;
209 
210  CompileRun(
211  "function A() { }\n"
212  "a = new A;");
213  const v8::HeapSnapshot* snapshot =
214  v8::HeapProfiler::TakeSnapshot(v8_str("children"));
215  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
216  for (int i = 0, count = global->GetChildrenCount(); i < count; ++i) {
217  const v8::HeapGraphEdge* prop = global->GetChild(i);
218  CHECK_EQ(global, prop->GetFromNode());
219  }
220  const v8::HeapGraphNode* a =
221  GetProperty(global, v8::HeapGraphEdge::kProperty, "a");
222  CHECK_NE(NULL, a);
223  for (int i = 0, count = a->GetChildrenCount(); i < count; ++i) {
224  const v8::HeapGraphEdge* prop = a->GetChild(i);
225  CHECK_EQ(a, prop->GetFromNode());
226  }
227 }
228 
229 
230 TEST(HeapSnapshotCodeObjects) {
231  v8::HandleScope scope;
232  LocalContext env;
233 
234  CompileRun(
235  "function lazy(x) { return x - 1; }\n"
236  "function compiled(x) { return x + 1; }\n"
237  "var anonymous = (function() { return function() { return 0; } })();\n"
238  "compiled(1)");
239  const v8::HeapSnapshot* snapshot =
240  v8::HeapProfiler::TakeSnapshot(v8_str("code"));
241 
242  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
243  const v8::HeapGraphNode* compiled =
244  GetProperty(global, v8::HeapGraphEdge::kProperty, "compiled");
245  CHECK_NE(NULL, compiled);
247  const v8::HeapGraphNode* lazy =
248  GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy");
249  CHECK_NE(NULL, lazy);
250  CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType());
251  const v8::HeapGraphNode* anonymous =
252  GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous");
253  CHECK_NE(NULL, anonymous);
254  CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
255  v8::String::AsciiValue anonymous_name(anonymous->GetName());
256  CHECK_EQ("", *anonymous_name);
257 
258  // Find references to code.
259  const v8::HeapGraphNode* compiled_code =
260  GetProperty(compiled, v8::HeapGraphEdge::kInternal, "shared");
261  CHECK_NE(NULL, compiled_code);
262  const v8::HeapGraphNode* lazy_code =
263  GetProperty(lazy, v8::HeapGraphEdge::kInternal, "shared");
264  CHECK_NE(NULL, lazy_code);
265 
266  // Verify that non-compiled code doesn't contain references to "x"
267  // literal, while compiled code does. The scope info is stored in FixedArray
268  // objects attached to the SharedFunctionInfo.
269  bool compiled_references_x = false, lazy_references_x = false;
270  for (int i = 0, count = compiled_code->GetChildrenCount(); i < count; ++i) {
271  const v8::HeapGraphEdge* prop = compiled_code->GetChild(i);
272  const v8::HeapGraphNode* node = prop->GetToNode();
273  if (node->GetType() == v8::HeapGraphNode::kArray) {
274  if (HasString(node, "x")) {
275  compiled_references_x = true;
276  break;
277  }
278  }
279  }
280  for (int i = 0, count = lazy_code->GetChildrenCount(); i < count; ++i) {
281  const v8::HeapGraphEdge* prop = lazy_code->GetChild(i);
282  const v8::HeapGraphNode* node = prop->GetToNode();
283  if (node->GetType() == v8::HeapGraphNode::kArray) {
284  if (HasString(node, "x")) {
285  lazy_references_x = true;
286  break;
287  }
288  }
289  }
290  CHECK(compiled_references_x);
291  CHECK(!lazy_references_x);
292 }
293 
294 
295 TEST(HeapSnapshotHeapNumbers) {
296  v8::HandleScope scope;
297  LocalContext env;
298  CompileRun(
299  "a = 1; // a is Smi\n"
300  "b = 2.5; // b is HeapNumber");
301  const v8::HeapSnapshot* snapshot =
302  v8::HeapProfiler::TakeSnapshot(v8_str("numbers"));
303  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
304  CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kProperty, "a"));
305  const v8::HeapGraphNode* b =
306  GetProperty(global, v8::HeapGraphEdge::kProperty, "b");
307  CHECK_NE(NULL, b);
309 }
310 
311 TEST(HeapSnapshotSlicedString) {
312  v8::HandleScope scope;
313  LocalContext env;
314  CompileRun(
315  "parent_string = \"123456789.123456789.123456789.123456789.123456789."
316  "123456789.123456789.123456789.123456789.123456789."
317  "123456789.123456789.123456789.123456789.123456789."
318  "123456789.123456789.123456789.123456789.123456789.\";"
319  "child_string = parent_string.slice(100);");
320  const v8::HeapSnapshot* snapshot =
321  v8::HeapProfiler::TakeSnapshot(v8_str("strings"));
322  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
323  const v8::HeapGraphNode* parent_string =
324  GetProperty(global, v8::HeapGraphEdge::kProperty, "parent_string");
325  CHECK_NE(NULL, parent_string);
326  const v8::HeapGraphNode* child_string =
327  GetProperty(global, v8::HeapGraphEdge::kProperty, "child_string");
328  CHECK_NE(NULL, child_string);
329  const v8::HeapGraphNode* parent =
330  GetProperty(child_string, v8::HeapGraphEdge::kInternal, "parent");
331  CHECK_EQ(parent_string, parent);
332 }
333 
334 TEST(HeapSnapshotInternalReferences) {
335  v8::HandleScope scope;
337  global_template->SetInternalFieldCount(2);
338  LocalContext env(NULL, global_template);
339  v8::Handle<v8::Object> global_proxy = env->Global();
340  v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
341  CHECK_EQ(2, global->InternalFieldCount());
343  global->SetInternalField(0, v8_num(17));
344  global->SetInternalField(1, obj);
345  const v8::HeapSnapshot* snapshot =
346  v8::HeapProfiler::TakeSnapshot(v8_str("internals"));
347  const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot);
348  // The first reference will not present, because it's a Smi.
349  CHECK_EQ(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0"));
350  // The second reference is to an object.
351  CHECK_NE(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "1"));
352 }
353 
354 
355 // Trying to introduce a check helper for uint32_t causes many
356 // overloading ambiguities, so it seems easier just to cast
357 // them to a signed type.
358 #define CHECK_EQ_SNAPSHOT_OBJECT_ID(a, b) \
359  CHECK_EQ(static_cast<int32_t>(a), static_cast<int32_t>(b))
360 #define CHECK_NE_SNAPSHOT_OBJECT_ID(a, b) \
361  CHECK((a) != (b)) // NOLINT
362 
363 TEST(HeapEntryIdsAndArrayShift) {
364  v8::HandleScope scope;
365  LocalContext env;
366 
367  CompileRun(
368  "function AnObject() {\n"
369  " this.first = 'first';\n"
370  " this.second = 'second';\n"
371  "}\n"
372  "var a = new Array();\n"
373  "for (var i = 0; i < 10; ++i)\n"
374  " a.push(new AnObject());\n");
375  const v8::HeapSnapshot* snapshot1 =
376  v8::HeapProfiler::TakeSnapshot(v8_str("s1"));
377 
378  CompileRun(
379  "for (var i = 0; i < 1; ++i)\n"
380  " a.shift();\n");
381 
382  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
383 
384  const v8::HeapSnapshot* snapshot2 =
385  v8::HeapProfiler::TakeSnapshot(v8_str("s2"));
386 
387  const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1);
388  const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2);
389  CHECK_NE_SNAPSHOT_OBJECT_ID(0, global1->GetId());
390  CHECK_EQ_SNAPSHOT_OBJECT_ID(global1->GetId(), global2->GetId());
391 
392  const v8::HeapGraphNode* a1 =
393  GetProperty(global1, v8::HeapGraphEdge::kProperty, "a");
394  CHECK_NE(NULL, a1);
395  const v8::HeapGraphNode* k1 =
396  GetProperty(a1, v8::HeapGraphEdge::kInternal, "elements");
397  CHECK_NE(NULL, k1);
398  const v8::HeapGraphNode* a2 =
399  GetProperty(global2, v8::HeapGraphEdge::kProperty, "a");
400  CHECK_NE(NULL, a2);
401  const v8::HeapGraphNode* k2 =
402  GetProperty(a2, v8::HeapGraphEdge::kInternal, "elements");
403  CHECK_NE(NULL, k2);
404 
405  CHECK_EQ_SNAPSHOT_OBJECT_ID(a1->GetId(), a2->GetId());
407 }
408 
409 TEST(HeapEntryIdsAndGC) {
410  v8::HandleScope scope;
411  LocalContext env;
412 
413  CompileRun(
414  "function A() {}\n"
415  "function B(x) { this.x = x; }\n"
416  "var a = new A();\n"
417  "var b = new B(a);");
418  v8::Local<v8::String> s1_str = v8_str("s1");
419  v8::Local<v8::String> s2_str = v8_str("s2");
420  const v8::HeapSnapshot* snapshot1 =
422 
423  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
424 
425  const v8::HeapSnapshot* snapshot2 =
427 
428  CHECK_GT(snapshot1->GetMaxSnapshotJSObjectId(), 7000);
429  CHECK(snapshot1->GetMaxSnapshotJSObjectId() <=
430  snapshot2->GetMaxSnapshotJSObjectId());
431 
432  const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1);
433  const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2);
434  CHECK_NE_SNAPSHOT_OBJECT_ID(0, global1->GetId());
435  CHECK_EQ_SNAPSHOT_OBJECT_ID(global1->GetId(), global2->GetId());
436  const v8::HeapGraphNode* A1 =
437  GetProperty(global1, v8::HeapGraphEdge::kProperty, "A");
438  CHECK_NE(NULL, A1);
439  const v8::HeapGraphNode* A2 =
440  GetProperty(global2, v8::HeapGraphEdge::kProperty, "A");
441  CHECK_NE(NULL, A2);
442  CHECK_NE_SNAPSHOT_OBJECT_ID(0, A1->GetId());
443  CHECK_EQ_SNAPSHOT_OBJECT_ID(A1->GetId(), A2->GetId());
444  const v8::HeapGraphNode* B1 =
445  GetProperty(global1, v8::HeapGraphEdge::kProperty, "B");
446  CHECK_NE(NULL, B1);
447  const v8::HeapGraphNode* B2 =
448  GetProperty(global2, v8::HeapGraphEdge::kProperty, "B");
449  CHECK_NE(NULL, B2);
450  CHECK_NE_SNAPSHOT_OBJECT_ID(0, B1->GetId());
451  CHECK_EQ_SNAPSHOT_OBJECT_ID(B1->GetId(), B2->GetId());
452  const v8::HeapGraphNode* a1 =
453  GetProperty(global1, v8::HeapGraphEdge::kProperty, "a");
454  CHECK_NE(NULL, a1);
455  const v8::HeapGraphNode* a2 =
456  GetProperty(global2, v8::HeapGraphEdge::kProperty, "a");
457  CHECK_NE(NULL, a2);
458  CHECK_NE_SNAPSHOT_OBJECT_ID(0, a1->GetId());
459  CHECK_EQ_SNAPSHOT_OBJECT_ID(a1->GetId(), a2->GetId());
460  const v8::HeapGraphNode* b1 =
461  GetProperty(global1, v8::HeapGraphEdge::kProperty, "b");
462  CHECK_NE(NULL, b1);
463  const v8::HeapGraphNode* b2 =
464  GetProperty(global2, v8::HeapGraphEdge::kProperty, "b");
465  CHECK_NE(NULL, b2);
466  CHECK_NE_SNAPSHOT_OBJECT_ID(0, b1->GetId());
467  CHECK_EQ_SNAPSHOT_OBJECT_ID(b1->GetId(), b2->GetId());
468 }
469 
470 
471 TEST(HeapSnapshotRootPreservedAfterSorting) {
472  v8::HandleScope scope;
473  LocalContext env;
474  const v8::HeapSnapshot* snapshot =
475  v8::HeapProfiler::TakeSnapshot(v8_str("s"));
476  const v8::HeapGraphNode* root1 = snapshot->GetRoot();
477  const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>(
478  snapshot))->GetSortedEntriesList();
479  const v8::HeapGraphNode* root2 = snapshot->GetRoot();
480  CHECK_EQ(root1, root2);
481 }
482 
483 
484 namespace {
485 
486 class TestJSONStream : public v8::OutputStream {
487  public:
488  TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {}
489  explicit TestJSONStream(int abort_countdown)
490  : eos_signaled_(0), abort_countdown_(abort_countdown) {}
491  virtual ~TestJSONStream() {}
492  virtual void EndOfStream() { ++eos_signaled_; }
493  virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) {
494  if (abort_countdown_ > 0) --abort_countdown_;
495  if (abort_countdown_ == 0) return kAbort;
496  CHECK_GT(chars_written, 0);
497  i::Vector<char> chunk = buffer_.AddBlock(chars_written, '\0');
498  memcpy(chunk.start(), buffer, chars_written);
499  return kContinue;
500  }
501  virtual WriteResult WriteUint32Chunk(uint32_t* buffer, int chars_written) {
502  ASSERT(false);
503  return kAbort;
504  }
505  void WriteTo(i::Vector<char> dest) { buffer_.WriteTo(dest); }
506  int eos_signaled() { return eos_signaled_; }
507  int size() { return buffer_.size(); }
508 
509  private:
511  int eos_signaled_;
512  int abort_countdown_;
513 };
514 
515 class AsciiResource: public v8::String::ExternalAsciiStringResource {
516  public:
517  explicit AsciiResource(i::Vector<char> string): data_(string.start()) {
518  length_ = string.length();
519  }
520  virtual const char* data() const { return data_; }
521  virtual size_t length() const { return length_; }
522  private:
523  const char* data_;
524  size_t length_;
525 };
526 
527 } // namespace
528 
529 TEST(HeapSnapshotJSONSerialization) {
530  v8::HandleScope scope;
531  LocalContext env;
532 
533 #define STRING_LITERAL_FOR_TEST \
534  "\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\""
535  CompileRun(
536  "function A(s) { this.s = s; }\n"
537  "function B(x) { this.x = x; }\n"
538  "var a = new A(" STRING_LITERAL_FOR_TEST ");\n"
539  "var b = new B(a);");
540  const v8::HeapSnapshot* snapshot =
541  v8::HeapProfiler::TakeSnapshot(v8_str("json"));
542  TestJSONStream stream;
543  snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
544  CHECK_GT(stream.size(), 0);
545  CHECK_EQ(1, stream.eos_signaled());
546  i::ScopedVector<char> json(stream.size());
547  stream.WriteTo(json);
548 
549  // Verify that snapshot string is valid JSON.
550  AsciiResource json_res(json);
551  v8::Local<v8::String> json_string = v8::String::NewExternal(&json_res);
552  env->Global()->Set(v8_str("json_snapshot"), json_string);
553  v8::Local<v8::Value> snapshot_parse_result = CompileRun(
554  "var parsed = JSON.parse(json_snapshot); true;");
555  CHECK(!snapshot_parse_result.IsEmpty());
556 
557  // Verify that snapshot object has required fields.
558  v8::Local<v8::Object> parsed_snapshot =
559  env->Global()->Get(v8_str("parsed"))->ToObject();
560  CHECK(parsed_snapshot->Has(v8_str("snapshot")));
561  CHECK(parsed_snapshot->Has(v8_str("nodes")));
562  CHECK(parsed_snapshot->Has(v8_str("edges")));
563  CHECK(parsed_snapshot->Has(v8_str("strings")));
564 
565  // Get node and edge "member" offsets.
566  v8::Local<v8::Value> meta_analysis_result = CompileRun(
567  "var meta = parsed.snapshot.meta;\n"
568  "var edge_count_offset = meta.node_fields.indexOf('edge_count');\n"
569  "var node_fields_count = meta.node_fields.length;\n"
570  "var edge_fields_count = meta.edge_fields.length;\n"
571  "var edge_type_offset = meta.edge_fields.indexOf('type');\n"
572  "var edge_name_offset = meta.edge_fields.indexOf('name_or_index');\n"
573  "var edge_to_node_offset = meta.edge_fields.indexOf('to_node');\n"
574  "var property_type ="
575  " meta.edge_types[edge_type_offset].indexOf('property');\n"
576  "var shortcut_type ="
577  " meta.edge_types[edge_type_offset].indexOf('shortcut');\n"
578  "var node_count = parsed.nodes.length / node_fields_count;\n"
579  "var first_edge_indexes = parsed.first_edge_indexes = [];\n"
580  "for (var i = 0, first_edge_index = 0; i < node_count; ++i) {\n"
581  " first_edge_indexes[i] = first_edge_index;\n"
582  " first_edge_index += edge_fields_count *\n"
583  " parsed.nodes[i * node_fields_count + edge_count_offset];\n"
584  "}\n");
585  CHECK(!meta_analysis_result.IsEmpty());
586 
587  // A helper function for processing encoded nodes.
588  CompileRun(
589  "function GetChildPosByProperty(pos, prop_name, prop_type) {\n"
590  " var nodes = parsed.nodes;\n"
591  " var edges = parsed.edges;\n"
592  " var strings = parsed.strings;\n"
593  " var node_ordinal = pos / node_fields_count;\n"
594  " for (var i = parsed.first_edge_indexes[node_ordinal],\n"
595  " count = parsed.first_edge_indexes[node_ordinal + 1];\n"
596  " i < count; i += edge_fields_count) {\n"
597  " if (edges[i + edge_type_offset] === prop_type\n"
598  " && strings[edges[i + edge_name_offset]] === prop_name)\n"
599  " return edges[i + edge_to_node_offset];\n"
600  " }\n"
601  " return null;\n"
602  "}\n");
603  // Get the string index using the path: <root> -> <global>.b.x.s
604  v8::Local<v8::Value> string_obj_pos_val = CompileRun(
605  "GetChildPosByProperty(\n"
606  " GetChildPosByProperty(\n"
607  " GetChildPosByProperty("
608  " parsed.edges[edge_to_node_offset],"
609  " \"b\", property_type),\n"
610  " \"x\", property_type),"
611  " \"s\", property_type)");
612  CHECK(!string_obj_pos_val.IsEmpty());
613  int string_obj_pos =
614  static_cast<int>(string_obj_pos_val->ToNumber()->Value());
615  v8::Local<v8::Object> nodes_array =
616  parsed_snapshot->Get(v8_str("nodes"))->ToObject();
617  int string_index = static_cast<int>(
618  nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value());
619  CHECK_GT(string_index, 0);
620  v8::Local<v8::Object> strings_array =
621  parsed_snapshot->Get(v8_str("strings"))->ToObject();
622  v8::Local<v8::String> string = strings_array->Get(string_index)->ToString();
623  v8::Local<v8::String> ref_string =
624  CompileRun(STRING_LITERAL_FOR_TEST)->ToString();
625 #undef STRING_LITERAL_FOR_TEST
626  CHECK_EQ(*v8::String::Utf8Value(ref_string),
627  *v8::String::Utf8Value(string));
628 }
629 
630 
631 TEST(HeapSnapshotJSONSerializationAborting) {
632  v8::HandleScope scope;
633  LocalContext env;
634  const v8::HeapSnapshot* snapshot =
635  v8::HeapProfiler::TakeSnapshot(v8_str("abort"));
636  TestJSONStream stream(5);
637  snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
638  CHECK_GT(stream.size(), 0);
639  CHECK_EQ(0, stream.eos_signaled());
640 }
641 
642 namespace {
643 
644 class TestStatsStream : public v8::OutputStream {
645  public:
646  TestStatsStream()
647  : eos_signaled_(0),
648  updates_written_(0),
649  entries_count_(0),
650  entries_size_(0),
651  intervals_count_(0),
652  first_interval_index_(-1) { }
653  TestStatsStream(const TestStatsStream& stream)
654  : v8::OutputStream(stream),
655  eos_signaled_(stream.eos_signaled_),
656  updates_written_(stream.updates_written_),
657  entries_count_(stream.entries_count_),
658  entries_size_(stream.entries_size_),
659  intervals_count_(stream.intervals_count_),
660  first_interval_index_(stream.first_interval_index_) { }
661  virtual ~TestStatsStream() {}
662  virtual void EndOfStream() { ++eos_signaled_; }
663  virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) {
664  ASSERT(false);
665  return kAbort;
666  }
667  virtual WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* buffer,
668  int updates_written) {
669  ++intervals_count_;
670  ASSERT(updates_written);
671  updates_written_ += updates_written;
672  entries_count_ = 0;
673  if (first_interval_index_ == -1 && updates_written != 0)
674  first_interval_index_ = buffer[0].index;
675  for (int i = 0; i < updates_written; ++i) {
676  entries_count_ += buffer[i].count;
677  entries_size_ += buffer[i].size;
678  }
679 
680  return kContinue;
681  }
682  int eos_signaled() { return eos_signaled_; }
683  int updates_written() { return updates_written_; }
684  uint32_t entries_count() const { return entries_count_; }
685  uint32_t entries_size() const { return entries_size_; }
686  int intervals_count() const { return intervals_count_; }
687  int first_interval_index() const { return first_interval_index_; }
688 
689  private:
690  int eos_signaled_;
691  int updates_written_;
692  uint32_t entries_count_;
693  uint32_t entries_size_;
694  int intervals_count_;
695  int first_interval_index_;
696 };
697 
698 } // namespace
699 
700 static TestStatsStream GetHeapStatsUpdate(
701  v8::SnapshotObjectId* object_id = NULL) {
702  TestStatsStream stream;
703  v8::SnapshotObjectId last_seen_id =
705  if (object_id)
706  *object_id = last_seen_id;
707  CHECK_EQ(1, stream.eos_signaled());
708  return stream;
709 }
710 
711 
712 TEST(HeapSnapshotObjectsStats) {
713  v8::HandleScope scope;
714  LocalContext env;
715 
717  // We have to call GC 5 times. In other case the garbage will be
718  // the reason of flakiness.
719  for (int i = 0; i < 5; ++i) {
720  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
721  }
722 
723  v8::SnapshotObjectId initial_id;
724  {
725  // Single chunk of data expected in update. Initial data.
726  TestStatsStream stats_update = GetHeapStatsUpdate(&initial_id);
727  CHECK_EQ(1, stats_update.intervals_count());
728  CHECK_EQ(1, stats_update.updates_written());
729  CHECK_LT(0, stats_update.entries_size());
730  CHECK_EQ(0, stats_update.first_interval_index());
731  }
732 
733  // No data expected in update because nothing has happened.
734  v8::SnapshotObjectId same_id;
735  CHECK_EQ(0, GetHeapStatsUpdate(&same_id).updates_written());
736  CHECK_EQ_SNAPSHOT_OBJECT_ID(initial_id, same_id);
737 
738  {
739  v8::SnapshotObjectId additional_string_id;
740  v8::HandleScope inner_scope_1;
741  v8_str("string1");
742  {
743  // Single chunk of data with one new entry expected in update.
744  TestStatsStream stats_update = GetHeapStatsUpdate(&additional_string_id);
745  CHECK_LT(same_id, additional_string_id);
746  CHECK_EQ(1, stats_update.intervals_count());
747  CHECK_EQ(1, stats_update.updates_written());
748  CHECK_LT(0, stats_update.entries_size());
749  CHECK_EQ(1, stats_update.entries_count());
750  CHECK_EQ(2, stats_update.first_interval_index());
751  }
752 
753  // No data expected in update because nothing happened.
754  v8::SnapshotObjectId last_id;
755  CHECK_EQ(0, GetHeapStatsUpdate(&last_id).updates_written());
756  CHECK_EQ_SNAPSHOT_OBJECT_ID(additional_string_id, last_id);
757 
758  {
759  v8::HandleScope inner_scope_2;
760  v8_str("string2");
761 
762  uint32_t entries_size;
763  {
764  v8::HandleScope inner_scope_3;
765  v8_str("string3");
766  v8_str("string4");
767 
768  {
769  // Single chunk of data with three new entries expected in update.
770  TestStatsStream stats_update = GetHeapStatsUpdate();
771  CHECK_EQ(1, stats_update.intervals_count());
772  CHECK_EQ(1, stats_update.updates_written());
773  CHECK_LT(0, entries_size = stats_update.entries_size());
774  CHECK_EQ(3, stats_update.entries_count());
775  CHECK_EQ(4, stats_update.first_interval_index());
776  }
777  }
778 
779  {
780  // Single chunk of data with two left entries expected in update.
781  TestStatsStream stats_update = GetHeapStatsUpdate();
782  CHECK_EQ(1, stats_update.intervals_count());
783  CHECK_EQ(1, stats_update.updates_written());
784  CHECK_GT(entries_size, stats_update.entries_size());
785  CHECK_EQ(1, stats_update.entries_count());
786  // Two strings from forth interval were released.
787  CHECK_EQ(4, stats_update.first_interval_index());
788  }
789  }
790 
791  {
792  // Single chunk of data with 0 left entries expected in update.
793  TestStatsStream stats_update = GetHeapStatsUpdate();
794  CHECK_EQ(1, stats_update.intervals_count());
795  CHECK_EQ(1, stats_update.updates_written());
796  CHECK_EQ(0, stats_update.entries_size());
797  CHECK_EQ(0, stats_update.entries_count());
798  // The last string from forth interval was released.
799  CHECK_EQ(4, stats_update.first_interval_index());
800  }
801  }
802  {
803  // Single chunk of data with 0 left entries expected in update.
804  TestStatsStream stats_update = GetHeapStatsUpdate();
805  CHECK_EQ(1, stats_update.intervals_count());
806  CHECK_EQ(1, stats_update.updates_written());
807  CHECK_EQ(0, stats_update.entries_size());
808  CHECK_EQ(0, stats_update.entries_count());
809  // The only string from the second interval was released.
810  CHECK_EQ(2, stats_update.first_interval_index());
811  }
812 
814  CHECK_EQ(0, array->Length());
815  // Force array's buffer allocation.
816  array->Set(2, v8_num(7));
817 
818  uint32_t entries_size;
819  {
820  // Single chunk of data with 2 entries expected in update.
821  TestStatsStream stats_update = GetHeapStatsUpdate();
822  CHECK_EQ(1, stats_update.intervals_count());
823  CHECK_EQ(1, stats_update.updates_written());
824  CHECK_LT(0, entries_size = stats_update.entries_size());
825  // They are the array and its buffer.
826  CHECK_EQ(2, stats_update.entries_count());
827  CHECK_EQ(8, stats_update.first_interval_index());
828  }
829 
830  for (int i = 0; i < 100; ++i)
831  array->Set(i, v8_num(i));
832 
833  {
834  // Single chunk of data with 1 entry expected in update.
835  TestStatsStream stats_update = GetHeapStatsUpdate();
836  CHECK_EQ(1, stats_update.intervals_count());
837  // The first interval was changed because old buffer was collected.
838  // The second interval was changed because new buffer was allocated.
839  CHECK_EQ(2, stats_update.updates_written());
840  CHECK_LT(entries_size, stats_update.entries_size());
841  CHECK_EQ(2, stats_update.entries_count());
842  CHECK_EQ(8, stats_update.first_interval_index());
843  }
844 
846 }
847 
848 
849 static void CheckChildrenIds(const v8::HeapSnapshot* snapshot,
850  const v8::HeapGraphNode* node,
851  int level, int max_level) {
852  if (level > max_level) return;
853  CHECK_EQ(node, snapshot->GetNodeById(node->GetId()));
854  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
855  const v8::HeapGraphEdge* prop = node->GetChild(i);
856  const v8::HeapGraphNode* child =
857  snapshot->GetNodeById(prop->GetToNode()->GetId());
858  CHECK_EQ_SNAPSHOT_OBJECT_ID(prop->GetToNode()->GetId(), child->GetId());
859  CHECK_EQ(prop->GetToNode(), child);
860  CheckChildrenIds(snapshot, child, level + 1, max_level);
861  }
862 }
863 
864 
865 TEST(HeapSnapshotGetNodeById) {
866  v8::HandleScope scope;
867  LocalContext env;
868 
869  const v8::HeapSnapshot* snapshot =
870  v8::HeapProfiler::TakeSnapshot(v8_str("id"));
871  const v8::HeapGraphNode* root = snapshot->GetRoot();
872  CheckChildrenIds(snapshot, root, 0, 3);
873  // Check a big id, which should not exist yet.
874  CHECK_EQ(NULL, snapshot->GetNodeById(0x1000000UL));
875 }
876 
877 
878 TEST(HeapSnapshotGetSnapshotObjectId) {
879  v8::HandleScope scope;
880  LocalContext env;
881  CompileRun("globalObject = {};\n");
882  const v8::HeapSnapshot* snapshot =
883  v8::HeapProfiler::TakeSnapshot(v8_str("get_snapshot_object_id"));
884  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
885  const v8::HeapGraphNode* global_object =
886  GetProperty(global, v8::HeapGraphEdge::kProperty, "globalObject");
887  CHECK(global_object);
888 
889  v8::Local<v8::Value> globalObjectHandle =
890  env->Global()->Get(v8::String::New("globalObject"));
891  CHECK(!globalObjectHandle.IsEmpty());
892  CHECK(globalObjectHandle->IsObject());
893 
895  v8::HeapProfiler::GetSnapshotObjectId(globalObjectHandle);
897  id);
898  CHECK_EQ(static_cast<int>(id), global_object->GetId());
899 }
900 
901 
902 TEST(HeapSnapshotUnknownSnapshotObjectId) {
903  v8::HandleScope scope;
904  LocalContext env;
905  CompileRun("globalObject = {};\n");
906  const v8::HeapSnapshot* snapshot =
907  v8::HeapProfiler::TakeSnapshot(v8_str("unknown_object_id"));
908  const v8::HeapGraphNode* node =
910  CHECK_EQ(NULL, node);
911 }
912 
913 
914 namespace {
915 
916 class TestActivityControl : public v8::ActivityControl {
917  public:
918  explicit TestActivityControl(int abort_count)
919  : done_(0), total_(0), abort_count_(abort_count) {}
920  ControlOption ReportProgressValue(int done, int total) {
921  done_ = done;
922  total_ = total;
923  return --abort_count_ != 0 ? kContinue : kAbort;
924  }
925  int done() { return done_; }
926  int total() { return total_; }
927 
928  private:
929  int done_;
930  int total_;
931  int abort_count_;
932 };
933 }
934 
935 TEST(TakeHeapSnapshotAborting) {
936  v8::HandleScope scope;
937  LocalContext env;
938 
939  const int snapshots_count = v8::HeapProfiler::GetSnapshotsCount();
940  TestActivityControl aborting_control(1);
941  const v8::HeapSnapshot* no_snapshot =
942  v8::HeapProfiler::TakeSnapshot(v8_str("abort"),
944  &aborting_control);
945  CHECK_EQ(NULL, no_snapshot);
946  CHECK_EQ(snapshots_count, v8::HeapProfiler::GetSnapshotsCount());
947  CHECK_GT(aborting_control.total(), aborting_control.done());
948 
949  TestActivityControl control(-1); // Don't abort.
950  const v8::HeapSnapshot* snapshot =
951  v8::HeapProfiler::TakeSnapshot(v8_str("full"),
953  &control);
954  CHECK_NE(NULL, snapshot);
955  CHECK_EQ(snapshots_count + 1, v8::HeapProfiler::GetSnapshotsCount());
956  CHECK_EQ(control.total(), control.done());
957  CHECK_GT(control.total(), 0);
958 }
959 
960 
961 namespace {
962 
963 class TestRetainedObjectInfo : public v8::RetainedObjectInfo {
964  public:
965  TestRetainedObjectInfo(int hash,
966  const char* group_label,
967  const char* label,
968  intptr_t element_count = -1,
969  intptr_t size = -1)
970  : disposed_(false),
971  hash_(hash),
972  group_label_(group_label),
973  label_(label),
974  element_count_(element_count),
975  size_(size) {
976  instances.Add(this);
977  }
978  virtual ~TestRetainedObjectInfo() {}
979  virtual void Dispose() {
980  CHECK(!disposed_);
981  disposed_ = true;
982  }
983  virtual bool IsEquivalent(RetainedObjectInfo* other) {
984  return GetHash() == other->GetHash();
985  }
986  virtual intptr_t GetHash() { return hash_; }
987  virtual const char* GetGroupLabel() { return group_label_; }
988  virtual const char* GetLabel() { return label_; }
989  virtual intptr_t GetElementCount() { return element_count_; }
990  virtual intptr_t GetSizeInBytes() { return size_; }
991  bool disposed() { return disposed_; }
992 
993  static v8::RetainedObjectInfo* WrapperInfoCallback(
994  uint16_t class_id, v8::Handle<v8::Value> wrapper) {
995  if (class_id == 1) {
996  if (wrapper->IsString()) {
997  v8::String::AsciiValue ascii(wrapper);
998  if (strcmp(*ascii, "AAA") == 0)
999  return new TestRetainedObjectInfo(1, "aaa-group", "aaa", 100);
1000  else if (strcmp(*ascii, "BBB") == 0)
1001  return new TestRetainedObjectInfo(1, "aaa-group", "aaa", 100);
1002  }
1003  } else if (class_id == 2) {
1004  if (wrapper->IsString()) {
1005  v8::String::AsciiValue ascii(wrapper);
1006  if (strcmp(*ascii, "CCC") == 0)
1007  return new TestRetainedObjectInfo(2, "ccc-group", "ccc");
1008  }
1009  }
1010  CHECK(false);
1011  return NULL;
1012  }
1013 
1014  static i::List<TestRetainedObjectInfo*> instances;
1015 
1016  private:
1017  bool disposed_;
1018  int category_;
1019  int hash_;
1020  const char* group_label_;
1021  const char* label_;
1022  intptr_t element_count_;
1023  intptr_t size_;
1024 };
1025 
1026 
1027 i::List<TestRetainedObjectInfo*> TestRetainedObjectInfo::instances;
1028 }
1029 
1030 
1031 static const v8::HeapGraphNode* GetNode(const v8::HeapGraphNode* parent,
1033  const char* name) {
1034  for (int i = 0, count = parent->GetChildrenCount(); i < count; ++i) {
1035  const v8::HeapGraphNode* node = parent->GetChild(i)->GetToNode();
1036  if (node->GetType() == type && strcmp(name,
1037  const_cast<i::HeapEntry*>(
1038  reinterpret_cast<const i::HeapEntry*>(node))->name()) == 0) {
1039  return node;
1040  }
1041  }
1042  return NULL;
1043 }
1044 
1045 
1046 TEST(HeapSnapshotRetainedObjectInfo) {
1047  v8::HandleScope scope;
1048  LocalContext env;
1049 
1051  1, TestRetainedObjectInfo::WrapperInfoCallback);
1053  2, TestRetainedObjectInfo::WrapperInfoCallback);
1055  v8::Persistent<v8::String>::New(v8_str("AAA"));
1056  p_AAA.SetWrapperClassId(1);
1058  v8::Persistent<v8::String>::New(v8_str("BBB"));
1059  p_BBB.SetWrapperClassId(1);
1061  v8::Persistent<v8::String>::New(v8_str("CCC"));
1062  p_CCC.SetWrapperClassId(2);
1063  CHECK_EQ(0, TestRetainedObjectInfo::instances.length());
1064  const v8::HeapSnapshot* snapshot =
1065  v8::HeapProfiler::TakeSnapshot(v8_str("retained"));
1066 
1067  CHECK_EQ(3, TestRetainedObjectInfo::instances.length());
1068  for (int i = 0; i < TestRetainedObjectInfo::instances.length(); ++i) {
1069  CHECK(TestRetainedObjectInfo::instances[i]->disposed());
1070  delete TestRetainedObjectInfo::instances[i];
1071  }
1072 
1073  const v8::HeapGraphNode* native_group_aaa = GetNode(
1074  snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "aaa-group");
1075  CHECK_NE(NULL, native_group_aaa);
1076  CHECK_EQ(1, native_group_aaa->GetChildrenCount());
1077  const v8::HeapGraphNode* aaa = GetNode(
1078  native_group_aaa, v8::HeapGraphNode::kNative, "aaa / 100 entries");
1079  CHECK_NE(NULL, aaa);
1080  CHECK_EQ(2, aaa->GetChildrenCount());
1081 
1082  const v8::HeapGraphNode* native_group_ccc = GetNode(
1083  snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "ccc-group");
1084  const v8::HeapGraphNode* ccc = GetNode(
1085  native_group_ccc, v8::HeapGraphNode::kNative, "ccc");
1086  CHECK_NE(NULL, ccc);
1087 
1088  const v8::HeapGraphNode* n_AAA = GetNode(
1089  aaa, v8::HeapGraphNode::kString, "AAA");
1090  CHECK_NE(NULL, n_AAA);
1091  const v8::HeapGraphNode* n_BBB = GetNode(
1092  aaa, v8::HeapGraphNode::kString, "BBB");
1093  CHECK_NE(NULL, n_BBB);
1094  CHECK_EQ(1, ccc->GetChildrenCount());
1095  const v8::HeapGraphNode* n_CCC = GetNode(
1096  ccc, v8::HeapGraphNode::kString, "CCC");
1097  CHECK_NE(NULL, n_CCC);
1098 
1099  CHECK_EQ(aaa, GetProperty(n_AAA, v8::HeapGraphEdge::kInternal, "native"));
1100  CHECK_EQ(aaa, GetProperty(n_BBB, v8::HeapGraphEdge::kInternal, "native"));
1101  CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "native"));
1102 }
1103 
1104 
1106  public:
1107  static const int kObjectsCount = 4;
1109  CHECK_EQ(NULL, instance_);
1110  instance_ = this;
1111  for (int i = 0; i < kObjectsCount; i++) {
1113  }
1114  (*env)->Global()->Set(v8_str("root_object"), objects_[0]);
1115  }
1117  instance_ = NULL;
1118  }
1119 
1120  static void gcPrologue() {
1121  instance_->AddImplicitReferences();
1122  }
1123 
1124  private:
1125  void AddImplicitReferences() {
1126  // 0 -> 1
1128  v8::Persistent<v8::Object>::Cast(objects_[0]), &objects_[1], 1);
1129  // Adding two more references(note length=2 in params): 1 -> 2, 1 -> 3
1131  v8::Persistent<v8::Object>::Cast(objects_[1]), &objects_[2], 2);
1132  }
1133 
1135  static GraphWithImplicitRefs* instance_;
1136 };
1137 
1138 GraphWithImplicitRefs* GraphWithImplicitRefs::instance_ = NULL;
1139 
1140 
1141 TEST(HeapSnapshotImplicitReferences) {
1142  v8::HandleScope scope;
1143  LocalContext env;
1144 
1145  GraphWithImplicitRefs graph(&env);
1147 
1148  const v8::HeapSnapshot* snapshot =
1149  v8::HeapProfiler::TakeSnapshot(v8_str("implicit_refs"));
1150 
1151  const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot);
1152  const v8::HeapGraphNode* obj0 = GetProperty(
1153  global_object, v8::HeapGraphEdge::kProperty, "root_object");
1154  CHECK(obj0);
1156  const v8::HeapGraphNode* obj1 = GetProperty(
1157  obj0, v8::HeapGraphEdge::kInternal, "native");
1158  CHECK(obj1);
1159  int implicit_targets_count = 0;
1160  for (int i = 0, count = obj1->GetChildrenCount(); i < count; ++i) {
1161  const v8::HeapGraphEdge* prop = obj1->GetChild(i);
1162  v8::String::AsciiValue prop_name(prop->GetName());
1163  if (prop->GetType() == v8::HeapGraphEdge::kInternal &&
1164  strcmp("native", *prop_name) == 0) {
1165  ++implicit_targets_count;
1166  }
1167  }
1168  CHECK_EQ(2, implicit_targets_count);
1170 }
1171 
1172 
1173 TEST(DeleteAllHeapSnapshots) {
1174  v8::HandleScope scope;
1175  LocalContext env;
1176 
1189 }
1190 
1191 
1192 TEST(DeleteHeapSnapshot) {
1193  v8::HandleScope scope;
1194  LocalContext env;
1195 
1197  const v8::HeapSnapshot* s1 =
1198  v8::HeapProfiler::TakeSnapshot(v8_str("1"));
1199  CHECK_NE(NULL, s1);
1201  unsigned uid1 = s1->GetUid();
1203  const_cast<v8::HeapSnapshot*>(s1)->Delete();
1206 
1207  const v8::HeapSnapshot* s2 =
1208  v8::HeapProfiler::TakeSnapshot(v8_str("2"));
1209  CHECK_NE(NULL, s2);
1211  unsigned uid2 = s2->GetUid();
1212  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
1214  const v8::HeapSnapshot* s3 =
1215  v8::HeapProfiler::TakeSnapshot(v8_str("3"));
1216  CHECK_NE(NULL, s3);
1218  unsigned uid3 = s3->GetUid();
1219  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
1221  const_cast<v8::HeapSnapshot*>(s2)->Delete();
1225  const_cast<v8::HeapSnapshot*>(s3)->Delete();
1228 }
1229 
1230 
1231 TEST(DocumentURL) {
1232  v8::HandleScope scope;
1233  LocalContext env;
1234 
1235  CompileRun("document = { URL:\"abcdefgh\" };");
1236 
1237  const v8::HeapSnapshot* snapshot =
1238  v8::HeapProfiler::TakeSnapshot(v8_str("document"));
1239  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1240  CHECK_NE(NULL, global);
1241  CHECK_EQ("Object / abcdefgh",
1242  const_cast<i::HeapEntry*>(
1243  reinterpret_cast<const i::HeapEntry*>(global))->name());
1244 }
1245 
1246 
1247 TEST(DocumentWithException) {
1248  v8::HandleScope scope;
1249  LocalContext env;
1250 
1251  CompileRun(
1252  "this.__defineGetter__(\"document\", function() { throw new Error(); })");
1253  const v8::HeapSnapshot* snapshot =
1254  v8::HeapProfiler::TakeSnapshot(v8_str("document"));
1255  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1256  CHECK_NE(NULL, global);
1257  CHECK_EQ("Object",
1258  const_cast<i::HeapEntry*>(
1259  reinterpret_cast<const i::HeapEntry*>(global))->name());
1260 }
1261 
1262 
1263 TEST(DocumentURLWithException) {
1264  v8::HandleScope scope;
1265  LocalContext env;
1266 
1267  CompileRun(
1268  "function URLWithException() {}\n"
1269  "URLWithException.prototype = { get URL() { throw new Error(); } };\n"
1270  "document = { URL: new URLWithException() };");
1271  const v8::HeapSnapshot* snapshot =
1272  v8::HeapProfiler::TakeSnapshot(v8_str("document"));
1273  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1274  CHECK_NE(NULL, global);
1275  CHECK_EQ("Object",
1276  const_cast<i::HeapEntry*>(
1277  reinterpret_cast<const i::HeapEntry*>(global))->name());
1278 }
1279 
1280 
1281 TEST(NoHandleLeaks) {
1282  v8::HandleScope scope;
1283  LocalContext env;
1284 
1285  CompileRun("document = { URL:\"abcdefgh\" };");
1286 
1287  v8::Handle<v8::String> name(v8_str("leakz"));
1288  int count_before = i::HandleScope::NumberOfHandles();
1290  int count_after = i::HandleScope::NumberOfHandles();
1291  CHECK_EQ(count_before, count_after);
1292 }
1293 
1294 
1295 TEST(NodesIteration) {
1296  v8::HandleScope scope;
1297  LocalContext env;
1298  const v8::HeapSnapshot* snapshot =
1299  v8::HeapProfiler::TakeSnapshot(v8_str("iteration"));
1300  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1301  CHECK_NE(NULL, global);
1302  // Verify that we can find this object by iteration.
1303  const int nodes_count = snapshot->GetNodesCount();
1304  int count = 0;
1305  for (int i = 0; i < nodes_count; ++i) {
1306  if (snapshot->GetNode(i) == global)
1307  ++count;
1308  }
1309  CHECK_EQ(1, count);
1310 }
1311 
1312 
1313 TEST(GetHeapValue) {
1314  v8::HandleScope scope;
1315  LocalContext env;
1316 
1317  CompileRun("a = { s_prop: \'value\', n_prop: 0.1 };");
1318  const v8::HeapSnapshot* snapshot =
1319  v8::HeapProfiler::TakeSnapshot(v8_str("value"));
1320  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1321  CHECK(global->GetHeapValue()->IsObject());
1322  v8::Local<v8::Object> js_global =
1323  env->Global()->GetPrototype().As<v8::Object>();
1324  CHECK(js_global == global->GetHeapValue());
1325  const v8::HeapGraphNode* obj = GetProperty(
1326  global, v8::HeapGraphEdge::kProperty, "a");
1327  CHECK(obj->GetHeapValue()->IsObject());
1328  v8::Local<v8::Object> js_obj = js_global->Get(v8_str("a")).As<v8::Object>();
1329  CHECK(js_obj == obj->GetHeapValue());
1330  const v8::HeapGraphNode* s_prop =
1331  GetProperty(obj, v8::HeapGraphEdge::kProperty, "s_prop");
1332  v8::Local<v8::String> js_s_prop =
1333  js_obj->Get(v8_str("s_prop")).As<v8::String>();
1334  CHECK(js_s_prop == s_prop->GetHeapValue());
1335  const v8::HeapGraphNode* n_prop =
1336  GetProperty(obj, v8::HeapGraphEdge::kProperty, "n_prop");
1337  v8::Local<v8::Number> js_n_prop =
1338  js_obj->Get(v8_str("n_prop")).As<v8::Number>();
1339  CHECK(js_n_prop == n_prop->GetHeapValue());
1340 }
1341 
1342 
1343 TEST(GetHeapValueForDeletedObject) {
1344  v8::HandleScope scope;
1345  LocalContext env;
1346 
1347  // It is impossible to delete a global property, so we are about to delete a
1348  // property of the "a" object. Also, the "p" object can't be an empty one
1349  // because the empty object is static and isn't actually deleted.
1350  CompileRun("a = { p: { r: {} } };");
1351  const v8::HeapSnapshot* snapshot =
1352  v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
1353  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1354  const v8::HeapGraphNode* obj = GetProperty(
1355  global, v8::HeapGraphEdge::kProperty, "a");
1356  const v8::HeapGraphNode* prop = GetProperty(
1357  obj, v8::HeapGraphEdge::kProperty, "p");
1358  {
1359  // Perform the check inside a nested local scope to avoid creating a
1360  // reference to the object we are deleting.
1361  v8::HandleScope scope;
1362  CHECK(prop->GetHeapValue()->IsObject());
1363  }
1364  CompileRun("delete a.p;");
1365  CHECK(prop->GetHeapValue()->IsUndefined());
1366 }
1367 
1368 
1369 static int StringCmp(const char* ref, i::String* act) {
1370  i::SmartArrayPointer<char> s_act = act->ToCString();
1371  int result = strcmp(ref, *s_act);
1372  if (result != 0)
1373  fprintf(stderr, "Expected: \"%s\", Actual: \"%s\"\n", ref, *s_act);
1374  return result;
1375 }
1376 
1377 
1378 TEST(GetConstructorName) {
1379  v8::HandleScope scope;
1380  LocalContext env;
1381 
1382  CompileRun(
1383  "function Constructor1() {};\n"
1384  "var obj1 = new Constructor1();\n"
1385  "var Constructor2 = function() {};\n"
1386  "var obj2 = new Constructor2();\n"
1387  "var obj3 = {};\n"
1388  "obj3.constructor = function Constructor3() {};\n"
1389  "var obj4 = {};\n"
1390  "// Slow properties\n"
1391  "for (var i=0; i<2000; ++i) obj4[\"p\" + i] = i;\n"
1392  "obj4.constructor = function Constructor4() {};\n"
1393  "var obj5 = {};\n"
1394  "var obj6 = {};\n"
1395  "obj6.constructor = 6;");
1396  v8::Local<v8::Object> js_global =
1397  env->Global()->GetPrototype().As<v8::Object>();
1398  v8::Local<v8::Object> obj1 = js_global->Get(v8_str("obj1")).As<v8::Object>();
1400  CHECK_EQ(0, StringCmp(
1401  "Constructor1", i::V8HeapExplorer::GetConstructorName(*js_obj1)));
1402  v8::Local<v8::Object> obj2 = js_global->Get(v8_str("obj2")).As<v8::Object>();
1404  CHECK_EQ(0, StringCmp(
1405  "Constructor2", i::V8HeapExplorer::GetConstructorName(*js_obj2)));
1406  v8::Local<v8::Object> obj3 = js_global->Get(v8_str("obj3")).As<v8::Object>();
1408  CHECK_EQ(0, StringCmp(
1409  "Constructor3", i::V8HeapExplorer::GetConstructorName(*js_obj3)));
1410  v8::Local<v8::Object> obj4 = js_global->Get(v8_str("obj4")).As<v8::Object>();
1412  CHECK_EQ(0, StringCmp(
1413  "Constructor4", i::V8HeapExplorer::GetConstructorName(*js_obj4)));
1414  v8::Local<v8::Object> obj5 = js_global->Get(v8_str("obj5")).As<v8::Object>();
1416  CHECK_EQ(0, StringCmp(
1417  "Object", i::V8HeapExplorer::GetConstructorName(*js_obj5)));
1418  v8::Local<v8::Object> obj6 = js_global->Get(v8_str("obj6")).As<v8::Object>();
1420  CHECK_EQ(0, StringCmp(
1421  "Object", i::V8HeapExplorer::GetConstructorName(*js_obj6)));
1422 }
1423 
1424 
1425 TEST(FastCaseGetter) {
1426  v8::HandleScope scope;
1427  LocalContext env;
1428 
1429  CompileRun("var obj1 = {};\n"
1430  "obj1.__defineGetter__('propWithGetter', function Y() {\n"
1431  " return 42;\n"
1432  "});\n"
1433  "obj1.__defineSetter__('propWithSetter', function Z(value) {\n"
1434  " return this.value_ = value;\n"
1435  "});\n");
1436  const v8::HeapSnapshot* snapshot =
1437  v8::HeapProfiler::TakeSnapshot(v8_str("fastCaseGetter"));
1438 
1439  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1440  CHECK_NE(NULL, global);
1441  const v8::HeapGraphNode* obj1 =
1442  GetProperty(global, v8::HeapGraphEdge::kProperty, "obj1");
1443  CHECK_NE(NULL, obj1);
1444  const v8::HeapGraphNode* getterFunction =
1445  GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter");
1446  CHECK_NE(NULL, getterFunction);
1447  const v8::HeapGraphNode* setterFunction =
1448  GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set-propWithSetter");
1449  CHECK_NE(NULL, setterFunction);
1450 }
1451 
1452 
1453 bool HasWeakEdge(const v8::HeapGraphNode* node) {
1454  for (int i = 0; i < node->GetChildrenCount(); ++i) {
1455  const v8::HeapGraphEdge* handle_edge = node->GetChild(i);
1456  if (handle_edge->GetType() == v8::HeapGraphEdge::kWeak) return true;
1457  }
1458  return false;
1459 }
1460 
1461 
1463  const v8::HeapSnapshot* snapshot =
1464  v8::HeapProfiler::TakeSnapshot(v8_str("weaks"));
1465  const v8::HeapGraphNode* gc_roots = GetNode(
1466  snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)");
1467  CHECK_NE(NULL, gc_roots);
1468  const v8::HeapGraphNode* global_handles = GetNode(
1469  gc_roots, v8::HeapGraphNode::kObject, "(Global handles)");
1470  CHECK_NE(NULL, global_handles);
1471  return HasWeakEdge(global_handles);
1472 }
1473 
1474 
1475 static void PersistentHandleCallback(v8::Persistent<v8::Value> handle, void*) {
1476  handle.Dispose();
1477 }
1478 
1479 
1480 TEST(WeakGlobalHandle) {
1481  v8::HandleScope scope;
1482  LocalContext env;
1483 
1485 
1488  handle.MakeWeak(NULL, PersistentHandleCallback);
1489 
1491 }
1492 
1493 
1494 TEST(WeakGlobalContextRefs) {
1495  v8::HandleScope scope;
1496  LocalContext env;
1497 
1498  const v8::HeapSnapshot* snapshot =
1499  v8::HeapProfiler::TakeSnapshot(v8_str("weaks"));
1500  const v8::HeapGraphNode* gc_roots = GetNode(
1501  snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)");
1502  CHECK_NE(NULL, gc_roots);
1503  const v8::HeapGraphNode* global_handles = GetNode(
1504  gc_roots, v8::HeapGraphNode::kObject, "(Global handles)");
1505  CHECK_NE(NULL, global_handles);
1506  const v8::HeapGraphNode* global_context = GetNode(
1507  global_handles, v8::HeapGraphNode::kHidden, "system / GlobalContext");
1508  CHECK_NE(NULL, global_context);
1509  CHECK(HasWeakEdge(global_context));
1510 }
1511 
1512 
1513 TEST(SfiAndJsFunctionWeakRefs) {
1514  v8::HandleScope scope;
1515  LocalContext env;
1516 
1517  CompileRun(
1518  "fun = (function (x) { return function () { return x + 1; } })(1);");
1519  const v8::HeapSnapshot* snapshot =
1520  v8::HeapProfiler::TakeSnapshot(v8_str("fun"));
1521  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1522  CHECK_NE(NULL, global);
1523  const v8::HeapGraphNode* fun =
1524  GetProperty(global, v8::HeapGraphEdge::kProperty, "fun");
1525  CHECK(HasWeakEdge(fun));
1526  const v8::HeapGraphNode* shared =
1527  GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared");
1528  CHECK(HasWeakEdge(shared));
1529 }
1530 
1531 
1532 TEST(NoDebugObjectInSnapshot) {
1533  v8::HandleScope scope;
1534  LocalContext env;
1535 
1536  v8::internal::Isolate::Current()->debug()->Load();
1537  CompileRun("foo = {};");
1538  const v8::HeapSnapshot* snapshot =
1539  v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
1540  const v8::HeapGraphNode* root = snapshot->GetRoot();
1541  int globals_count = 0;
1542  for (int i = 0; i < root->GetChildrenCount(); ++i) {
1543  const v8::HeapGraphEdge* edge = root->GetChild(i);
1544  if (edge->GetType() == v8::HeapGraphEdge::kShortcut) {
1545  ++globals_count;
1546  const v8::HeapGraphNode* global = edge->GetToNode();
1547  const v8::HeapGraphNode* foo =
1548  GetProperty(global, v8::HeapGraphEdge::kProperty, "foo");
1549  CHECK_NE(NULL, foo);
1550  }
1551  }
1552  CHECK_EQ(1, globals_count);
1553 }
1554 
1555 
1556 TEST(PersistentHandleCount) {
1557  v8::HandleScope scope;
1558  LocalContext env;
1559 
1560  // V8 also uses global handles internally, so we can't test for an absolute
1561  // number.
1562  int global_handle_count = v8::HeapProfiler::GetPersistentHandleCount();
1563 
1564  // Create some persistent handles.
1566  v8::Persistent<v8::String>::New(v8_str("AAA"));
1567  CHECK_EQ(global_handle_count + 1,
1570  v8::Persistent<v8::String>::New(v8_str("BBB"));
1571  CHECK_EQ(global_handle_count + 2,
1574  v8::Persistent<v8::String>::New(v8_str("CCC"));
1575  CHECK_EQ(global_handle_count + 3,
1577 
1578  // Dipose the persistent handles in a different order.
1579  p_AAA.Dispose();
1580  CHECK_EQ(global_handle_count + 2,
1582  p_CCC.Dispose();
1583  CHECK_EQ(global_handle_count + 1,
1585  p_BBB.Dispose();
1586  CHECK_EQ(global_handle_count, v8::HeapProfiler::GetPersistentHandleCount());
1587 }
1588 
1589 
1590 TEST(AllStrongGcRootsHaveNames) {
1591  v8::HandleScope scope;
1592  LocalContext env;
1593 
1594  CompileRun("foo = {};");
1595  const v8::HeapSnapshot* snapshot =
1596  v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
1597  const v8::HeapGraphNode* gc_roots = GetNode(
1598  snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)");
1599  CHECK_NE(NULL, gc_roots);
1600  const v8::HeapGraphNode* strong_roots = GetNode(
1601  gc_roots, v8::HeapGraphNode::kObject, "(Strong roots)");
1602  CHECK_NE(NULL, strong_roots);
1603  for (int i = 0; i < strong_roots->GetChildrenCount(); ++i) {
1604  const v8::HeapGraphEdge* edge = strong_roots->GetChild(i);
1607  CHECK(isalpha(**name));
1608  }
1609 }
1610 
1611 
1612 TEST(NoRefsToNonEssentialEntries) {
1613  v8::HandleScope scope;
1614  LocalContext env;
1615  CompileRun("global_object = {};\n");
1616  const v8::HeapSnapshot* snapshot =
1617  v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
1618  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1619  const v8::HeapGraphNode* global_object =
1620  GetProperty(global, v8::HeapGraphEdge::kProperty, "global_object");
1621  CHECK_NE(NULL, global_object);
1622  const v8::HeapGraphNode* properties =
1623  GetProperty(global_object, v8::HeapGraphEdge::kInternal, "properties");
1624  CHECK_EQ(NULL, properties);
1625  const v8::HeapGraphNode* elements =
1626  GetProperty(global_object, v8::HeapGraphEdge::kInternal, "elements");
1627  CHECK_EQ(NULL, elements);
1628 }
void MakeWeak(void *parameters, WeakReferenceCallback callback)
Definition: v8.h:4075
const SwVfpRegister s2
static void DeleteAllSnapshots()
Definition: api.cc:6253
Local< S > As()
Definition: v8.h:290
const HeapGraphEdge * GetChild(int index) const
Definition: api.cc:6069
static int NumberOfHandles()
Definition: handles.cc:48
#define CHECK_EQ(expected, value)
Definition: checks.h:219
static const HeapSnapshot * TakeSnapshot(Handle< String > title, HeapSnapshot::Type type=HeapSnapshot::kFull, ActivityControl *control=NULL)
Definition: api.cc:6213
void Dispose()
Definition: v8.h:4065
const HeapGraphNode * GetFromNode() const
Definition: api.cc:6011
virtual intptr_t GetHash()=0
V8EXPORT Local< Value > Get(Handle< Value > key)
Definition: api.cc:2845
#define CHECK_GT(a, b)
Definition: checks.h:227
Handle< Value > GetName() const
Definition: api.cc:5990
GraphWithImplicitRefs(LocalContext *env)
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
Definition: flags.cc:1349
Handle< String > GetName() const
Definition: api.cc:6040
SnapshotObjectId GetId() const
Definition: api.cc:6048
static V8EXPORT Local< String > New(const char *data, int length=-1)
Definition: api.cc:4655
const HeapGraphNode * GetNodeById(SnapshotObjectId id) const
Definition: api.cc:6134
const HeapGraphNode * GetNode(int index) const
Definition: api.cc:6149
#define CHECK_LT(a, b)
Definition: checks.h:229
#define ASSERT(condition)
Definition: checks.h:270
V8EXPORT Local< Number > ToNumber() const
Definition: api.cc:2382
static int GetSnapshotsCount()
Definition: api.cc:6182
unsigned short uint16_t
Definition: unicode.cc:46
int GetSelfSize() const
Definition: api.cc:6055
static void DefineWrapperClass(uint16_t class_id, WrapperInfoCallback callback)
Definition: api.cc:6260
Type GetType() const
Definition: api.cc:5983
#define CHECK(condition)
Definition: checks.h:56
AsciiResource(Vector< const char > string)
Definition: test-strings.cc:69
StringInputBuffer *const buffer_
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:282
virtual ControlOption ReportProgressValue(int done, int total)=0
V8EXPORT void SetInternalField(int index, Handle< Value > value)
Definition: api.cc:4150
int foo
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
Definition: objects.cc:6161
const SwVfpRegister s3
V8EXPORT int InternalFieldCount()
Definition: api.cc:4121
int GetChildrenCount() const
Definition: api.cc:6062
virtual bool IsEquivalent(RetainedObjectInfo *other)=0
T * start() const
Definition: utils.h:389
static const HeapSnapshot * FindSnapshot(unsigned uid)
Definition: api.cc:6197
static Local< ObjectTemplate > New()
Definition: api.cc:1246
static void StopHeapObjectsTracking()
Definition: api.cc:6239
SnapshotObjectId GetMaxSnapshotJSObjectId() const
Definition: api.cc:6157
V8EXPORT Local< Value > GetPrototype()
Definition: api.cc:2892
static String * GetConstructorName(JSObject *object)
virtual const char * GetLabel()=0
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
static const int kNoGCFlags
Definition: heap.h:1049
void SetInternalFieldCount(int value)
Definition: api.cc:1431
static SnapshotObjectId PushHeapObjectsStats(OutputStream *stream)
Definition: api.cc:6246
virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate *data, int count)
Definition: v8.h:3814
Local< Object > Global()
Definition: api.cc:4467
TEST(HeapSnapshot)
int length() const
Definition: utils.h:383
#define STRING_LITERAL_FOR_TEST
void SetWrapperClassId(uint16_t class_id)
Definition: v8.h:4092
static Persistent< T > New(Handle< T > that)
Definition: v8.h:4043
static const int kObjectsCount
bool IsUndefined() const
Definition: v8.h:4277
#define CHECK_NE(unexpected, value)
Definition: checks.h:223
bool IsString() const
Definition: v8.h:4313
const SwVfpRegister s1
V8EXPORT bool IsObject() const
Definition: api.cc:2169
virtual WriteResult WriteAsciiChunk(char *data, int size)=0
virtual size_t length() const =0
virtual void Dispose()=0
List< HeapEntry * > * GetSortedEntriesList()
uint32_t SnapshotObjectId
Definition: v8-profiler.h:67
int GetNodesCount() const
Definition: api.cc:6142
virtual const char * data() const =0
const HeapGraphNode * GetRoot() const
Definition: api.cc:6127
#define HEAP
Definition: isolate.h:1408
virtual intptr_t GetElementCount()
Definition: v8-profiler.h:550
static void SetGlobalGCPrologueCallback(GCCallback)
Definition: api.cc:5245
bool IsEmpty() const
Definition: v8.h:208
static int GetPersistentHandleCount()
Definition: api.cc:6267
Handle< Value > GetHeapValue() const
Definition: api.cc:6077
bool HasWeakEdge(const v8::HeapGraphNode *node)
Type GetType() const
Definition: api.cc:6033
V8EXPORT uint32_t Length() const
Definition: api.cc:5040
virtual void EndOfStream()=0
static void StartHeapObjectsTracking()
Definition: api.cc:6232
#define CHECK_NE_SNAPSHOT_OBJECT_ID(a, b)
unsigned GetUid() const
Definition: api.cc:6112
static V8EXPORT Local< String > NewExternal(ExternalStringResource *resource)
Definition: api.cc:4747
#define CHECK_EQ_SNAPSHOT_OBJECT_ID(a, b)
virtual intptr_t GetSizeInBytes()
Definition: v8-profiler.h:553
static SnapshotObjectId GetSnapshotObjectId(Handle< Value > value)
Definition: api.cc:6205
const HeapGraphNode * GetToNode() const
Definition: api.cc:6019
bool HasWeakGlobalHandle()
Definition: v8.h:105
void Serialize(OutputStream *stream, SerializationFormat format) const
Definition: api.cc:6164
static void AddImplicitReferences(Persistent< Object > parent, Persistent< Value > *children, size_t length)
Definition: api.cc:5223
virtual const char * GetGroupLabel()
Definition: v8-profiler.h:544
FlagType type() const
Definition: flags.cc:1358
static V8EXPORT Local< Object > New()
Definition: api.cc:4829
static v8::internal::Handle< v8::internal::TemplateInfo > OpenHandle(const Template *that)
static const SnapshotObjectId kUnknownObjectId
Definition: v8-profiler.h:426
V8EXPORT bool Set(Handle< Value > key, Handle< Value > value, PropertyAttribute attribs=None)
Definition: api.cc:2757