v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-cpu-profiler.cc
Go to the documentation of this file.
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // Tests of profiles generator and utilities.
29 
30 #include "v8.h"
31 #include "cpu-profiler-inl.h"
32 #include "cctest.h"
33 #include "platform.h"
34 #include "profiler-extension.h"
35 #include "smart-pointers.h"
36 #include "utils.h"
37 #include "../include/v8-profiler.h"
38 using i::CodeEntry;
39 using i::CpuProfile;
40 using i::CpuProfiler;
42 using i::Heap;
44 using i::ProfileNode;
46 using i::ScopedVector;
47 using i::SmartPointer;
48 using i::TimeDelta;
49 using i::Vector;
50 
51 
52 TEST(StartStop) {
53  i::Isolate* isolate = CcTest::i_isolate();
54  CpuProfilesCollection profiles(isolate->heap());
55  ProfileGenerator generator(&profiles);
56  SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
57  &generator, NULL, TimeDelta::FromMicroseconds(100)));
58  processor->Start();
59  processor->StopSynchronously();
60 }
61 
62 
63 static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
64  i::Address frame1,
65  i::Address frame2 = NULL,
66  i::Address frame3 = NULL) {
67  i::TickSample* sample = proc->StartTickSample();
68  sample->pc = frame1;
69  sample->tos = frame1;
70  sample->frames_count = 0;
71  if (frame2 != NULL) {
72  sample->stack[0] = frame2;
73  sample->frames_count = 1;
74  }
75  if (frame3 != NULL) {
76  sample->stack[1] = frame3;
77  sample->frames_count = 2;
78  }
79  proc->FinishTickSample();
80 }
81 
82 namespace {
83 
84 class TestSetup {
85  public:
86  TestSetup()
87  : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
88  i::FLAG_prof_browser_mode = false;
89  }
90 
91  ~TestSetup() {
92  i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
93  }
94 
95  private:
96  bool old_flag_prof_browser_mode_;
97 };
98 
99 } // namespace
100 
101 
103  static int counter = 0;
106 
107  i::OS::SNPrintF(name, "function_%d", ++counter);
108  const char* name_start = name.start();
109  i::OS::SNPrintF(script,
110  "function %s() {\n"
111  "var counter = 0;\n"
112  "for (var i = 0; i < %d; ++i) counter += i;\n"
113  "return '%s_' + counter;\n"
114  "}\n"
115  "%s();\n", name_start, counter, name_start, name_start);
116  CompileRun(script.start());
119  (*env)->Global()->Get(v8_str(name_start))));
120  return fun->code();
121 }
122 
123 
124 TEST(CodeEvents) {
126  LocalContext env;
127  i::Isolate* isolate = CcTest::i_isolate();
128  i::Factory* factory = isolate->factory();
129  TestSetup test_setup;
130 
131  i::HandleScope scope(isolate);
132 
133  i::Code* aaa_code = CreateCode(&env);
134  i::Code* comment_code = CreateCode(&env);
135  i::Code* args5_code = CreateCode(&env);
136  i::Code* comment2_code = CreateCode(&env);
137  i::Code* moved_code = CreateCode(&env);
138  i::Code* args3_code = CreateCode(&env);
139  i::Code* args4_code = CreateCode(&env);
140 
141  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
142  profiles->StartProfiling("", false);
143  ProfileGenerator generator(profiles);
144  SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
145  &generator, NULL, TimeDelta::FromMicroseconds(100)));
146  processor->Start();
147  CpuProfiler profiler(isolate, profiles, &generator, processor.get());
148 
149  // Enqueue code creation events.
150  const char* aaa_str = "aaa";
151  i::Handle<i::String> aaa_name = factory->NewStringFromAscii(
152  i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
153  profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG, aaa_code, *aaa_name);
154  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment_code, "comment");
155  profiler.CodeCreateEvent(i::Logger::STUB_TAG, args5_code, 5);
156  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment2_code, "comment2");
157  profiler.CodeMoveEvent(comment2_code->address(), moved_code->address());
158  profiler.CodeCreateEvent(i::Logger::STUB_TAG, args3_code, 3);
159  profiler.CodeCreateEvent(i::Logger::STUB_TAG, args4_code, 4);
160 
161  // Enqueue a tick event to enable code events processing.
162  EnqueueTickSampleEvent(processor.get(), aaa_code->address());
163 
164  processor->StopSynchronously();
165 
166  // Check the state of profile generator.
167  CodeEntry* aaa = generator.code_map()->FindEntry(aaa_code->address());
168  CHECK_NE(NULL, aaa);
169  CHECK_EQ(aaa_str, aaa->name());
170 
171  CodeEntry* comment = generator.code_map()->FindEntry(comment_code->address());
172  CHECK_NE(NULL, comment);
173  CHECK_EQ("comment", comment->name());
174 
175  CodeEntry* args5 = generator.code_map()->FindEntry(args5_code->address());
176  CHECK_NE(NULL, args5);
177  CHECK_EQ("5", args5->name());
178 
179  CHECK_EQ(NULL, generator.code_map()->FindEntry(comment2_code->address()));
180 
181  CodeEntry* comment2 = generator.code_map()->FindEntry(moved_code->address());
182  CHECK_NE(NULL, comment2);
183  CHECK_EQ("comment2", comment2->name());
184 }
185 
186 
187 template<typename T>
188 static int CompareProfileNodes(const T* p1, const T* p2) {
189  return strcmp((*p1)->entry()->name(), (*p2)->entry()->name());
190 }
191 
192 
193 TEST(TickEvents) {
194  TestSetup test_setup;
195  LocalContext env;
196  i::Isolate* isolate = CcTest::i_isolate();
197  i::HandleScope scope(isolate);
198 
199  i::Code* frame1_code = CreateCode(&env);
200  i::Code* frame2_code = CreateCode(&env);
201  i::Code* frame3_code = CreateCode(&env);
202 
203  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
204  profiles->StartProfiling("", false);
205  ProfileGenerator generator(profiles);
206  SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
207  &generator, NULL, TimeDelta::FromMicroseconds(100)));
208  processor->Start();
209  CpuProfiler profiler(isolate, profiles, &generator, processor.get());
210 
211  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb");
212  profiler.CodeCreateEvent(i::Logger::STUB_TAG, frame2_code, 5);
213  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame3_code, "ddd");
214 
215  EnqueueTickSampleEvent(processor.get(), frame1_code->instruction_start());
216  EnqueueTickSampleEvent(
217  processor.get(),
218  frame2_code->instruction_start() + frame2_code->ExecutableSize() / 2,
219  frame1_code->instruction_start() + frame2_code->ExecutableSize() / 2);
220  EnqueueTickSampleEvent(
221  processor.get(),
222  frame3_code->instruction_end() - 1,
223  frame2_code->instruction_end() - 1,
224  frame1_code->instruction_end() - 1);
225 
226  processor->StopSynchronously();
227  CpuProfile* profile = profiles->StopProfiling("");
228  CHECK_NE(NULL, profile);
229 
230  // Check call trees.
231  const i::List<ProfileNode*>* top_down_root_children =
232  profile->top_down()->root()->children();
233  CHECK_EQ(1, top_down_root_children->length());
234  CHECK_EQ("bbb", top_down_root_children->last()->entry()->name());
235  const i::List<ProfileNode*>* top_down_bbb_children =
236  top_down_root_children->last()->children();
237  CHECK_EQ(1, top_down_bbb_children->length());
238  CHECK_EQ("5", top_down_bbb_children->last()->entry()->name());
239  const i::List<ProfileNode*>* top_down_stub_children =
240  top_down_bbb_children->last()->children();
241  CHECK_EQ(1, top_down_stub_children->length());
242  CHECK_EQ("ddd", top_down_stub_children->last()->entry()->name());
243  const i::List<ProfileNode*>* top_down_ddd_children =
244  top_down_stub_children->last()->children();
245  CHECK_EQ(0, top_down_ddd_children->length());
246 }
247 
248 
249 // http://crbug/51594
250 // This test must not crash.
251 TEST(CrashIfStoppingLastNonExistentProfile) {
253  TestSetup test_setup;
254  CpuProfiler* profiler = CcTest::i_isolate()->cpu_profiler();
255  profiler->StartProfiling("1");
256  profiler->StopProfiling("2");
257  profiler->StartProfiling("1");
258  profiler->StopProfiling("");
259 }
260 
261 
262 // http://code.google.com/p/v8/issues/detail?id=1398
263 // Long stacks (exceeding max frames limit) must not be erased.
264 TEST(Issue1398) {
265  TestSetup test_setup;
266  LocalContext env;
267  i::Isolate* isolate = CcTest::i_isolate();
268  i::HandleScope scope(isolate);
269 
270  i::Code* code = CreateCode(&env);
271 
272  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
273  profiles->StartProfiling("", false);
274  ProfileGenerator generator(profiles);
275  SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
276  &generator, NULL, TimeDelta::FromMicroseconds(100)));
277  processor->Start();
278  CpuProfiler profiler(isolate, profiles, &generator, processor.get());
279 
280  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb");
281 
282  i::TickSample* sample = processor->StartTickSample();
283  sample->pc = code->address();
284  sample->tos = 0;
286  for (int i = 0; i < sample->frames_count; ++i) {
287  sample->stack[i] = code->address();
288  }
289  processor->FinishTickSample();
290 
291  processor->StopSynchronously();
292  CpuProfile* profile = profiles->StopProfiling("");
293  CHECK_NE(NULL, profile);
294 
295  int actual_depth = 0;
296  const ProfileNode* node = profile->top_down()->root();
297  while (node->children()->length() > 0) {
298  node = node->children()->last();
299  ++actual_depth;
300  }
301 
302  CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth); // +1 for PC.
303 }
304 
305 
306 TEST(DeleteAllCpuProfiles) {
308  TestSetup test_setup;
309  CpuProfiler* profiler = CcTest::i_isolate()->cpu_profiler();
310  CHECK_EQ(0, profiler->GetProfilesCount());
311  profiler->DeleteAllProfiles();
312  CHECK_EQ(0, profiler->GetProfilesCount());
313 
314  profiler->StartProfiling("1");
315  profiler->StopProfiling("1");
316  CHECK_EQ(1, profiler->GetProfilesCount());
317  profiler->DeleteAllProfiles();
318  CHECK_EQ(0, profiler->GetProfilesCount());
319  profiler->StartProfiling("1");
320  profiler->StartProfiling("2");
321  profiler->StopProfiling("2");
322  profiler->StopProfiling("1");
323  CHECK_EQ(2, profiler->GetProfilesCount());
324  profiler->DeleteAllProfiles();
325  CHECK_EQ(0, profiler->GetProfilesCount());
326 
327  // Test profiling cancellation by the 'delete' command.
328  profiler->StartProfiling("1");
329  profiler->StartProfiling("2");
330  CHECK_EQ(0, profiler->GetProfilesCount());
331  profiler->DeleteAllProfiles();
332  CHECK_EQ(0, profiler->GetProfilesCount());
333 }
334 
335 
336 static bool FindCpuProfile(v8::CpuProfiler* v8profiler,
337  const v8::CpuProfile* v8profile) {
338  i::CpuProfiler* profiler = reinterpret_cast<i::CpuProfiler*>(v8profiler);
339  const i::CpuProfile* profile =
340  reinterpret_cast<const i::CpuProfile*>(v8profile);
341  int length = profiler->GetProfilesCount();
342  for (int i = 0; i < length; i++) {
343  if (profile == profiler->GetProfile(i))
344  return true;
345  }
346  return false;
347 }
348 
349 
350 TEST(DeleteCpuProfile) {
351  LocalContext env;
352  v8::HandleScope scope(env->GetIsolate());
353  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
354  i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(cpu_profiler);
355 
356  CHECK_EQ(0, iprofiler->GetProfilesCount());
358  cpu_profiler->StartCpuProfiling(name1);
359  const v8::CpuProfile* p1 = cpu_profiler->StopCpuProfiling(name1);
360  CHECK_NE(NULL, p1);
361  CHECK_EQ(1, iprofiler->GetProfilesCount());
362  CHECK(FindCpuProfile(cpu_profiler, p1));
363  const_cast<v8::CpuProfile*>(p1)->Delete();
364  CHECK_EQ(0, iprofiler->GetProfilesCount());
365 
367  cpu_profiler->StartCpuProfiling(name2);
368  const v8::CpuProfile* p2 = cpu_profiler->StopCpuProfiling(name2);
369  CHECK_NE(NULL, p2);
370  CHECK_EQ(1, iprofiler->GetProfilesCount());
371  CHECK(FindCpuProfile(cpu_profiler, p2));
373  cpu_profiler->StartCpuProfiling(name3);
374  const v8::CpuProfile* p3 = cpu_profiler->StopCpuProfiling(name3);
375  CHECK_NE(NULL, p3);
376  CHECK_EQ(2, iprofiler->GetProfilesCount());
377  CHECK_NE(p2, p3);
378  CHECK(FindCpuProfile(cpu_profiler, p3));
379  CHECK(FindCpuProfile(cpu_profiler, p2));
380  const_cast<v8::CpuProfile*>(p2)->Delete();
381  CHECK_EQ(1, iprofiler->GetProfilesCount());
382  CHECK(!FindCpuProfile(cpu_profiler, p2));
383  CHECK(FindCpuProfile(cpu_profiler, p3));
384  const_cast<v8::CpuProfile*>(p3)->Delete();
385  CHECK_EQ(0, iprofiler->GetProfilesCount());
386 }
387 
388 
389 TEST(ProfileStartEndTime) {
390  LocalContext env;
391  v8::HandleScope scope(env->GetIsolate());
392  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
393 
394  v8::Local<v8::String> profile_name =
395  v8::String::NewFromUtf8(env->GetIsolate(), "test");
396  cpu_profiler->StartCpuProfiling(profile_name);
397  const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name);
398  CHECK(profile->GetStartTime() <= profile->GetEndTime());
399 }
400 
401 
402 static const v8::CpuProfile* RunProfiler(
404  v8::Handle<v8::Value> argv[], int argc,
405  unsigned min_js_samples) {
406  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
407  v8::Local<v8::String> profile_name =
408  v8::String::NewFromUtf8(env->GetIsolate(), "my_profile");
409 
410  cpu_profiler->StartCpuProfiling(profile_name);
411 
412  i::Sampler* sampler =
413  reinterpret_cast<i::Isolate*>(env->GetIsolate())->logger()->sampler();
414  sampler->StartCountingSamples();
415  do {
416  function->Call(env->Global(), argc, argv);
417  } while (sampler->js_and_external_sample_count() < min_js_samples);
418 
419  const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name);
420 
421  CHECK_NE(NULL, profile);
422  // Dump collected profile to have a better diagnostic in case of failure.
423  reinterpret_cast<i::CpuProfile*>(
424  const_cast<v8::CpuProfile*>(profile))->Print();
425 
426  return profile;
427 }
428 
429 
430 static bool ContainsString(v8::Handle<v8::String> string,
431  const Vector<v8::Handle<v8::String> >& vector) {
432  for (int i = 0; i < vector.length(); i++) {
433  if (string->Equals(vector[i]))
434  return true;
435  }
436  return false;
437 }
438 
439 
440 static void CheckChildrenNames(const v8::CpuProfileNode* node,
441  const Vector<v8::Handle<v8::String> >& names) {
442  int count = node->GetChildrenCount();
443  for (int i = 0; i < count; i++) {
445  CHECK(ContainsString(name, names));
446  // Check that there are no duplicates.
447  for (int j = 0; j < count; j++) {
448  if (j == i) continue;
449  CHECK_NE(name, node->GetChild(j)->GetFunctionName());
450  }
451  }
452 }
453 
454 
455 static const v8::CpuProfileNode* FindChild(v8::Isolate* isolate,
456  const v8::CpuProfileNode* node,
457  const char* name) {
458  int count = node->GetChildrenCount();
459  v8::Handle<v8::String> nameHandle = v8::String::NewFromUtf8(isolate, name);
460  for (int i = 0; i < count; i++) {
461  const v8::CpuProfileNode* child = node->GetChild(i);
462  if (nameHandle->Equals(child->GetFunctionName())) return child;
463  }
464  return NULL;
465 }
466 
467 
468 static const v8::CpuProfileNode* GetChild(v8::Isolate* isolate,
469  const v8::CpuProfileNode* node,
470  const char* name) {
471  const v8::CpuProfileNode* result = FindChild(isolate, node, name);
472  if (!result) {
473  char buffer[100];
474  i::OS::SNPrintF(Vector<char>(buffer, ARRAY_SIZE(buffer)),
475  "Failed to GetChild: %s", name);
476  FATAL(buffer);
477  }
478  return result;
479 }
480 
481 
482 static void CheckSimpleBranch(v8::Isolate* isolate,
483  const v8::CpuProfileNode* node,
484  const char* names[], int length) {
485  for (int i = 0; i < length; i++) {
486  const char* name = names[i];
487  node = GetChild(isolate, node, name);
488  int expectedChildrenCount = (i == length - 1) ? 0 : 1;
489  CHECK_EQ(expectedChildrenCount, node->GetChildrenCount());
490  }
491 }
492 
493 
494 static const char* cpu_profiler_test_source = "function loop(timeout) {\n"
495 " this.mmm = 0;\n"
496 " var start = Date.now();\n"
497 " while (Date.now() - start < timeout) {\n"
498 " var n = 100*1000;\n"
499 " while(n > 1) {\n"
500 " n--;\n"
501 " this.mmm += n * n * n;\n"
502 " }\n"
503 " }\n"
504 "}\n"
505 "function delay() { try { loop(10); } catch(e) { } }\n"
506 "function bar() { delay(); }\n"
507 "function baz() { delay(); }\n"
508 "function foo() {\n"
509 " try {\n"
510 " delay();\n"
511 " bar();\n"
512 " delay();\n"
513 " baz();\n"
514 " } catch (e) { }\n"
515 "}\n"
516 "function start(timeout) {\n"
517 " var start = Date.now();\n"
518 " do {\n"
519 " foo();\n"
520 " var duration = Date.now() - start;\n"
521 " } while (duration < timeout);\n"
522 " return duration;\n"
523 "}\n";
524 
525 
526 // Check that the profile tree for the script above will look like the
527 // following:
528 //
529 // [Top down]:
530 // 1062 0 (root) [-1]
531 // 1054 0 start [-1]
532 // 1054 1 foo [-1]
533 // 265 0 baz [-1]
534 // 265 1 delay [-1]
535 // 264 264 loop [-1]
536 // 525 3 delay [-1]
537 // 522 522 loop [-1]
538 // 263 0 bar [-1]
539 // 263 1 delay [-1]
540 // 262 262 loop [-1]
541 // 2 2 (program) [-1]
542 // 6 6 (garbage collector) [-1]
543 TEST(CollectCpuProfile) {
544  LocalContext env;
545  v8::HandleScope scope(env->GetIsolate());
546 
548  cpu_profiler_test_source))->Run();
550  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
551 
552  int32_t profiling_interval_ms = 200;
553  v8::Handle<v8::Value> args[] = {
554  v8::Integer::New(env->GetIsolate(), profiling_interval_ms)
555  };
556  const v8::CpuProfile* profile =
557  RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 200);
558  function->Call(env->Global(), ARRAY_SIZE(args), args);
559 
560  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
561 
562  ScopedVector<v8::Handle<v8::String> > names(3);
563  names[0] = v8::String::NewFromUtf8(
564  env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
565  names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
566  ProfileGenerator::kProgramEntryName);
567  names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
568  CheckChildrenNames(root, names);
569 
570  const v8::CpuProfileNode* startNode =
571  GetChild(env->GetIsolate(), root, "start");
572  CHECK_EQ(1, startNode->GetChildrenCount());
573 
574  const v8::CpuProfileNode* fooNode =
575  GetChild(env->GetIsolate(), startNode, "foo");
576  CHECK_EQ(3, fooNode->GetChildrenCount());
577 
578  const char* barBranch[] = { "bar", "delay", "loop" };
579  CheckSimpleBranch(env->GetIsolate(), fooNode, barBranch,
580  ARRAY_SIZE(barBranch));
581  const char* bazBranch[] = { "baz", "delay", "loop" };
582  CheckSimpleBranch(env->GetIsolate(), fooNode, bazBranch,
583  ARRAY_SIZE(bazBranch));
584  const char* delayBranch[] = { "delay", "loop" };
585  CheckSimpleBranch(env->GetIsolate(), fooNode, delayBranch,
586  ARRAY_SIZE(delayBranch));
587 
588  const_cast<v8::CpuProfile*>(profile)->Delete();
589 }
590 
591 
592 
593 static const char* cpu_profiler_test_source2 = "function loop() {}\n"
594 "function delay() { loop(); }\n"
595 "function start(count) {\n"
596 " var k = 0;\n"
597 " do {\n"
598 " delay();\n"
599 " } while (++k < count*100*1000);\n"
600 "}\n";
601 
602 // Check that the profile tree doesn't contain unexpected traces:
603 // - 'loop' can be called only by 'delay'
604 // - 'delay' may be called only by 'start'
605 // The profile will look like the following:
606 //
607 // [Top down]:
608 // 135 0 (root) [-1] #1
609 // 121 72 start [-1] #3
610 // 49 33 delay [-1] #4
611 // 16 16 loop [-1] #5
612 // 14 14 (program) [-1] #2
613 TEST(SampleWhenFrameIsNotSetup) {
614  LocalContext env;
615  v8::HandleScope scope(env->GetIsolate());
616 
618  env->GetIsolate(), cpu_profiler_test_source2))->Run();
620  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
621 
622  int32_t repeat_count = 100;
623 #if defined(USE_SIMULATOR)
624  // Simulators are much slower.
625  repeat_count = 1;
626 #endif
627  v8::Handle<v8::Value> args[] = {
628  v8::Integer::New(env->GetIsolate(), repeat_count)
629  };
630  const v8::CpuProfile* profile =
631  RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
632 
633  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
634 
635  ScopedVector<v8::Handle<v8::String> > names(3);
636  names[0] = v8::String::NewFromUtf8(
637  env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
638  names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
639  ProfileGenerator::kProgramEntryName);
640  names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
641  CheckChildrenNames(root, names);
642 
643  const v8::CpuProfileNode* startNode =
644  FindChild(env->GetIsolate(), root, "start");
645  // On slow machines there may be no meaningfull samples at all, skip the
646  // check there.
647  if (startNode && startNode->GetChildrenCount() > 0) {
648  CHECK_EQ(1, startNode->GetChildrenCount());
649  const v8::CpuProfileNode* delayNode =
650  GetChild(env->GetIsolate(), startNode, "delay");
651  if (delayNode->GetChildrenCount() > 0) {
652  CHECK_EQ(1, delayNode->GetChildrenCount());
653  GetChild(env->GetIsolate(), delayNode, "loop");
654  }
655  }
656 
657  const_cast<v8::CpuProfile*>(profile)->Delete();
658 }
659 
660 
661 static const char* native_accessor_test_source = "function start(count) {\n"
662 " for (var i = 0; i < count; i++) {\n"
663 " var o = instance.foo;\n"
664 " instance.foo = o + 1;\n"
665 " }\n"
666 "}\n";
667 
668 
670  public:
671  explicit TestApiCallbacks(int min_duration_ms)
672  : min_duration_ms_(min_duration_ms),
673  is_warming_up_(false) {}
674 
675  static void Getter(v8::Local<v8::String> name,
677  TestApiCallbacks* data = fromInfo(info);
678  data->Wait();
679  }
680 
681  static void Setter(v8::Local<v8::String> name,
682  v8::Local<v8::Value> value,
684  TestApiCallbacks* data = fromInfo(info);
685  data->Wait();
686  }
687 
689  TestApiCallbacks* data = fromInfo(info);
690  data->Wait();
691  }
692 
693  void set_warming_up(bool value) { is_warming_up_ = value; }
694 
695  private:
696  void Wait() {
697  if (is_warming_up_) return;
698  double start = i::OS::TimeCurrentMillis();
699  double duration = 0;
700  while (duration < min_duration_ms_) {
701  i::OS::Sleep(1);
702  duration = i::OS::TimeCurrentMillis() - start;
703  }
704  }
705 
706  template<typename T>
707  static TestApiCallbacks* fromInfo(const T& info) {
708  void* data = v8::External::Cast(*info.Data())->Value();
709  return reinterpret_cast<TestApiCallbacks*>(data);
710  }
711 
712  int min_duration_ms_;
713  bool is_warming_up_;
714 };
715 
716 
717 // Test that native accessors are properly reported in the CPU profile.
718 // This test checks the case when the long-running accessors are called
719 // only once and the optimizer doesn't have chance to change the invocation
720 // code.
721 TEST(NativeAccessorUninitializedIC) {
722  LocalContext env;
723  v8::Isolate* isolate = env->GetIsolate();
724  v8::HandleScope scope(isolate);
725 
726  v8::Local<v8::FunctionTemplate> func_template =
727  v8::FunctionTemplate::New(isolate);
728  v8::Local<v8::ObjectTemplate> instance_template =
729  func_template->InstanceTemplate();
730 
731  TestApiCallbacks accessors(100);
733  v8::External::New(isolate, &accessors);
734  instance_template->SetAccessor(
735  v8::String::NewFromUtf8(isolate, "foo"),
737  v8::Local<v8::Function> func = func_template->GetFunction();
738  v8::Local<v8::Object> instance = func->NewInstance();
739  env->Global()->Set(v8::String::NewFromUtf8(isolate, "instance"),
740  instance);
741 
743  v8::String::NewFromUtf8(isolate, native_accessor_test_source))
744  ->Run();
746  env->Global()->Get(v8::String::NewFromUtf8(isolate, "start")));
747 
748  int32_t repeat_count = 1;
749  v8::Handle<v8::Value> args[] = { v8::Integer::New(isolate, repeat_count) };
750  const v8::CpuProfile* profile =
751  RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 180);
752 
753  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
754  const v8::CpuProfileNode* startNode =
755  GetChild(isolate, root, "start");
756  GetChild(isolate, startNode, "get foo");
757  GetChild(isolate, startNode, "set foo");
758 
759  const_cast<v8::CpuProfile*>(profile)->Delete();
760 }
761 
762 
763 // Test that native accessors are properly reported in the CPU profile.
764 // This test makes sure that the accessors are called enough times to become
765 // hot and to trigger optimizations.
766 TEST(NativeAccessorMonomorphicIC) {
767  LocalContext env;
768  v8::Isolate* isolate = env->GetIsolate();
769  v8::HandleScope scope(isolate);
770 
771  v8::Local<v8::FunctionTemplate> func_template =
772  v8::FunctionTemplate::New(isolate);
773  v8::Local<v8::ObjectTemplate> instance_template =
774  func_template->InstanceTemplate();
775 
776  TestApiCallbacks accessors(1);
778  v8::External::New(isolate, &accessors);
779  instance_template->SetAccessor(
780  v8::String::NewFromUtf8(isolate, "foo"),
782  v8::Local<v8::Function> func = func_template->GetFunction();
783  v8::Local<v8::Object> instance = func->NewInstance();
784  env->Global()->Set(v8::String::NewFromUtf8(isolate, "instance"),
785  instance);
786 
788  v8::String::NewFromUtf8(isolate, native_accessor_test_source))
789  ->Run();
791  env->Global()->Get(v8::String::NewFromUtf8(isolate, "start")));
792 
793  {
794  // Make sure accessors ICs are in monomorphic state before starting
795  // profiling.
796  accessors.set_warming_up(true);
797  int32_t warm_up_iterations = 3;
798  v8::Handle<v8::Value> args[] = {
799  v8::Integer::New(isolate, warm_up_iterations)
800  };
801  function->Call(env->Global(), ARRAY_SIZE(args), args);
802  accessors.set_warming_up(false);
803  }
804 
805  int32_t repeat_count = 100;
806  v8::Handle<v8::Value> args[] = { v8::Integer::New(isolate, repeat_count) };
807  const v8::CpuProfile* profile =
808  RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 200);
809 
810  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
811  const v8::CpuProfileNode* startNode =
812  GetChild(isolate, root, "start");
813  GetChild(isolate, startNode, "get foo");
814  GetChild(isolate, startNode, "set foo");
815 
816  const_cast<v8::CpuProfile*>(profile)->Delete();
817 }
818 
819 
820 static const char* native_method_test_source = "function start(count) {\n"
821 " for (var i = 0; i < count; i++) {\n"
822 " instance.fooMethod();\n"
823 " }\n"
824 "}\n";
825 
826 
827 TEST(NativeMethodUninitializedIC) {
828  LocalContext env;
829  v8::Isolate* isolate = env->GetIsolate();
830  v8::HandleScope scope(isolate);
831 
832  TestApiCallbacks callbacks(100);
834  v8::External::New(isolate, &callbacks);
835 
836  v8::Local<v8::FunctionTemplate> func_template =
837  v8::FunctionTemplate::New(isolate);
838  func_template->SetClassName(
839  v8::String::NewFromUtf8(isolate, "Test_InstanceCostructor"));
840  v8::Local<v8::ObjectTemplate> proto_template =
841  func_template->PrototypeTemplate();
842  v8::Local<v8::Signature> signature =
843  v8::Signature::New(isolate, func_template);
844  proto_template->Set(v8::String::NewFromUtf8(isolate, "fooMethod"),
847  data, signature, 0));
848 
849  v8::Local<v8::Function> func = func_template->GetFunction();
850  v8::Local<v8::Object> instance = func->NewInstance();
851  env->Global()->Set(v8::String::NewFromUtf8(isolate, "instance"),
852  instance);
853 
855  isolate, native_method_test_source))->Run();
857  env->Global()->Get(v8::String::NewFromUtf8(isolate, "start")));
858 
859  int32_t repeat_count = 1;
860  v8::Handle<v8::Value> args[] = { v8::Integer::New(isolate, repeat_count) };
861  const v8::CpuProfile* profile =
862  RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
863 
864  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
865  const v8::CpuProfileNode* startNode =
866  GetChild(isolate, root, "start");
867  GetChild(isolate, startNode, "fooMethod");
868 
869  const_cast<v8::CpuProfile*>(profile)->Delete();
870 }
871 
872 
873 TEST(NativeMethodMonomorphicIC) {
874  LocalContext env;
875  v8::Isolate* isolate = env->GetIsolate();
876  v8::HandleScope scope(isolate);
877 
878  TestApiCallbacks callbacks(1);
880  v8::External::New(isolate, &callbacks);
881 
882  v8::Local<v8::FunctionTemplate> func_template =
883  v8::FunctionTemplate::New(isolate);
884  func_template->SetClassName(
885  v8::String::NewFromUtf8(isolate, "Test_InstanceCostructor"));
886  v8::Local<v8::ObjectTemplate> proto_template =
887  func_template->PrototypeTemplate();
888  v8::Local<v8::Signature> signature =
889  v8::Signature::New(isolate, func_template);
890  proto_template->Set(v8::String::NewFromUtf8(isolate, "fooMethod"),
893  data, signature, 0));
894 
895  v8::Local<v8::Function> func = func_template->GetFunction();
896  v8::Local<v8::Object> instance = func->NewInstance();
897  env->Global()->Set(v8::String::NewFromUtf8(isolate, "instance"),
898  instance);
899 
901  isolate, native_method_test_source))->Run();
903  env->Global()->Get(v8::String::NewFromUtf8(isolate, "start")));
904  {
905  // Make sure method ICs are in monomorphic state before starting
906  // profiling.
907  callbacks.set_warming_up(true);
908  int32_t warm_up_iterations = 3;
909  v8::Handle<v8::Value> args[] = {
910  v8::Integer::New(isolate, warm_up_iterations)
911  };
912  function->Call(env->Global(), ARRAY_SIZE(args), args);
913  callbacks.set_warming_up(false);
914  }
915 
916  int32_t repeat_count = 100;
917  v8::Handle<v8::Value> args[] = { v8::Integer::New(isolate, repeat_count) };
918  const v8::CpuProfile* profile =
919  RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
920 
921  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
922  GetChild(isolate, root, "start");
923  const v8::CpuProfileNode* startNode =
924  GetChild(isolate, root, "start");
925  GetChild(isolate, startNode, "fooMethod");
926 
927  const_cast<v8::CpuProfile*>(profile)->Delete();
928 }
929 
930 
931 static const char* bound_function_test_source = "function foo(iterations) {\n"
932 " var r = 0;\n"
933 " for (var i = 0; i < iterations; i++) { r += i; }\n"
934 " return r;\n"
935 "}\n"
936 "function start(duration) {\n"
937 " var callback = foo.bind(this);\n"
938 " var start = Date.now();\n"
939 " while (Date.now() - start < duration) {\n"
940 " callback(10 * 1000);\n"
941 " }\n"
942 "}";
943 
944 
945 TEST(BoundFunctionCall) {
946  LocalContext env;
947  v8::HandleScope scope(env->GetIsolate());
948 
950  v8::String::NewFromUtf8(env->GetIsolate(), bound_function_test_source))
951  ->Run();
953  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
954 
955  int32_t duration_ms = 100;
956  v8::Handle<v8::Value> args[] = {
957  v8::Integer::New(env->GetIsolate(), duration_ms)
958  };
959  const v8::CpuProfile* profile =
960  RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
961 
962  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
963  ScopedVector<v8::Handle<v8::String> > names(3);
964  names[0] = v8::String::NewFromUtf8(
965  env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
966  names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
967  ProfileGenerator::kProgramEntryName);
968  names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
969  // Don't allow |foo| node to be at the top level.
970  CheckChildrenNames(root, names);
971 
972  const v8::CpuProfileNode* startNode =
973  GetChild(env->GetIsolate(), root, "start");
974  GetChild(env->GetIsolate(), startNode, "foo");
975 
976  const_cast<v8::CpuProfile*>(profile)->Delete();
977 }
978 
979 
980 static const char* call_function_test_source = "function bar(iterations) {\n"
981 "}\n"
982 "function start(duration) {\n"
983 " var start = Date.now();\n"
984 " while (Date.now() - start < duration) {\n"
985 " try {\n"
986 " bar.call(this, 10 * 1000);\n"
987 " } catch(e) {}\n"
988 " }\n"
989 "}";
990 
991 
992 // Test that if we sampled thread when it was inside FunctionCall buitin then
993 // its caller frame will be '(unresolved function)' as we have no reliable way
994 // to resolve it.
995 //
996 // [Top down]:
997 // 96 0 (root) [-1] #1
998 // 1 1 (garbage collector) [-1] #4
999 // 5 0 (unresolved function) [-1] #5
1000 // 5 5 call [-1] #6
1001 // 71 70 start [-1] #3
1002 // 1 1 bar [-1] #7
1003 // 19 19 (program) [-1] #2
1004 TEST(FunctionCallSample) {
1005  LocalContext env;
1006  v8::HandleScope scope(env->GetIsolate());
1007 
1008  // Collect garbage that might have be generated while installing extensions.
1009  CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
1010 
1012  env->GetIsolate(), call_function_test_source))->Run();
1014  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
1015 
1016  int32_t duration_ms = 100;
1017  v8::Handle<v8::Value> args[] = {
1018  v8::Integer::New(env->GetIsolate(), duration_ms)
1019  };
1020  const v8::CpuProfile* profile =
1021  RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
1022 
1023  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1024  {
1025  ScopedVector<v8::Handle<v8::String> > names(4);
1026  names[0] = v8::String::NewFromUtf8(
1027  env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
1028  names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
1029  ProfileGenerator::kProgramEntryName);
1030  names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
1031  names[3] = v8::String::NewFromUtf8(
1033  // Don't allow |bar| and |call| nodes to be at the top level.
1034  CheckChildrenNames(root, names);
1035  }
1036 
1037  // In case of GC stress tests all samples may be in GC phase and there
1038  // won't be |start| node in the profiles.
1039  bool is_gc_stress_testing =
1040  (i::FLAG_gc_interval != -1) || i::FLAG_stress_compaction;
1041  const v8::CpuProfileNode* startNode =
1042  FindChild(env->GetIsolate(), root, "start");
1043  CHECK(is_gc_stress_testing || startNode);
1044  if (startNode) {
1045  ScopedVector<v8::Handle<v8::String> > names(2);
1046  names[0] = v8::String::NewFromUtf8(env->GetIsolate(), "bar");
1047  names[1] = v8::String::NewFromUtf8(env->GetIsolate(), "call");
1048  CheckChildrenNames(startNode, names);
1049  }
1050 
1051  const v8::CpuProfileNode* unresolvedNode = FindChild(
1053  if (unresolvedNode) {
1054  ScopedVector<v8::Handle<v8::String> > names(1);
1055  names[0] = v8::String::NewFromUtf8(env->GetIsolate(), "call");
1056  CheckChildrenNames(unresolvedNode, names);
1057  }
1058 
1059  const_cast<v8::CpuProfile*>(profile)->Delete();
1060 }
1061 
1062 
1063 static const char* function_apply_test_source = "function bar(iterations) {\n"
1064 "}\n"
1065 "function test() {\n"
1066 " bar.apply(this, [10 * 1000]);\n"
1067 "}\n"
1068 "function start(duration) {\n"
1069 " var start = Date.now();\n"
1070 " while (Date.now() - start < duration) {\n"
1071 " try {\n"
1072 " test();\n"
1073 " } catch(e) {}\n"
1074 " }\n"
1075 "}";
1076 
1077 
1078 // [Top down]:
1079 // 94 0 (root) [-1] #0 1
1080 // 2 2 (garbage collector) [-1] #0 7
1081 // 82 49 start [-1] #16 3
1082 // 1 0 (unresolved function) [-1] #0 8
1083 // 1 1 apply [-1] #0 9
1084 // 32 21 test [-1] #16 4
1085 // 2 2 bar [-1] #16 6
1086 // 9 9 apply [-1] #0 5
1087 // 10 10 (program) [-1] #0 2
1088 TEST(FunctionApplySample) {
1089  LocalContext env;
1090  v8::HandleScope scope(env->GetIsolate());
1091 
1093  v8::String::NewFromUtf8(env->GetIsolate(), function_apply_test_source))
1094  ->Run();
1096  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
1097 
1098  int32_t duration_ms = 100;
1099  v8::Handle<v8::Value> args[] = {
1100  v8::Integer::New(env->GetIsolate(), duration_ms)
1101  };
1102 
1103  const v8::CpuProfile* profile =
1104  RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
1105 
1106  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1107  {
1108  ScopedVector<v8::Handle<v8::String> > names(3);
1109  names[0] = v8::String::NewFromUtf8(
1110  env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
1111  names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
1112  ProfileGenerator::kProgramEntryName);
1113  names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
1114  // Don't allow |test|, |bar| and |apply| nodes to be at the top level.
1115  CheckChildrenNames(root, names);
1116  }
1117 
1118  const v8::CpuProfileNode* startNode =
1119  FindChild(env->GetIsolate(), root, "start");
1120  if (startNode) {
1121  {
1122  ScopedVector<v8::Handle<v8::String> > names(2);
1123  names[0] = v8::String::NewFromUtf8(env->GetIsolate(), "test");
1124  names[1] = v8::String::NewFromUtf8(
1125  env->GetIsolate(), ProfileGenerator::kUnresolvedFunctionName);
1126  CheckChildrenNames(startNode, names);
1127  }
1128 
1129  const v8::CpuProfileNode* testNode =
1130  FindChild(env->GetIsolate(), startNode, "test");
1131  if (testNode) {
1132  ScopedVector<v8::Handle<v8::String> > names(2);
1133  names[0] = v8::String::NewFromUtf8(env->GetIsolate(), "bar");
1134  names[1] = v8::String::NewFromUtf8(env->GetIsolate(), "apply");
1135  CheckChildrenNames(testNode, names);
1136  }
1137 
1138  if (const v8::CpuProfileNode* unresolvedNode =
1139  FindChild(env->GetIsolate(), startNode,
1140  ProfileGenerator::kUnresolvedFunctionName)) {
1141  ScopedVector<v8::Handle<v8::String> > names(1);
1142  names[0] = v8::String::NewFromUtf8(env->GetIsolate(), "apply");
1143  CheckChildrenNames(unresolvedNode, names);
1144  GetChild(env->GetIsolate(), unresolvedNode, "apply");
1145  }
1146  }
1147 
1148  const_cast<v8::CpuProfile*>(profile)->Delete();
1149 }
1150 
1151 
1152 static const char* js_native_js_test_source =
1153 "var is_profiling = false;\n"
1154 "function foo(iterations) {\n"
1155 " if (!is_profiling) {\n"
1156 " is_profiling = true;\n"
1157 " startProfiling('my_profile');\n"
1158 " }\n"
1159 " var r = 0;\n"
1160 " for (var i = 0; i < iterations; i++) { r += i; }\n"
1161 " return r;\n"
1162 "}\n"
1163 "function bar(iterations) {\n"
1164 " try { foo(iterations); } catch(e) {}\n"
1165 "}\n"
1166 "function start(duration) {\n"
1167 " var start = Date.now();\n"
1168 " while (Date.now() - start < duration) {\n"
1169 " try {\n"
1170 " CallJsFunction(bar, 10 * 1000);\n"
1171 " } catch(e) {}\n"
1172 " }\n"
1173 "}";
1174 
1175 static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
1176  v8::Handle<v8::Function> function = info[0].As<v8::Function>();
1177  v8::Handle<v8::Value> argv[] = { info[1] };
1178  function->Call(info.This(), ARRAY_SIZE(argv), argv);
1179 }
1180 
1181 
1182 // [Top down]:
1183 // 58 0 (root) #0 1
1184 // 2 2 (program) #0 2
1185 // 56 1 start #16 3
1186 // 55 0 CallJsFunction #0 4
1187 // 55 1 bar #16 5
1188 // 54 54 foo #16 6
1189 TEST(JsNativeJsSample) {
1191  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1192  v8::Context::Scope context_scope(env);
1193 
1195  env->GetIsolate(), CallJsFunction);
1196  v8::Local<v8::Function> func = func_template->GetFunction();
1197  func->SetName(v8::String::NewFromUtf8(env->GetIsolate(), "CallJsFunction"));
1198  env->Global()->Set(
1199  v8::String::NewFromUtf8(env->GetIsolate(), "CallJsFunction"), func);
1200 
1202  js_native_js_test_source))->Run();
1204  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
1205 
1206  int32_t duration_ms = 20;
1207  v8::Handle<v8::Value> args[] = {
1208  v8::Integer::New(env->GetIsolate(), duration_ms)
1209  };
1210  const v8::CpuProfile* profile =
1211  RunProfiler(env, function, args, ARRAY_SIZE(args), 10);
1212 
1213  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1214  {
1215  ScopedVector<v8::Handle<v8::String> > names(3);
1216  names[0] = v8::String::NewFromUtf8(
1217  env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
1218  names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
1219  ProfileGenerator::kProgramEntryName);
1220  names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
1221  CheckChildrenNames(root, names);
1222  }
1223 
1224  const v8::CpuProfileNode* startNode =
1225  GetChild(env->GetIsolate(), root, "start");
1226  CHECK_EQ(1, startNode->GetChildrenCount());
1227  const v8::CpuProfileNode* nativeFunctionNode =
1228  GetChild(env->GetIsolate(), startNode, "CallJsFunction");
1229 
1230  CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
1231  const v8::CpuProfileNode* barNode =
1232  GetChild(env->GetIsolate(), nativeFunctionNode, "bar");
1233 
1234  CHECK_EQ(1, barNode->GetChildrenCount());
1235  GetChild(env->GetIsolate(), barNode, "foo");
1236 
1237  const_cast<v8::CpuProfile*>(profile)->Delete();
1238 }
1239 
1240 
1241 static const char* js_native_js_runtime_js_test_source =
1242 "var is_profiling = false;\n"
1243 "function foo(iterations) {\n"
1244 " if (!is_profiling) {\n"
1245 " is_profiling = true;\n"
1246 " startProfiling('my_profile');\n"
1247 " }\n"
1248 " var r = 0;\n"
1249 " for (var i = 0; i < iterations; i++) { r += i; }\n"
1250 " return r;\n"
1251 "}\n"
1252 "var bound = foo.bind(this);\n"
1253 "function bar(iterations) {\n"
1254 " try { bound(iterations); } catch(e) {}\n"
1255 "}\n"
1256 "function start(duration) {\n"
1257 " var start = Date.now();\n"
1258 " while (Date.now() - start < duration) {\n"
1259 " try {\n"
1260 " CallJsFunction(bar, 10 * 1000);\n"
1261 " } catch(e) {}\n"
1262 " }\n"
1263 "}";
1264 
1265 
1266 // [Top down]:
1267 // 57 0 (root) #0 1
1268 // 55 1 start #16 3
1269 // 54 0 CallJsFunction #0 4
1270 // 54 3 bar #16 5
1271 // 51 51 foo #16 6
1272 // 2 2 (program) #0 2
1273 TEST(JsNativeJsRuntimeJsSample) {
1275  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1276  v8::Context::Scope context_scope(env);
1277 
1279  env->GetIsolate(), CallJsFunction);
1280  v8::Local<v8::Function> func = func_template->GetFunction();
1281  func->SetName(v8::String::NewFromUtf8(env->GetIsolate(), "CallJsFunction"));
1282  env->Global()->Set(
1283  v8::String::NewFromUtf8(env->GetIsolate(), "CallJsFunction"), func);
1284 
1287  js_native_js_runtime_js_test_source))->Run();
1289  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
1290 
1291  int32_t duration_ms = 20;
1292  v8::Handle<v8::Value> args[] = {
1293  v8::Integer::New(env->GetIsolate(), duration_ms)
1294  };
1295  const v8::CpuProfile* profile =
1296  RunProfiler(env, function, args, ARRAY_SIZE(args), 10);
1297 
1298  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1299  ScopedVector<v8::Handle<v8::String> > names(3);
1300  names[0] = v8::String::NewFromUtf8(
1301  env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
1302  names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
1303  ProfileGenerator::kProgramEntryName);
1304  names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
1305  CheckChildrenNames(root, names);
1306 
1307  const v8::CpuProfileNode* startNode =
1308  GetChild(env->GetIsolate(), root, "start");
1309  CHECK_EQ(1, startNode->GetChildrenCount());
1310  const v8::CpuProfileNode* nativeFunctionNode =
1311  GetChild(env->GetIsolate(), startNode, "CallJsFunction");
1312 
1313  CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
1314  const v8::CpuProfileNode* barNode =
1315  GetChild(env->GetIsolate(), nativeFunctionNode, "bar");
1316 
1317  CHECK_EQ(1, barNode->GetChildrenCount());
1318  GetChild(env->GetIsolate(), barNode, "foo");
1319 
1320  const_cast<v8::CpuProfile*>(profile)->Delete();
1321 }
1322 
1323 
1324 static void CallJsFunction2(const v8::FunctionCallbackInfo<v8::Value>& info) {
1325  CallJsFunction(info);
1326 }
1327 
1328 
1329 static const char* js_native1_js_native2_js_test_source =
1330 "var is_profiling = false;\n"
1331 "function foo(iterations) {\n"
1332 " if (!is_profiling) {\n"
1333 " is_profiling = true;\n"
1334 " startProfiling('my_profile');\n"
1335 " }\n"
1336 " var r = 0;\n"
1337 " for (var i = 0; i < iterations; i++) { r += i; }\n"
1338 " return r;\n"
1339 "}\n"
1340 "function bar(iterations) {\n"
1341 " CallJsFunction2(foo, iterations);\n"
1342 "}\n"
1343 "function start(duration) {\n"
1344 " var start = Date.now();\n"
1345 " while (Date.now() - start < duration) {\n"
1346 " try {\n"
1347 " CallJsFunction1(bar, 10 * 1000);\n"
1348 " } catch(e) {}\n"
1349 " }\n"
1350 "}";
1351 
1352 
1353 // [Top down]:
1354 // 57 0 (root) #0 1
1355 // 55 1 start #16 3
1356 // 54 0 CallJsFunction1 #0 4
1357 // 54 0 bar #16 5
1358 // 54 0 CallJsFunction2 #0 6
1359 // 54 54 foo #16 7
1360 // 2 2 (program) #0 2
1361 TEST(JsNative1JsNative2JsSample) {
1363  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1364  v8::Context::Scope context_scope(env);
1365 
1367  env->GetIsolate(), CallJsFunction);
1368  v8::Local<v8::Function> func1 = func_template->GetFunction();
1369  func1->SetName(v8::String::NewFromUtf8(env->GetIsolate(), "CallJsFunction1"));
1370  env->Global()->Set(
1371  v8::String::NewFromUtf8(env->GetIsolate(), "CallJsFunction1"), func1);
1372 
1374  env->GetIsolate(), CallJsFunction2)->GetFunction();
1375  func2->SetName(v8::String::NewFromUtf8(env->GetIsolate(), "CallJsFunction2"));
1376  env->Global()->Set(
1377  v8::String::NewFromUtf8(env->GetIsolate(), "CallJsFunction2"), func2);
1378 
1381  js_native1_js_native2_js_test_source))->Run();
1383  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
1384 
1385  int32_t duration_ms = 20;
1386  v8::Handle<v8::Value> args[] = {
1387  v8::Integer::New(env->GetIsolate(), duration_ms)
1388  };
1389  const v8::CpuProfile* profile =
1390  RunProfiler(env, function, args, ARRAY_SIZE(args), 10);
1391 
1392  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1393  ScopedVector<v8::Handle<v8::String> > names(3);
1394  names[0] = v8::String::NewFromUtf8(
1395  env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
1396  names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
1397  ProfileGenerator::kProgramEntryName);
1398  names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
1399  CheckChildrenNames(root, names);
1400 
1401  const v8::CpuProfileNode* startNode =
1402  GetChild(env->GetIsolate(), root, "start");
1403  CHECK_EQ(1, startNode->GetChildrenCount());
1404  const v8::CpuProfileNode* nativeNode1 =
1405  GetChild(env->GetIsolate(), startNode, "CallJsFunction1");
1406 
1407  CHECK_EQ(1, nativeNode1->GetChildrenCount());
1408  const v8::CpuProfileNode* barNode =
1409  GetChild(env->GetIsolate(), nativeNode1, "bar");
1410 
1411  CHECK_EQ(1, barNode->GetChildrenCount());
1412  const v8::CpuProfileNode* nativeNode2 =
1413  GetChild(env->GetIsolate(), barNode, "CallJsFunction2");
1414 
1415  CHECK_EQ(1, nativeNode2->GetChildrenCount());
1416  GetChild(env->GetIsolate(), nativeNode2, "foo");
1417 
1418  const_cast<v8::CpuProfile*>(profile)->Delete();
1419 }
1420 
1421 
1422 // [Top down]:
1423 // 6 0 (root) #0 1
1424 // 3 3 (program) #0 2
1425 // 3 3 (idle) #0 3
1426 TEST(IdleTime) {
1427  LocalContext env;
1428  v8::HandleScope scope(env->GetIsolate());
1429  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
1430 
1431  v8::Local<v8::String> profile_name =
1432  v8::String::NewFromUtf8(env->GetIsolate(), "my_profile");
1433  cpu_profiler->StartCpuProfiling(profile_name);
1434 
1435  i::Isolate* isolate = CcTest::i_isolate();
1436  i::ProfilerEventsProcessor* processor = isolate->cpu_profiler()->processor();
1437  processor->AddCurrentStack(isolate);
1438 
1439  cpu_profiler->SetIdle(true);
1440 
1441  for (int i = 0; i < 3; i++) {
1442  processor->AddCurrentStack(isolate);
1443  }
1444 
1445  cpu_profiler->SetIdle(false);
1446  processor->AddCurrentStack(isolate);
1447 
1448 
1449  const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name);
1450  CHECK_NE(NULL, profile);
1451  // Dump collected profile to have a better diagnostic in case of failure.
1452  reinterpret_cast<i::CpuProfile*>(
1453  const_cast<v8::CpuProfile*>(profile))->Print();
1454 
1455  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1456  ScopedVector<v8::Handle<v8::String> > names(3);
1457  names[0] = v8::String::NewFromUtf8(
1458  env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
1459  names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
1460  ProfileGenerator::kProgramEntryName);
1461  names[2] = v8::String::NewFromUtf8(env->GetIsolate(),
1462  ProfileGenerator::kIdleEntryName);
1463  CheckChildrenNames(root, names);
1464 
1465  const v8::CpuProfileNode* programNode =
1466  GetChild(env->GetIsolate(), root, ProfileGenerator::kProgramEntryName);
1467  CHECK_EQ(0, programNode->GetChildrenCount());
1468  CHECK_GE(programNode->GetHitCount(), 3);
1469 
1470  const v8::CpuProfileNode* idleNode =
1471  GetChild(env->GetIsolate(), root, ProfileGenerator::kIdleEntryName);
1472  CHECK_EQ(0, idleNode->GetChildrenCount());
1473  CHECK_GE(idleNode->GetHitCount(), 3);
1474 
1475  const_cast<v8::CpuProfile*>(profile)->Delete();
1476 }
1477 
1478 
1479 static void CheckFunctionDetails(v8::Isolate* isolate,
1480  const v8::CpuProfileNode* node,
1481  const char* name, const char* script_name,
1482  int script_id, int line, int column) {
1483  CHECK_EQ(v8::String::NewFromUtf8(isolate, name),
1484  node->GetFunctionName());
1485  CHECK_EQ(v8::String::NewFromUtf8(isolate, script_name),
1486  node->GetScriptResourceName());
1487  CHECK_EQ(script_id, node->GetScriptId());
1488  CHECK_EQ(line, node->GetLineNumber());
1489  CHECK_EQ(column, node->GetColumnNumber());
1490 }
1491 
1492 
1493 TEST(FunctionDetails) {
1495  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1496  v8::Context::Scope context_scope(env);
1497 
1498  v8::Handle<v8::Script> script_a = CompileWithOrigin(
1499  " function foo\n() { try { bar(); } catch(e) {} }\n"
1500  " function bar() { startProfiling(); }\n",
1501  "script_a");
1502  script_a->Run();
1503  v8::Handle<v8::Script> script_b = CompileWithOrigin(
1504  "\n\n function baz() { try { foo(); } catch(e) {} }\n"
1505  "\n\nbaz();\n"
1506  "stopProfiling();\n",
1507  "script_b");
1508  script_b->Run();
1510  const v8::CpuProfileNode* current = profile->GetTopDownRoot();
1511  reinterpret_cast<ProfileNode*>(
1512  const_cast<v8::CpuProfileNode*>(current))->Print(0);
1513  // The tree should look like this:
1514  // 0 (root) 0 #1
1515  // 0 (anonymous function) 19 #2 no reason script_b:1
1516  // 0 baz 19 #3 TryCatchStatement script_b:3
1517  // 0 foo 18 #4 TryCatchStatement script_a:2
1518  // 1 bar 18 #5 no reason script_a:3
1519  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1520  const v8::CpuProfileNode* script = GetChild(env->GetIsolate(), root,
1521  ProfileGenerator::kAnonymousFunctionName);
1522  CheckFunctionDetails(env->GetIsolate(), script,
1523  ProfileGenerator::kAnonymousFunctionName, "script_b",
1524  script_b->GetId(), 1, 1);
1525  const v8::CpuProfileNode* baz = GetChild(env->GetIsolate(), script, "baz");
1526  CheckFunctionDetails(env->GetIsolate(), baz, "baz", "script_b",
1527  script_b->GetId(), 3, 16);
1528  const v8::CpuProfileNode* foo = GetChild(env->GetIsolate(), baz, "foo");
1529  CheckFunctionDetails(env->GetIsolate(), foo, "foo", "script_a",
1530  script_a->GetId(), 2, 1);
1531  const v8::CpuProfileNode* bar = GetChild(env->GetIsolate(), foo, "bar");
1532  CheckFunctionDetails(env->GetIsolate(), bar, "bar", "script_a",
1533  script_a->GetId(), 3, 14);
1534 }
1535 
1536 
1537 TEST(DontStopOnFinishedProfileDelete) {
1539  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1540  v8::Context::Scope context_scope(env);
1541  v8::Isolate* isolate = env->GetIsolate();
1542 
1543  v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
1544  i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
1545 
1546  CHECK_EQ(0, iprofiler->GetProfilesCount());
1547  v8::Handle<v8::String> outer = v8::String::NewFromUtf8(isolate, "outer");
1548  profiler->StartCpuProfiling(outer);
1549  CHECK_EQ(0, iprofiler->GetProfilesCount());
1550 
1551  v8::Handle<v8::String> inner = v8::String::NewFromUtf8(isolate, "inner");
1552  profiler->StartCpuProfiling(inner);
1553  CHECK_EQ(0, iprofiler->GetProfilesCount());
1554 
1555  const v8::CpuProfile* inner_profile = profiler->StopCpuProfiling(inner);
1556  CHECK(inner_profile);
1557  CHECK_EQ(1, iprofiler->GetProfilesCount());
1558  const_cast<v8::CpuProfile*>(inner_profile)->Delete();
1559  inner_profile = NULL;
1560  CHECK_EQ(0, iprofiler->GetProfilesCount());
1561 
1562  const v8::CpuProfile* outer_profile = profiler->StopCpuProfiling(outer);
1563  CHECK(outer_profile);
1564  CHECK_EQ(1, iprofiler->GetProfilesCount());
1565  const_cast<v8::CpuProfile*>(outer_profile)->Delete();
1566  outer_profile = NULL;
1567  CHECK_EQ(0, iprofiler->GetProfilesCount());
1568 }
void StartProfiling(const char *title, bool record_samples=false)
byte * Address
Definition: globals.h:186
void SetAccessor(Handle< String > name, AccessorGetterCallback getter, AccessorSetterCallback setter=0, Handle< Value > data=Handle< Value >(), AccessControl settings=DEFAULT, PropertyAttribute attribute=None, Handle< AccessorSignature > signature=Handle< AccessorSignature >())
Definition: api.cc:1404
static Local< Signature > New(Isolate *isolate, Handle< FunctionTemplate > receiver=Handle< FunctionTemplate >(), int argc=0, Handle< FunctionTemplate > argv[]=0)
Definition: api.cc:957
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
#define CHECK_EQ(expected, value)
Definition: checks.h:252
CpuProfiler * GetCpuProfiler()
Definition: api.cc:6346
TEST(StartStop)
void CollectAllGarbage(int flags, const char *gc_reason=NULL, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Definition: heap.cc:731
unsigned js_and_external_sample_count() const
Definition: sampler.h:116
#define FATAL(msg)
Definition: checks.h:48
void AddCurrentStack(Isolate *isolate)
Definition: cpu-profiler.cc:65
static const int kMaxFramesCount
Definition: sampler.h:70
static const char *const kUnresolvedFunctionName
TickSample * sample
Handle< String > NewStringFromAscii(Vector< const char > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.h:141
int64_t GetStartTime() const
Definition: api.cc:7116
const CpuProfileNode * GetChild(int index) const
Definition: api.cc:7081
Local< ObjectTemplate > InstanceTemplate()
Definition: api.cc:1223
int int32_t
Definition: unicode.cc:47
Handle< String > GetScriptResourceName() const
Definition: api.cc:7036
static const v8::CpuProfile * last_profile
byte * instruction_end()
Definition: objects-inl.h:5862
static i::Heap * heap()
Definition: cctest.h:106
static Local< Integer > New(Isolate *isolate, int32_t value)
Definition: api.cc:6233
#define CHECK(condition)
Definition: checks.h:75
void Set(Handle< String > name, Handle< Data > value, PropertyAttribute attributes=None)
Definition: api.cc:841
Factory * factory()
Definition: isolate.h:995
#define CHECK_GE(a, b)
Definition: checks.h:261
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
bool Equals(Handle< Value > that) const
Definition: api.cc:2950
void set_warming_up(bool value)
Handle< String > GetFunctionName() const
Definition: api.cc:7011
static v8::Local< v8::Context > NewContext(CcTestExtensionFlags extensions, v8::Isolate *isolate=CcTest::isolate())
Definition: cctest.cc:90
int GetId()
Definition: v8.h:1067
TestApiCallbacks(int min_duration_ms)
v8::Isolate * GetIsolate()
Definition: api.cc:5233
void SetClassName(Handle< String > name)
Definition: api.cc:1250
int foo
void StartCpuProfiling(Handle< String > title, bool record_samples=false)
Definition: api.cc:7146
const CpuProfile * StopCpuProfiling(Handle< String > title)
Definition: api.cc:7158
T * start() const
Definition: utils.h:426
T & last() const
Definition: list.h:91
static void Callback(const v8::FunctionCallbackInfo< v8::Value > &info)
byte * instruction_start()
Definition: objects-inl.h:5857
int64_t GetEndTime() const
Definition: api.cc:7122
static Local< External > New(Isolate *isolate, void *value)
Definition: api.cc:5322
void StartCountingSamples()
Definition: sampler.h:119
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >(), int length=0)
Definition: api.cc:942
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *script_data=NULL)
Definition: api.cc:1832
Local< Object > NewInstance() const
Definition: api.cc:3970
Local< Object > Global()
Definition: api.cc:5239
static i::Isolate * i_isolate()
Definition: cctest.h:102
static double TimeCurrentMillis()
V8_INLINE Local< Object > This() const
Definition: v8.h:6042
Address stack[kMaxFramesCount]
Definition: sampler.h:71
static V8_INLINE External * Cast(Value *obj)
Definition: v8.h:6503
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT enable GDBJIT interface for all code objects dump only objects containing this substring stress the GC compactor to flush out pretty print source code print source AST function name where to insert a breakpoint print scopes for builtins trace contexts operations print stuff during garbage collection report code statistics after GC report handles after GC trace cache state transitions print interface inference details prints when objects are turned into dictionaries report heap spill statistics along with trace isolate state changes trace regexp bytecode execution Minimal Log all events to the log file Log API events to the log file Log heap samples on garbage collection for the hp2ps tool log positions Log suspect operations Used with turns on browser compatible mode for profiling v8 Specify the name of the log file Enable low level linux profiler Enable perf linux profiler(experimental annotate support).") DEFINE_string(gc_fake_mmap
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
#define CHECK_NE(unexpected, value)
Definition: checks.h:256
static V8_INLINE Local< T > Cast(Local< S > that)
Definition: v8.h:372
static void Sleep(const int milliseconds)
int StrLength(const char *string)
Definition: utils.h:253
#define T(name, string, precedence)
Definition: token.cc:48
int GetScriptId() const
Definition: api.cc:7029
i::Code * CreateCode(LocalContext *env)
void SetName(Handle< String > name)
Definition: api.cc:4022
static int SNPrintF(Vector< char > str, const char *format,...)
const CpuProfileNode * GetTopDownRoot() const
Definition: api.cc:7104
static void InitializeVM()
Definition: cctest.h:116
CpuProfiler * cpu_profiler() const
Definition: isolate.h:984
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
Local< Function > GetFunction()
Definition: api.cc:5299
int ExecutableSize()
Definition: objects.h:5499
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
int GetChildrenCount() const
Definition: api.cc:7076
int baz
int GetColumnNumber() const
Definition: api.cc:7049
CpuProfile * GetProfile(int index)
Local< ObjectTemplate > PrototypeTemplate()
Definition: api.cc:888
static void Getter(v8::Local< v8::String > name, const v8::PropertyCallbackInfo< v8::Value > &info)
unsigned GetHitCount() const
Definition: api.cc:7061
Local< Value > Run()
Definition: api.cc:1686
static void Setter(v8::Local< v8::String > name, v8::Local< v8::Value > value, const v8::PropertyCallbackInfo< void > &info)
ProfilerEventsProcessor * processor() const
Definition: cpu-profiler.h:263
v8::Local< v8::Context > local()
Definition: cctest.h:272
int bar
#define ARRAY_SIZE(a)
Definition: globals.h:333
Definition: v8.h:124
int GetLineNumber() const
Definition: api.cc:7044
static v8::Isolate * isolate()
Definition: cctest.h:96
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5417