OLD | NEW |
---|---|
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 "use strict" | 5 "use strict" |
6 | 6 |
7 let codeKinds = [ | 7 let codeKinds = [ |
8 "UNKNOWN", | 8 "UNKNOWN", |
9 "CPPCOMP", | 9 "CPPCOMP", |
10 "CPPGC", | 10 "CPPGC", |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 kind = "CPPGC"; | 65 kind = "CPPGC"; |
66 } else if (vmState === 2) { | 66 } else if (vmState === 2) { |
67 kind = "CPPCOMP"; | 67 kind = "CPPCOMP"; |
68 } else if (vmState === 4) { | 68 } else if (vmState === 4) { |
69 kind = "CPPEXT"; | 69 kind = "CPPEXT"; |
70 } | 70 } |
71 } | 71 } |
72 return kind; | 72 return kind; |
73 } | 73 } |
74 | 74 |
75 function createNodeFromStackEntry(code) { | 75 function createNodeFromStackEntry(code, codeId) { |
76 let name = code ? code.name : "UNKNOWN"; | 76 let name = code ? code.name : "UNKNOWN"; |
77 | 77 |
78 return { name, type : resolveCodeKind(code), | 78 return { name, codeId, type : resolveCodeKind(code), |
79 children : [], ownTicks : 0, ticks : 0 }; | 79 children : [], ownTicks : 0, ticks : 0 }; |
80 } | 80 } |
81 | 81 |
82 function childIdFromCode(codeId, code) { | 82 function childIdFromCode(codeId, code) { |
83 // For JavaScript function, pretend there is one instance of optimized | 83 // For JavaScript function, pretend there is one instance of optimized |
84 // function and one instance of unoptimized function per SFI. | 84 // function and one instance of unoptimized function per SFI. |
85 // Otherwise, just compute the id from code id. | 85 // Otherwise, just compute the id from code id. |
86 let type = resolveCodeKind(code); | 86 let type = resolveCodeKind(code); |
87 if (type === "JSOPT") { | 87 if (type === "JSOPT") { |
88 return code.func * 4 + 1; | 88 return code.func * 4 + 1; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 // If we are doing top-down call tree, update own ticks. | 136 // If we are doing top-down call tree, update own ticks. |
137 if (!ascending) { | 137 if (!ascending) { |
138 parent.ownTicks++; | 138 parent.ownTicks++; |
139 } | 139 } |
140 } else { | 140 } else { |
141 console.assert(stackPos >= 0 && stackPos < stack.length); | 141 console.assert(stackPos >= 0 && stackPos < stack.length); |
142 // We found a child node. | 142 // We found a child node. |
143 let childId = childIdFromCode(codeId, code); | 143 let childId = childIdFromCode(codeId, code); |
144 let child = parent.children[childId]; | 144 let child = parent.children[childId]; |
145 if (!child) { | 145 if (!child) { |
146 child = createNodeFromStackEntry(code); | 146 child = createNodeFromStackEntry(code, codeId); |
147 child.delayedExpansion = { frameList : [], ascending }; | 147 child.delayedExpansion = { frameList : [], ascending }; |
148 parent.children[childId] = child; | 148 parent.children[childId] = child; |
149 } | 149 } |
150 child.ticks++; | 150 child.ticks++; |
151 addFrameToFrameList(child.delayedExpansion.frameList, stackIndex, stackPos); | 151 addFrameToFrameList(child.delayedExpansion.frameList, stackIndex, stackPos); |
152 } | 152 } |
153 } | 153 } |
154 | 154 |
155 // This expands a tree node (direct children only). | 155 // This expands a tree node (direct children only). |
156 function expandTreeNode(file, node, filter) { | 156 function expandTreeNode(file, node, filter) { |
(...skipping 13 matching lines...) Expand all Loading... | |
170 let stackPos = findNextFrame(file, stack, depth + step, step, filter); | 170 let stackPos = findNextFrame(file, stack, depth + step, step, filter); |
171 addOrUpdateChildNode(node, file, stackIndex, stackPos, ascending); | 171 addOrUpdateChildNode(node, file, stackIndex, stackPos, ascending); |
172 } | 172 } |
173 } | 173 } |
174 node.delayedExpansion = null; | 174 node.delayedExpansion = null; |
175 } | 175 } |
176 | 176 |
177 function createEmptyNode(name) { | 177 function createEmptyNode(name) { |
178 return { | 178 return { |
179 name : name, | 179 name : name, |
180 codeId: -1, | |
180 type : "CAT", | 181 type : "CAT", |
181 children : [], | 182 children : [], |
182 ownTicks : 0, | 183 ownTicks : 0, |
183 ticks : 0 | 184 ticks : 0 |
184 }; | 185 }; |
185 } | 186 } |
186 | 187 |
187 class PlainCallTreeProcessor { | 188 class PlainCallTreeProcessor { |
188 constructor(filter, isBottomUp) { | 189 constructor(filter, isBottomUp) { |
189 this.filter = filter; | 190 this.filter = filter; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
258 } | 259 } |
259 } | 260 } |
260 | 261 |
261 class FunctionListTree { | 262 class FunctionListTree { |
262 constructor(filter, withCategories) { | 263 constructor(filter, withCategories) { |
263 if (withCategories) { | 264 if (withCategories) { |
264 let { categories, root } = buildCategoryTreeAndLookup(); | 265 let { categories, root } = buildCategoryTreeAndLookup(); |
265 this.tree = root; | 266 this.tree = root; |
266 this.categories = categories; | 267 this.categories = categories; |
267 } else { | 268 } else { |
268 this.tree = { name : "root", children : [], ownTicks : 0, ticks : 0 }; | 269 this.tree = { |
270 name : "root", | |
271 codeId: -1, | |
272 children : [], | |
273 ownTicks : 0, | |
274 ticks : 0 | |
275 }; | |
269 this.categories = null; | 276 this.categories = null; |
270 } | 277 } |
271 | 278 |
272 this.codeVisited = []; | 279 this.codeVisited = []; |
273 this.filter = filter; | 280 this.filter = filter; |
274 } | 281 } |
275 | 282 |
276 addStack(file, tickIndex) { | 283 addStack(file, tickIndex) { |
277 let stack = file.ticks[tickIndex].s; | 284 let stack = file.ticks[tickIndex].s; |
278 let vmState = file.ticks[tickIndex].vm; | 285 let vmState = file.ticks[tickIndex].vm; |
(...skipping 13 matching lines...) Expand all Loading... | |
292 } | 299 } |
293 let childId = childIdFromCode(codeId, code); | 300 let childId = childIdFromCode(codeId, code); |
294 if (this.categories) { | 301 if (this.categories) { |
295 let kind = resolveCodeKindAndVmState(code, vmState); | 302 let kind = resolveCodeKindAndVmState(code, vmState); |
296 tree = this.categories[kind]; | 303 tree = this.categories[kind]; |
297 } else { | 304 } else { |
298 tree = this.tree; | 305 tree = this.tree; |
299 } | 306 } |
300 child = tree.children[childId]; | 307 child = tree.children[childId]; |
301 if (!child) { | 308 if (!child) { |
302 child = createNodeFromStackEntry(code); | 309 child = createNodeFromStackEntry(code, codeId); |
303 child.children[0] = createEmptyNode("Top-down tree"); | 310 child.children[0] = createEmptyNode("Top-down tree"); |
304 child.children[0].delayedExpansion = | 311 child.children[0].delayedExpansion = |
305 { frameList : [], ascending : false }; | 312 { frameList : [], ascending : false }; |
306 child.children[1] = createEmptyNode("Bottom-up tree"); | 313 child.children[1] = createEmptyNode("Bottom-up tree"); |
307 child.children[1].delayedExpansion = | 314 child.children[1].delayedExpansion = |
308 { frameList : [], ascending : true }; | 315 { frameList : [], ascending : true }; |
309 tree.children[childId] = child; | 316 tree.children[childId] = child; |
310 } | 317 } |
311 child.ticks++; | 318 child.ticks++; |
312 child.children[0].ticks++; | 319 child.children[0].ticks++; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
360 let bucket = this.buckets[i]; | 367 let bucket = this.buckets[i]; |
361 bucket.total++; | 368 bucket.total++; |
362 | 369 |
363 let codeId = (stack.length > 0) ? stack[0] : -1; | 370 let codeId = (stack.length > 0) ? stack[0] : -1; |
364 let code = codeId >= 0 ? file.code[codeId] : undefined; | 371 let code = codeId >= 0 ? file.code[codeId] : undefined; |
365 let kind = resolveCodeKindAndVmState(code, vmState); | 372 let kind = resolveCodeKindAndVmState(code, vmState); |
366 bucket[kind]++; | 373 bucket[kind]++; |
367 } | 374 } |
368 } | 375 } |
369 | 376 |
377 class FunctionTimelineProcessor { | |
378 constructor(functionCodeId, filter) { | |
379 this.functionCodeId = functionCodeId; | |
380 this.filter = filter; | |
381 this.blocks = []; | |
382 this.currentBlock = null; | |
383 } | |
384 | |
385 addStack(file, tickIndex) { | |
386 let { tm : timestamp, vm : vmState, s : stack } = file.ticks[tickIndex]; | |
387 | |
388 let codeInStack = stack.includes(this.functionCodeId); | |
389 if (codeInStack) { | |
390 let topOfStack = -1; | |
391 for (let i = 0; i < stack.length - 1; i += 2) { | |
392 let codeId = stack[i]; | |
393 let code = codeId >= 0 ? file.code[codeId] : undefined; | |
394 let type = code ? code.type : undefined; | |
395 let kind = code ? code.kind : undefined; | |
396 if (!this.filter(type, kind)) continue; | |
397 | |
398 topOfStack = i; | |
399 break; | |
400 } | |
401 | |
402 let codeIsTopOfStack = | |
403 (topOfStack !== -1 && stack[topOfStack] === this.functionCodeId); | |
Jarin
2017/03/08 16:35:56
This will not quite work for optimized code becaus
| |
404 | |
405 if (this.currentBlock !== null) { | |
406 this.currentBlock.end = timestamp; | |
407 | |
408 if (codeIsTopOfStack === this.currentBlock.topOfStack) { | |
409 return; | |
410 } | |
411 } | |
412 | |
413 this.currentBlock = { | |
414 start: timestamp, | |
415 end: timestamp, | |
416 topOfStack: codeIsTopOfStack | |
417 }; | |
418 this.blocks.push(this.currentBlock); | |
419 } else { | |
420 this.currentBlock = null; | |
421 } | |
422 } | |
423 } | |
424 | |
370 // Generates a tree out of a ticks sequence. | 425 // Generates a tree out of a ticks sequence. |
371 // {file} is the JSON files with the ticks and code objects. | 426 // {file} is the JSON files with the ticks and code objects. |
372 // {startTime}, {endTime} is the interval. | 427 // {startTime}, {endTime} is the interval. |
373 // {tree} is the processor of stacks. | 428 // {tree} is the processor of stacks. |
374 function generateTree( | 429 function generateTree( |
375 file, startTime, endTime, tree) { | 430 file, startTime, endTime, tree) { |
376 let ticks = file.ticks; | 431 let ticks = file.ticks; |
377 let i = 0; | 432 let i = 0; |
378 while (i < ticks.length && ticks[i].tm < startTime) { | 433 while (i < ticks.length && ticks[i].tm < startTime) { |
379 i++; | 434 i++; |
380 } | 435 } |
381 | 436 |
382 let tickCount = 0; | 437 let tickCount = 0; |
383 while (i < ticks.length && ticks[i].tm < endTime) { | 438 while (i < ticks.length && ticks[i].tm < endTime) { |
384 tree.addStack(file, i); | 439 tree.addStack(file, i); |
385 i++; | 440 i++; |
386 tickCount++; | 441 tickCount++; |
387 } | 442 } |
388 | 443 |
389 return tickCount; | 444 return tickCount; |
390 } | 445 } |
OLD | NEW |