| 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 // Try to combine with the previous code run. | 104 // Try to combine with the previous code run. |
| 105 if (paths.length > 0 && | 105 if (paths.length > 0 && |
| 106 paths[paths.length - 3] + 1 === pathIndex && | 106 paths[paths.length - 3] + 1 === pathIndex && |
| 107 paths[paths.length - 2] === depth) { | 107 paths[paths.length - 2] === depth) { |
| 108 paths[paths.length - 1]++; | 108 paths[paths.length - 1]++; |
| 109 } else { | 109 } else { |
| 110 paths.push(pathIndex, depth, 1); | 110 paths.push(pathIndex, depth, 1); |
| 111 } | 111 } |
| 112 } | 112 } |
| 113 | 113 |
| 114 function findNextFrame(file, stack, stackPos, step, filter) { |
| 115 let codeId = -1; |
| 116 let code = null; |
| 117 while (stackPos >= 0 && stackPos < stack.length) { |
| 118 codeId = stack[stackPos]; |
| 119 code = codeId >= 0 ? file.code[codeId] : undefined; |
| 120 if (filter) { |
| 121 let type = code ? code.type : undefined; |
| 122 let kind = code ? code.kind : undefined; |
| 123 if (filter(type, kind)) return stackPos; |
| 124 } |
| 125 stackPos += step; |
| 126 } |
| 127 return -1; |
| 128 } |
| 129 |
| 130 function addOrUpdateChildNode(parent, file, stackIndex, stackPos, ascending) { |
| 131 let stack = file.ticks[stackIndex].s; |
| 132 let codeId = stack[stackPos]; |
| 133 let code = codeId >= 0 ? file.code[codeId] : undefined; |
| 134 if (stackPos === -1) { |
| 135 // We reached the end without finding the next step. |
| 136 // If we are doing top-down call tree, update own ticks. |
| 137 if (!ascending) { |
| 138 parent.ownTicks++; |
| 139 } |
| 140 } else { |
| 141 console.assert(stackPos >= 0 && stackPos < stack.length); |
| 142 // We found a child node. |
| 143 let childId = childIdFromCode(codeId, code); |
| 144 let child = parent.children[childId]; |
| 145 if (!child) { |
| 146 child = createNodeFromStackEntry(code); |
| 147 child.delayedExpansion = { frameList : [], ascending }; |
| 148 parent.children[childId] = child; |
| 149 } |
| 150 child.ticks++; |
| 151 addFrameToFrameList(child.delayedExpansion.frameList, stackIndex, stackPos); |
| 152 } |
| 153 } |
| 154 |
| 114 // This expands a tree node (direct children only). | 155 // This expands a tree node (direct children only). |
| 115 function expandTreeNode(file, node, filter) { | 156 function expandTreeNode(file, node, filter) { |
| 116 let { frameList, ascending } = node.delayedExpansion; | 157 let { frameList, ascending } = node.delayedExpansion; |
| 117 | 158 |
| 118 let step = ascending ? 2 : -2; | 159 let step = ascending ? 2 : -2; |
| 119 | 160 |
| 120 for (let i = 0; i < frameList.length; i+= 3) { | 161 for (let i = 0; i < frameList.length; i+= 3) { |
| 121 let stackIndex = frameList[i]; | 162 let firstStackIndex = frameList[i]; |
| 122 let depth = frameList[i + 1]; | 163 let depth = frameList[i + 1]; |
| 123 let count = frameList[i + 2]; | 164 let count = frameList[i + 2]; |
| 124 for (let j = 0; j < count; j++) { | 165 for (let j = 0; j < count; j++) { |
| 125 let tick = file.ticks[stackIndex + j]; | 166 let stackIndex = firstStackIndex + j; |
| 126 let stack = tick.s; | 167 let stack = file.ticks[stackIndex].s; |
| 127 | 168 |
| 128 // Get to the next frame that has not been filtered out. | 169 // Get to the next frame that has not been filtered out. |
| 129 let k = depth + step; | 170 let stackPos = findNextFrame(file, stack, depth + step, step, filter); |
| 130 let codeId = -1; | 171 addOrUpdateChildNode(node, file, stackIndex, stackPos, ascending); |
| 131 let code = null; | |
| 132 while (k >= 0 && k < stack.length) { | |
| 133 codeId = stack[k]; | |
| 134 code = codeId >= 0 ? file.code[codeId] : undefined; | |
| 135 if (filter) { | |
| 136 let type = code ? code.type : undefined; | |
| 137 let kind = code ? code.kind : undefined; | |
| 138 if (filter(type, kind)) break; | |
| 139 } | |
| 140 k += step; | |
| 141 } | |
| 142 if (k < 0 || k >= stack.length) { | |
| 143 // We reached the end without finding the next step. | |
| 144 // If we are doing top-down call tree, update own ticks. | |
| 145 if (!ascending) { | |
| 146 node.ownTicks++; | |
| 147 } | |
| 148 } else { | |
| 149 // We found a child node. | |
| 150 let childId = childIdFromCode(codeId, code); | |
| 151 let child = node.children[childId]; | |
| 152 if (!child) { | |
| 153 child = createNodeFromStackEntry(code); | |
| 154 child.delayedExpansion = { frameList : [], ascending }; | |
| 155 node.children[childId] = child; | |
| 156 } | |
| 157 child.ticks++; | |
| 158 addFrameToFrameList(child.delayedExpansion.frameList, stackIndex, k); | |
| 159 } | |
| 160 } | 172 } |
| 161 } | 173 } |
| 162 node.delayedExpansion = null; | 174 node.delayedExpansion = null; |
| 163 } | 175 } |
| 164 | 176 |
| 165 function addStackToTree(file, stack, tree, filter, ascending, start) { | |
| 166 if (start === undefined) { | |
| 167 start = ascending ? 0 : stack.length - 2; | |
| 168 } | |
| 169 tree.ticks++; | |
| 170 for (let i = start; | |
| 171 ascending ? (i < stack.length) : (i >= 0); | |
| 172 i += ascending ? 2 : -2) { | |
| 173 let codeId = stack[i]; | |
| 174 let code = codeId >= 0 ? file.code[codeId] : undefined; | |
| 175 if (filter) { | |
| 176 let type = code ? code.type : undefined; | |
| 177 let kind = code ? code.kind : undefined; | |
| 178 if (!filter(type, kind)) continue; | |
| 179 } | |
| 180 | |
| 181 // For JavaScript function, pretend there is one instance of optimized | |
| 182 // function and one instance of unoptimized function per SFI. | |
| 183 let childId = childIdFromCode(codeId, code); | |
| 184 let child = tree.children[childId]; | |
| 185 if (!child) { | |
| 186 child = createNodeFromStackEntry(code); | |
| 187 tree.children[childId] = child; | |
| 188 } | |
| 189 child.ticks++; | |
| 190 tree = child; | |
| 191 } | |
| 192 tree.ownTicks++; | |
| 193 } | |
| 194 | |
| 195 function createEmptyNode(name) { | 177 function createEmptyNode(name) { |
| 196 return { | 178 return { |
| 197 name : name, | 179 name : name, |
| 198 type : "CAT", | 180 type : "CAT", |
| 199 children : [], | 181 children : [], |
| 200 ownTicks : 0, | 182 ownTicks : 0, |
| 201 ticks : 0 | 183 ticks : 0 |
| 202 }; | 184 }; |
| 203 } | 185 } |
| 204 | 186 |
| 205 class PlainCallTreeProcessor { | 187 class PlainCallTreeProcessor { |
| 206 constructor(filter, isBottomUp) { | 188 constructor(filter, isBottomUp) { |
| 207 this.filter = filter; | 189 this.filter = filter; |
| 208 this.tree = createEmptyNode("root"); | 190 this.tree = createEmptyNode("root"); |
| 191 this.tree.delayedExpansion = { frameList : [], ascending : isBottomUp }; |
| 209 this.isBottomUp = isBottomUp; | 192 this.isBottomUp = isBottomUp; |
| 210 } | 193 } |
| 211 | 194 |
| 212 addStack(file, tickIndex) { | 195 addStack(file, tickIndex) { |
| 213 let stack = file.ticks[tickIndex].s; | 196 let stack = file.ticks[tickIndex].s; |
| 214 addStackToTree(file, stack, this.tree, this.filter, this.isBottomUp); | 197 let step = this.isBottomUp ? 2 : -2; |
| 198 let start = this.isBottomUp ? 0 : stack.length - 2; |
| 199 |
| 200 let stackPos = findNextFrame(file, stack, start, step, this.filter); |
| 201 addOrUpdateChildNode(this.tree, file, tickIndex, stackPos, this.isBottomUp); |
| 202 |
| 203 this.tree.ticks++; |
| 215 } | 204 } |
| 216 } | 205 } |
| 217 | 206 |
| 218 function buildCategoryTreeAndLookup() { | 207 function buildCategoryTreeAndLookup() { |
| 219 let root = createEmptyNode("root"); | 208 let root = createEmptyNode("root"); |
| 220 let categories = {}; | 209 let categories = {}; |
| 221 function addCategory(name, types) { | 210 function addCategory(name, types) { |
| 222 let n = createEmptyNode(name); | 211 let n = createEmptyNode(name); |
| 223 for (let i = 0; i < types.length; i++) { | 212 for (let i = 0; i < types.length; i++) { |
| 224 categories[types[i]] = n; | 213 categories[types[i]] = n; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 252 addStack(file, tickIndex) { | 241 addStack(file, tickIndex) { |
| 253 let stack = file.ticks[tickIndex].s; | 242 let stack = file.ticks[tickIndex].s; |
| 254 let vmState = file.ticks[tickIndex].vm; | 243 let vmState = file.ticks[tickIndex].vm; |
| 255 if (stack.length === 0) return; | 244 if (stack.length === 0) return; |
| 256 let codeId = stack[0]; | 245 let codeId = stack[0]; |
| 257 let code = codeId >= 0 ? file.code[codeId] : undefined; | 246 let code = codeId >= 0 ? file.code[codeId] : undefined; |
| 258 let kind = resolveCodeKindAndVmState(code, vmState); | 247 let kind = resolveCodeKindAndVmState(code, vmState); |
| 259 let node = this.categories[kind]; | 248 let node = this.categories[kind]; |
| 260 | 249 |
| 261 this.tree.ticks++; | 250 this.tree.ticks++; |
| 251 node.ticks++; |
| 262 | 252 |
| 263 console.assert(node); | 253 let step = this.isBottomUp ? 2 : -2; |
| 254 let start = this.isBottomUp ? 0 : stack.length - 2; |
| 264 | 255 |
| 265 addStackToTree(file, stack, node, this.filter, this.isBottomUp); | 256 let stackPos = findNextFrame(file, stack, start, step, this.filter); |
| 257 addOrUpdateChildNode(node, file, tickIndex, stackPos, this.isBottomUp); |
| 266 } | 258 } |
| 267 } | 259 } |
| 268 | 260 |
| 269 class FunctionListTree { | 261 class FunctionListTree { |
| 270 constructor(filter, withCategories) { | 262 constructor(filter, withCategories) { |
| 271 if (withCategories) { | 263 if (withCategories) { |
| 272 let { categories, root } = buildCategoryTreeAndLookup(); | 264 let { categories, root } = buildCategoryTreeAndLookup(); |
| 273 this.tree = root; | 265 this.tree = root; |
| 274 this.categories = categories; | 266 this.categories = categories; |
| 275 } else { | 267 } else { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 | 381 |
| 390 let tickCount = 0; | 382 let tickCount = 0; |
| 391 while (i < ticks.length && ticks[i].tm < endTime) { | 383 while (i < ticks.length && ticks[i].tm < endTime) { |
| 392 tree.addStack(file, i); | 384 tree.addStack(file, i); |
| 393 i++; | 385 i++; |
| 394 tickCount++; | 386 tickCount++; |
| 395 } | 387 } |
| 396 | 388 |
| 397 return tickCount; | 389 return tickCount; |
| 398 } | 390 } |
| OLD | NEW |