Chromium Code Reviews| 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 |