blob: fa7dc155ee747fcf4ff204a779e707e84f8b3f73 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Steve Block6ded16b2010-05-10 14:33:55 +010027//
28// Tests of profiles generator and utilities.
29
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/v8.h"
31
32#include "include/v8-profiler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033#include "src/profiler/cpu-profiler.h"
34#include "src/profiler/profile-generator-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#include "test/cctest/cctest.h"
36#include "test/cctest/profiler-extension.h"
Steve Block6ded16b2010-05-10 14:33:55 +010037
Steve Block6ded16b2010-05-10 14:33:55 +010038using i::CodeEntry;
39using i::CodeMap;
40using i::CpuProfile;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010041using i::CpuProfiler;
Steve Block6ded16b2010-05-10 14:33:55 +010042using i::CpuProfilesCollection;
43using i::ProfileNode;
44using i::ProfileTree;
45using i::ProfileGenerator;
Steve Block6ded16b2010-05-10 14:33:55 +010046using i::TickSample;
47using i::Vector;
48
49
50TEST(ProfileNodeFindOrAddChild) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 CcTest::InitializeVM();
52 ProfileTree tree(CcTest::i_isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053 ProfileNode* node = tree.root();
54 CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
55 ProfileNode* childNode1 = node->FindOrAddChild(&entry1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 CHECK(childNode1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 CHECK_EQ(childNode1, node->FindOrAddChild(&entry1));
58 CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
59 ProfileNode* childNode2 = node->FindOrAddChild(&entry2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 CHECK(childNode2);
Steve Block6ded16b2010-05-10 14:33:55 +010061 CHECK_NE(childNode1, childNode2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 CHECK_EQ(childNode1, node->FindOrAddChild(&entry1));
63 CHECK_EQ(childNode2, node->FindOrAddChild(&entry2));
64 CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
65 ProfileNode* childNode3 = node->FindOrAddChild(&entry3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 CHECK(childNode3);
Steve Block6ded16b2010-05-10 14:33:55 +010067 CHECK_NE(childNode1, childNode3);
68 CHECK_NE(childNode2, childNode3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 CHECK_EQ(childNode1, node->FindOrAddChild(&entry1));
70 CHECK_EQ(childNode2, node->FindOrAddChild(&entry2));
71 CHECK_EQ(childNode3, node->FindOrAddChild(&entry3));
Steve Block6ded16b2010-05-10 14:33:55 +010072}
73
74
Kristian Monsen0d5e1162010-09-30 15:31:59 +010075TEST(ProfileNodeFindOrAddChildForSameFunction) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 CcTest::InitializeVM();
Kristian Monsen0d5e1162010-09-30 15:31:59 +010077 const char* aaa = "aaa";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 ProfileTree tree(CcTest::i_isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 ProfileNode* node = tree.root();
80 CodeEntry entry1(i::Logger::FUNCTION_TAG, aaa);
81 ProfileNode* childNode1 = node->FindOrAddChild(&entry1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 CHECK(childNode1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 CHECK_EQ(childNode1, node->FindOrAddChild(&entry1));
Kristian Monsen0d5e1162010-09-30 15:31:59 +010084 // The same function again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000085 CodeEntry entry2(i::Logger::FUNCTION_TAG, aaa);
86 CHECK_EQ(childNode1, node->FindOrAddChild(&entry2));
Kristian Monsen0d5e1162010-09-30 15:31:59 +010087 // Now with a different security token.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 CodeEntry entry3(i::Logger::FUNCTION_TAG, aaa);
89 CHECK_EQ(childNode1, node->FindOrAddChild(&entry3));
Kristian Monsen0d5e1162010-09-30 15:31:59 +010090}
91
92
Steve Block6ded16b2010-05-10 14:33:55 +010093namespace {
94
95class ProfileTreeTestHelper {
96 public:
97 explicit ProfileTreeTestHelper(const ProfileTree* tree)
98 : tree_(tree) { }
99
100 ProfileNode* Walk(CodeEntry* entry1,
101 CodeEntry* entry2 = NULL,
102 CodeEntry* entry3 = NULL) {
103 ProfileNode* node = tree_->root();
104 node = node->FindChild(entry1);
105 if (node == NULL) return NULL;
106 if (entry2 != NULL) {
107 node = node->FindChild(entry2);
108 if (node == NULL) return NULL;
109 }
110 if (entry3 != NULL) {
111 node = node->FindChild(entry3);
112 }
113 return node;
114 }
115
116 private:
117 const ProfileTree* tree_;
118};
119
120} // namespace
121
Steve Block6ded16b2010-05-10 14:33:55 +0100122
123TEST(ProfileTreeAddPathFromEnd) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 CcTest::InitializeVM();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125 CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
126 CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
127 CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 ProfileTree tree(CcTest::i_isolate());
Steve Block6ded16b2010-05-10 14:33:55 +0100129 ProfileTreeTestHelper helper(&tree);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130 CHECK(!helper.Walk(&entry1));
131 CHECK(!helper.Walk(&entry2));
132 CHECK(!helper.Walk(&entry3));
Steve Block6ded16b2010-05-10 14:33:55 +0100133
134 CodeEntry* path[] = {NULL, &entry3, NULL, &entry2, NULL, NULL, &entry1, NULL};
135 Vector<CodeEntry*> path_vec(path, sizeof(path) / sizeof(path[0]));
136 tree.AddPathFromEnd(path_vec);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137 CHECK(!helper.Walk(&entry2));
138 CHECK(!helper.Walk(&entry3));
Steve Block6ded16b2010-05-10 14:33:55 +0100139 ProfileNode* node1 = helper.Walk(&entry1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 CHECK(node1);
141 CHECK_EQ(0u, node1->self_ticks());
142 CHECK(!helper.Walk(&entry1, &entry1));
143 CHECK(!helper.Walk(&entry1, &entry3));
Steve Block6ded16b2010-05-10 14:33:55 +0100144 ProfileNode* node2 = helper.Walk(&entry1, &entry2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 CHECK(node2);
Steve Block6ded16b2010-05-10 14:33:55 +0100146 CHECK_NE(node1, node2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 CHECK_EQ(0u, node2->self_ticks());
148 CHECK(!helper.Walk(&entry1, &entry2, &entry1));
149 CHECK(!helper.Walk(&entry1, &entry2, &entry2));
Steve Block6ded16b2010-05-10 14:33:55 +0100150 ProfileNode* node3 = helper.Walk(&entry1, &entry2, &entry3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 CHECK(node3);
Steve Block6ded16b2010-05-10 14:33:55 +0100152 CHECK_NE(node1, node3);
153 CHECK_NE(node2, node3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154 CHECK_EQ(1u, node3->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100155
156 tree.AddPathFromEnd(path_vec);
157 CHECK_EQ(node1, helper.Walk(&entry1));
158 CHECK_EQ(node2, helper.Walk(&entry1, &entry2));
159 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160 CHECK_EQ(0u, node1->self_ticks());
161 CHECK_EQ(0u, node2->self_ticks());
162 CHECK_EQ(2u, node3->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100163
164 CodeEntry* path2[] = {&entry2, &entry2, &entry1};
165 Vector<CodeEntry*> path2_vec(path2, sizeof(path2) / sizeof(path2[0]));
166 tree.AddPathFromEnd(path2_vec);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 CHECK(!helper.Walk(&entry2));
168 CHECK(!helper.Walk(&entry3));
Steve Block6ded16b2010-05-10 14:33:55 +0100169 CHECK_EQ(node1, helper.Walk(&entry1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 CHECK(!helper.Walk(&entry1, &entry1));
171 CHECK(!helper.Walk(&entry1, &entry3));
Steve Block6ded16b2010-05-10 14:33:55 +0100172 CHECK_EQ(node2, helper.Walk(&entry1, &entry2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 CHECK(!helper.Walk(&entry1, &entry2, &entry1));
Steve Block6ded16b2010-05-10 14:33:55 +0100174 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 CHECK_EQ(2u, node3->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100176 ProfileNode* node4 = helper.Walk(&entry1, &entry2, &entry2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177 CHECK(node4);
Steve Block6ded16b2010-05-10 14:33:55 +0100178 CHECK_NE(node3, node4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 CHECK_EQ(1u, node4->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100180}
181
182
183TEST(ProfileTreeCalculateTotalTicks) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 CcTest::InitializeVM();
185 ProfileTree empty_tree(CcTest::i_isolate());
186 CHECK_EQ(0u, empty_tree.root()->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100187 empty_tree.root()->IncrementSelfTicks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 CHECK_EQ(1u, empty_tree.root()->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100189
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
Steve Block6ded16b2010-05-10 14:33:55 +0100191 CodeEntry* e1_path[] = {&entry1};
192 Vector<CodeEntry*> e1_path_vec(
193 e1_path, sizeof(e1_path) / sizeof(e1_path[0]));
Leon Clarkef7060e22010-06-03 12:02:55 +0100194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 ProfileTree single_child_tree(CcTest::i_isolate());
196 single_child_tree.AddPathFromEnd(e1_path_vec);
Leon Clarkef7060e22010-06-03 12:02:55 +0100197 single_child_tree.root()->IncrementSelfTicks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 CHECK_EQ(1u, single_child_tree.root()->self_ticks());
Leon Clarkef7060e22010-06-03 12:02:55 +0100199 ProfileTreeTestHelper single_child_helper(&single_child_tree);
200 ProfileNode* node1 = single_child_helper.Walk(&entry1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 CHECK(node1);
202 CHECK_EQ(1u, single_child_tree.root()->self_ticks());
203 CHECK_EQ(1u, node1->self_ticks());
Leon Clarkef7060e22010-06-03 12:02:55 +0100204
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 CodeEntry* e2_e1_path[] = {&entry2, &entry1};
207 Vector<CodeEntry*> e2_e1_path_vec(e2_e1_path,
208 sizeof(e2_e1_path) / sizeof(e2_e1_path[0]));
Steve Block6ded16b2010-05-10 14:33:55 +0100209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 ProfileTree flat_tree(CcTest::i_isolate());
Steve Block6ded16b2010-05-10 14:33:55 +0100211 ProfileTreeTestHelper flat_helper(&flat_tree);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 flat_tree.AddPathFromEnd(e1_path_vec);
213 flat_tree.AddPathFromEnd(e1_path_vec);
214 flat_tree.AddPathFromEnd(e2_e1_path_vec);
215 flat_tree.AddPathFromEnd(e2_e1_path_vec);
216 flat_tree.AddPathFromEnd(e2_e1_path_vec);
Steve Block6ded16b2010-05-10 14:33:55 +0100217 // Results in {root,0,0} -> {entry1,0,2} -> {entry2,0,3}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 CHECK_EQ(0u, flat_tree.root()->self_ticks());
Leon Clarkef7060e22010-06-03 12:02:55 +0100219 node1 = flat_helper.Walk(&entry1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 CHECK(node1);
221 CHECK_EQ(2u, node1->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100222 ProfileNode* node2 = flat_helper.Walk(&entry1, &entry2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223 CHECK(node2);
224 CHECK_EQ(3u, node2->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100225 // Must calculate {root,5,0} -> {entry1,5,2} -> {entry2,3,3}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000226 CHECK_EQ(0u, flat_tree.root()->self_ticks());
227 CHECK_EQ(2u, node1->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100228
229 CodeEntry* e2_path[] = {&entry2};
230 Vector<CodeEntry*> e2_path_vec(
231 e2_path, sizeof(e2_path) / sizeof(e2_path[0]));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
Steve Block6ded16b2010-05-10 14:33:55 +0100233 CodeEntry* e3_path[] = {&entry3};
234 Vector<CodeEntry*> e3_path_vec(
235 e3_path, sizeof(e3_path) / sizeof(e3_path[0]));
236
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 ProfileTree wide_tree(CcTest::i_isolate());
Steve Block6ded16b2010-05-10 14:33:55 +0100238 ProfileTreeTestHelper wide_helper(&wide_tree);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 wide_tree.AddPathFromEnd(e1_path_vec);
240 wide_tree.AddPathFromEnd(e1_path_vec);
241 wide_tree.AddPathFromEnd(e2_e1_path_vec);
242 wide_tree.AddPathFromEnd(e2_path_vec);
243 wide_tree.AddPathFromEnd(e2_path_vec);
244 wide_tree.AddPathFromEnd(e2_path_vec);
245 wide_tree.AddPathFromEnd(e3_path_vec);
246 wide_tree.AddPathFromEnd(e3_path_vec);
247 wide_tree.AddPathFromEnd(e3_path_vec);
248 wide_tree.AddPathFromEnd(e3_path_vec);
Steve Block6ded16b2010-05-10 14:33:55 +0100249 // Results in -> {entry1,0,2} -> {entry2,0,1}
250 // {root,0,0} -> {entry2,0,3}
251 // -> {entry3,0,4}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 CHECK_EQ(0u, wide_tree.root()->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100253 node1 = wide_helper.Walk(&entry1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254 CHECK(node1);
255 CHECK_EQ(2u, node1->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100256 ProfileNode* node1_2 = wide_helper.Walk(&entry1, &entry2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257 CHECK(node1_2);
258 CHECK_EQ(1u, node1_2->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100259 node2 = wide_helper.Walk(&entry2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260 CHECK(node2);
261 CHECK_EQ(3u, node2->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100262 ProfileNode* node3 = wide_helper.Walk(&entry3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 CHECK(node3);
264 CHECK_EQ(4u, node3->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100265 // Calculates -> {entry1,3,2} -> {entry2,1,1}
266 // {root,10,0} -> {entry2,3,3}
267 // -> {entry3,4,4}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 CHECK_EQ(0u, wide_tree.root()->self_ticks());
269 CHECK_EQ(2u, node1->self_ticks());
270 CHECK_EQ(1u, node1_2->self_ticks());
271 CHECK_EQ(3u, node2->self_ticks());
272 CHECK_EQ(4u, node3->self_ticks());
Steve Block6ded16b2010-05-10 14:33:55 +0100273}
274
275
276static inline i::Address ToAddress(int n) {
277 return reinterpret_cast<i::Address>(n);
278}
279
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000280
Steve Block6ded16b2010-05-10 14:33:55 +0100281TEST(CodeMapAddCode) {
282 CodeMap code_map;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283 CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
284 CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
285 CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
286 CodeEntry entry4(i::Logger::FUNCTION_TAG, "ddd");
Steve Block6ded16b2010-05-10 14:33:55 +0100287 code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
288 code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
289 code_map.AddCode(ToAddress(0x1900), &entry3, 0x50);
290 code_map.AddCode(ToAddress(0x1950), &entry4, 0x10);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 CHECK(!code_map.FindEntry(0));
292 CHECK(!code_map.FindEntry(ToAddress(0x1500 - 1)));
Steve Block6ded16b2010-05-10 14:33:55 +0100293 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
294 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500 + 0x100)));
295 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500 + 0x200 - 1)));
296 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700)));
297 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700 + 0x50)));
298 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700 + 0x100 - 1)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 CHECK(!code_map.FindEntry(ToAddress(0x1700 + 0x100)));
300 CHECK(!code_map.FindEntry(ToAddress(0x1900 - 1)));
Steve Block6ded16b2010-05-10 14:33:55 +0100301 CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1900)));
302 CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1900 + 0x28)));
303 CHECK_EQ(&entry4, code_map.FindEntry(ToAddress(0x1950)));
304 CHECK_EQ(&entry4, code_map.FindEntry(ToAddress(0x1950 + 0x7)));
305 CHECK_EQ(&entry4, code_map.FindEntry(ToAddress(0x1950 + 0x10 - 1)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 CHECK(!code_map.FindEntry(ToAddress(0x1950 + 0x10)));
307 CHECK(!code_map.FindEntry(ToAddress(0xFFFFFFFF)));
Steve Block6ded16b2010-05-10 14:33:55 +0100308}
309
310
311TEST(CodeMapMoveAndDeleteCode) {
312 CodeMap code_map;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000313 CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
314 CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
Steve Block6ded16b2010-05-10 14:33:55 +0100315 code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
316 code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
317 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
318 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700)));
Ben Murdoch589d6972011-11-30 16:04:58 +0000319 code_map.MoveCode(ToAddress(0x1500), ToAddress(0x1700)); // Deprecate bbb.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 CHECK(!code_map.FindEntry(ToAddress(0x1500)));
Ben Murdoch589d6972011-11-30 16:04:58 +0000321 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1700)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000322 CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
Ben Murdoch589d6972011-11-30 16:04:58 +0000323 code_map.AddCode(ToAddress(0x1750), &entry3, 0x100);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 CHECK(!code_map.FindEntry(ToAddress(0x1700)));
Ben Murdoch589d6972011-11-30 16:04:58 +0000325 CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1750)));
Steve Block6ded16b2010-05-10 14:33:55 +0100326}
327
328
329namespace {
330
331class TestSetup {
332 public:
333 TestSetup()
334 : old_flag_prof_browser_mode_(i::FLAG_prof_browser_mode) {
335 i::FLAG_prof_browser_mode = false;
336 }
337
338 ~TestSetup() {
339 i::FLAG_prof_browser_mode = old_flag_prof_browser_mode_;
340 }
341
342 private:
343 bool old_flag_prof_browser_mode_;
344};
345
346} // namespace
347
348TEST(RecordTickSample) {
349 TestSetup test_setup;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 CpuProfilesCollection profiles(CcTest::heap());
351 profiles.StartProfiling("", false);
Steve Block6ded16b2010-05-10 14:33:55 +0100352 ProfileGenerator generator(&profiles);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353 CodeEntry* entry1 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
354 CodeEntry* entry2 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb");
355 CodeEntry* entry3 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "ccc");
Steve Block6ded16b2010-05-10 14:33:55 +0100356 generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
357 generator.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
358 generator.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
359
360 // We are building the following calls tree:
361 // -> aaa - sample1
362 // aaa -> bbb -> ccc - sample2
363 // -> ccc -> aaa - sample3
364 TickSample sample1;
365 sample1.pc = ToAddress(0x1600);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100366 sample1.tos = ToAddress(0x1500);
Steve Block6ded16b2010-05-10 14:33:55 +0100367 sample1.stack[0] = ToAddress(0x1510);
368 sample1.frames_count = 1;
369 generator.RecordTickSample(sample1);
370 TickSample sample2;
371 sample2.pc = ToAddress(0x1925);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100372 sample2.tos = ToAddress(0x1900);
Steve Block6ded16b2010-05-10 14:33:55 +0100373 sample2.stack[0] = ToAddress(0x1780);
374 sample2.stack[1] = ToAddress(0x10000); // non-existent.
375 sample2.stack[2] = ToAddress(0x1620);
376 sample2.frames_count = 3;
377 generator.RecordTickSample(sample2);
378 TickSample sample3;
379 sample3.pc = ToAddress(0x1510);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100380 sample3.tos = ToAddress(0x1500);
Steve Block6ded16b2010-05-10 14:33:55 +0100381 sample3.stack[0] = ToAddress(0x1910);
382 sample3.stack[1] = ToAddress(0x1610);
383 sample3.frames_count = 2;
384 generator.RecordTickSample(sample3);
385
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000386 CpuProfile* profile = profiles.StopProfiling("");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387 CHECK(profile);
Steve Block6ded16b2010-05-10 14:33:55 +0100388 ProfileTreeTestHelper top_down_test_helper(profile->top_down());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389 CHECK(!top_down_test_helper.Walk(entry2));
390 CHECK(!top_down_test_helper.Walk(entry3));
Steve Block6ded16b2010-05-10 14:33:55 +0100391 ProfileNode* node1 = top_down_test_helper.Walk(entry1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 CHECK(node1);
Steve Block6ded16b2010-05-10 14:33:55 +0100393 CHECK_EQ(entry1, node1->entry());
394 ProfileNode* node2 = top_down_test_helper.Walk(entry1, entry1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395 CHECK(node2);
Steve Block6ded16b2010-05-10 14:33:55 +0100396 CHECK_EQ(entry1, node2->entry());
397 ProfileNode* node3 = top_down_test_helper.Walk(entry1, entry2, entry3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000398 CHECK(node3);
Steve Block6ded16b2010-05-10 14:33:55 +0100399 CHECK_EQ(entry3, node3->entry());
400 ProfileNode* node4 = top_down_test_helper.Walk(entry1, entry3, entry1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401 CHECK(node4);
Steve Block6ded16b2010-05-10 14:33:55 +0100402 CHECK_EQ(entry1, node4->entry());
403}
404
405
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406static void CheckNodeIds(ProfileNode* node, unsigned* expectedId) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 CHECK_EQ((*expectedId)++, node->id());
408 for (int i = 0; i < node->children()->length(); i++) {
409 CheckNodeIds(node->children()->at(i), expectedId);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100410 }
411}
412
413
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000414TEST(SampleIds) {
415 TestSetup test_setup;
416 CpuProfilesCollection profiles(CcTest::heap());
417 profiles.StartProfiling("", true);
418 ProfileGenerator generator(&profiles);
419 CodeEntry* entry1 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
420 CodeEntry* entry2 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb");
421 CodeEntry* entry3 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "ccc");
422 generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
423 generator.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
424 generator.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
425
426 // We are building the following calls tree:
427 // -> aaa #3 - sample1
428 // (root)#1 -> aaa #2 -> bbb #4 -> ccc #5 - sample2
429 // -> ccc #6 -> aaa #7 - sample3
430 TickSample sample1;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100431 sample1.timestamp = v8::base::TimeTicks::HighResolutionNow();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432 sample1.pc = ToAddress(0x1600);
433 sample1.stack[0] = ToAddress(0x1510);
434 sample1.frames_count = 1;
435 generator.RecordTickSample(sample1);
436 TickSample sample2;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100437 sample2.timestamp = v8::base::TimeTicks::HighResolutionNow();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 sample2.pc = ToAddress(0x1925);
439 sample2.stack[0] = ToAddress(0x1780);
440 sample2.stack[1] = ToAddress(0x10000); // non-existent.
441 sample2.stack[2] = ToAddress(0x1620);
442 sample2.frames_count = 3;
443 generator.RecordTickSample(sample2);
444 TickSample sample3;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100445 sample3.timestamp = v8::base::TimeTicks::HighResolutionNow();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000446 sample3.pc = ToAddress(0x1510);
447 sample3.stack[0] = ToAddress(0x1910);
448 sample3.stack[1] = ToAddress(0x1610);
449 sample3.frames_count = 2;
450 generator.RecordTickSample(sample3);
451
452 CpuProfile* profile = profiles.StopProfiling("");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 unsigned nodeId = 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454 CheckNodeIds(profile->top_down()->root(), &nodeId);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 CHECK_EQ(7u, nodeId - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000456
457 CHECK_EQ(3, profile->samples_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 unsigned expected_id[] = {3, 5, 7};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000459 for (int i = 0; i < 3; i++) {
460 CHECK_EQ(expected_id[i], profile->sample(i)->id());
461 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100462}
463
464
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000465TEST(NoSamples) {
466 TestSetup test_setup;
467 CpuProfilesCollection profiles(CcTest::heap());
468 profiles.StartProfiling("", false);
469 ProfileGenerator generator(&profiles);
470 CodeEntry* entry1 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
471 generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
472
473 // We are building the following calls tree:
474 // (root)#1 -> aaa #2 -> aaa #3 - sample1
475 TickSample sample1;
476 sample1.pc = ToAddress(0x1600);
477 sample1.stack[0] = ToAddress(0x1510);
478 sample1.frames_count = 1;
479 generator.RecordTickSample(sample1);
480
481 CpuProfile* profile = profiles.StopProfiling("");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000482 unsigned nodeId = 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483 CheckNodeIds(profile->top_down()->root(), &nodeId);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 CHECK_EQ(3u, nodeId - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000485
486 CHECK_EQ(0, profile->samples_count());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100487}
488
489
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100490static const ProfileNode* PickChild(const ProfileNode* parent,
491 const char* name) {
492 for (int i = 0; i < parent->children()->length(); ++i) {
493 const ProfileNode* child = parent->children()->at(i);
494 if (strcmp(child->entry()->name(), name) == 0) return child;
495 }
496 return NULL;
497}
498
499
500TEST(RecordStackTraceAtStartProfiling) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100501 // This test does not pass with inlining enabled since inlined functions
502 // don't appear in the stack trace.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 i::FLAG_turbo_inlining = false;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100504 i::FLAG_use_inlining = false;
505
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506 v8::HandleScope scope(CcTest::isolate());
507 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
508 v8::Context::Scope context_scope(env);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100509
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 CpuProfiler* profiler = CcTest::i_isolate()->cpu_profiler();
511 CHECK_EQ(0, profiler->GetProfilesCount());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100512 CompileRun(
513 "function c() { startProfiling(); }\n"
514 "function b() { c(); }\n"
515 "function a() { b(); }\n"
516 "a();\n"
517 "stopProfiling();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518 CHECK_EQ(1, profiler->GetProfilesCount());
519 CpuProfile* profile = profiler->GetProfile(0);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100520 const ProfileTree* topDown = profile->top_down();
521 const ProfileNode* current = topDown->root();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100522 const_cast<ProfileNode*>(current)->Print(0);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100523 // The tree should look like this:
524 // (root)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000525 // ""
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100526 // a
527 // b
528 // c
Ben Murdochb0fe1622011-05-05 13:52:32 +0100529 // There can also be:
530 // startProfiling
531 // if the sampler managed to get a tick.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 current = PickChild(current, "");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 CHECK(const_cast<ProfileNode*>(current));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100534 current = PickChild(current, "a");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000535 CHECK(const_cast<ProfileNode*>(current));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100536 current = PickChild(current, "b");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537 CHECK(const_cast<ProfileNode*>(current));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100538 current = PickChild(current, "c");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 CHECK(const_cast<ProfileNode*>(current));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100540 CHECK(current->children()->length() == 0 ||
541 current->children()->length() == 1);
542 if (current->children()->length() == 1) {
543 current = PickChild(current, "startProfiling");
544 CHECK_EQ(0, current->children()->length());
545 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100546}
547
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100548
549TEST(Issue51919) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000550 CpuProfilesCollection collection(CcTest::heap());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100551 i::EmbeddedVector<char*,
552 CpuProfilesCollection::kMaxSimultaneousProfiles> titles;
553 for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) {
554 i::Vector<char> title = i::Vector<char>::New(16);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 i::SNPrintF(title, "%d", i);
556 CHECK(collection.StartProfiling(title.start(), false));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100557 titles[i] = title.start();
558 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 CHECK(!collection.StartProfiling("maximum", false));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100560 for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i)
561 i::DeleteArray(titles[i]);
562}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000563
564
565static const v8::CpuProfileNode* PickChild(const v8::CpuProfileNode* parent,
566 const char* name) {
567 for (int i = 0; i < parent->GetChildrenCount(); ++i) {
568 const v8::CpuProfileNode* child = parent->GetChild(i);
569 v8::String::Utf8Value function_name(child->GetFunctionName());
570 if (strcmp(*function_name, name) == 0) return child;
571 }
572 return NULL;
573}
574
575
576TEST(ProfileNodeScriptId) {
577 // This test does not pass with inlining enabled since inlined functions
578 // don't appear in the stack trace.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 i::FLAG_turbo_inlining = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580 i::FLAG_use_inlining = false;
581
582 v8::HandleScope scope(CcTest::isolate());
583 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
584 v8::Context::Scope context_scope(env);
585
586 v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
587 i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
588 CHECK_EQ(0, iprofiler->GetProfilesCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000589 v8::Local<v8::Script> script_a =
590 v8_compile(v8_str("function a() { startProfiling(); }\n"));
591 script_a->Run(v8::Isolate::GetCurrent()->GetCurrentContext())
592 .ToLocalChecked();
593 v8::Local<v8::Script> script_b =
594 v8_compile(v8_str("function b() { a(); }\n"
595 "b();\n"
596 "stopProfiling();\n"));
597 script_b->Run(v8::Isolate::GetCurrent()->GetCurrentContext())
598 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000599 CHECK_EQ(1, iprofiler->GetProfilesCount());
600 const v8::CpuProfile* profile = i::ProfilerExtension::last_profile;
601 const v8::CpuProfileNode* current = profile->GetTopDownRoot();
602 reinterpret_cast<ProfileNode*>(
603 const_cast<v8::CpuProfileNode*>(current))->Print(0);
604 // The tree should look like this:
605 // (root)
606 // ""
607 // b
608 // a
609 // There can also be:
610 // startProfiling
611 // if the sampler managed to get a tick.
612 current = PickChild(current, "");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000613 CHECK(const_cast<v8::CpuProfileNode*>(current));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614
615 current = PickChild(current, "b");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000616 CHECK(const_cast<v8::CpuProfileNode*>(current));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 CHECK_EQ(script_b->GetUnboundScript()->GetId(), current->GetScriptId());
618
619 current = PickChild(current, "a");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 CHECK(const_cast<v8::CpuProfileNode*>(current));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000621 CHECK_EQ(script_a->GetUnboundScript()->GetId(), current->GetScriptId());
622}
623
624
625
626
627static const char* line_number_test_source_existing_functions =
628"function foo_at_the_first_line() {\n"
629"}\n"
630"foo_at_the_first_line();\n"
631"function lazy_func_at_forth_line() {}\n";
632
633
634static const char* line_number_test_source_profile_time_functions =
635"// Empty first line\n"
636"function bar_at_the_second_line() {\n"
637" foo_at_the_first_line();\n"
638"}\n"
639"bar_at_the_second_line();\n"
640"function lazy_func_at_6th_line() {}";
641
642int GetFunctionLineNumber(LocalContext* env, const char* name) {
643 CpuProfiler* profiler = CcTest::i_isolate()->cpu_profiler();
644 CodeMap* code_map = profiler->generator()->code_map();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645 i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(
646 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
647 (*(*env))
648 ->Global()
649 ->Get(v8::Isolate::GetCurrent()->GetCurrentContext(),
650 v8_str(name))
651 .ToLocalChecked())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 CodeEntry* func_entry = code_map->FindEntry(func->code()->address());
653 if (!func_entry)
654 FATAL(name);
655 return func_entry->line_number();
656}
657
658
659TEST(LineNumber) {
660 i::FLAG_use_inlining = false;
661
662 CcTest::InitializeVM();
663 LocalContext env;
664 i::Isolate* isolate = CcTest::i_isolate();
665 TestSetup test_setup;
666
667 i::HandleScope scope(isolate);
668
669 CompileRun(line_number_test_source_existing_functions);
670
671 CpuProfiler* profiler = isolate->cpu_profiler();
672 profiler->StartProfiling("LineNumber");
673
674 CompileRun(line_number_test_source_profile_time_functions);
675
676 profiler->processor()->StopSynchronously();
677
678 CHECK_EQ(1, GetFunctionLineNumber(&env, "foo_at_the_first_line"));
679 CHECK_EQ(0, GetFunctionLineNumber(&env, "lazy_func_at_forth_line"));
680 CHECK_EQ(2, GetFunctionLineNumber(&env, "bar_at_the_second_line"));
681 CHECK_EQ(0, GetFunctionLineNumber(&env, "lazy_func_at_6th_line"));
682
683 profiler->StopProfiling("LineNumber");
684}
685
686
687
688TEST(BailoutReason) {
689 v8::HandleScope scope(CcTest::isolate());
690 v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
691 v8::Context::Scope context_scope(env);
692
693 v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
694 i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
695 CHECK_EQ(0, iprofiler->GetProfilesCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000696 v8::Local<v8::Script> script =
697 v8_compile(v8_str("function Debugger() {\n"
698 " debugger;\n"
699 " startProfiling();\n"
700 "}\n"
701 "function TryFinally() {\n"
702 " try {\n"
703 " Debugger();\n"
704 " } finally { };\n"
705 "}\n"
706 "TryFinally();\n"
707 "stopProfiling();"));
708 script->Run(v8::Isolate::GetCurrent()->GetCurrentContext()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000709 CHECK_EQ(1, iprofiler->GetProfilesCount());
710 const v8::CpuProfile* profile = i::ProfilerExtension::last_profile;
711 CHECK(profile);
712 const v8::CpuProfileNode* current = profile->GetTopDownRoot();
713 reinterpret_cast<ProfileNode*>(
714 const_cast<v8::CpuProfileNode*>(current))->Print(0);
715 // The tree should look like this:
716 // (root)
717 // ""
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 // kTryFinallyStatement
719 // kDebuggerStatement
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720 current = PickChild(current, "");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 CHECK(const_cast<v8::CpuProfileNode*>(current));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000722
723 current = PickChild(current, "TryFinally");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000724 CHECK(const_cast<v8::CpuProfileNode*>(current));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000725 CHECK(!strcmp("TryFinallyStatement", current->GetBailoutReason()));
726
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000727 current = PickChild(current, "Debugger");
728 CHECK(const_cast<v8::CpuProfileNode*>(current));
729 CHECK(!strcmp("DebuggerStatement", current->GetBailoutReason()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000730}