Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: test/cctest/test-cpu-profiler.cc

Issue 1665303004: Unflake CPU profiler tests. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: make top level functions to be JS ones. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/profiler-extension.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 static const char* reason(const i::Deoptimizer::DeoptReason reason) { 68 static const char* reason(const i::Deoptimizer::DeoptReason reason) {
69 return i::Deoptimizer::GetDeoptReason(reason); 69 return i::Deoptimizer::GetDeoptReason(reason);
70 } 70 }
71 71
72 72
73 TEST(StartStop) { 73 TEST(StartStop) {
74 i::Isolate* isolate = CcTest::i_isolate(); 74 i::Isolate* isolate = CcTest::i_isolate();
75 CpuProfilesCollection profiles(isolate->heap()); 75 CpuProfilesCollection profiles(isolate->heap());
76 ProfileGenerator generator(&profiles); 76 ProfileGenerator generator(&profiles);
77 SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor( 77 SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
78 &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100))); 78 &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
79 processor->Start(); 79 processor->Start();
80 processor->StopSynchronously(); 80 processor->StopSynchronously();
81 } 81 }
82 82
83 83
84 static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc, 84 static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
85 i::Address frame1, 85 i::Address frame1,
86 i::Address frame2 = NULL, 86 i::Address frame2 = NULL,
87 i::Address frame3 = NULL) { 87 i::Address frame3 = NULL) {
88 i::TickSample* sample = proc->StartTickSample(); 88 i::TickSample* sample = proc->StartTickSample();
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name); 439 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
440 440
441 CHECK(profile); 441 CHECK(profile);
442 // Dump collected profile to have a better diagnostic in case of failure. 442 // Dump collected profile to have a better diagnostic in case of failure.
443 reinterpret_cast<i::CpuProfile*>(profile)->Print(); 443 reinterpret_cast<i::CpuProfile*>(profile)->Print();
444 444
445 return profile; 445 return profile;
446 } 446 }
447 447
448 448
449 static bool ContainsString(v8::Local<v8::Context> context,
450 v8::Local<v8::String> string,
451 const Vector<v8::Local<v8::String> >& vector) {
452 for (int i = 0; i < vector.length(); i++) {
453 if (string->Equals(context, vector[i]).FromJust()) return true;
454 }
455 return false;
456 }
457
458
459 static void CheckChildrenNames(v8::Local<v8::Context> context,
460 const v8::CpuProfileNode* node,
461 const Vector<v8::Local<v8::String> >& names) {
462 int count = node->GetChildrenCount();
463 for (int i = 0; i < count; i++) {
464 v8::Local<v8::String> name = node->GetChild(i)->GetFunctionName();
465 if (!ContainsString(context, name, names)) {
466 char buffer[100];
467 i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
468 "Unexpected child '%s' found in '%s'",
469 *v8::String::Utf8Value(name),
470 *v8::String::Utf8Value(node->GetFunctionName()));
471 FATAL(buffer);
472 }
473 // Check that there are no duplicates.
474 for (int j = 0; j < count; j++) {
475 if (j == i) continue;
476 if (name->Equals(context, node->GetChild(j)->GetFunctionName())
477 .FromJust()) {
478 char buffer[100];
479 i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
480 "Second child with the same name '%s' found in '%s'",
481 *v8::String::Utf8Value(name),
482 *v8::String::Utf8Value(node->GetFunctionName()));
483 FATAL(buffer);
484 }
485 }
486 }
487 }
488
489
490 static const v8::CpuProfileNode* FindChild(v8::Local<v8::Context> context, 449 static const v8::CpuProfileNode* FindChild(v8::Local<v8::Context> context,
491 const v8::CpuProfileNode* node, 450 const v8::CpuProfileNode* node,
492 const char* name) { 451 const char* name) {
493 int count = node->GetChildrenCount(); 452 int count = node->GetChildrenCount();
494 v8::Local<v8::String> nameHandle = v8_str(name); 453 v8::Local<v8::String> name_handle = v8_str(name);
495 for (int i = 0; i < count; i++) { 454 for (int i = 0; i < count; i++) {
496 const v8::CpuProfileNode* child = node->GetChild(i); 455 const v8::CpuProfileNode* child = node->GetChild(i);
497 if (nameHandle->Equals(context, child->GetFunctionName()).FromJust()) { 456 if (name_handle->Equals(context, child->GetFunctionName()).FromJust()) {
498 return child; 457 return child;
499 } 458 }
500 } 459 }
501 return NULL; 460 return NULL;
502 } 461 }
503 462
504 463
505 static const v8::CpuProfileNode* GetChild(v8::Local<v8::Context> context, 464 static const v8::CpuProfileNode* GetChild(v8::Local<v8::Context> context,
506 const v8::CpuProfileNode* node, 465 const v8::CpuProfileNode* node,
507 const char* name) { 466 const char* name) {
508 const v8::CpuProfileNode* result = FindChild(context, node, name); 467 const v8::CpuProfileNode* result = FindChild(context, node, name);
509 if (!result) { 468 if (!result) {
510 char buffer[100]; 469 char buffer[100];
511 i::SNPrintF(Vector<char>(buffer, arraysize(buffer)), 470 i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
512 "Failed to GetChild: %s", name); 471 "Failed to GetChild: %s", name);
513 FATAL(buffer); 472 FATAL(buffer);
514 } 473 }
515 return result; 474 return result;
516 } 475 }
517 476
518 477
519 static void CheckSimpleBranch(v8::Local<v8::Context> context, 478 static void CheckSimpleBranch(v8::Local<v8::Context> context,
520 const v8::CpuProfileNode* node, 479 const v8::CpuProfileNode* node,
521 const char* names[], int length) { 480 const char* names[], int length) {
522 for (int i = 0; i < length; i++) { 481 for (int i = 0; i < length; i++) {
523 const char* name = names[i]; 482 const char* name = names[i];
524 node = GetChild(context, node, name); 483 node = GetChild(context, node, name);
525 int expectedChildrenCount = (i == length - 1) ? 0 : 1;
526 CHECK_EQ(expectedChildrenCount, node->GetChildrenCount());
527 } 484 }
528 } 485 }
529 486
530 487
531 static const ProfileNode* GetSimpleBranch(v8::Local<v8::Context> context, 488 static const ProfileNode* GetSimpleBranch(v8::Local<v8::Context> context,
532 v8::CpuProfile* profile, 489 v8::CpuProfile* profile,
533 const char* names[], int length) { 490 const char* names[], int length) {
534 const v8::CpuProfileNode* node = profile->GetTopDownRoot(); 491 const v8::CpuProfileNode* node = profile->GetTopDownRoot();
535 for (int i = 0; i < length; i++) { 492 for (int i = 0; i < length; i++) {
536 node = GetChild(context, node, names[i]); 493 node = GetChild(context, node, names[i]);
537 } 494 }
538 return reinterpret_cast<const ProfileNode*>(node); 495 return reinterpret_cast<const ProfileNode*>(node);
539 } 496 }
540 497
541 static void CallCollectSample(const v8::FunctionCallbackInfo<v8::Value>& info) { 498 static void CallCollectSample(const v8::FunctionCallbackInfo<v8::Value>& info) {
542 info.GetIsolate()->GetCpuProfiler()->CollectSample(); 499 info.GetIsolate()->GetCpuProfiler()->CollectSample();
543 } 500 }
544 501
545 static const char* cpu_profiler_test_source = "function loop(timeout) {\n" 502 static const char* cpu_profiler_test_source =
546 " this.mmm = 0;\n" 503 "%NeverOptimizeFunction(loop);\n"
547 " var start = Date.now();\n" 504 "%NeverOptimizeFunction(delay);\n"
548 " while (Date.now() - start < timeout) {\n" 505 "%NeverOptimizeFunction(bar);\n"
549 " var n = 100*1000;\n" 506 "%NeverOptimizeFunction(baz);\n"
550 " while(n > 1) {\n" 507 "%NeverOptimizeFunction(foo);\n"
551 " n--;\n" 508 "%NeverOptimizeFunction(start);\n"
552 " this.mmm += n * n * n;\n" 509 "function loop(timeout) {\n"
553 " }\n" 510 " this.mmm = 0;\n"
554 " }\n" 511 " var start = Date.now();\n"
555 "}\n" 512 " do {\n"
556 "function delay() { try { loop(10); } catch(e) { } }\n" 513 " var n = 1000;\n"
557 "function bar() { delay(); }\n" 514 " while(n > 1) {\n"
558 "function baz() { delay(); }\n" 515 " n--;\n"
559 "function foo() {\n" 516 " this.mmm += n * n * n;\n"
560 " try {\n" 517 " }\n"
561 " delay();\n" 518 " } while (Date.now() - start < timeout);\n"
562 " bar();\n" 519 "}\n"
563 " delay();\n" 520 "function delay() { loop(10); }\n"
564 " baz();\n" 521 "function bar() { delay(); }\n"
565 " } catch (e) { }\n" 522 "function baz() { delay(); }\n"
566 "}\n" 523 "function foo() {\n"
567 "function start(timeout) {\n" 524 " delay();\n"
568 " var start = Date.now();\n" 525 " bar();\n"
569 " do {\n" 526 " delay();\n"
570 " foo();\n" 527 " baz();\n"
571 " var duration = Date.now() - start;\n" 528 "}\n"
572 " } while (duration < timeout);\n" 529 "function start(duration) {\n"
573 " return duration;\n" 530 " var start = Date.now();\n"
574 "}\n"; 531 " do {\n"
575 532 " foo();\n"
533 " } while (Date.now() - start < duration);\n"
534 "}\n";
576 535
577 // Check that the profile tree for the script above will look like the 536 // Check that the profile tree for the script above will look like the
578 // following: 537 // following:
579 // 538 //
580 // [Top down]: 539 // [Top down]:
581 // 1062 0 (root) [-1] 540 // 1062 0 (root) [-1]
582 // 1054 0 start [-1] 541 // 1054 0 start [-1]
583 // 1054 1 foo [-1] 542 // 1054 1 foo [-1]
584 // 265 0 baz [-1] 543 // 265 0 baz [-1]
585 // 265 1 delay [-1] 544 // 265 1 delay [-1]
586 // 264 264 loop [-1] 545 // 264 264 loop [-1]
587 // 525 3 delay [-1] 546 // 525 3 delay [-1]
588 // 522 522 loop [-1] 547 // 522 522 loop [-1]
589 // 263 0 bar [-1] 548 // 263 0 bar [-1]
590 // 263 1 delay [-1] 549 // 263 1 delay [-1]
591 // 262 262 loop [-1] 550 // 262 262 loop [-1]
592 // 2 2 (program) [-1] 551 // 2 2 (program) [-1]
593 // 6 6 (garbage collector) [-1] 552 // 6 6 (garbage collector) [-1]
594 TEST(CollectCpuProfile) { 553 TEST(CollectCpuProfile) {
554 i::FLAG_allow_natives_syntax = true;
595 LocalContext env; 555 LocalContext env;
596 v8::HandleScope scope(env->GetIsolate()); 556 v8::HandleScope scope(env->GetIsolate());
597 557
598 CompileRun(cpu_profiler_test_source); 558 CompileRun(cpu_profiler_test_source);
599 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 559 v8::Local<v8::Function> function = GetFunction(env.local(), "start");
600 560
601 int32_t profiling_interval_ms = 200; 561 int32_t profiling_interval_ms = 200;
602 v8::Local<v8::Value> args[] = { 562 v8::Local<v8::Value> args[] = {
603 v8::Integer::New(env->GetIsolate(), profiling_interval_ms)}; 563 v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
604 v8::CpuProfile* profile = 564 v8::CpuProfile* profile =
605 RunProfiler(env.local(), function, args, arraysize(args), 200); 565 RunProfiler(env.local(), function, args, arraysize(args), 1000);
606 function->Call(env.local(), env->Global(), arraysize(args), args)
607 .ToLocalChecked();
608 566
609 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 567 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
568 const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
569 const v8::CpuProfileNode* foo_node = GetChild(env.local(), start_node, "foo");
610 570
611 ScopedVector<v8::Local<v8::String> > names(3); 571 const char* bar_branch[] = {"bar", "delay", "loop"};
612 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName); 572 CheckSimpleBranch(env.local(), foo_node, bar_branch, arraysize(bar_branch));
613 names[1] = v8_str(ProfileGenerator::kProgramEntryName); 573 const char* baz_branch[] = {"baz", "delay", "loop"};
614 names[2] = v8_str("start"); 574 CheckSimpleBranch(env.local(), foo_node, baz_branch, arraysize(baz_branch));
615 CheckChildrenNames(env.local(), root, names); 575 const char* delay_branch[] = {"delay", "loop"};
616 576 CheckSimpleBranch(env.local(), foo_node, delay_branch,
617 const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start"); 577 arraysize(delay_branch));
618 CHECK_EQ(1, startNode->GetChildrenCount());
619
620 const v8::CpuProfileNode* fooNode = GetChild(env.local(), startNode, "foo");
621 CHECK_EQ(3, fooNode->GetChildrenCount());
622
623 const char* barBranch[] = { "bar", "delay", "loop" };
624 CheckSimpleBranch(env.local(), fooNode, barBranch, arraysize(barBranch));
625 const char* bazBranch[] = { "baz", "delay", "loop" };
626 CheckSimpleBranch(env.local(), fooNode, bazBranch, arraysize(bazBranch));
627 const char* delayBranch[] = { "delay", "loop" };
628 CheckSimpleBranch(env.local(), fooNode, delayBranch, arraysize(delayBranch));
629 578
630 profile->Delete(); 579 profile->Delete();
631 } 580 }
632 581
633
634 static const char* hot_deopt_no_frame_entry_test_source = 582 static const char* hot_deopt_no_frame_entry_test_source =
635 "function foo(a, b) {\n" 583 "%NeverOptimizeFunction(foo);\n"
636 " try {\n" 584 "%NeverOptimizeFunction(start);\n"
637 " return a + b;\n" 585 "function foo(a, b) {\n"
638 " } catch (e) { }\n" 586 " return a + b;\n"
639 "}\n" 587 "}\n"
640 "function start(timeout) {\n" 588 "function start(timeout) {\n"
641 " var start = Date.now();\n" 589 " var start = Date.now();\n"
642 " do {\n" 590 " do {\n"
643 " for (var i = 1; i < 1000; ++i) foo(1, i);\n" 591 " for (var i = 1; i < 1000; ++i) foo(1, i);\n"
644 " var duration = Date.now() - start;\n" 592 " var duration = Date.now() - start;\n"
645 " } while (duration < timeout);\n" 593 " } while (duration < timeout);\n"
646 " return duration;\n" 594 " return duration;\n"
647 "}\n"; 595 "}\n";
648 596
649 // Check that the profile tree for the script above will look like the 597 // Check that the profile tree for the script above will look like the
650 // following: 598 // following:
651 // 599 //
652 // [Top down]: 600 // [Top down]:
653 // 1062 0 (root) [-1] 601 // 1062 0 (root) [-1]
654 // 1054 0 start [-1] 602 // 1054 0 start [-1]
655 // 1054 1 foo [-1] 603 // 1054 1 foo [-1]
656 // 2 2 (program) [-1] 604 // 2 2 (program) [-1]
657 // 6 6 (garbage collector) [-1] 605 // 6 6 (garbage collector) [-1]
658 // 606 //
659 // The test checks no FP ranges are present in a deoptimized funcion. 607 // The test checks no FP ranges are present in a deoptimized funcion.
660 // If 'foo' has no ranges the samples falling into the prologue will miss the 608 // If 'foo' has no ranges the samples falling into the prologue will miss the
661 // 'start' function on the stack, so 'foo' will be attached to the (root). 609 // 'start' function on the stack, so 'foo' will be attached to the (root).
662 TEST(HotDeoptNoFrameEntry) { 610 TEST(HotDeoptNoFrameEntry) {
611 i::FLAG_allow_natives_syntax = true;
663 LocalContext env; 612 LocalContext env;
664 v8::HandleScope scope(env->GetIsolate()); 613 v8::HandleScope scope(env->GetIsolate());
665 614
666 CompileRun(hot_deopt_no_frame_entry_test_source); 615 CompileRun(hot_deopt_no_frame_entry_test_source);
667 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 616 v8::Local<v8::Function> function = GetFunction(env.local(), "start");
668 617
669 int32_t profiling_interval_ms = 200; 618 int32_t profiling_interval_ms = 200;
670 v8::Local<v8::Value> args[] = { 619 v8::Local<v8::Value> args[] = {
671 v8::Integer::New(env->GetIsolate(), profiling_interval_ms)}; 620 v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
672 v8::CpuProfile* profile = 621 v8::CpuProfile* profile =
673 RunProfiler(env.local(), function, args, arraysize(args), 200); 622 RunProfiler(env.local(), function, args, arraysize(args), 1000);
674 function->Call(env.local(), env->Global(), arraysize(args), args) 623 function->Call(env.local(), env->Global(), arraysize(args), args)
675 .ToLocalChecked(); 624 .ToLocalChecked();
676 625
677 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 626 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
678 627 const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
679 ScopedVector<v8::Local<v8::String> > names(3); 628 GetChild(env.local(), start_node, "foo");
680 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
681 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
682 names[2] = v8_str("start");
683 CheckChildrenNames(env.local(), root, names);
684
685 const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
686 CHECK_EQ(1, startNode->GetChildrenCount());
687
688 GetChild(env.local(), startNode, "foo");
689 629
690 profile->Delete(); 630 profile->Delete();
691 } 631 }
692 632
693
694 TEST(CollectCpuProfileSamples) { 633 TEST(CollectCpuProfileSamples) {
634 i::FLAG_allow_natives_syntax = true;
695 LocalContext env; 635 LocalContext env;
696 v8::HandleScope scope(env->GetIsolate()); 636 v8::HandleScope scope(env->GetIsolate());
697 637
698 CompileRun(cpu_profiler_test_source); 638 CompileRun(cpu_profiler_test_source);
699 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 639 v8::Local<v8::Function> function = GetFunction(env.local(), "start");
700 640
701 int32_t profiling_interval_ms = 200; 641 int32_t profiling_interval_ms = 200;
702 v8::Local<v8::Value> args[] = { 642 v8::Local<v8::Value> args[] = {
703 v8::Integer::New(env->GetIsolate(), profiling_interval_ms)}; 643 v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
704 v8::CpuProfile* profile = 644 v8::CpuProfile* profile =
705 RunProfiler(env.local(), function, args, arraysize(args), 200, true); 645 RunProfiler(env.local(), function, args, arraysize(args), 1000, true);
706 646
707 CHECK_LE(200, profile->GetSamplesCount()); 647 CHECK_LE(200, profile->GetSamplesCount());
708 uint64_t end_time = profile->GetEndTime(); 648 uint64_t end_time = profile->GetEndTime();
709 uint64_t current_time = profile->GetStartTime(); 649 uint64_t current_time = profile->GetStartTime();
710 CHECK_LE(current_time, end_time); 650 CHECK_LE(current_time, end_time);
711 for (int i = 0; i < profile->GetSamplesCount(); i++) { 651 for (int i = 0; i < profile->GetSamplesCount(); i++) {
712 CHECK(profile->GetSample(i)); 652 CHECK(profile->GetSample(i));
713 uint64_t timestamp = profile->GetSampleTimestamp(i); 653 uint64_t timestamp = profile->GetSampleTimestamp(i);
714 CHECK_LE(current_time, timestamp); 654 CHECK_LE(current_time, timestamp);
715 CHECK_LE(timestamp, end_time); 655 CHECK_LE(timestamp, end_time);
716 current_time = timestamp; 656 current_time = timestamp;
717 } 657 }
718 658
719 profile->Delete(); 659 profile->Delete();
720 } 660 }
721 661
722 662 static const char* cpu_profiler_test_source2 =
723 static const char* cpu_profiler_test_source2 = "function loop() {}\n" 663 "%NeverOptimizeFunction(loop);\n"
724 "function delay() { loop(); }\n" 664 "%NeverOptimizeFunction(delay);\n"
725 "function start(count) {\n" 665 "%NeverOptimizeFunction(start);\n"
726 " var k = 0;\n" 666 "function loop() {}\n"
727 " do {\n" 667 "function delay() { loop(); }\n"
728 " delay();\n" 668 "function start(duration) {\n"
729 " } while (++k < count*100*1000);\n" 669 " var start = Date.now();\n"
730 "}\n"; 670 " do {\n"
671 " for (var i = 0; i < 10000; ++i) delay();\n"
672 " } while (Date.now() - start < duration);\n"
673 "}";
731 674
732 // Check that the profile tree doesn't contain unexpected traces: 675 // Check that the profile tree doesn't contain unexpected traces:
733 // - 'loop' can be called only by 'delay' 676 // - 'loop' can be called only by 'delay'
734 // - 'delay' may be called only by 'start' 677 // - 'delay' may be called only by 'start'
735 // The profile will look like the following: 678 // The profile will look like the following:
736 // 679 //
737 // [Top down]: 680 // [Top down]:
738 // 135 0 (root) [-1] #1 681 // 135 0 (root) [-1] #1
739 // 121 72 start [-1] #3 682 // 121 72 start [-1] #3
740 // 49 33 delay [-1] #4 683 // 49 33 delay [-1] #4
741 // 16 16 loop [-1] #5 684 // 16 16 loop [-1] #5
742 // 14 14 (program) [-1] #2 685 // 14 14 (program) [-1] #2
743 TEST(SampleWhenFrameIsNotSetup) { 686 TEST(SampleWhenFrameIsNotSetup) {
687 i::FLAG_allow_natives_syntax = true;
744 LocalContext env; 688 LocalContext env;
745 v8::HandleScope scope(env->GetIsolate()); 689 v8::HandleScope scope(env->GetIsolate());
746 690
747 CompileRun(cpu_profiler_test_source2); 691 CompileRun(cpu_profiler_test_source2);
748 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 692 v8::Local<v8::Function> function = GetFunction(env.local(), "start");
749 693
750 int32_t repeat_count = 100; 694 int32_t duration_ms = 100;
751 #if defined(USE_SIMULATOR)
752 // Simulators are much slower.
753 repeat_count = 1;
754 #endif
755 v8::Local<v8::Value> args[] = { 695 v8::Local<v8::Value> args[] = {
756 v8::Integer::New(env->GetIsolate(), repeat_count)}; 696 v8::Integer::New(env->GetIsolate(), duration_ms)};
757 v8::CpuProfile* profile = 697 v8::CpuProfile* profile =
758 RunProfiler(env.local(), function, args, arraysize(args), 100); 698 RunProfiler(env.local(), function, args, arraysize(args), 1000);
759 699
760 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 700 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
761 701 const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
762 ScopedVector<v8::Local<v8::String> > names(3); 702 const v8::CpuProfileNode* delay_node =
763 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName); 703 GetChild(env.local(), start_node, "delay");
764 names[1] = v8_str(ProfileGenerator::kProgramEntryName); 704 GetChild(env.local(), delay_node, "loop");
765 names[2] = v8_str("start");
766 CheckChildrenNames(env.local(), root, names);
767
768 const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
769 // On slow machines there may be no meaningfull samples at all, skip the
770 // check there.
771 if (startNode && startNode->GetChildrenCount() > 0) {
772 CHECK_EQ(1, startNode->GetChildrenCount());
773 const v8::CpuProfileNode* delayNode =
774 GetChild(env.local(), startNode, "delay");
775 if (delayNode->GetChildrenCount() > 0) {
776 CHECK_EQ(1, delayNode->GetChildrenCount());
777 GetChild(env.local(), delayNode, "loop");
778 }
779 }
780 705
781 profile->Delete(); 706 profile->Delete();
782 } 707 }
783 708
784
785 static const char* native_accessor_test_source = "function start(count) {\n" 709 static const char* native_accessor_test_source = "function start(count) {\n"
786 " for (var i = 0; i < count; i++) {\n" 710 " for (var i = 0; i < count; i++) {\n"
787 " var o = instance.foo;\n" 711 " var o = instance.foo;\n"
788 " instance.foo = o + 1;\n" 712 " instance.foo = o + 1;\n"
789 " }\n" 713 " }\n"
790 "}\n"; 714 "}\n";
791 715
792
793 class TestApiCallbacks { 716 class TestApiCallbacks {
794 public: 717 public:
795 explicit TestApiCallbacks(int min_duration_ms) 718 explicit TestApiCallbacks(int min_duration_ms)
796 : min_duration_ms_(min_duration_ms), 719 : min_duration_ms_(min_duration_ms),
797 is_warming_up_(false) {} 720 is_warming_up_(false) {}
798 721
799 static void Getter(v8::Local<v8::String> name, 722 static void Getter(v8::Local<v8::String> name,
800 const v8::PropertyCallbackInfo<v8::Value>& info) { 723 const v8::PropertyCallbackInfo<v8::Value>& info) {
801 TestApiCallbacks* data = fromInfo(info); 724 TestApiCallbacks* data = FromInfo(info);
802 data->Wait(); 725 data->Wait();
803 } 726 }
804 727
805 static void Setter(v8::Local<v8::String> name, 728 static void Setter(v8::Local<v8::String> name,
806 v8::Local<v8::Value> value, 729 v8::Local<v8::Value> value,
807 const v8::PropertyCallbackInfo<void>& info) { 730 const v8::PropertyCallbackInfo<void>& info) {
808 TestApiCallbacks* data = fromInfo(info); 731 TestApiCallbacks* data = FromInfo(info);
809 data->Wait(); 732 data->Wait();
810 } 733 }
811 734
812 static void Callback(const v8::FunctionCallbackInfo<v8::Value>& info) { 735 static void Callback(const v8::FunctionCallbackInfo<v8::Value>& info) {
813 TestApiCallbacks* data = fromInfo(info); 736 TestApiCallbacks* data = FromInfo(info);
814 data->Wait(); 737 data->Wait();
815 } 738 }
816 739
817 void set_warming_up(bool value) { is_warming_up_ = value; } 740 void set_warming_up(bool value) { is_warming_up_ = value; }
818 741
819 private: 742 private:
820 void Wait() { 743 void Wait() {
821 if (is_warming_up_) return; 744 if (is_warming_up_) return;
822 double start = v8::base::OS::TimeCurrentMillis(); 745 double start = v8::base::OS::TimeCurrentMillis();
823 double duration = 0; 746 double duration = 0;
824 while (duration < min_duration_ms_) { 747 while (duration < min_duration_ms_) {
825 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1)); 748 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1));
826 duration = v8::base::OS::TimeCurrentMillis() - start; 749 duration = v8::base::OS::TimeCurrentMillis() - start;
827 } 750 }
828 } 751 }
829 752
830 template<typename T> 753 template <typename T>
831 static TestApiCallbacks* fromInfo(const T& info) { 754 static TestApiCallbacks* FromInfo(const T& info) {
832 void* data = v8::External::Cast(*info.Data())->Value(); 755 void* data = v8::External::Cast(*info.Data())->Value();
833 return reinterpret_cast<TestApiCallbacks*>(data); 756 return reinterpret_cast<TestApiCallbacks*>(data);
834 } 757 }
835 758
836 int min_duration_ms_; 759 int min_duration_ms_;
837 bool is_warming_up_; 760 bool is_warming_up_;
838 }; 761 };
839 762
840 763
841 // Test that native accessors are properly reported in the CPU profile. 764 // Test that native accessors are properly reported in the CPU profile.
(...skipping 23 matching lines...) Expand all
865 788
866 CompileRun(native_accessor_test_source); 789 CompileRun(native_accessor_test_source);
867 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 790 v8::Local<v8::Function> function = GetFunction(env.local(), "start");
868 791
869 int32_t repeat_count = 1; 792 int32_t repeat_count = 1;
870 v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)}; 793 v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
871 v8::CpuProfile* profile = 794 v8::CpuProfile* profile =
872 RunProfiler(env.local(), function, args, arraysize(args), 180); 795 RunProfiler(env.local(), function, args, arraysize(args), 180);
873 796
874 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 797 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
875 const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start"); 798 const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
876 GetChild(env.local(), startNode, "get foo"); 799 GetChild(env.local(), start_node, "get foo");
877 GetChild(env.local(), startNode, "set foo"); 800 GetChild(env.local(), start_node, "set foo");
878 801
879 profile->Delete(); 802 profile->Delete();
880 } 803 }
881 804
882 805
883 // Test that native accessors are properly reported in the CPU profile. 806 // Test that native accessors are properly reported in the CPU profile.
884 // This test makes sure that the accessors are called enough times to become 807 // This test makes sure that the accessors are called enough times to become
885 // hot and to trigger optimizations. 808 // hot and to trigger optimizations.
886 TEST(NativeAccessorMonomorphicIC) { 809 TEST(NativeAccessorMonomorphicIC) {
887 LocalContext env; 810 LocalContext env;
(...skipping 30 matching lines...) Expand all
918 .ToLocalChecked(); 841 .ToLocalChecked();
919 accessors.set_warming_up(false); 842 accessors.set_warming_up(false);
920 } 843 }
921 844
922 int32_t repeat_count = 100; 845 int32_t repeat_count = 100;
923 v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)}; 846 v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
924 v8::CpuProfile* profile = 847 v8::CpuProfile* profile =
925 RunProfiler(env.local(), function, args, arraysize(args), 200); 848 RunProfiler(env.local(), function, args, arraysize(args), 200);
926 849
927 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 850 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
928 const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start"); 851 const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
929 GetChild(env.local(), startNode, "get foo"); 852 GetChild(env.local(), start_node, "get foo");
930 GetChild(env.local(), startNode, "set foo"); 853 GetChild(env.local(), start_node, "set foo");
931 854
932 profile->Delete(); 855 profile->Delete();
933 } 856 }
934 857
935 858
936 static const char* native_method_test_source = "function start(count) {\n" 859 static const char* native_method_test_source = "function start(count) {\n"
937 " for (var i = 0; i < count; i++) {\n" 860 " for (var i = 0; i < count; i++) {\n"
938 " instance.fooMethod();\n" 861 " instance.fooMethod();\n"
939 " }\n" 862 " }\n"
940 "}\n"; 863 "}\n";
(...skipping 28 matching lines...) Expand all
969 892
970 CompileRun(native_method_test_source); 893 CompileRun(native_method_test_source);
971 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 894 v8::Local<v8::Function> function = GetFunction(env.local(), "start");
972 895
973 int32_t repeat_count = 1; 896 int32_t repeat_count = 1;
974 v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)}; 897 v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
975 v8::CpuProfile* profile = 898 v8::CpuProfile* profile =
976 RunProfiler(env.local(), function, args, arraysize(args), 100); 899 RunProfiler(env.local(), function, args, arraysize(args), 100);
977 900
978 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 901 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
979 const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start"); 902 const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
980 GetChild(env.local(), startNode, "fooMethod"); 903 GetChild(env.local(), start_node, "fooMethod");
981 904
982 profile->Delete(); 905 profile->Delete();
983 } 906 }
984 907
985 908
986 TEST(NativeMethodMonomorphicIC) { 909 TEST(NativeMethodMonomorphicIC) {
987 LocalContext env; 910 LocalContext env;
988 v8::Isolate* isolate = env->GetIsolate(); 911 v8::Isolate* isolate = env->GetIsolate();
989 v8::HandleScope scope(isolate); 912 v8::HandleScope scope(isolate);
990 913
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 callbacks.set_warming_up(false); 947 callbacks.set_warming_up(false);
1025 } 948 }
1026 949
1027 int32_t repeat_count = 100; 950 int32_t repeat_count = 100;
1028 v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)}; 951 v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
1029 v8::CpuProfile* profile = 952 v8::CpuProfile* profile =
1030 RunProfiler(env.local(), function, args, arraysize(args), 100); 953 RunProfiler(env.local(), function, args, arraysize(args), 100);
1031 954
1032 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 955 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1033 GetChild(env.local(), root, "start"); 956 GetChild(env.local(), root, "start");
1034 const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start"); 957 const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
1035 GetChild(env.local(), startNode, "fooMethod"); 958 GetChild(env.local(), start_node, "fooMethod");
1036 959
1037 profile->Delete(); 960 profile->Delete();
1038 } 961 }
1039 962
1040 963
1041 static const char* bound_function_test_source = 964 static const char* bound_function_test_source =
1042 "function foo() {\n" 965 "function foo() {\n"
1043 " startProfiling('my_profile');\n" 966 " startProfiling('my_profile');\n"
1044 "}\n" 967 "}\n"
1045 "function start() {\n" 968 "function start() {\n"
1046 " var callback = foo.bind(this);\n" 969 " var callback = foo.bind(this);\n"
1047 " callback();\n" 970 " callback();\n"
1048 "}"; 971 "}";
1049 972
1050 973
1051 TEST(BoundFunctionCall) { 974 TEST(BoundFunctionCall) {
1052 v8::HandleScope scope(CcTest::isolate()); 975 v8::HandleScope scope(CcTest::isolate());
1053 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 976 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1054 v8::Context::Scope context_scope(env); 977 v8::Context::Scope context_scope(env);
1055 978
1056 CompileRun(bound_function_test_source); 979 CompileRun(bound_function_test_source);
1057 v8::Local<v8::Function> function = GetFunction(env, "start"); 980 v8::Local<v8::Function> function = GetFunction(env, "start");
1058 981
1059 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0); 982 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
1060 983
1061 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 984 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1062 ScopedVector<v8::Local<v8::String> > names(3);
1063 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
1064 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
1065 names[2] = v8_str("start");
1066 // Don't allow |foo| node to be at the top level.
1067 CheckChildrenNames(env, root, names);
1068 985
1069 const v8::CpuProfileNode* startNode = GetChild(env, root, "start"); 986 const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
1070 GetChild(env, startNode, "foo"); 987 GetChild(env, start_node, "foo");
1071 988
1072 profile->Delete(); 989 profile->Delete();
1073 } 990 }
1074 991
1075 992
1076 // This tests checks distribution of the samples through the source lines. 993 // This tests checks distribution of the samples through the source lines.
1077 TEST(TickLines) { 994 TEST(TickLines) {
1078 CcTest::InitializeVM(); 995 CcTest::InitializeVM();
1079 LocalContext env; 996 LocalContext env;
1080 i::FLAG_turbo_source_positions = true; 997 i::FLAG_turbo_source_positions = true;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 CHECK(func_node->GetLineTicks(&entries[0], line_count)); 1080 CHECK(func_node->GetLineTicks(&entries[0], line_count));
1164 int value = 0; 1081 int value = 0;
1165 for (int i = 0; i < entries.length(); i++) 1082 for (int i = 0; i < entries.length(); i++)
1166 if (entries[i].line == hit_line) { 1083 if (entries[i].line == hit_line) {
1167 value = entries[i].hit_count; 1084 value = entries[i].hit_count;
1168 break; 1085 break;
1169 } 1086 }
1170 CHECK_EQ(hit_count, value); 1087 CHECK_EQ(hit_count, value);
1171 } 1088 }
1172 1089
1173 1090 static const char* call_function_test_source =
1174 static const char* call_function_test_source = "function bar(iterations) {\n" 1091 "%NeverOptimizeFunction(bar);\n"
1175 "}\n" 1092 "%NeverOptimizeFunction(start);\n"
1176 "function start(duration) {\n" 1093 "function bar(n) {\n"
1177 " var start = Date.now();\n" 1094 " var s = 0;\n"
1178 " while (Date.now() - start < duration) {\n" 1095 " for (var i = 0; i < n; i++) s += i * i * i;\n"
1179 " try {\n" 1096 " return s;\n"
1180 " bar.call(this, 10 * 1000);\n" 1097 "}\n"
1181 " } catch(e) {}\n" 1098 "function start(duration) {\n"
1182 " }\n" 1099 " var start = Date.now();\n"
1183 "}"; 1100 " do {\n"
1184 1101 " for (var i = 0; i < 100; ++i)\n"
1102 " bar.call(this, 1000);\n"
1103 " } while (Date.now() - start < duration);\n"
1104 "}";
1185 1105
1186 // Test that if we sampled thread when it was inside FunctionCall buitin then 1106 // Test that if we sampled thread when it was inside FunctionCall buitin then
1187 // its caller frame will be '(unresolved function)' as we have no reliable way 1107 // its caller frame will be '(unresolved function)' as we have no reliable way
1188 // to resolve it. 1108 // to resolve it.
1189 // 1109 //
1190 // [Top down]: 1110 // [Top down]:
1191 // 96 0 (root) [-1] #1 1111 // 96 0 (root) [-1] #1
1192 // 1 1 (garbage collector) [-1] #4 1112 // 1 1 (garbage collector) [-1] #4
1193 // 5 0 (unresolved function) [-1] #5 1113 // 5 0 (unresolved function) [-1] #5
1194 // 5 5 call [-1] #6 1114 // 5 5 call [-1] #6
1195 // 71 70 start [-1] #3 1115 // 71 70 start [-1] #3
1196 // 1 1 bar [-1] #7 1116 // 1 1 bar [-1] #7
1197 // 19 19 (program) [-1] #2 1117 // 19 19 (program) [-1] #2
1198 TEST(FunctionCallSample) { 1118 TEST(FunctionCallSample) {
1119 i::FLAG_allow_natives_syntax = true;
1199 LocalContext env; 1120 LocalContext env;
1200 v8::HandleScope scope(env->GetIsolate()); 1121 v8::HandleScope scope(env->GetIsolate());
1201 1122
1202 // Collect garbage that might have be generated while installing 1123 // Collect garbage that might have be generated while installing
1203 // extensions. 1124 // extensions.
1204 CcTest::heap()->CollectAllGarbage(); 1125 CcTest::heap()->CollectAllGarbage();
1205 1126
1206 CompileRun(call_function_test_source); 1127 CompileRun(call_function_test_source);
1207 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 1128 v8::Local<v8::Function> function = GetFunction(env.local(), "start");
1208 1129
1209 int32_t duration_ms = 100; 1130 int32_t duration_ms = 100;
1210 v8::Local<v8::Value> args[] = { 1131 v8::Local<v8::Value> args[] = {
1211 v8::Integer::New(env->GetIsolate(), duration_ms)}; 1132 v8::Integer::New(env->GetIsolate(), duration_ms)};
1212 v8::CpuProfile* profile = 1133 v8::CpuProfile* profile =
1213 RunProfiler(env.local(), function, args, arraysize(args), 100); 1134 RunProfiler(env.local(), function, args, arraysize(args), 1000);
1214 1135
1215 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1136 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1216 { 1137 const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
1217 ScopedVector<v8::Local<v8::String> > names(4); 1138 GetChild(env.local(), start_node, "bar");
1218 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
1219 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
1220 names[2] = v8_str("start");
1221 names[3] = v8_str(i::ProfileGenerator::kUnresolvedFunctionName);
1222 // Don't allow |bar| and |call| nodes to be at the top level.
1223 CheckChildrenNames(env.local(), root, names);
1224 }
1225 1139
1226 // In case of GC stress tests all samples may be in GC phase and there 1140 const v8::CpuProfileNode* unresolved_node = FindChild(
1227 // won't be |start| node in the profiles.
1228 bool is_gc_stress_testing =
1229 (i::FLAG_gc_interval != -1) || i::FLAG_stress_compaction;
1230 const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
1231 CHECK(is_gc_stress_testing || startNode);
1232 if (startNode) {
1233 ScopedVector<v8::Local<v8::String> > names(2);
1234 names[0] = v8_str("bar");
1235 names[1] = v8_str("call");
1236 CheckChildrenNames(env.local(), startNode, names);
1237 }
1238
1239 const v8::CpuProfileNode* unresolvedNode = FindChild(
1240 env.local(), root, i::ProfileGenerator::kUnresolvedFunctionName); 1141 env.local(), root, i::ProfileGenerator::kUnresolvedFunctionName);
1241 if (unresolvedNode) { 1142 CHECK(!unresolved_node || GetChild(env.local(), unresolved_node, "call"));
1242 ScopedVector<v8::Local<v8::String> > names(1);
1243 names[0] = v8_str("call");
1244 CheckChildrenNames(env.local(), unresolvedNode, names);
1245 }
1246 1143
1247 profile->Delete(); 1144 profile->Delete();
1248 } 1145 }
1249 1146
1250
1251 static const char* function_apply_test_source = 1147 static const char* function_apply_test_source =
1252 "function bar(iterations) {\n" 1148 "%NeverOptimizeFunction(bar);\n"
1149 "%NeverOptimizeFunction(test);\n"
1150 "%NeverOptimizeFunction(start);\n"
1151 "function bar(n) {\n"
1152 " var s = 0;\n"
1153 " for (var i = 0; i < n; i++) s += i * i * i;\n"
1154 " return s;\n"
1253 "}\n" 1155 "}\n"
1254 "function test() {\n" 1156 "function test() {\n"
1255 " bar.apply(this, [10 * 1000]);\n" 1157 " bar.apply(this, [1000]);\n"
1256 "}\n" 1158 "}\n"
1257 "function start(duration) {\n" 1159 "function start(duration) {\n"
1258 " var start = Date.now();\n" 1160 " var start = Date.now();\n"
1259 " while (Date.now() - start < duration) {\n" 1161 " do {\n"
1260 " try {\n" 1162 " for (var i = 0; i < 100; ++i) test();\n"
1261 " test();\n" 1163 " } while (Date.now() - start < duration);\n"
1262 " } catch(e) {}\n"
1263 " }\n"
1264 "}"; 1164 "}";
1265 1165
1266
1267 // [Top down]: 1166 // [Top down]:
1268 // 94 0 (root) [-1] #0 1 1167 // 94 0 (root) [-1] #0 1
1269 // 2 2 (garbage collector) [-1] #0 7 1168 // 2 2 (garbage collector) [-1] #0 7
1270 // 82 49 start [-1] #16 3 1169 // 82 49 start [-1] #16 3
1271 // 1 0 (unresolved function) [-1] #0 8 1170 // 1 0 (unresolved function) [-1] #0 8
1272 // 1 1 apply [-1] #0 9 1171 // 1 1 apply [-1] #0 9
1273 // 32 21 test [-1] #16 4 1172 // 32 21 test [-1] #16 4
1274 // 2 2 bar [-1] #16 6 1173 // 2 2 bar [-1] #16 6
1275 // 9 9 apply [-1] #0 5
1276 // 10 10 (program) [-1] #0 2 1174 // 10 10 (program) [-1] #0 2
1277 TEST(FunctionApplySample) { 1175 TEST(FunctionApplySample) {
1176 i::FLAG_allow_natives_syntax = true;
1278 LocalContext env; 1177 LocalContext env;
1279 v8::HandleScope scope(env->GetIsolate()); 1178 v8::HandleScope scope(env->GetIsolate());
1280 1179
1281 CompileRun(function_apply_test_source); 1180 CompileRun(function_apply_test_source);
1282 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 1181 v8::Local<v8::Function> function = GetFunction(env.local(), "start");
1283 1182
1284 int32_t duration_ms = 100; 1183 int32_t duration_ms = 100;
1285 v8::Local<v8::Value> args[] = { 1184 v8::Local<v8::Value> args[] = {
1286 v8::Integer::New(env->GetIsolate(), duration_ms)}; 1185 v8::Integer::New(env->GetIsolate(), duration_ms)};
1287 1186
1288 v8::CpuProfile* profile = 1187 v8::CpuProfile* profile =
1289 RunProfiler(env.local(), function, args, arraysize(args), 100); 1188 RunProfiler(env.local(), function, args, arraysize(args), 1000);
1290 1189
1291 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1190 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1292 { 1191 const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
1293 ScopedVector<v8::Local<v8::String> > names(3); 1192 const v8::CpuProfileNode* test_node =
1294 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName); 1193 GetChild(env.local(), start_node, "test");
1295 names[1] = v8_str(ProfileGenerator::kProgramEntryName); 1194 GetChild(env.local(), test_node, "bar");
1296 names[2] = v8_str("start");
1297 // Don't allow |test|, |bar| and |apply| nodes to be at the top level.
1298 CheckChildrenNames(env.local(), root, names);
1299 }
1300 1195
1301 const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start"); 1196 const v8::CpuProfileNode* unresolved_node = FindChild(
1302 if (startNode) { 1197 env.local(), start_node, ProfileGenerator::kUnresolvedFunctionName);
1303 { 1198 CHECK(!unresolved_node || GetChild(env.local(), unresolved_node, "apply"));
1304 ScopedVector<v8::Local<v8::String> > names(2);
1305 names[0] = v8_str("test");
1306 names[1] = v8_str(ProfileGenerator::kUnresolvedFunctionName);
1307 CheckChildrenNames(env.local(), startNode, names);
1308 }
1309
1310 const v8::CpuProfileNode* testNode =
1311 FindChild(env.local(), startNode, "test");
1312 if (testNode) {
1313 ScopedVector<v8::Local<v8::String> > names(3);
1314 names[0] = v8_str("bar");
1315 names[1] = v8_str("apply");
1316 // apply calls "get length" before invoking the function itself
1317 // and we may get hit into it.
1318 names[2] = v8_str("get length");
1319 CheckChildrenNames(env.local(), testNode, names);
1320 }
1321
1322 if (const v8::CpuProfileNode* unresolvedNode =
1323 FindChild(env.local(), startNode,
1324 ProfileGenerator::kUnresolvedFunctionName)) {
1325 ScopedVector<v8::Local<v8::String> > names(1);
1326 names[0] = v8_str("apply");
1327 CheckChildrenNames(env.local(), unresolvedNode, names);
1328 GetChild(env.local(), unresolvedNode, "apply");
1329 }
1330 }
1331 1199
1332 profile->Delete(); 1200 profile->Delete();
1333 } 1201 }
1334 1202
1335
1336 static const char* cpu_profiler_deep_stack_test_source = 1203 static const char* cpu_profiler_deep_stack_test_source =
1337 "function foo(n) {\n" 1204 "function foo(n) {\n"
1338 " if (n)\n" 1205 " if (n)\n"
1339 " foo(n - 1);\n" 1206 " foo(n - 1);\n"
1340 " else\n" 1207 " else\n"
1341 " startProfiling('my_profile');\n" 1208 " collectSample();\n"
1342 "}\n" 1209 "}\n"
1343 "function start() {\n" 1210 "function start() {\n"
1344 " foo(250);\n" 1211 " startProfiling('my_profile');\n"
1345 "}\n"; 1212 " foo(250);\n"
1346 1213 "}\n";
1347 1214
1348 // Check a deep stack 1215 // Check a deep stack
1349 // 1216 //
1350 // [Top down]: 1217 // [Top down]:
1351 // 0 (root) 0 #1 1218 // 0 (root) 0 #1
1352 // 2 (program) 0 #2 1219 // 2 (program) 0 #2
1353 // 0 start 21 #3 no reason 1220 // 0 start 21 #3 no reason
1354 // 0 foo 21 #4 no reason 1221 // 0 foo 21 #4 no reason
1355 // 0 foo 21 #5 no reason 1222 // 0 foo 21 #5 no reason
1356 // .... 1223 // ....
1357 // 0 foo 21 #253 no reason 1224 // 0 foo 21 #254 no reason
1358 // 1 startProfiling 0 #254
1359 TEST(CpuProfileDeepStack) { 1225 TEST(CpuProfileDeepStack) {
1360 v8::HandleScope scope(CcTest::isolate()); 1226 v8::HandleScope scope(CcTest::isolate());
1361 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1227 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1362 v8::Context::Scope context_scope(env); 1228 v8::Context::Scope context_scope(env);
1363 1229
1364 CompileRun(cpu_profiler_deep_stack_test_source); 1230 CompileRun(cpu_profiler_deep_stack_test_source);
1365 v8::Local<v8::Function> function = GetFunction(env, "start"); 1231 v8::Local<v8::Function> function = GetFunction(env, "start");
1366 1232
1367 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); 1233 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
1368 v8::Local<v8::String> profile_name = v8_str("my_profile"); 1234 v8::Local<v8::String> profile_name = v8_str("my_profile");
1369 function->Call(env, env->Global(), 0, NULL).ToLocalChecked(); 1235 function->Call(env, env->Global(), 0, NULL).ToLocalChecked();
1370 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name); 1236 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
1371 CHECK(profile); 1237 CHECK(profile);
1372 // Dump collected profile to have a better diagnostic in case of failure. 1238 // Dump collected profile to have a better diagnostic in case of failure.
1373 reinterpret_cast<i::CpuProfile*>(profile)->Print(); 1239 reinterpret_cast<i::CpuProfile*>(profile)->Print();
1374 1240
1375 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1241 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1376 {
1377 ScopedVector<v8::Local<v8::String> > names(3);
1378 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
1379 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
1380 names[2] = v8_str("start");
1381 CheckChildrenNames(env, root, names);
1382 }
1383
1384 const v8::CpuProfileNode* node = GetChild(env, root, "start"); 1242 const v8::CpuProfileNode* node = GetChild(env, root, "start");
1385 for (int i = 0; i < 250; ++i) { 1243 for (int i = 0; i <= 250; ++i) {
1386 node = GetChild(env, node, "foo"); 1244 node = GetChild(env, node, "foo");
1387 } 1245 }
1388 // TODO(alph): 1246 CHECK(!FindChild(env, node, "foo"));
1389 // In theory there must be one more 'foo' and a 'startProfiling' nodes,
1390 // but due to unstable top frame extraction these might be missing.
1391 1247
1392 profile->Delete(); 1248 profile->Delete();
1393 } 1249 }
1394 1250
1395
1396 static const char* js_native_js_test_source = 1251 static const char* js_native_js_test_source =
1397 "function foo() {\n" 1252 "%NeverOptimizeFunction(foo);\n"
1398 " startProfiling('my_profile');\n" 1253 "%NeverOptimizeFunction(bar);\n"
1254 "%NeverOptimizeFunction(start);\n"
1255 "function foo(n) {\n"
1256 " var s = 0;\n"
1257 " for (var i = 0; i < n; i++) s += i * i * i;\n"
1258 " return s;\n"
1399 "}\n" 1259 "}\n"
1400 "function bar() {\n" 1260 "function bar() {\n"
1401 " try { foo(); } catch(e) {}\n" 1261 " foo(1000);\n"
1402 "}\n" 1262 "}\n"
1403 "function start() {\n" 1263 "function start() {\n"
1404 " try {\n" 1264 " CallJsFunction(bar);\n"
1405 " CallJsFunction(bar);\n"
1406 " } catch(e) {}\n"
1407 "}"; 1265 "}";
1408 1266
1409 static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) { 1267 static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
1410 v8::Local<v8::Function> function = info[0].As<v8::Function>(); 1268 v8::Local<v8::Function> function = info[0].As<v8::Function>();
1411 v8::Local<v8::Value> argv[] = {info[1]}; 1269 v8::Local<v8::Value> argv[] = {info[1]};
1412 function->Call(info.GetIsolate()->GetCurrentContext(), info.This(), 1270 function->Call(info.GetIsolate()->GetCurrentContext(), info.This(),
1413 arraysize(argv), argv) 1271 arraysize(argv), argv)
1414 .ToLocalChecked(); 1272 .ToLocalChecked();
1415 } 1273 }
1416 1274
1417
1418 // [Top down]: 1275 // [Top down]:
1419 // 58 0 (root) #0 1 1276 // 58 0 (root) #0 1
1420 // 2 2 (program) #0 2 1277 // 2 2 (program) #0 2
1421 // 56 1 start #16 3 1278 // 56 1 start #16 3
1422 // 55 0 CallJsFunction #0 4 1279 // 55 0 CallJsFunction #0 4
1423 // 55 1 bar #16 5 1280 // 55 1 bar #16 5
1424 // 54 54 foo #16 6 1281 // 54 54 foo #16 6
1425 TEST(JsNativeJsSample) { 1282 TEST(JsNativeJsSample) {
1283 i::FLAG_allow_natives_syntax = true;
1426 v8::HandleScope scope(CcTest::isolate()); 1284 v8::HandleScope scope(CcTest::isolate());
1427 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1285 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1428 v8::Context::Scope context_scope(env); 1286 v8::Context::Scope context_scope(env);
1429 1287
1430 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New( 1288 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
1431 env->GetIsolate(), CallJsFunction); 1289 env->GetIsolate(), CallJsFunction);
1432 v8::Local<v8::Function> func = 1290 v8::Local<v8::Function> func =
1433 func_template->GetFunction(env).ToLocalChecked(); 1291 func_template->GetFunction(env).ToLocalChecked();
1434 func->SetName(v8_str("CallJsFunction")); 1292 func->SetName(v8_str("CallJsFunction"));
1435 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust(); 1293 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust();
1436 1294
1437 CompileRun(js_native_js_test_source); 1295 CompileRun(js_native_js_test_source);
1438 v8::Local<v8::Function> function = GetFunction(env, "start"); 1296 v8::Local<v8::Function> function = GetFunction(env, "start");
1439 1297
1440 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0); 1298 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
1441 1299
1442 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1300 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1443 { 1301 const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
1444 ScopedVector<v8::Local<v8::String> > names(3); 1302 const v8::CpuProfileNode* native_node =
1445 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName); 1303 GetChild(env, start_node, "CallJsFunction");
1446 names[1] = v8_str(ProfileGenerator::kProgramEntryName); 1304 const v8::CpuProfileNode* bar_node = GetChild(env, native_node, "bar");
1447 names[2] = v8_str("start"); 1305 GetChild(env, bar_node, "foo");
1448 CheckChildrenNames(env, root, names);
1449 }
1450
1451 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
1452 CHECK_EQ(1, startNode->GetChildrenCount());
1453 const v8::CpuProfileNode* nativeFunctionNode =
1454 GetChild(env, startNode, "CallJsFunction");
1455
1456 CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
1457 const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar");
1458
1459 CHECK_EQ(1, barNode->GetChildrenCount());
1460 GetChild(env, barNode, "foo");
1461 1306
1462 profile->Delete(); 1307 profile->Delete();
1463 } 1308 }
1464 1309
1465
1466 static const char* js_native_js_runtime_js_test_source = 1310 static const char* js_native_js_runtime_js_test_source =
1467 "function foo() {\n" 1311 "%NeverOptimizeFunction(foo);\n"
1468 " startProfiling('my_profile');\n" 1312 "%NeverOptimizeFunction(bar);\n"
1313 "%NeverOptimizeFunction(start);\n"
1314 "function foo(n) {\n"
1315 " var s = 0;\n"
1316 " for (var i = 0; i < n; i++) s += i * i * i;\n"
1317 " return s;\n"
1469 "}\n" 1318 "}\n"
1470 "var bound = foo.bind(this);\n" 1319 "var bound = foo.bind(this);\n"
1471 "function bar() {\n" 1320 "function bar() {\n"
1472 " try { bound(); } catch(e) {}\n" 1321 " bound(1000);\n"
1473 "}\n" 1322 "}\n"
1474 "function start() {\n" 1323 "function start() {\n"
1475 " try {\n" 1324 " CallJsFunction(bar);\n"
1476 " CallJsFunction(bar);\n"
1477 " } catch(e) {}\n"
1478 "}"; 1325 "}";
1479 1326
1480
1481 // [Top down]: 1327 // [Top down]:
1482 // 57 0 (root) #0 1 1328 // 57 0 (root) #0 1
1483 // 55 1 start #16 3 1329 // 55 1 start #16 3
1484 // 54 0 CallJsFunction #0 4 1330 // 54 0 CallJsFunction #0 4
1485 // 54 3 bar #16 5 1331 // 54 3 bar #16 5
1486 // 51 51 foo #16 6 1332 // 51 51 foo #16 6
1487 // 2 2 (program) #0 2 1333 // 2 2 (program) #0 2
1488 TEST(JsNativeJsRuntimeJsSample) { 1334 TEST(JsNativeJsRuntimeJsSample) {
1335 i::FLAG_allow_natives_syntax = true;
1489 v8::HandleScope scope(CcTest::isolate()); 1336 v8::HandleScope scope(CcTest::isolate());
1490 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1337 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1491 v8::Context::Scope context_scope(env); 1338 v8::Context::Scope context_scope(env);
1492 1339
1493 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New( 1340 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
1494 env->GetIsolate(), CallJsFunction); 1341 env->GetIsolate(), CallJsFunction);
1495 v8::Local<v8::Function> func = 1342 v8::Local<v8::Function> func =
1496 func_template->GetFunction(env).ToLocalChecked(); 1343 func_template->GetFunction(env).ToLocalChecked();
1497 func->SetName(v8_str("CallJsFunction")); 1344 func->SetName(v8_str("CallJsFunction"));
1498 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust(); 1345 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust();
1499 1346
1500 CompileRun(js_native_js_runtime_js_test_source); 1347 CompileRun(js_native_js_runtime_js_test_source);
1501 v8::Local<v8::Function> function = GetFunction(env, "start"); 1348 v8::Local<v8::Function> function = GetFunction(env, "start");
1502 1349 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
1503 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
1504 1350
1505 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1351 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1506 ScopedVector<v8::Local<v8::String> > names(3); 1352 const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
1507 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName); 1353 const v8::CpuProfileNode* native_node =
1508 names[1] = v8_str(ProfileGenerator::kProgramEntryName); 1354 GetChild(env, start_node, "CallJsFunction");
1509 names[2] = v8_str("start"); 1355 const v8::CpuProfileNode* bar_node = GetChild(env, native_node, "bar");
1510 CheckChildrenNames(env, root, names); 1356 GetChild(env, bar_node, "foo");
1511
1512 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
1513 CHECK_EQ(1, startNode->GetChildrenCount());
1514 const v8::CpuProfileNode* nativeFunctionNode =
1515 GetChild(env, startNode, "CallJsFunction");
1516
1517 CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
1518 const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar");
1519
1520 // The child is in fact a bound foo.
1521 // A bound function has a wrapper that may make calls to
1522 // other functions e.g. "get length".
1523 CHECK_LE(1, barNode->GetChildrenCount());
1524 CHECK_GE(2, barNode->GetChildrenCount());
1525 GetChild(env, barNode, "foo");
1526 1357
1527 profile->Delete(); 1358 profile->Delete();
1528 } 1359 }
1529 1360
1530
1531 static void CallJsFunction2(const v8::FunctionCallbackInfo<v8::Value>& info) { 1361 static void CallJsFunction2(const v8::FunctionCallbackInfo<v8::Value>& info) {
1532 v8::base::OS::Print("In CallJsFunction2\n"); 1362 v8::base::OS::Print("In CallJsFunction2\n");
1533 CallJsFunction(info); 1363 CallJsFunction(info);
1534 } 1364 }
1535 1365
1536
1537 static const char* js_native1_js_native2_js_test_source = 1366 static const char* js_native1_js_native2_js_test_source =
1367 "%NeverOptimizeFunction(foo);\n"
1368 "%NeverOptimizeFunction(bar);\n"
1369 "%NeverOptimizeFunction(start);\n"
1538 "function foo() {\n" 1370 "function foo() {\n"
1539 " try {\n" 1371 " var s = 0;\n"
1540 " startProfiling('my_profile');\n" 1372 " for (var i = 0; i < 1000; i++) s += i * i * i;\n"
1541 " } catch(e) {}\n" 1373 " return s;\n"
1542 "}\n" 1374 "}\n"
1543 "function bar() {\n" 1375 "function bar() {\n"
1544 " CallJsFunction2(foo);\n" 1376 " CallJsFunction2(foo);\n"
1545 "}\n" 1377 "}\n"
1546 "function start() {\n" 1378 "function start() {\n"
1547 " try {\n" 1379 " CallJsFunction1(bar);\n"
1548 " CallJsFunction1(bar);\n"
1549 " } catch(e) {}\n"
1550 "}"; 1380 "}";
1551 1381
1552
1553 // [Top down]: 1382 // [Top down]:
1554 // 57 0 (root) #0 1 1383 // 57 0 (root) #0 1
1555 // 55 1 start #16 3 1384 // 55 1 start #16 3
1556 // 54 0 CallJsFunction1 #0 4 1385 // 54 0 CallJsFunction1 #0 4
1557 // 54 0 bar #16 5 1386 // 54 0 bar #16 5
1558 // 54 0 CallJsFunction2 #0 6 1387 // 54 0 CallJsFunction2 #0 6
1559 // 54 54 foo #16 7 1388 // 54 54 foo #16 7
1560 // 2 2 (program) #0 2 1389 // 2 2 (program) #0 2
1561 TEST(JsNative1JsNative2JsSample) { 1390 TEST(JsNative1JsNative2JsSample) {
1391 i::FLAG_allow_natives_syntax = true;
1562 v8::HandleScope scope(CcTest::isolate()); 1392 v8::HandleScope scope(CcTest::isolate());
1563 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1393 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1564 v8::Context::Scope context_scope(env); 1394 v8::Context::Scope context_scope(env);
1565 1395
1566 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
1567 env->GetIsolate(), CallJsFunction);
1568 v8::Local<v8::Function> func1 = 1396 v8::Local<v8::Function> func1 =
1569 func_template->GetFunction(env).ToLocalChecked(); 1397 v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction)
1398 ->GetFunction(env)
1399 .ToLocalChecked();
1570 func1->SetName(v8_str("CallJsFunction1")); 1400 func1->SetName(v8_str("CallJsFunction1"));
1571 env->Global()->Set(env, v8_str("CallJsFunction1"), func1).FromJust(); 1401 env->Global()->Set(env, v8_str("CallJsFunction1"), func1).FromJust();
1572 1402
1573 v8::Local<v8::Function> func2 = 1403 v8::Local<v8::Function> func2 =
1574 v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction2) 1404 v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction2)
1575 ->GetFunction(env) 1405 ->GetFunction(env)
1576 .ToLocalChecked(); 1406 .ToLocalChecked();
1577 func2->SetName(v8_str("CallJsFunction2")); 1407 func2->SetName(v8_str("CallJsFunction2"));
1578 env->Global()->Set(env, v8_str("CallJsFunction2"), func2).FromJust(); 1408 env->Global()->Set(env, v8_str("CallJsFunction2"), func2).FromJust();
1579 1409
1580 CompileRun(js_native1_js_native2_js_test_source); 1410 CompileRun(js_native1_js_native2_js_test_source);
1581 v8::Local<v8::Function> function = GetFunction(env, "start"); 1411 v8::Local<v8::Function> function = GetFunction(env, "start");
1582 1412
1583 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0); 1413 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
1584 1414
1585 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1415 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1586 ScopedVector<v8::Local<v8::String> > names(3); 1416 const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
1587 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName); 1417 const v8::CpuProfileNode* native_node1 =
1588 names[1] = v8_str(ProfileGenerator::kProgramEntryName); 1418 GetChild(env, start_node, "CallJsFunction1");
1589 names[2] = v8_str("start"); 1419 const v8::CpuProfileNode* bar_node = GetChild(env, native_node1, "bar");
1590 CheckChildrenNames(env, root, names); 1420 const v8::CpuProfileNode* native_node2 =
1591 1421 GetChild(env, bar_node, "CallJsFunction2");
1592 const v8::CpuProfileNode* startNode = GetChild(env, root, "start"); 1422 GetChild(env, native_node2, "foo");
1593 CHECK_EQ(1, startNode->GetChildrenCount());
1594 const v8::CpuProfileNode* nativeNode1 =
1595 GetChild(env, startNode, "CallJsFunction1");
1596
1597 CHECK_EQ(1, nativeNode1->GetChildrenCount());
1598 const v8::CpuProfileNode* barNode = GetChild(env, nativeNode1, "bar");
1599
1600 CHECK_EQ(1, barNode->GetChildrenCount());
1601 const v8::CpuProfileNode* nativeNode2 =
1602 GetChild(env, barNode, "CallJsFunction2");
1603
1604 CHECK_EQ(1, nativeNode2->GetChildrenCount());
1605 GetChild(env, nativeNode2, "foo");
1606 1423
1607 profile->Delete(); 1424 profile->Delete();
1608 } 1425 }
1609 1426
1610 static const char* js_force_collect_sample_source = 1427 static const char* js_force_collect_sample_source =
1611 "function start() {\n" 1428 "function start() {\n"
1612 " CallCollectSample();\n" 1429 " CallCollectSample();\n"
1613 "}"; 1430 "}";
1614 1431
1615 TEST(CollectSampleAPI) { 1432 TEST(CollectSampleAPI) {
1616 v8::HandleScope scope(CcTest::isolate()); 1433 v8::HandleScope scope(CcTest::isolate());
1617 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1434 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1618 v8::Context::Scope context_scope(env); 1435 v8::Context::Scope context_scope(env);
1619 1436
1620 v8::Local<v8::FunctionTemplate> func_template = 1437 v8::Local<v8::FunctionTemplate> func_template =
1621 v8::FunctionTemplate::New(env->GetIsolate(), CallCollectSample); 1438 v8::FunctionTemplate::New(env->GetIsolate(), CallCollectSample);
1622 v8::Local<v8::Function> func = 1439 v8::Local<v8::Function> func =
1623 func_template->GetFunction(env).ToLocalChecked(); 1440 func_template->GetFunction(env).ToLocalChecked();
1624 func->SetName(v8_str("CallCollectSample")); 1441 func->SetName(v8_str("CallCollectSample"));
1625 env->Global()->Set(env, v8_str("CallCollectSample"), func).FromJust(); 1442 env->Global()->Set(env, v8_str("CallCollectSample"), func).FromJust();
1626 1443
1627 CompileRun(js_force_collect_sample_source); 1444 CompileRun(js_force_collect_sample_source);
1628 v8::Local<v8::Function> function = GetFunction(env, "start"); 1445 v8::Local<v8::Function> function = GetFunction(env, "start");
1629
1630 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0); 1446 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
1631 1447
1632 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1448 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1633 const v8::CpuProfileNode* startNode = GetChild(env, root, "start"); 1449 const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
1634 CHECK_LE(1, startNode->GetChildrenCount()); 1450 CHECK_LE(1, start_node->GetChildrenCount());
1635 GetChild(env, startNode, "CallCollectSample"); 1451 GetChild(env, start_node, "CallCollectSample");
1636 1452
1637 profile->Delete(); 1453 profile->Delete();
1638 } 1454 }
1639 1455
1640 static const char* js_native_js_runtime_multiple_test_source = 1456 static const char* js_native_js_runtime_multiple_test_source =
1457 "%NeverOptimizeFunction(foo);\n"
1458 "%NeverOptimizeFunction(bar);\n"
1459 "%NeverOptimizeFunction(start);\n"
1641 "function foo() {\n" 1460 "function foo() {\n"
1642 " CallCollectSample();"
1643 " return Math.sin(Math.random());\n" 1461 " return Math.sin(Math.random());\n"
1644 "}\n" 1462 "}\n"
1645 "var bound = foo.bind(this);\n" 1463 "var bound = foo.bind(this);\n"
1646 "function bar() {\n" 1464 "function bar() {\n"
1647 " try { return bound(); } catch(e) {}\n" 1465 " return bound();\n"
1648 "}\n" 1466 "}\n"
1649 "function start() {\n" 1467 "function start() {\n"
1650 " try {\n" 1468 " startProfiling('my_profile');\n"
1651 " startProfiling('my_profile');\n" 1469 " var startTime = Date.now();\n"
1652 " var startTime = Date.now();\n" 1470 " do {\n"
1653 " do {\n" 1471 " CallJsFunction(bar);\n"
1654 " CallJsFunction(bar);\n" 1472 " } while (Date.now() - startTime < 200);\n"
1655 " } while (Date.now() - startTime < 200);\n"
1656 " } catch(e) {}\n"
1657 "}"; 1473 "}";
1658 1474
1659 // The test check multiple entrances/exits between JS and native code. 1475 // The test check multiple entrances/exits between JS and native code.
1660 // 1476 //
1661 // [Top down]: 1477 // [Top down]:
1662 // (root) #0 1 1478 // (root) #0 1
1663 // start #16 3 1479 // start #16 3
1664 // CallJsFunction #0 4 1480 // CallJsFunction #0 4
1665 // bar #16 5 1481 // bar #16 5
1666 // foo #16 6 1482 // foo #16 6
1667 // CallCollectSample
1668 // (program) #0 2 1483 // (program) #0 2
1669 TEST(JsNativeJsRuntimeJsSampleMultiple) { 1484 TEST(JsNativeJsRuntimeJsSampleMultiple) {
1485 i::FLAG_allow_natives_syntax = true;
1670 v8::HandleScope scope(CcTest::isolate()); 1486 v8::HandleScope scope(CcTest::isolate());
1671 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1487 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1672 v8::Context::Scope context_scope(env); 1488 v8::Context::Scope context_scope(env);
1673 1489
1674 v8::Local<v8::FunctionTemplate> func_template = 1490 v8::Local<v8::FunctionTemplate> func_template =
1675 v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction); 1491 v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction);
1676 v8::Local<v8::Function> func = 1492 v8::Local<v8::Function> func =
1677 func_template->GetFunction(env).ToLocalChecked(); 1493 func_template->GetFunction(env).ToLocalChecked();
1678 func->SetName(v8_str("CallJsFunction")); 1494 func->SetName(v8_str("CallJsFunction"));
1679 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust(); 1495 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust();
1680 1496
1681 func_template =
1682 v8::FunctionTemplate::New(env->GetIsolate(), CallCollectSample);
1683 func = func_template->GetFunction(env).ToLocalChecked();
1684 func->SetName(v8_str("CallCollectSample"));
1685 env->Global()->Set(env, v8_str("CallCollectSample"), func).FromJust();
1686
1687 CompileRun(js_native_js_runtime_multiple_test_source); 1497 CompileRun(js_native_js_runtime_multiple_test_source);
1688 v8::Local<v8::Function> function = GetFunction(env, "start"); 1498 v8::Local<v8::Function> function = GetFunction(env, "start");
1689 1499
1690 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000); 1500 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
1691 1501
1692 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1502 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1693 const v8::CpuProfileNode* startNode = GetChild(env, root, "start"); 1503 const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
1694 const v8::CpuProfileNode* nativeFunctionNode = 1504 const v8::CpuProfileNode* native_node =
1695 GetChild(env, startNode, "CallJsFunction"); 1505 GetChild(env, start_node, "CallJsFunction");
1696 1506 const v8::CpuProfileNode* bar_node = GetChild(env, native_node, "bar");
1697 const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar"); 1507 GetChild(env, bar_node, "foo");
1698 const v8::CpuProfileNode* fooNode = GetChild(env, barNode, "foo");
1699 GetChild(env, fooNode, "CallCollectSample");
1700 1508
1701 profile->Delete(); 1509 profile->Delete();
1702 } 1510 }
1703 1511
1704 // [Top down]: 1512 // [Top down]:
1705 // 0 (root) #0 1 1513 // 0 (root) #0 1
1706 // 2 (program) #0 2 1514 // 2 (program) #0 2
1707 // 3 (idle) #0 3 1515 // 3 (idle) #0 3
1708 TEST(IdleTime) { 1516 TEST(IdleTime) {
1709 LocalContext env; 1517 LocalContext env;
1710 v8::HandleScope scope(env->GetIsolate()); 1518 v8::HandleScope scope(env->GetIsolate());
1711 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); 1519 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
1712 1520
1713 v8::Local<v8::String> profile_name = v8_str("my_profile"); 1521 v8::Local<v8::String> profile_name = v8_str("my_profile");
1714 cpu_profiler->StartProfiling(profile_name); 1522 cpu_profiler->StartProfiling(profile_name);
1715 1523
1716 i::Isolate* isolate = CcTest::i_isolate(); 1524 i::Isolate* isolate = CcTest::i_isolate();
1717 i::ProfilerEventsProcessor* processor = isolate->cpu_profiler()->processor(); 1525 i::ProfilerEventsProcessor* processor = isolate->cpu_profiler()->processor();
1526
1718 processor->AddCurrentStack(isolate, true); 1527 processor->AddCurrentStack(isolate, true);
1719
1720 cpu_profiler->SetIdle(true); 1528 cpu_profiler->SetIdle(true);
1721
1722 for (int i = 0; i < 3; i++) { 1529 for (int i = 0; i < 3; i++) {
1723 processor->AddCurrentStack(isolate, true); 1530 processor->AddCurrentStack(isolate, true);
1724 } 1531 }
1725
1726 cpu_profiler->SetIdle(false); 1532 cpu_profiler->SetIdle(false);
1727 processor->AddCurrentStack(isolate, true); 1533 processor->AddCurrentStack(isolate, true);
1728 1534
1729 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name); 1535 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
1730 CHECK(profile); 1536 CHECK(profile);
1731 // Dump collected profile to have a better diagnostic in case of failure. 1537 // Dump collected profile to have a better diagnostic in case of failure.
1732 reinterpret_cast<i::CpuProfile*>(profile)->Print(); 1538 reinterpret_cast<i::CpuProfile*>(profile)->Print();
1733 1539
1734 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1540 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1735 ScopedVector<v8::Local<v8::String> > names(3); 1541 const v8::CpuProfileNode* program_node =
1736 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName); 1542 GetChild(env.local(), root, ProfileGenerator::kProgramEntryName);
1737 names[1] = v8_str(ProfileGenerator::kProgramEntryName); 1543 CHECK_EQ(0, program_node->GetChildrenCount());
1738 names[2] = v8_str(ProfileGenerator::kIdleEntryName); 1544 CHECK_GE(program_node->GetHitCount(), 2u);
1739 CheckChildrenNames(env.local(), root, names);
1740 1545
1741 const v8::CpuProfileNode* programNode = 1546 const v8::CpuProfileNode* idle_node =
1742 GetChild(env.local(), root, ProfileGenerator::kProgramEntryName);
1743 CHECK_EQ(0, programNode->GetChildrenCount());
1744 CHECK_GE(programNode->GetHitCount(), 2u);
1745
1746 const v8::CpuProfileNode* idleNode =
1747 GetChild(env.local(), root, ProfileGenerator::kIdleEntryName); 1547 GetChild(env.local(), root, ProfileGenerator::kIdleEntryName);
1748 CHECK_EQ(0, idleNode->GetChildrenCount()); 1548 CHECK_EQ(0, idle_node->GetChildrenCount());
1749 CHECK_GE(idleNode->GetHitCount(), 3u); 1549 CHECK_GE(idle_node->GetHitCount(), 3u);
1750 1550
1751 profile->Delete(); 1551 profile->Delete();
1752 } 1552 }
1753 1553
1754
1755 static void CheckFunctionDetails(v8::Isolate* isolate, 1554 static void CheckFunctionDetails(v8::Isolate* isolate,
1756 const v8::CpuProfileNode* node, 1555 const v8::CpuProfileNode* node,
1757 const char* name, const char* script_name, 1556 const char* name, const char* script_name,
1758 int script_id, int line, int column) { 1557 int script_id, int line, int column) {
1759 v8::Local<v8::Context> context = isolate->GetCurrentContext(); 1558 v8::Local<v8::Context> context = isolate->GetCurrentContext();
1760 CHECK(v8_str(name)->Equals(context, node->GetFunctionName()).FromJust()); 1559 CHECK(v8_str(name)->Equals(context, node->GetFunctionName()).FromJust());
1761 CHECK(v8_str(script_name) 1560 CHECK(v8_str(script_name)
1762 ->Equals(context, node->GetScriptResourceName()) 1561 ->Equals(context, node->GetScriptResourceName())
1763 .FromJust()); 1562 .FromJust());
1764 CHECK_EQ(script_id, node->GetScriptId()); 1563 CHECK_EQ(script_id, node->GetScriptId());
1765 CHECK_EQ(line, node->GetLineNumber()); 1564 CHECK_EQ(line, node->GetLineNumber());
1766 CHECK_EQ(column, node->GetColumnNumber()); 1565 CHECK_EQ(column, node->GetColumnNumber());
1767 } 1566 }
1768 1567
1769 1568
1770 TEST(FunctionDetails) { 1569 TEST(FunctionDetails) {
1570 i::FLAG_allow_natives_syntax = true;
1771 v8::HandleScope scope(CcTest::isolate()); 1571 v8::HandleScope scope(CcTest::isolate());
1772 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1572 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1773 v8::Context::Scope context_scope(env); 1573 v8::Context::Scope context_scope(env);
1774 1574
1775 v8::Local<v8::Script> script_a = CompileWithOrigin( 1575 v8::Local<v8::Script> script_a = CompileWithOrigin(
1776 " function foo\n() { try { bar(); } catch(e) {} }\n" 1576 "%NeverOptimizeFunction(foo);\n"
1577 "%NeverOptimizeFunction(bar);\n"
1578 " function foo\n() { bar(); }\n"
1777 " function bar() { startProfiling(); }\n", 1579 " function bar() { startProfiling(); }\n",
1778 "script_a"); 1580 "script_a");
1779 script_a->Run(env).ToLocalChecked(); 1581 script_a->Run(env).ToLocalChecked();
1780 v8::Local<v8::Script> script_b = CompileWithOrigin( 1582 v8::Local<v8::Script> script_b = CompileWithOrigin(
1781 "\n\n function baz() { try { foo(); } catch(e) {} }\n" 1583 "%NeverOptimizeFunction(baz);"
1584 "\n\n function baz() { foo(); }\n"
1782 "\n\nbaz();\n" 1585 "\n\nbaz();\n"
1783 "stopProfiling();\n", 1586 "stopProfiling();\n",
1784 "script_b"); 1587 "script_b");
1785 script_b->Run(env).ToLocalChecked(); 1588 script_b->Run(env).ToLocalChecked();
1786 const v8::CpuProfile* profile = i::ProfilerExtension::last_profile; 1589 const v8::CpuProfile* profile = i::ProfilerExtension::last_profile;
1787 const v8::CpuProfileNode* current = profile->GetTopDownRoot(); 1590 const v8::CpuProfileNode* current = profile->GetTopDownRoot();
1788 reinterpret_cast<ProfileNode*>( 1591 reinterpret_cast<ProfileNode*>(
1789 const_cast<v8::CpuProfileNode*>(current))->Print(0); 1592 const_cast<v8::CpuProfileNode*>(current))->Print(0);
1790 // The tree should look like this: 1593 // The tree should look like this:
1791 // 0 (root) 0 #1 1594 // 0 (root) 0 #1
1792 // 0 "" 19 #2 no reason script_b:1 1595 // 0 "" 19 #2 no reason script_b:1
1793 // 0 baz 19 #3 TryCatchStatement script_b:3 1596 // 0 baz 19 #3 TryCatchStatement script_b:3
1794 // 0 foo 18 #4 TryCatchStatement script_a:2 1597 // 0 foo 18 #4 TryCatchStatement script_a:2
1795 // 1 bar 18 #5 no reason script_a:3 1598 // 1 bar 18 #5 no reason script_a:3
1796 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1599 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1797 const v8::CpuProfileNode* script = GetChild(env, root, ""); 1600 const v8::CpuProfileNode* script = GetChild(env, root, "");
1798 CheckFunctionDetails(env->GetIsolate(), script, "", "script_b", 1601 CheckFunctionDetails(env->GetIsolate(), script, "", "script_b",
1799 script_b->GetUnboundScript()->GetId(), 1, 1); 1602 script_b->GetUnboundScript()->GetId(), 1, 1);
1800 const v8::CpuProfileNode* baz = GetChild(env, script, "baz"); 1603 const v8::CpuProfileNode* baz = GetChild(env, script, "baz");
1801 CheckFunctionDetails(env->GetIsolate(), baz, "baz", "script_b", 1604 CheckFunctionDetails(env->GetIsolate(), baz, "baz", "script_b",
1802 script_b->GetUnboundScript()->GetId(), 3, 16); 1605 script_b->GetUnboundScript()->GetId(), 3, 16);
1803 const v8::CpuProfileNode* foo = GetChild(env, baz, "foo"); 1606 const v8::CpuProfileNode* foo = GetChild(env, baz, "foo");
1804 CheckFunctionDetails(env->GetIsolate(), foo, "foo", "script_a", 1607 CheckFunctionDetails(env->GetIsolate(), foo, "foo", "script_a",
1805 script_a->GetUnboundScript()->GetId(), 2, 1); 1608 script_a->GetUnboundScript()->GetId(), 4, 1);
1806 const v8::CpuProfileNode* bar = GetChild(env, foo, "bar"); 1609 const v8::CpuProfileNode* bar = GetChild(env, foo, "bar");
1807 CheckFunctionDetails(env->GetIsolate(), bar, "bar", "script_a", 1610 CheckFunctionDetails(env->GetIsolate(), bar, "bar", "script_a",
1808 script_a->GetUnboundScript()->GetId(), 3, 14); 1611 script_a->GetUnboundScript()->GetId(), 5, 14);
1809 } 1612 }
1810 1613
1811 1614
1812 TEST(DontStopOnFinishedProfileDelete) { 1615 TEST(DontStopOnFinishedProfileDelete) {
1813 v8::HandleScope scope(CcTest::isolate()); 1616 v8::HandleScope scope(CcTest::isolate());
1814 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1617 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1815 v8::Context::Scope context_scope(env); 1618 v8::Context::Scope context_scope(env);
1816 1619
1817 v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler(); 1620 v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
1818 i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler); 1621 i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
2164 iprofile->Print(); 1967 iprofile->Print();
2165 v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile); 1968 v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile);
2166 1969
2167 const char* branch[] = {"", "test"}; 1970 const char* branch[] = {"", "test"};
2168 const ProfileNode* itest_node = 1971 const ProfileNode* itest_node =
2169 GetSimpleBranch(env, profile, branch, arraysize(branch)); 1972 GetSimpleBranch(env, profile, branch, arraysize(branch));
2170 CHECK_EQ(0U, itest_node->deopt_infos().size()); 1973 CHECK_EQ(0U, itest_node->deopt_infos().size());
2171 1974
2172 iprofiler->DeleteProfile(iprofile); 1975 iprofiler->DeleteProfile(iprofile);
2173 } 1976 }
OLDNEW
« no previous file with comments | « test/cctest/profiler-extension.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698