blob: bd966fa21b9ac8c9bb06938f4d380b9b98ca10ee [file] [log] [blame]
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001// 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
9namespace i = v8::internal;
10
11using i::CodeEntry;
12using i::CpuProfilesCollection;
13using i::ProfileGenerator;
14using i::ProfileNode;
15using i::ProfilerEventsProcessor;
16
17
18TEST(StartStop) {
19 CpuProfilesCollection profiles;
20 ProfileGenerator generator(&profiles);
21 ProfilerEventsProcessor processor(&generator);
22 processor.Start();
23 while (!processor.running()) {
24 i::Thread::YieldCPU();
25 }
26 processor.Stop();
27 processor.Join();
28}
29
30static v8::Persistent<v8::Context> env;
31
32static void InitializeVM() {
33 if (env.IsEmpty()) env = v8::Context::New();
34 v8::HandleScope scope;
35 env->Enter();
36}
37
38static inline i::Address ToAddress(int n) {
39 return reinterpret_cast<i::Address>(n);
40}
41
42static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
43 i::Address frame1,
44 i::Address frame2 = NULL,
45 i::Address frame3 = NULL) {
46 i::TickSample* sample = proc->TickSampleEvent();
47 sample->pc = frame1;
48 sample->function = frame1;
49 sample->frames_count = 0;
50 if (frame2 != NULL) {
51 sample->stack[0] = frame2;
52 sample->frames_count = 1;
53 }
54 if (frame3 != NULL) {
55 sample->stack[1] = frame3;
56 sample->frames_count = 2;
57 }
58}
59
60TEST(CodeEvents) {
61 InitializeVM();
62 CpuProfilesCollection profiles;
63 profiles.AddProfile(0);
64 ProfileGenerator generator(&profiles);
65 ProfilerEventsProcessor processor(&generator);
66 processor.Start();
67 processor.SetUpSamplesProducer();
68 while (!processor.running()) {
69 i::Thread::YieldCPU();
70 }
71
72 // Enqueue code creation events.
73 i::HandleScope scope;
74 const char* aaa_str = "aaa";
75 i::Handle<i::String> aaa_name = i::Factory::NewStringFromAscii(
76 i::Vector<const char>(aaa_str, strlen(aaa_str)));
77 processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
78 *aaa_name,
79 i::Heap::empty_string(),
80 0,
81 ToAddress(0x1000),
82 0x100);
83 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
84 "bbb",
85 ToAddress(0x1200),
86 0x80);
87 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
88 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
89 "ddd",
90 ToAddress(0x1400),
91 0x80);
92 processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500));
93 processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
94 processor.CodeDeleteEvent(ToAddress(0x1600));
95 processor.FunctionCreateEvent(ToAddress(0x1700), ToAddress(0x1000));
96 // Enqueue a tick event to enable code events processing.
97 EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
98
99 processor.Stop();
100 processor.Join();
101
102 // Check the state of profile generator.
103 CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000));
104 CHECK_NE(NULL, entry1);
105 CHECK_EQ(aaa_str, entry1->name());
106 CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200));
107 CHECK_NE(NULL, entry2);
108 CHECK_EQ("bbb", entry2->name());
109 CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300));
110 CHECK_NE(NULL, entry3);
111 CHECK_EQ("args_count: 5", entry3->name());
112 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400)));
113 CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500));
114 CHECK_NE(NULL, entry4);
115 CHECK_EQ("ddd", entry4->name());
116 CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600)));
117 CodeEntry* entry5 = generator.code_map()->FindEntry(ToAddress(0x1700));
118 CHECK_NE(NULL, entry5);
119 CHECK_EQ(aaa_str, entry5->name());
120
121 processor.TearDownSamplesProducer();
122}
123
124
125template<typename T>
126static int CompareProfileNodes(const T* p1, const T* p2) {
127 return strcmp((*p1)->entry()->name(), (*p2)->entry()->name());
128}
129
130TEST(TickEvents) {
131 CpuProfilesCollection profiles;
132 profiles.AddProfile(0);
133 ProfileGenerator generator(&profiles);
134 ProfilerEventsProcessor processor(&generator);
135 processor.Start();
136 processor.SetUpSamplesProducer();
137 while (!processor.running()) {
138 i::Thread::YieldCPU();
139 }
140
141 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
142 "bbb",
143 ToAddress(0x1200),
144 0x80);
145 processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
146 processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
147 "ddd",
148 ToAddress(0x1400),
149 0x80);
150 EnqueueTickSampleEvent(&processor, ToAddress(0x1210));
151 EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220));
152 EnqueueTickSampleEvent(&processor,
153 ToAddress(0x1404),
154 ToAddress(0x1305),
155 ToAddress(0x1230));
156
157 processor.Stop();
158 processor.Join();
159
160 // Check call trees.
161 i::List<ProfileNode*> top_down_root_children;
162 profiles.profile()->top_down()->root()->GetChildren(&top_down_root_children);
163 CHECK_EQ(1, top_down_root_children.length());
164 CHECK_EQ("bbb", top_down_root_children.last()->entry()->name());
165 i::List<ProfileNode*> top_down_bbb_children;
166 top_down_root_children.last()->GetChildren(&top_down_bbb_children);
167 CHECK_EQ(1, top_down_bbb_children.length());
168 CHECK_EQ("args_count: 5", top_down_bbb_children.last()->entry()->name());
169 i::List<ProfileNode*> top_down_stub_children;
170 top_down_bbb_children.last()->GetChildren(&top_down_stub_children);
171 CHECK_EQ(1, top_down_stub_children.length());
172 CHECK_EQ("ddd", top_down_stub_children.last()->entry()->name());
173 i::List<ProfileNode*> top_down_ddd_children;
174 top_down_stub_children.last()->GetChildren(&top_down_ddd_children);
175 CHECK_EQ(0, top_down_ddd_children.length());
176
177 i::List<ProfileNode*> bottom_up_root_children;
178 profiles.profile()->bottom_up()->root()->GetChildren(
179 &bottom_up_root_children);
180 CHECK_EQ(3, bottom_up_root_children.length());
181 bottom_up_root_children.Sort(&CompareProfileNodes);
182 CHECK_EQ("args_count: 5", bottom_up_root_children[0]->entry()->name());
183 CHECK_EQ("bbb", bottom_up_root_children[1]->entry()->name());
184 CHECK_EQ("ddd", bottom_up_root_children[2]->entry()->name());
185 i::List<ProfileNode*> bottom_up_stub_children;
186 bottom_up_root_children[0]->GetChildren(&bottom_up_stub_children);
187 CHECK_EQ(1, bottom_up_stub_children.length());
188 CHECK_EQ("bbb", bottom_up_stub_children.last()->entry()->name());
189 i::List<ProfileNode*> bottom_up_bbb_children;
190 bottom_up_root_children[1]->GetChildren(&bottom_up_bbb_children);
191 CHECK_EQ(0, bottom_up_bbb_children.length());
192 i::List<ProfileNode*> bottom_up_ddd_children;
193 bottom_up_root_children[2]->GetChildren(&bottom_up_ddd_children);
194 CHECK_EQ(1, bottom_up_ddd_children.length());
195 CHECK_EQ("args_count: 5", bottom_up_ddd_children.last()->entry()->name());
196 i::List<ProfileNode*> bottom_up_ddd_stub_children;
197 bottom_up_ddd_children.last()->GetChildren(&bottom_up_ddd_stub_children);
198 CHECK_EQ(1, bottom_up_ddd_stub_children.length());
199 CHECK_EQ("bbb", bottom_up_ddd_stub_children.last()->entry()->name());
200
201 processor.TearDownSamplesProducer();
202}