Chromium Code Reviews

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: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
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 399 matching lines...)
410 LocalContext env; 410 LocalContext env;
411 v8::HandleScope scope(env->GetIsolate()); 411 v8::HandleScope scope(env->GetIsolate());
412 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); 412 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
413 413
414 v8::Local<v8::String> profile_name = v8_str("test"); 414 v8::Local<v8::String> profile_name = v8_str("test");
415 cpu_profiler->StartProfiling(profile_name); 415 cpu_profiler->StartProfiling(profile_name);
416 const v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name); 416 const v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
417 CHECK(profile->GetStartTime() <= profile->GetEndTime()); 417 CHECK(profile->GetStartTime() <= profile->GetEndTime());
418 } 418 }
419 419
420
421 static v8::CpuProfile* RunProfiler(v8::Local<v8::Context> env, 420 static v8::CpuProfile* RunProfiler(v8::Local<v8::Context> env,
422 v8::Local<v8::Function> function, 421 v8::Local<v8::Function> function,
423 v8::Local<v8::Value> argv[], int argc, 422 v8::Local<v8::Value> argv[], int argc,
424 unsigned min_js_samples, 423 unsigned min_js_samples = 0,
425 bool collect_samples = false) { 424 bool collect_samples = false) {
426 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); 425 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
427 v8::Local<v8::String> profile_name = v8_str("my_profile"); 426 v8::Local<v8::String> profile_name = v8_str("my_profile");
428 427
429 cpu_profiler->SetSamplingInterval(100); 428 cpu_profiler->SetSamplingInterval(100);
430 cpu_profiler->StartProfiling(profile_name, collect_samples); 429 cpu_profiler->StartProfiling(profile_name, collect_samples);
431 430
432 i::Sampler* sampler = 431 i::Sampler* sampler =
433 reinterpret_cast<i::Isolate*>(env->GetIsolate())->logger()->sampler(); 432 reinterpret_cast<i::Isolate*>(env->GetIsolate())->logger()->sampler();
434 sampler->StartCountingSamples(); 433 sampler->StartCountingSamples();
435 do { 434 do {
436 function->Call(env, env->Global(), argc, argv).ToLocalChecked(); 435 function->Call(env, env->Global(), argc, argv).ToLocalChecked();
437 } while (sampler->js_and_external_sample_count() < min_js_samples); 436 } while (sampler->js_and_external_sample_count() < min_js_samples);
438 437
439 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name); 438 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
440 439
441 CHECK(profile); 440 CHECK(profile);
442 // Dump collected profile to have a better diagnostic in case of failure. 441 // Dump collected profile to have a better diagnostic in case of failure.
443 reinterpret_cast<i::CpuProfile*>(profile)->Print(); 442 reinterpret_cast<i::CpuProfile*>(profile)->Print();
444 443
445 return profile; 444 return profile;
446 } 445 }
447 446
448 447
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, 448 static const v8::CpuProfileNode* FindChild(v8::Local<v8::Context> context,
491 const v8::CpuProfileNode* node, 449 const v8::CpuProfileNode* node,
492 const char* name) { 450 const char* name) {
493 int count = node->GetChildrenCount(); 451 int count = node->GetChildrenCount();
494 v8::Local<v8::String> nameHandle = v8_str(name); 452 v8::Local<v8::String> nameHandle = v8_str(name);
495 for (int i = 0; i < count; i++) { 453 for (int i = 0; i < count; i++) {
496 const v8::CpuProfileNode* child = node->GetChild(i); 454 const v8::CpuProfileNode* child = node->GetChild(i);
497 if (nameHandle->Equals(context, child->GetFunctionName()).FromJust()) { 455 if (nameHandle->Equals(context, child->GetFunctionName()).FromJust()) {
498 return child; 456 return child;
499 } 457 }
(...skipping 15 matching lines...)
515 return result; 473 return result;
516 } 474 }
517 475
518 476
519 static void CheckSimpleBranch(v8::Local<v8::Context> context, 477 static void CheckSimpleBranch(v8::Local<v8::Context> context,
520 const v8::CpuProfileNode* node, 478 const v8::CpuProfileNode* node,
521 const char* names[], int length) { 479 const char* names[], int length) {
522 for (int i = 0; i < length; i++) { 480 for (int i = 0; i < length; i++) {
523 const char* name = names[i]; 481 const char* name = names[i];
524 node = GetChild(context, node, name); 482 node = GetChild(context, node, name);
525 int expectedChildrenCount = (i == length - 1) ? 0 : 1;
526 CHECK_EQ(expectedChildrenCount, node->GetChildrenCount());
527 } 483 }
528 } 484 }
529 485
530 486
531 static const ProfileNode* GetSimpleBranch(v8::Local<v8::Context> context, 487 static const ProfileNode* GetSimpleBranch(v8::Local<v8::Context> context,
532 v8::CpuProfile* profile, 488 v8::CpuProfile* profile,
533 const char* names[], int length) { 489 const char* names[], int length) {
534 const v8::CpuProfileNode* node = profile->GetTopDownRoot(); 490 const v8::CpuProfileNode* node = profile->GetTopDownRoot();
535 for (int i = 0; i < length; i++) { 491 for (int i = 0; i < length; i++) {
536 node = GetChild(context, node, names[i]); 492 node = GetChild(context, node, names[i]);
537 } 493 }
538 return reinterpret_cast<const ProfileNode*>(node); 494 return reinterpret_cast<const ProfileNode*>(node);
539 } 495 }
540 496
541 static void CallCollectSample(const v8::FunctionCallbackInfo<v8::Value>& info) { 497 static void CallCollectSample(const v8::FunctionCallbackInfo<v8::Value>& info) {
542 info.GetIsolate()->GetCpuProfiler()->CollectSample(); 498 info.GetIsolate()->GetCpuProfiler()->CollectSample();
543 } 499 }
544 500
545 static const char* cpu_profiler_test_source = "function loop(timeout) {\n" 501 static const char* cpu_profiler_test_source =
546 " this.mmm = 0;\n" 502 "function loop(timeout) {\n"
547 " var start = Date.now();\n" 503 " var start = Date.now();\n"
548 " while (Date.now() - start < timeout) {\n" 504 " while (Date.now() - start < timeout) {\n"
549 " var n = 100*1000;\n" 505 " collectSample();\n"
550 " while(n > 1) {\n" 506 " }\n"
551 " n--;\n" 507 "}\n"
552 " this.mmm += n * n * n;\n" 508 "function delay() { try { loop(10); } catch(e) { } }\n"
553 " }\n" 509 "function bar() { delay(); }\n"
554 " }\n" 510 "function baz() { delay(); }\n"
555 "}\n" 511 "function foo() {\n"
556 "function delay() { try { loop(10); } catch(e) { } }\n" 512 " try {\n"
557 "function bar() { delay(); }\n" 513 " delay();\n"
558 "function baz() { delay(); }\n" 514 " bar();\n"
559 "function foo() {\n" 515 " delay();\n"
560 " try {\n" 516 " baz();\n"
561 " delay();\n" 517 " } catch (e) { }\n"
562 " bar();\n" 518 "}\n"
563 " delay();\n" 519 "function start() {\n"
564 " baz();\n" 520 " try { foo(); } catch (e) { }\n"
565 " } catch (e) { }\n" 521 "}\n";
566 "}\n"
567 "function start(timeout) {\n"
568 " var start = Date.now();\n"
569 " do {\n"
570 " foo();\n"
571 " var duration = Date.now() - start;\n"
572 " } while (duration < timeout);\n"
573 " return duration;\n"
574 "}\n";
575
576 522
577 // Check that the profile tree for the script above will look like the 523 // Check that the profile tree for the script above will look like the
578 // following: 524 // following:
579 // 525 //
580 // [Top down]: 526 // [Top down]:
581 // 1062 0 (root) [-1] 527 // 1062 0 (root) [-1]
582 // 1054 0 start [-1] 528 // 1054 0 start [-1]
583 // 1054 1 foo [-1] 529 // 1054 1 foo [-1]
584 // 265 0 baz [-1] 530 // 265 0 baz [-1]
585 // 265 1 delay [-1] 531 // 265 1 delay [-1]
586 // 264 264 loop [-1] 532 // 264 264 loop [-1]
587 // 525 3 delay [-1] 533 // 525 3 delay [-1]
588 // 522 522 loop [-1] 534 // 522 522 loop [-1]
589 // 263 0 bar [-1] 535 // 263 0 bar [-1]
590 // 263 1 delay [-1] 536 // 263 1 delay [-1]
591 // 262 262 loop [-1] 537 // 262 262 loop [-1]
592 // 2 2 (program) [-1] 538 // 2 2 (program) [-1]
593 // 6 6 (garbage collector) [-1] 539 // 6 6 (garbage collector) [-1]
594 TEST(CollectCpuProfile) { 540 TEST(CollectCpuProfile) {
595 LocalContext env; 541 v8::HandleScope scope(CcTest::isolate());
596 v8::HandleScope scope(env->GetIsolate()); 542 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
543 v8::Context::Scope context_scope(env);
597 544
598 CompileRun(cpu_profiler_test_source); 545 CompileRun(cpu_profiler_test_source);
599 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 546 v8::Local<v8::Function> function = GetFunction(env, "start");
600 547
601 int32_t profiling_interval_ms = 200; 548 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0);
602 v8::Local<v8::Value> args[] = {
603 v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
604 v8::CpuProfile* profile =
605 RunProfiler(env.local(), function, args, arraysize(args), 200);
606 function->Call(env.local(), env->Global(), arraysize(args), args)
607 .ToLocalChecked();
608 549
609 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 550 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
610 551
611 ScopedVector<v8::Local<v8::String> > names(3); 552 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
612 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName); 553 const v8::CpuProfileNode* fooNode = GetChild(env, startNode, "foo");
613 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
614 names[2] = v8_str("start");
615 CheckChildrenNames(env.local(), root, names);
616
617 const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
618 CHECK_EQ(1, startNode->GetChildrenCount());
619
620 const v8::CpuProfileNode* fooNode = GetChild(env.local(), startNode, "foo");
621 CHECK_EQ(3, fooNode->GetChildrenCount());
622 554
623 const char* barBranch[] = { "bar", "delay", "loop" }; 555 const char* barBranch[] = { "bar", "delay", "loop" };
624 CheckSimpleBranch(env.local(), fooNode, barBranch, arraysize(barBranch)); 556 CheckSimpleBranch(env, fooNode, barBranch, arraysize(barBranch));
625 const char* bazBranch[] = { "baz", "delay", "loop" }; 557 const char* bazBranch[] = { "baz", "delay", "loop" };
626 CheckSimpleBranch(env.local(), fooNode, bazBranch, arraysize(bazBranch)); 558 CheckSimpleBranch(env, fooNode, bazBranch, arraysize(bazBranch));
627 const char* delayBranch[] = { "delay", "loop" }; 559 const char* delayBranch[] = { "delay", "loop" };
628 CheckSimpleBranch(env.local(), fooNode, delayBranch, arraysize(delayBranch)); 560 CheckSimpleBranch(env, fooNode, delayBranch, arraysize(delayBranch));
629 561
630 profile->Delete(); 562 profile->Delete();
631 } 563 }
632 564
633
634 static const char* hot_deopt_no_frame_entry_test_source = 565 static const char* hot_deopt_no_frame_entry_test_source =
635 "function foo(a, b) {\n" 566 "function foo(a, b) {\n"
636 " try {\n" 567 " try {\n"
637 " return a + b;\n" 568 " return a + b;\n"
638 " } catch (e) { }\n" 569 " } catch (e) { }\n"
639 "}\n" 570 "}\n"
640 "function start(timeout) {\n" 571 "function start(timeout) {\n"
641 " var start = Date.now();\n" 572 " var start = Date.now();\n"
642 " do {\n" 573 " do {\n"
643 " for (var i = 1; i < 1000; ++i) foo(1, i);\n" 574 " for (var i = 1; i < 1000; ++i) foo(1, i);\n"
644 " var duration = Date.now() - start;\n" 575 " var duration = Date.now() - start;\n"
645 " } while (duration < timeout);\n" 576 " } while (duration < timeout);\n"
646 " return duration;\n" 577 " return duration;\n"
647 "}\n"; 578 "}\n";
648 579
649 // Check that the profile tree for the script above will look like the 580 // Check that the profile tree for the script above will look like the
650 // following: 581 // following:
651 // 582 //
652 // [Top down]: 583 // [Top down]:
653 // 1062 0 (root) [-1] 584 // 1062 0 (root) [-1]
654 // 1054 0 start [-1] 585 // 1054 0 start [-1]
655 // 1054 1 foo [-1] 586 // 1054 1 foo [-1]
656 // 2 2 (program) [-1] 587 // 2 2 (program) [-1]
657 // 6 6 (garbage collector) [-1] 588 // 6 6 (garbage collector) [-1]
658 // 589 //
659 // The test checks no FP ranges are present in a deoptimized funcion. 590 // 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 591 // 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). 592 // 'start' function on the stack, so 'foo' will be attached to the (root).
662 TEST(HotDeoptNoFrameEntry) { 593 TEST(HotDeoptNoFrameEntry) {
663 LocalContext env; 594 LocalContext env;
664 v8::HandleScope scope(env->GetIsolate()); 595 v8::HandleScope scope(env->GetIsolate());
665 596
666 CompileRun(hot_deopt_no_frame_entry_test_source); 597 CompileRun(hot_deopt_no_frame_entry_test_source);
667 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 598 v8::Local<v8::Function> function = GetFunction(env.local(), "start");
668 599
669 int32_t profiling_interval_ms = 200; 600 int32_t profiling_interval_ms = 200;
670 v8::Local<v8::Value> args[] = { 601 v8::Local<v8::Value> args[] = {
671 v8::Integer::New(env->GetIsolate(), profiling_interval_ms)}; 602 v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
672 v8::CpuProfile* profile = 603 v8::CpuProfile* profile =
673 RunProfiler(env.local(), function, args, arraysize(args), 200); 604 RunProfiler(env.local(), function, args, arraysize(args), 2000);
674 function->Call(env.local(), env->Global(), arraysize(args), args) 605 function->Call(env.local(), env->Global(), arraysize(args), args)
675 .ToLocalChecked(); 606 .ToLocalChecked();
676 607
677 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 608 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
678
679 ScopedVector<v8::Local<v8::String> > names(3);
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"); 609 const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
686 CHECK_EQ(1, startNode->GetChildrenCount());
687
688 GetChild(env.local(), startNode, "foo"); 610 GetChild(env.local(), startNode, "foo");
611 CHECK(!FindChild(env.local(), root, "foo"));
689 612
690 profile->Delete(); 613 profile->Delete();
691 } 614 }
692 615
693 616
694 TEST(CollectCpuProfileSamples) { 617 TEST(CollectCpuProfileSamples) {
695 LocalContext env; 618 LocalContext env;
696 v8::HandleScope scope(env->GetIsolate()); 619 v8::HandleScope scope(env->GetIsolate());
697 620
698 CompileRun(cpu_profiler_test_source); 621 CompileRun(cpu_profiler_test_source);
(...skipping 13 matching lines...)
712 CHECK(profile->GetSample(i)); 635 CHECK(profile->GetSample(i));
713 uint64_t timestamp = profile->GetSampleTimestamp(i); 636 uint64_t timestamp = profile->GetSampleTimestamp(i);
714 CHECK_LE(current_time, timestamp); 637 CHECK_LE(current_time, timestamp);
715 CHECK_LE(timestamp, end_time); 638 CHECK_LE(timestamp, end_time);
716 current_time = timestamp; 639 current_time = timestamp;
717 } 640 }
718 641
719 profile->Delete(); 642 profile->Delete();
720 } 643 }
721 644
722
723 static const char* cpu_profiler_test_source2 = "function loop() {}\n" 645 static const char* cpu_profiler_test_source2 = "function loop() {}\n"
724 "function delay() { loop(); }\n" 646 "function delay() { loop(); }\n"
725 "function start(count) {\n" 647 "function start(count) {\n"
726 " var k = 0;\n" 648 " var k = 0;\n"
727 " do {\n" 649 " do {\n"
728 " delay();\n" 650 " delay();\n"
729 " } while (++k < count*100*1000);\n" 651 " } while (++k < count*100*1000);\n"
730 "}\n"; 652 "}\n";
731 653
732 // Check that the profile tree doesn't contain unexpected traces: 654 // Check that the profile tree doesn't contain unexpected traces:
(...skipping 18 matching lines...)
751 #if defined(USE_SIMULATOR) 673 #if defined(USE_SIMULATOR)
752 // Simulators are much slower. 674 // Simulators are much slower.
753 repeat_count = 1; 675 repeat_count = 1;
754 #endif 676 #endif
755 v8::Local<v8::Value> args[] = { 677 v8::Local<v8::Value> args[] = {
756 v8::Integer::New(env->GetIsolate(), repeat_count)}; 678 v8::Integer::New(env->GetIsolate(), repeat_count)};
757 v8::CpuProfile* profile = 679 v8::CpuProfile* profile =
758 RunProfiler(env.local(), function, args, arraysize(args), 100); 680 RunProfiler(env.local(), function, args, arraysize(args), 100);
759 681
760 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 682 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
761
762 ScopedVector<v8::Local<v8::String> > names(3);
763 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
764 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
765 names[2] = v8_str("start");
766 CheckChildrenNames(env.local(), root, names);
767
768 const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start"); 683 const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
769 // On slow machines there may be no meaningfull samples at all, skip the 684 // On slow machines there may be no meaningfull samples at all, skip the
770 // check there. 685 // check there.
771 if (startNode && startNode->GetChildrenCount() > 0) { 686 if (startNode && startNode->GetChildrenCount() > 0) {
772 CHECK_EQ(1, startNode->GetChildrenCount());
773 const v8::CpuProfileNode* delayNode = 687 const v8::CpuProfileNode* delayNode =
774 GetChild(env.local(), startNode, "delay"); 688 GetChild(env.local(), startNode, "delay");
775 if (delayNode->GetChildrenCount() > 0) { 689 if (delayNode->GetChildrenCount() > 0) {
776 CHECK_EQ(1, delayNode->GetChildrenCount());
777 GetChild(env.local(), delayNode, "loop"); 690 GetChild(env.local(), delayNode, "loop");
778 } 691 }
779 } 692 }
780 693
781 profile->Delete(); 694 profile->Delete();
782 } 695 }
783 696
784
785 static const char* native_accessor_test_source = "function start(count) {\n" 697 static const char* native_accessor_test_source = "function start(count) {\n"
786 " for (var i = 0; i < count; i++) {\n" 698 " for (var i = 0; i < count; i++) {\n"
787 " var o = instance.foo;\n" 699 " var o = instance.foo;\n"
788 " instance.foo = o + 1;\n" 700 " instance.foo = o + 1;\n"
789 " }\n" 701 " }\n"
790 "}\n"; 702 "}\n";
791 703
792 704
793 class TestApiCallbacks { 705 class TestApiCallbacks {
794 public: 706 public:
(...skipping 257 matching lines...)
1052 v8::HandleScope scope(CcTest::isolate()); 964 v8::HandleScope scope(CcTest::isolate());
1053 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 965 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1054 v8::Context::Scope context_scope(env); 966 v8::Context::Scope context_scope(env);
1055 967
1056 CompileRun(bound_function_test_source); 968 CompileRun(bound_function_test_source);
1057 v8::Local<v8::Function> function = GetFunction(env, "start"); 969 v8::Local<v8::Function> function = GetFunction(env, "start");
1058 970
1059 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0); 971 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
1060 972
1061 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 973 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 974
1069 const v8::CpuProfileNode* startNode = GetChild(env, root, "start"); 975 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
1070 GetChild(env, startNode, "foo"); 976 GetChild(env, startNode, "foo");
1071 977
1072 profile->Delete(); 978 profile->Delete();
1073 } 979 }
1074 980
1075 981
1076 // This tests checks distribution of the samples through the source lines. 982 // This tests checks distribution of the samples through the source lines.
1077 TEST(TickLines) { 983 TEST(TickLines) {
(...skipping 85 matching lines...)
1163 CHECK(func_node->GetLineTicks(&entries[0], line_count)); 1069 CHECK(func_node->GetLineTicks(&entries[0], line_count));
1164 int value = 0; 1070 int value = 0;
1165 for (int i = 0; i < entries.length(); i++) 1071 for (int i = 0; i < entries.length(); i++)
1166 if (entries[i].line == hit_line) { 1072 if (entries[i].line == hit_line) {
1167 value = entries[i].hit_count; 1073 value = entries[i].hit_count;
1168 break; 1074 break;
1169 } 1075 }
1170 CHECK_EQ(hit_count, value); 1076 CHECK_EQ(hit_count, value);
1171 } 1077 }
1172 1078
1173 1079 static const char* call_function_test_source =
1174 static const char* call_function_test_source = "function bar(iterations) {\n" 1080 "function bar() {\n"
1175 "}\n" 1081 " collectSample();\n"
1176 "function start(duration) {\n" 1082 "}\n"
1177 " var start = Date.now();\n" 1083 "function start() {\n"
1178 " while (Date.now() - start < duration) {\n" 1084 " try {\n"
1179 " try {\n" 1085 " bar.call(this, 10 * 1000);\n"
1180 " bar.call(this, 10 * 1000);\n" 1086 " } catch(e) {}\n"
1181 " } catch(e) {}\n" 1087 "}";
1182 " }\n"
1183 "}";
1184
1185 1088
1186 // Test that if we sampled thread when it was inside FunctionCall buitin then 1089 // 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 1090 // its caller frame will be '(unresolved function)' as we have no reliable way
1188 // to resolve it. 1091 // to resolve it.
1189 // 1092 //
1190 // [Top down]: 1093 // [Top down]:
1191 // 96 0 (root) [-1] #1 1094 // 96 0 (root) [-1] #1
1192 // 1 1 (garbage collector) [-1] #4 1095 // 1 1 (garbage collector) [-1] #4
1193 // 5 0 (unresolved function) [-1] #5
1194 // 5 5 call [-1] #6
1195 // 71 70 start [-1] #3 1096 // 71 70 start [-1] #3
1196 // 1 1 bar [-1] #7 1097 // 1 1 bar [-1] #7
1197 // 19 19 (program) [-1] #2 1098 // 19 19 (program) [-1] #2
1198 TEST(FunctionCallSample) { 1099 TEST(FunctionCallSample) {
yurys 2016/02/05 17:33:04 This test doesn't check that Function.call gets in
alph 2016/02/05 17:52:26 Does it have to be visible in the user callstack?
yurys 2016/02/05 18:07:33 According to the table above it should be visible
1199 LocalContext env; 1100 v8::HandleScope scope(CcTest::isolate());
1200 v8::HandleScope scope(env->GetIsolate()); 1101 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1201 1102 v8::Context::Scope context_scope(env);
1202 // Collect garbage that might have be generated while installing
1203 // extensions.
1204 CcTest::heap()->CollectAllGarbage();
1205 1103
1206 CompileRun(call_function_test_source); 1104 CompileRun(call_function_test_source);
1207 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 1105 v8::Local<v8::Function> function = GetFunction(env, "start");
1208 1106 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0);
1209 int32_t duration_ms = 100;
1210 v8::Local<v8::Value> args[] = {
1211 v8::Integer::New(env->GetIsolate(), duration_ms)};
1212 v8::CpuProfile* profile =
1213 RunProfiler(env.local(), function, args, arraysize(args), 100);
1214 1107
1215 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1108 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1216 { 1109 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
1217 ScopedVector<v8::Local<v8::String> > names(4); 1110 GetChild(env, startNode, "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
1226 // In case of GC stress tests all samples may be in GC phase and there
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);
1241 if (unresolvedNode) {
1242 ScopedVector<v8::Local<v8::String> > names(1);
1243 names[0] = v8_str("call");
1244 CheckChildrenNames(env.local(), unresolvedNode, names);
1245 }
1246 1111
1247 profile->Delete(); 1112 profile->Delete();
1248 } 1113 }
1249 1114
1250
1251 static const char* function_apply_test_source = 1115 static const char* function_apply_test_source =
1252 "function bar(iterations) {\n" 1116 "function bar() {\n"
1117 " collectSample();\n"
1253 "}\n" 1118 "}\n"
1254 "function test() {\n" 1119 "function test() {\n"
1255 " bar.apply(this, [10 * 1000]);\n" 1120 " bar.apply(this, []);\n"
1256 "}\n" 1121 "}\n"
1257 "function start(duration) {\n" 1122 "function start() {\n"
1258 " var start = Date.now();\n" 1123 " try {\n"
1259 " while (Date.now() - start < duration) {\n" 1124 " test();\n"
1260 " try {\n" 1125 " } catch(e) {}\n"
1261 " test();\n"
1262 " } catch(e) {}\n"
1263 " }\n"
1264 "}"; 1126 "}";
1265 1127
1266
1267 // [Top down]: 1128 // [Top down]:
1268 // 94 0 (root) [-1] #0 1 1129 // 94 0 (root) [-1] #0 1
1269 // 2 2 (garbage collector) [-1] #0 7 1130 // 2 2 (garbage collector) [-1] #0 7
1270 // 82 49 start [-1] #16 3 1131 // 82 49 start [-1] #16 3
1271 // 1 0 (unresolved function) [-1] #0 8
1272 // 1 1 apply [-1] #0 9
1273 // 32 21 test [-1] #16 4 1132 // 32 21 test [-1] #16 4
1274 // 2 2 bar [-1] #16 6 1133 // 2 2 bar [-1] #16 6
1275 // 9 9 apply [-1] #0 5
1276 // 10 10 (program) [-1] #0 2 1134 // 10 10 (program) [-1] #0 2
1277 TEST(FunctionApplySample) { 1135 TEST(FunctionApplySample) {
yurys 2016/02/05 17:33:04 This test as its name implies should check that th
alph 2016/02/05 17:52:26 It just checks that functions called through apply
yurys 2016/02/05 18:07:33 See my reply above.
1278 LocalContext env; 1136 v8::HandleScope scope(CcTest::isolate());
1279 v8::HandleScope scope(env->GetIsolate()); 1137 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1138 v8::Context::Scope context_scope(env);
1280 1139
1281 CompileRun(function_apply_test_source); 1140 CompileRun(function_apply_test_source);
1282 v8::Local<v8::Function> function = GetFunction(env.local(), "start"); 1141 v8::Local<v8::Function> function = GetFunction(env, "start");
1283 1142 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0);
1284 int32_t duration_ms = 100;
1285 v8::Local<v8::Value> args[] = {
1286 v8::Integer::New(env->GetIsolate(), duration_ms)};
1287
1288 v8::CpuProfile* profile =
1289 RunProfiler(env.local(), function, args, arraysize(args), 100);
1290 1143
1291 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1144 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1292 { 1145 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
1293 ScopedVector<v8::Local<v8::String> > names(3); 1146 const v8::CpuProfileNode* testNode = GetChild(env, startNode, "test");
1294 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName); 1147 GetChild(env, testNode, "bar");
1295 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
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
1301 const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
1302 if (startNode) {
1303 {
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 1148
1332 profile->Delete(); 1149 profile->Delete();
1333 } 1150 }
1334 1151
1335
1336 static const char* cpu_profiler_deep_stack_test_source = 1152 static const char* cpu_profiler_deep_stack_test_source =
1337 "function foo(n) {\n" 1153 "function foo(n) {\n"
1338 " if (n)\n" 1154 " try {\n"
1339 " foo(n - 1);\n" 1155 " if (n)\n"
1340 " else\n" 1156 " foo(n - 1);\n"
1341 " startProfiling('my_profile');\n" 1157 " else\n"
1342 "}\n" 1158 " collectSample();\n"
1343 "function start() {\n" 1159 " } catch (e) {}\n"
1344 " foo(250);\n" 1160 "}\n"
1345 "}\n"; 1161 "function start() {\n"
1346 1162 " try {\n"
1163 " foo(250);\n"
1164 " } catch (e) {}\n"
1165 "}\n";
1347 1166
1348 // Check a deep stack 1167 // Check a deep stack
1349 // 1168 //
1350 // [Top down]: 1169 // [Top down]:
1351 // 0 (root) 0 #1 1170 // 0 (root) 0 #1
1352 // 2 (program) 0 #2 1171 // 2 (program) 0 #2
1353 // 0 start 21 #3 no reason 1172 // 0 start 21 #3 no reason
1354 // 0 foo 21 #4 no reason 1173 // 0 foo 21 #4 no reason
1355 // 0 foo 21 #5 no reason 1174 // 0 foo 21 #5 no reason
1356 // .... 1175 // ....
1357 // 0 foo 21 #253 no reason 1176 // 0 foo 21 #253 no reason
1358 // 1 startProfiling 0 #254 1177 // 1 collectSample 0 #254
1359 TEST(CpuProfileDeepStack) { 1178 TEST(CpuProfileDeepStack) {
1360 v8::HandleScope scope(CcTest::isolate()); 1179 v8::HandleScope scope(CcTest::isolate());
1361 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1180 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1362 v8::Context::Scope context_scope(env); 1181 v8::Context::Scope context_scope(env);
1363 1182
1364 CompileRun(cpu_profiler_deep_stack_test_source); 1183 CompileRun(cpu_profiler_deep_stack_test_source);
1365 v8::Local<v8::Function> function = GetFunction(env, "start"); 1184 v8::Local<v8::Function> function = GetFunction(env, "start");
1366 1185 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0);
1367 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
1368 v8::Local<v8::String> profile_name = v8_str("my_profile");
1369 function->Call(env, env->Global(), 0, NULL).ToLocalChecked();
1370 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
1371 CHECK(profile);
1372 // Dump collected profile to have a better diagnostic in case of failure.
1373 reinterpret_cast<i::CpuProfile*>(profile)->Print();
1374 1186
1375 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1187 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"); 1188 const v8::CpuProfileNode* node = GetChild(env, root, "start");
1385 for (int i = 0; i < 250; ++i) { 1189 for (int i = 0; i <= 250; ++i) {
1386 node = GetChild(env, node, "foo"); 1190 node = GetChild(env, node, "foo");
1387 } 1191 }
1388 // TODO(alph): 1192 GetChild(env, node, "collectSample");
1389 // In theory there must be one more 'foo' and a 'startProfiling' nodes, 1193 CHECK(!FindChild(env, node, "foo"));
1390 // but due to unstable top frame extraction these might be missing.
1391 1194
1392 profile->Delete(); 1195 profile->Delete();
1393 } 1196 }
1394 1197
1395
1396 static const char* js_native_js_test_source = 1198 static const char* js_native_js_test_source =
1397 "function foo() {\n" 1199 "function foo() {\n"
1398 " startProfiling('my_profile');\n" 1200 " collectSample();\n"
1399 "}\n" 1201 "}\n"
1400 "function bar() {\n" 1202 "function bar() {\n"
1401 " try { foo(); } catch(e) {}\n" 1203 " try { foo(); } catch(e) {}\n"
1402 "}\n" 1204 "}\n"
1403 "function start() {\n" 1205 "function start() {\n"
1404 " try {\n" 1206 " try {\n"
1405 " CallJsFunction(bar);\n" 1207 " CallJsFunction(bar);\n"
1406 " } catch(e) {}\n" 1208 " } catch(e) {}\n"
1407 "}"; 1209 "}";
1408 1210
1409 static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) { 1211 static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
1410 v8::Local<v8::Function> function = info[0].As<v8::Function>(); 1212 v8::Local<v8::Function> function = info[0].As<v8::Function>();
1411 v8::Local<v8::Value> argv[] = {info[1]}; 1213 v8::Local<v8::Value> argv[] = {info[1]};
1412 function->Call(info.GetIsolate()->GetCurrentContext(), info.This(), 1214 function->Call(info.GetIsolate()->GetCurrentContext(), info.This(),
1413 arraysize(argv), argv) 1215 arraysize(argv), argv)
1414 .ToLocalChecked(); 1216 .ToLocalChecked();
1415 } 1217 }
1416 1218
1417
1418 // [Top down]: 1219 // [Top down]:
1419 // 58 0 (root) #0 1 1220 // 58 0 (root) #0 1
1420 // 2 2 (program) #0 2 1221 // 2 2 (program) #0 2
1421 // 56 1 start #16 3 1222 // 56 1 start #16 3
1422 // 55 0 CallJsFunction #0 4 1223 // 55 0 CallJsFunction #0 4
1423 // 55 1 bar #16 5 1224 // 55 1 bar #16 5
1424 // 54 54 foo #16 6 1225 // 54 54 foo #16 6
1425 TEST(JsNativeJsSample) { 1226 TEST(JsNativeJsSample) {
1426 v8::HandleScope scope(CcTest::isolate()); 1227 v8::HandleScope scope(CcTest::isolate());
1427 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1228 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1428 v8::Context::Scope context_scope(env); 1229 v8::Context::Scope context_scope(env);
1429 1230
1430 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New( 1231 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
1431 env->GetIsolate(), CallJsFunction); 1232 env->GetIsolate(), CallJsFunction);
1432 v8::Local<v8::Function> func = 1233 v8::Local<v8::Function> func =
1433 func_template->GetFunction(env).ToLocalChecked(); 1234 func_template->GetFunction(env).ToLocalChecked();
1434 func->SetName(v8_str("CallJsFunction")); 1235 func->SetName(v8_str("CallJsFunction"));
1435 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust(); 1236 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust();
1436 1237
1437 CompileRun(js_native_js_test_source); 1238 CompileRun(js_native_js_test_source);
1438 v8::Local<v8::Function> function = GetFunction(env, "start"); 1239 v8::Local<v8::Function> function = GetFunction(env, "start");
1439 1240 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0);
1440 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
1441 1241
1442 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1242 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1443 {
1444 ScopedVector<v8::Local<v8::String> > names(3);
1445 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
1446 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
1447 names[2] = v8_str("start");
1448 CheckChildrenNames(env, root, names);
1449 }
1450 1243
1451 const v8::CpuProfileNode* startNode = GetChild(env, root, "start"); 1244 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
1452 CHECK_EQ(1, startNode->GetChildrenCount());
1453 const v8::CpuProfileNode* nativeFunctionNode = 1245 const v8::CpuProfileNode* nativeFunctionNode =
1454 GetChild(env, startNode, "CallJsFunction"); 1246 GetChild(env, startNode, "CallJsFunction");
1455
1456 CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
1457 const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar"); 1247 const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar");
1458
1459 CHECK_EQ(1, barNode->GetChildrenCount());
1460 GetChild(env, barNode, "foo"); 1248 GetChild(env, barNode, "foo");
1461 1249
1462 profile->Delete(); 1250 profile->Delete();
1463 } 1251 }
1464 1252
1465
1466 static const char* js_native_js_runtime_js_test_source = 1253 static const char* js_native_js_runtime_js_test_source =
1467 "function foo() {\n" 1254 "function foo() {\n"
1468 " startProfiling('my_profile');\n" 1255 " collectSample();\n"
1469 "}\n" 1256 "}\n"
1470 "var bound = foo.bind(this);\n" 1257 "var bound = foo.bind(this);\n"
1471 "function bar() {\n" 1258 "function bar() {\n"
1472 " try { bound(); } catch(e) {}\n" 1259 " try { bound(); } catch(e) {}\n"
1473 "}\n" 1260 "}\n"
1474 "function start() {\n" 1261 "function start() {\n"
1475 " try {\n" 1262 " try {\n"
1476 " CallJsFunction(bar);\n" 1263 " CallJsFunction(bar);\n"
1477 " } catch(e) {}\n" 1264 " } catch(e) {}\n"
1478 "}"; 1265 "}";
1479 1266
1480
1481 // [Top down]: 1267 // [Top down]:
1482 // 57 0 (root) #0 1 1268 // 57 0 (root) #0 1
1483 // 55 1 start #16 3 1269 // 55 1 start #16 3
1484 // 54 0 CallJsFunction #0 4 1270 // 54 0 CallJsFunction #0 4
1485 // 54 3 bar #16 5 1271 // 54 3 bar #16 5
1486 // 51 51 foo #16 6 1272 // 51 51 foo #16 6
1487 // 2 2 (program) #0 2 1273 // 2 2 (program) #0 2
1488 TEST(JsNativeJsRuntimeJsSample) { 1274 TEST(JsNativeJsRuntimeJsSample) {
1489 v8::HandleScope scope(CcTest::isolate()); 1275 v8::HandleScope scope(CcTest::isolate());
1490 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1276 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1491 v8::Context::Scope context_scope(env); 1277 v8::Context::Scope context_scope(env);
1492 1278
1493 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New( 1279 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
1494 env->GetIsolate(), CallJsFunction); 1280 env->GetIsolate(), CallJsFunction);
1495 v8::Local<v8::Function> func = 1281 v8::Local<v8::Function> func =
1496 func_template->GetFunction(env).ToLocalChecked(); 1282 func_template->GetFunction(env).ToLocalChecked();
1497 func->SetName(v8_str("CallJsFunction")); 1283 func->SetName(v8_str("CallJsFunction"));
1498 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust(); 1284 env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust();
1499 1285
1500 CompileRun(js_native_js_runtime_js_test_source); 1286 CompileRun(js_native_js_runtime_js_test_source);
1501 v8::Local<v8::Function> function = GetFunction(env, "start"); 1287 v8::Local<v8::Function> function = GetFunction(env, "start");
1502
1503 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0); 1288 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
1504 1289
1505 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1290 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1506 ScopedVector<v8::Local<v8::String> > names(3);
1507 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
1508 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
1509 names[2] = v8_str("start");
1510 CheckChildrenNames(env, root, names);
1511
1512 const v8::CpuProfileNode* startNode = GetChild(env, root, "start"); 1291 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
1513 CHECK_EQ(1, startNode->GetChildrenCount());
1514 const v8::CpuProfileNode* nativeFunctionNode = 1292 const v8::CpuProfileNode* nativeFunctionNode =
1515 GetChild(env, startNode, "CallJsFunction"); 1293 GetChild(env, startNode, "CallJsFunction");
1516
1517 CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
1518 const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar"); 1294 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"); 1295 GetChild(env, barNode, "foo");
1526 1296
1527 profile->Delete(); 1297 profile->Delete();
1528 } 1298 }
1529 1299
1530 1300
1531 static void CallJsFunction2(const v8::FunctionCallbackInfo<v8::Value>& info) { 1301 static void CallJsFunction2(const v8::FunctionCallbackInfo<v8::Value>& info) {
1532 v8::base::OS::Print("In CallJsFunction2\n"); 1302 v8::base::OS::Print("In CallJsFunction2\n");
1533 CallJsFunction(info); 1303 CallJsFunction(info);
1534 } 1304 }
1535 1305
1536
1537 static const char* js_native1_js_native2_js_test_source = 1306 static const char* js_native1_js_native2_js_test_source =
1538 "function foo() {\n" 1307 "function foo() {\n"
1539 " try {\n" 1308 " try {\n"
1540 " startProfiling('my_profile');\n" 1309 " collectSample();\n"
1541 " } catch(e) {}\n" 1310 " } catch(e) {}\n"
1542 "}\n" 1311 "}\n"
1543 "function bar() {\n" 1312 "function bar() {\n"
1544 " CallJsFunction2(foo);\n" 1313 " CallJsFunction2(foo);\n"
1545 "}\n" 1314 "}\n"
1546 "function start() {\n" 1315 "function start() {\n"
1547 " try {\n" 1316 " try {\n"
1548 " CallJsFunction1(bar);\n" 1317 " CallJsFunction1(bar);\n"
1549 " } catch(e) {}\n" 1318 " } catch(e) {}\n"
1550 "}"; 1319 "}";
1551 1320
1552
1553 // [Top down]: 1321 // [Top down]:
1554 // 57 0 (root) #0 1 1322 // 57 0 (root) #0 1
1555 // 55 1 start #16 3 1323 // 55 1 start #16 3
1556 // 54 0 CallJsFunction1 #0 4 1324 // 54 0 CallJsFunction1 #0 4
1557 // 54 0 bar #16 5 1325 // 54 0 bar #16 5
1558 // 54 0 CallJsFunction2 #0 6 1326 // 54 0 CallJsFunction2 #0 6
1559 // 54 54 foo #16 7 1327 // 54 54 foo #16 7
1560 // 2 2 (program) #0 2 1328 // 2 2 (program) #0 2
1561 TEST(JsNative1JsNative2JsSample) { 1329 TEST(JsNative1JsNative2JsSample) {
1562 v8::HandleScope scope(CcTest::isolate()); 1330 v8::HandleScope scope(CcTest::isolate());
1563 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1331 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1564 v8::Context::Scope context_scope(env); 1332 v8::Context::Scope context_scope(env);
1565 1333
1566 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
1567 env->GetIsolate(), CallJsFunction);
1568 v8::Local<v8::Function> func1 = 1334 v8::Local<v8::Function> func1 =
1569 func_template->GetFunction(env).ToLocalChecked(); 1335 v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction)
1336 ->GetFunction(env)
1337 .ToLocalChecked();
1570 func1->SetName(v8_str("CallJsFunction1")); 1338 func1->SetName(v8_str("CallJsFunction1"));
1571 env->Global()->Set(env, v8_str("CallJsFunction1"), func1).FromJust(); 1339 env->Global()->Set(env, v8_str("CallJsFunction1"), func1).FromJust();
1572 1340
1573 v8::Local<v8::Function> func2 = 1341 v8::Local<v8::Function> func2 =
1574 v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction2) 1342 v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction2)
1575 ->GetFunction(env) 1343 ->GetFunction(env)
1576 .ToLocalChecked(); 1344 .ToLocalChecked();
1577 func2->SetName(v8_str("CallJsFunction2")); 1345 func2->SetName(v8_str("CallJsFunction2"));
1578 env->Global()->Set(env, v8_str("CallJsFunction2"), func2).FromJust(); 1346 env->Global()->Set(env, v8_str("CallJsFunction2"), func2).FromJust();
1579 1347
1580 CompileRun(js_native1_js_native2_js_test_source); 1348 CompileRun(js_native1_js_native2_js_test_source);
1581 v8::Local<v8::Function> function = GetFunction(env, "start"); 1349 v8::Local<v8::Function> function = GetFunction(env, "start");
1582 1350
1583 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0); 1351 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
1584 1352
1585 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1353 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1586 ScopedVector<v8::Local<v8::String> > names(3);
1587 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
1588 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
1589 names[2] = v8_str("start");
1590 CheckChildrenNames(env, root, names);
1591
1592 const v8::CpuProfileNode* startNode = GetChild(env, root, "start"); 1354 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
1593 CHECK_EQ(1, startNode->GetChildrenCount());
1594 const v8::CpuProfileNode* nativeNode1 = 1355 const v8::CpuProfileNode* nativeNode1 =
1595 GetChild(env, startNode, "CallJsFunction1"); 1356 GetChild(env, startNode, "CallJsFunction1");
1596
1597 CHECK_EQ(1, nativeNode1->GetChildrenCount());
1598 const v8::CpuProfileNode* barNode = GetChild(env, nativeNode1, "bar"); 1357 const v8::CpuProfileNode* barNode = GetChild(env, nativeNode1, "bar");
1599
1600 CHECK_EQ(1, barNode->GetChildrenCount());
1601 const v8::CpuProfileNode* nativeNode2 = 1358 const v8::CpuProfileNode* nativeNode2 =
1602 GetChild(env, barNode, "CallJsFunction2"); 1359 GetChild(env, barNode, "CallJsFunction2");
1603
1604 CHECK_EQ(1, nativeNode2->GetChildrenCount());
1605 GetChild(env, nativeNode2, "foo"); 1360 GetChild(env, nativeNode2, "foo");
1606 1361
1607 profile->Delete(); 1362 profile->Delete();
1608 } 1363 }
1609 1364
1610 static const char* js_force_collect_sample_source = 1365 static const char* js_force_collect_sample_source =
1611 "function start() {\n" 1366 "function start() {\n"
1612 " CallCollectSample();\n" 1367 " CallCollectSample();\n"
1613 "}"; 1368 "}";
1614 1369
1615 TEST(CollectSampleAPI) { 1370 TEST(CollectSampleAPI) {
1616 v8::HandleScope scope(CcTest::isolate()); 1371 v8::HandleScope scope(CcTest::isolate());
1617 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); 1372 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
1618 v8::Context::Scope context_scope(env); 1373 v8::Context::Scope context_scope(env);
1619 1374
1620 v8::Local<v8::FunctionTemplate> func_template = 1375 v8::Local<v8::FunctionTemplate> func_template =
1621 v8::FunctionTemplate::New(env->GetIsolate(), CallCollectSample); 1376 v8::FunctionTemplate::New(env->GetIsolate(), CallCollectSample);
1622 v8::Local<v8::Function> func = 1377 v8::Local<v8::Function> func =
1623 func_template->GetFunction(env).ToLocalChecked(); 1378 func_template->GetFunction(env).ToLocalChecked();
1624 func->SetName(v8_str("CallCollectSample")); 1379 func->SetName(v8_str("CallCollectSample"));
1625 env->Global()->Set(env, v8_str("CallCollectSample"), func).FromJust(); 1380 env->Global()->Set(env, v8_str("CallCollectSample"), func).FromJust();
1626 1381
1627 CompileRun(js_force_collect_sample_source); 1382 CompileRun(js_force_collect_sample_source);
1628 v8::Local<v8::Function> function = GetFunction(env, "start"); 1383 v8::Local<v8::Function> function = GetFunction(env, "start");
1629
1630 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0); 1384 v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
1631 1385
1632 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1386 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1633 const v8::CpuProfileNode* startNode = GetChild(env, root, "start"); 1387 const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
1634 CHECK_LE(1, startNode->GetChildrenCount()); 1388 CHECK_LE(1, startNode->GetChildrenCount());
1635 GetChild(env, startNode, "CallCollectSample"); 1389 GetChild(env, startNode, "CallCollectSample");
1636 1390
1637 profile->Delete(); 1391 profile->Delete();
1638 } 1392 }
1639 1393
(...skipping 68 matching lines...)
1708 TEST(IdleTime) { 1462 TEST(IdleTime) {
1709 LocalContext env; 1463 LocalContext env;
1710 v8::HandleScope scope(env->GetIsolate()); 1464 v8::HandleScope scope(env->GetIsolate());
1711 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); 1465 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
1712 1466
1713 v8::Local<v8::String> profile_name = v8_str("my_profile"); 1467 v8::Local<v8::String> profile_name = v8_str("my_profile");
1714 cpu_profiler->StartProfiling(profile_name); 1468 cpu_profiler->StartProfiling(profile_name);
1715 1469
1716 i::Isolate* isolate = CcTest::i_isolate(); 1470 i::Isolate* isolate = CcTest::i_isolate();
1717 i::ProfilerEventsProcessor* processor = isolate->cpu_profiler()->processor(); 1471 i::ProfilerEventsProcessor* processor = isolate->cpu_profiler()->processor();
1472
1718 processor->AddCurrentStack(isolate, true); 1473 processor->AddCurrentStack(isolate, true);
1719
1720 cpu_profiler->SetIdle(true); 1474 cpu_profiler->SetIdle(true);
1721
1722 for (int i = 0; i < 3; i++) { 1475 for (int i = 0; i < 3; i++) {
1723 processor->AddCurrentStack(isolate, true); 1476 processor->AddCurrentStack(isolate, true);
1724 } 1477 }
1725
1726 cpu_profiler->SetIdle(false); 1478 cpu_profiler->SetIdle(false);
1727 processor->AddCurrentStack(isolate, true); 1479 processor->AddCurrentStack(isolate, true);
1728 1480
1729 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name); 1481 v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
1730 CHECK(profile);
1731 // Dump collected profile to have a better diagnostic in case of failure.
1732 reinterpret_cast<i::CpuProfile*>(profile)->Print();
1733 1482
1734 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); 1483 const v8::CpuProfileNode* root = profile->GetTopDownRoot();
1735 ScopedVector<v8::Local<v8::String> > names(3);
1736 names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
1737 names[1] = v8_str(ProfileGenerator::kProgramEntryName);
1738 names[2] = v8_str(ProfileGenerator::kIdleEntryName);
1739 CheckChildrenNames(env.local(), root, names);
1740 1484
1741 const v8::CpuProfileNode* programNode = 1485 const v8::CpuProfileNode* programNode =
1742 GetChild(env.local(), root, ProfileGenerator::kProgramEntryName); 1486 GetChild(env.local(), root, ProfileGenerator::kProgramEntryName);
1743 CHECK_EQ(0, programNode->GetChildrenCount()); 1487 CHECK_EQ(0, programNode->GetChildrenCount());
1744 CHECK_GE(programNode->GetHitCount(), 2u); 1488 CHECK_GE(programNode->GetHitCount(), 2u);
1745 1489
1746 const v8::CpuProfileNode* idleNode = 1490 const v8::CpuProfileNode* idleNode =
1747 GetChild(env.local(), root, ProfileGenerator::kIdleEntryName); 1491 GetChild(env.local(), root, ProfileGenerator::kIdleEntryName);
1748 CHECK_EQ(0, idleNode->GetChildrenCount()); 1492 CHECK_EQ(0, idleNode->GetChildrenCount());
1749 CHECK_GE(idleNode->GetHitCount(), 3u); 1493 CHECK_GE(idleNode->GetHitCount(), 3u);
(...skipping 414 matching lines...)
2164 iprofile->Print(); 1908 iprofile->Print();
2165 v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile); 1909 v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile);
2166 1910
2167 const char* branch[] = {"", "test"}; 1911 const char* branch[] = {"", "test"};
2168 const ProfileNode* itest_node = 1912 const ProfileNode* itest_node =
2169 GetSimpleBranch(env, profile, branch, arraysize(branch)); 1913 GetSimpleBranch(env, profile, branch, arraysize(branch));
2170 CHECK_EQ(0U, itest_node->deopt_infos().size()); 1914 CHECK_EQ(0U, itest_node->deopt_infos().size());
2171 1915
2172 iprofiler->DeleteProfile(iprofile); 1916 iprofiler->DeleteProfile(iprofile);
2173 } 1917 }
OLDNEW
« test/cctest/profiler-extension.cc ('K') | « test/cctest/profiler-extension.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine