Home | History | Annotate | Download | only in cctest
      1 // Copyright 2010 the V8 project authors. All rights reserved.
      2 //
      3 // Tests of profiles generator and utilities.
      4 
      5 #include "v8.h"
      6 #include "cpu-profiler-inl.h"
      7 #include "cctest.h"
      8 #include "../include/v8-profiler.h"
      9 
     10 using i::CodeEntry;
     11 using i::CpuProfile;
     12 using i::CpuProfiler;
     13 using i::CpuProfilesCollection;
     14 using i::ProfileGenerator;
     15 using i::ProfileNode;
     16 using i::ProfilerEventsProcessor;
     17 using i::TokenEnumerator;
     18 
     19 
     20 TEST(StartStop) {
     21   CpuProfilesCollection profiles;
     22   ProfileGenerator generator(&profiles);
     23   ProfilerEventsProcessor processor(&generator);
     24   processor.Start();
     25   processor.Stop();
     26   processor.Join();
     27 }
     28 
     29 static v8::Persistent<v8::Context> env;
     30 
     31 static void InitializeVM() {
     32   if (env.IsEmpty()) env = v8::Context::New();
     33   v8::HandleScope scope;
     34   env->Enter();
     35 }
     36 
     37 static inline i::Address ToAddress(int n) {
     38   return reinterpret_cast<i::Address>(n);
     39 }
     40 
     41 static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
     42                                    i::Address frame1,
     43                                    i::Address frame2 = NULL,
     44                                    i::Address frame3 = NULL) {
     45   i::TickSample* sample = proc->TickSampleEvent();
     46   sample->pc = frame1;
     47   sample->tos = frame1;
     48   sample->frames_count = 0;
     49   if (frame2 != NULL) {
     50     sample->stack[0] = frame2;
     51     sample->frames_count = 1;
     52   }
     53   if (frame3 != NULL) {
     54     sample->stack[1] = frame3;
     55     sample->frames_count = 2;
     56   }
     57 }
     58 
     59 namespace {
     60 
     61 class TestSetup {
     62  public:
     63   TestSetup()
     64       : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
     65     i::FLAG_prof_browser_mode = false;
     66   }
     67 
     68   ~TestSetup() {
     69     i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
     70   }
     71 
     72  private:
     73   bool old_flag_prof_browser_mode_;
     74 };
     75 
     76 }  // namespace
     77 
     78 TEST(CodeEvents) {
     79   InitializeVM();
     80   TestSetup test_setup;
     81   CpuProfilesCollection profiles;
     82   profiles.StartProfiling("", 1);
     83   ProfileGenerator generator(&profiles);
     84   ProfilerEventsProcessor processor(&generator);
     85   processor.Start();
     86 
     87   // Enqueue code creation events.
     88   i::HandleScope scope;
     89   const char* aaa_str = "aaa";
     90   i::Handle<i::String> aaa_name = FACTORY->NewStringFromAscii(
     91       i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
     92   processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
     93                             *aaa_name,
     94                             HEAP->empty_string(),
     95                             0,
     96                             ToAddress(0x1000),
     97                             0x100,
     98                             ToAddress(0x10000));
     99   processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
    100                             "bbb",
    101                             ToAddress(0x1200),
    102                             0x80);
    103   processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
    104   processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
    105                             "ddd",
    106                             ToAddress(0x1400),
    107                             0x80);
    108   processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500));
    109   processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
    110   processor.CodeCreateEvent(i::Logger::STUB_TAG, 4, ToAddress(0x1605), 0x10);
    111   // Enqueue a tick event to enable code events processing.
    112   EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
    113 
    114   processor.Stop();
    115   processor.Join();
    116 
    117   // Check the state of profile generator.
    118   CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000));
    119   CHECK_NE(NULL, entry1);
    120   CHECK_EQ(aaa_str, entry1->name());
    121   CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200));
    122   CHECK_NE(NULL, entry2);
    123   CHECK_EQ("bbb", entry2->name());
    124   CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300));
    125   CHECK_NE(NULL, entry3);
    126   CHECK_EQ("5", entry3->name());
    127   CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400)));
    128   CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500));
    129   CHECK_NE(NULL, entry4);
    130   CHECK_EQ("ddd", entry4->name());
    131   CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600)));
    132 }
    133 
    134 
    135 template<typename T>
    136 static int CompareProfileNodes(const T* p1, const T* p2) {
    137   return strcmp((*p1)->entry()->name(), (*p2)->entry()->name());
    138 }
    139 
    140 TEST(TickEvents) {
    141   TestSetup test_setup;
    142   CpuProfilesCollection profiles;
    143   profiles.StartProfiling("", 1);
    144   ProfileGenerator generator(&profiles);
    145   ProfilerEventsProcessor processor(&generator);
    146   processor.Start();
    147 
    148   processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
    149                             "bbb",
    150                             ToAddress(0x1200),
    151                             0x80);
    152   processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
    153   processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
    154                             "ddd",
    155                             ToAddress(0x1400),
    156                             0x80);
    157   EnqueueTickSampleEvent(&processor, ToAddress(0x1210));
    158   EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220));
    159   EnqueueTickSampleEvent(&processor,
    160                          ToAddress(0x1404),
    161                          ToAddress(0x1305),
    162                          ToAddress(0x1230));
    163 
    164   processor.Stop();
    165   processor.Join();
    166   CpuProfile* profile =
    167       profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
    168   CHECK_NE(NULL, profile);
    169 
    170   // Check call trees.
    171   const i::List<ProfileNode*>* top_down_root_children =
    172       profile->top_down()->root()->children();
    173   CHECK_EQ(1, top_down_root_children->length());
    174   CHECK_EQ("bbb", top_down_root_children->last()->entry()->name());
    175   const i::List<ProfileNode*>* top_down_bbb_children =
    176       top_down_root_children->last()->children();
    177   CHECK_EQ(1, top_down_bbb_children->length());
    178   CHECK_EQ("5", top_down_bbb_children->last()->entry()->name());
    179   const i::List<ProfileNode*>* top_down_stub_children =
    180       top_down_bbb_children->last()->children();
    181   CHECK_EQ(1, top_down_stub_children->length());
    182   CHECK_EQ("ddd", top_down_stub_children->last()->entry()->name());
    183   const i::List<ProfileNode*>* top_down_ddd_children =
    184       top_down_stub_children->last()->children();
    185   CHECK_EQ(0, top_down_ddd_children->length());
    186 
    187   const i::List<ProfileNode*>* bottom_up_root_children_unsorted =
    188       profile->bottom_up()->root()->children();
    189   CHECK_EQ(3, bottom_up_root_children_unsorted->length());
    190   i::List<ProfileNode*> bottom_up_root_children(3);
    191   bottom_up_root_children.AddAll(*bottom_up_root_children_unsorted);
    192   bottom_up_root_children.Sort(&CompareProfileNodes);
    193   CHECK_EQ("5", bottom_up_root_children[0]->entry()->name());
    194   CHECK_EQ("bbb", bottom_up_root_children[1]->entry()->name());
    195   CHECK_EQ("ddd", bottom_up_root_children[2]->entry()->name());
    196   const i::List<ProfileNode*>* bottom_up_stub_children =
    197       bottom_up_root_children[0]->children();
    198   CHECK_EQ(1, bottom_up_stub_children->length());
    199   CHECK_EQ("bbb", bottom_up_stub_children->last()->entry()->name());
    200   const i::List<ProfileNode*>* bottom_up_bbb_children =
    201       bottom_up_root_children[1]->children();
    202   CHECK_EQ(0, bottom_up_bbb_children->length());
    203   const i::List<ProfileNode*>* bottom_up_ddd_children =
    204       bottom_up_root_children[2]->children();
    205   CHECK_EQ(1, bottom_up_ddd_children->length());
    206   CHECK_EQ("5", bottom_up_ddd_children->last()->entry()->name());
    207   const i::List<ProfileNode*>* bottom_up_ddd_stub_children =
    208       bottom_up_ddd_children->last()->children();
    209   CHECK_EQ(1, bottom_up_ddd_stub_children->length());
    210   CHECK_EQ("bbb", bottom_up_ddd_stub_children->last()->entry()->name());
    211 }
    212 
    213 
    214 // http://crbug/51594
    215 // This test must not crash.
    216 TEST(CrashIfStoppingLastNonExistentProfile) {
    217   InitializeVM();
    218   TestSetup test_setup;
    219   CpuProfiler::SetUp();
    220   CpuProfiler::StartProfiling("1");
    221   CpuProfiler::StopProfiling("2");
    222   CpuProfiler::StartProfiling("1");
    223   CpuProfiler::StopProfiling("");
    224   CpuProfiler::TearDown();
    225 }
    226 
    227 
    228 // http://code.google.com/p/v8/issues/detail?id=1398
    229 // Long stacks (exceeding max frames limit) must not be erased.
    230 TEST(Issue1398) {
    231   TestSetup test_setup;
    232   CpuProfilesCollection profiles;
    233   profiles.StartProfiling("", 1);
    234   ProfileGenerator generator(&profiles);
    235   ProfilerEventsProcessor processor(&generator);
    236   processor.Start();
    237 
    238   processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
    239                             "bbb",
    240                             ToAddress(0x1200),
    241                             0x80);
    242 
    243   i::TickSample* sample = processor.TickSampleEvent();
    244   sample->pc = ToAddress(0x1200);
    245   sample->tos = 0;
    246   sample->frames_count = i::TickSample::kMaxFramesCount;
    247   for (int i = 0; i < sample->frames_count; ++i) {
    248     sample->stack[i] = ToAddress(0x1200);
    249   }
    250 
    251   processor.Stop();
    252   processor.Join();
    253   CpuProfile* profile =
    254       profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
    255   CHECK_NE(NULL, profile);
    256 
    257   int actual_depth = 0;
    258   const ProfileNode* node = profile->top_down()->root();
    259   while (node->children()->length() > 0) {
    260     node = node->children()->last();
    261     ++actual_depth;
    262   }
    263 
    264   CHECK_EQ(1 + i::TickSample::kMaxFramesCount, actual_depth);  // +1 for PC.
    265 }
    266 
    267 
    268 TEST(DeleteAllCpuProfiles) {
    269   InitializeVM();
    270   TestSetup test_setup;
    271   CpuProfiler::SetUp();
    272   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    273   CpuProfiler::DeleteAllProfiles();
    274   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    275 
    276   CpuProfiler::StartProfiling("1");
    277   CpuProfiler::StopProfiling("1");
    278   CHECK_EQ(1, CpuProfiler::GetProfilesCount());
    279   CpuProfiler::DeleteAllProfiles();
    280   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    281   CpuProfiler::StartProfiling("1");
    282   CpuProfiler::StartProfiling("2");
    283   CpuProfiler::StopProfiling("2");
    284   CpuProfiler::StopProfiling("1");
    285   CHECK_EQ(2, CpuProfiler::GetProfilesCount());
    286   CpuProfiler::DeleteAllProfiles();
    287   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    288 
    289   // Test profiling cancellation by the 'delete' command.
    290   CpuProfiler::StartProfiling("1");
    291   CpuProfiler::StartProfiling("2");
    292   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    293   CpuProfiler::DeleteAllProfiles();
    294   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    295 
    296   CpuProfiler::TearDown();
    297 }
    298 
    299 
    300 TEST(DeleteCpuProfile) {
    301   v8::HandleScope scope;
    302   LocalContext env;
    303 
    304   CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
    305   v8::Local<v8::String> name1 = v8::String::New("1");
    306   v8::CpuProfiler::StartProfiling(name1);
    307   const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
    308   CHECK_NE(NULL, p1);
    309   CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
    310   unsigned uid1 = p1->GetUid();
    311   CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
    312   const_cast<v8::CpuProfile*>(p1)->Delete();
    313   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    314   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
    315 
    316   v8::Local<v8::String> name2 = v8::String::New("2");
    317   v8::CpuProfiler::StartProfiling(name2);
    318   const v8::CpuProfile* p2 = v8::CpuProfiler::StopProfiling(name2);
    319   CHECK_NE(NULL, p2);
    320   CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
    321   unsigned uid2 = p2->GetUid();
    322   CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
    323   CHECK_EQ(p2, v8::CpuProfiler::FindProfile(uid2));
    324   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
    325   v8::Local<v8::String> name3 = v8::String::New("3");
    326   v8::CpuProfiler::StartProfiling(name3);
    327   const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
    328   CHECK_NE(NULL, p3);
    329   CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
    330   unsigned uid3 = p3->GetUid();
    331   CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
    332   CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
    333   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
    334   const_cast<v8::CpuProfile*>(p2)->Delete();
    335   CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
    336   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
    337   CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
    338   const_cast<v8::CpuProfile*>(p3)->Delete();
    339   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    340   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
    341   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
    342   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
    343 }
    344 
    345 
    346 TEST(DeleteCpuProfileDifferentTokens) {
    347   v8::HandleScope scope;
    348   LocalContext env;
    349 
    350   CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount());
    351   v8::Local<v8::String> name1 = v8::String::New("1");
    352   v8::CpuProfiler::StartProfiling(name1);
    353   const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1);
    354   CHECK_NE(NULL, p1);
    355   CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
    356   unsigned uid1 = p1->GetUid();
    357   CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1));
    358   v8::Local<v8::String> token1 = v8::String::New("token1");
    359   const v8::CpuProfile* p1_t1 = v8::CpuProfiler::FindProfile(uid1, token1);
    360   CHECK_NE(NULL, p1_t1);
    361   CHECK_NE(p1, p1_t1);
    362   CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
    363   const_cast<v8::CpuProfile*>(p1)->Delete();
    364   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    365   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
    366   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1, token1));
    367   const_cast<v8::CpuProfile*>(p1_t1)->Delete();
    368   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    369 
    370   v8::Local<v8::String> name2 = v8::String::New("2");
    371   v8::CpuProfiler::StartProfiling(name2);
    372   v8::Local<v8::String> token2 = v8::String::New("token2");
    373   const v8::CpuProfile* p2_t2 = v8::CpuProfiler::StopProfiling(name2, token2);
    374   CHECK_NE(NULL, p2_t2);
    375   CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
    376   unsigned uid2 = p2_t2->GetUid();
    377   CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
    378   const v8::CpuProfile* p2 = v8::CpuProfiler::FindProfile(uid2);
    379   CHECK_NE(p2_t2, p2);
    380   v8::Local<v8::String> name3 = v8::String::New("3");
    381   v8::CpuProfiler::StartProfiling(name3);
    382   const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3);
    383   CHECK_NE(NULL, p3);
    384   CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount());
    385   unsigned uid3 = p3->GetUid();
    386   CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
    387   CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
    388   const_cast<v8::CpuProfile*>(p2_t2)->Delete();
    389   CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
    390   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
    391   CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
    392   const_cast<v8::CpuProfile*>(p2)->Delete();
    393   CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
    394   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
    395   CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
    396   const_cast<v8::CpuProfile*>(p3)->Delete();
    397   CHECK_EQ(0, CpuProfiler::GetProfilesCount());
    398   CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
    399 }
    400