| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 this._strings = profile.strings; | 36 this._strings = profile.strings; |
| 37 this._liveObjectStats = liveObjectStats; | 37 this._liveObjectStats = liveObjectStats; |
| 38 | 38 |
| 39 this._nextNodeId = 1; | 39 this._nextNodeId = 1; |
| 40 this._functionInfos = [] | 40 this._functionInfos = [] |
| 41 this._idToNode = {}; | 41 this._idToNode = {}; |
| 42 this._collapsedTopNodeIdToFunctionInfo = {}; | 42 this._collapsedTopNodeIdToFunctionInfo = {}; |
| 43 | 43 |
| 44 this._traceTops = null; | 44 this._traceTops = null; |
| 45 | 45 |
| 46 this._buildAllocationFunctionInfos(profile); | 46 this._buildFunctionAllocationInfos(profile); |
| 47 this._traceTree = this._buildInvertedAllocationTree(profile, liveObjectStats
); | 47 this._traceTree = this._buildAllocationTree(profile, liveObjectStats); |
| 48 } | 48 } |
| 49 | 49 |
| 50 WebInspector.AllocationProfile.prototype = { | 50 WebInspector.AllocationProfile.prototype = { |
| 51 _buildAllocationFunctionInfos: function(profile) | 51 _buildFunctionAllocationInfos: function(profile) |
| 52 { | 52 { |
| 53 var strings = this._strings; | 53 var strings = this._strings; |
| 54 | 54 |
| 55 var functionInfoFields = profile.snapshot.meta.trace_function_info_field
s; | 55 var functionInfoFields = profile.snapshot.meta.trace_function_info_field
s; |
| 56 var functionIdOffset = functionInfoFields.indexOf("function_id"); | 56 var functionIdOffset = functionInfoFields.indexOf("function_id"); |
| 57 var functionNameOffset = functionInfoFields.indexOf("name"); | 57 var functionNameOffset = functionInfoFields.indexOf("name"); |
| 58 var scriptNameOffset = functionInfoFields.indexOf("script_name"); | 58 var scriptNameOffset = functionInfoFields.indexOf("script_name"); |
| 59 var scriptIdOffset = functionInfoFields.indexOf("script_id"); | 59 var scriptIdOffset = functionInfoFields.indexOf("script_id"); |
| 60 var lineOffset = functionInfoFields.indexOf("line"); | 60 var lineOffset = functionInfoFields.indexOf("line"); |
| 61 var columnOffset = functionInfoFields.indexOf("column"); | 61 var columnOffset = functionInfoFields.indexOf("column"); |
| 62 var functionInfoFieldCount = functionInfoFields.length; | 62 var functionInfoFieldCount = functionInfoFields.length; |
| 63 | 63 |
| 64 var rawInfos = profile.trace_function_infos; | 64 var rawInfos = profile.trace_function_infos; |
| 65 var infoLength = rawInfos.length; | 65 var infoLength = rawInfos.length; |
| 66 var functionInfos = this._functionInfos = new Array(infoLength / functio
nInfoFieldCount); | 66 var functionInfos = this._functionInfos = new Array(infoLength / functio
nInfoFieldCount); |
| 67 var index = 0; | 67 var index = 0; |
| 68 for (var i = 0; i < infoLength; i += functionInfoFieldCount) { | 68 for (var i = 0; i < infoLength; i += functionInfoFieldCount) { |
| 69 functionInfos[index++] = new WebInspector.FunctionAllocationInfo( | 69 functionInfos[index++] = new WebInspector.FunctionAllocationInfo( |
| 70 strings[rawInfos[i + functionNameOffset]], | 70 strings[rawInfos[i + functionNameOffset]], |
| 71 strings[rawInfos[i + scriptNameOffset]], | 71 strings[rawInfos[i + scriptNameOffset]], |
| 72 rawInfos[i + scriptIdOffset], | 72 rawInfos[i + scriptIdOffset], |
| 73 rawInfos[i + lineOffset], | 73 rawInfos[i + lineOffset], |
| 74 rawInfos[i + columnOffset]); | 74 rawInfos[i + columnOffset]); |
| 75 } | 75 } |
| 76 }, | 76 }, |
| 77 | 77 |
| 78 _buildInvertedAllocationTree: function(profile, liveObjectStats) | 78 _buildAllocationTree: function(profile, liveObjectStats) |
| 79 { | 79 { |
| 80 var traceTreeRaw = profile.trace_tree; | 80 var traceTreeRaw = profile.trace_tree; |
| 81 var functionInfos = this._functionInfos; | 81 var functionInfos = this._functionInfos; |
| 82 | 82 |
| 83 var traceNodeFields = profile.snapshot.meta.trace_node_fields; | 83 var traceNodeFields = profile.snapshot.meta.trace_node_fields; |
| 84 var nodeIdOffset = traceNodeFields.indexOf("id"); | 84 var nodeIdOffset = traceNodeFields.indexOf("id"); |
| 85 var functionInfoIndexOffset = traceNodeFields.indexOf("function_info_ind
ex"); | 85 var functionInfoIndexOffset = traceNodeFields.indexOf("function_info_ind
ex"); |
| 86 var allocationCountOffset = traceNodeFields.indexOf("count"); | 86 var allocationCountOffset = traceNodeFields.indexOf("count"); |
| 87 var allocationSizeOffset = traceNodeFields.indexOf("size"); | 87 var allocationSizeOffset = traceNodeFields.indexOf("size"); |
| 88 var childrenOffset = traceNodeFields.indexOf("children"); | 88 var childrenOffset = traceNodeFields.indexOf("children"); |
| 89 var nodeFieldCount = traceNodeFields.length; | 89 var nodeFieldCount = traceNodeFields.length; |
| 90 | 90 |
| 91 function traverseNode(rawNodeArray, nodeOffset, parent) | 91 function traverseNode(rawNodeArray, nodeOffset, parent) |
| 92 { | 92 { |
| 93 var functionInfo = functionInfos[rawNodeArray[nodeOffset + functionI
nfoIndexOffset]]; | 93 var functionInfo = functionInfos[rawNodeArray[nodeOffset + functionI
nfoIndexOffset]]; |
| 94 var id = rawNodeArray[nodeOffset + nodeIdOffset]; | 94 var id = rawNodeArray[nodeOffset + nodeIdOffset]; |
| 95 var stats = liveObjectStats[id]; | 95 var stats = liveObjectStats[id]; |
| 96 var liveCount = stats ? stats.count : 0; | 96 var liveCount = stats ? stats.count : 0; |
| 97 var liveSize = stats ? stats.size : 0; | 97 var liveSize = stats ? stats.size : 0; |
| 98 var result = new WebInspector.AllocationTraceNode( | 98 var result = new WebInspector.TopDownAllocationNode( |
| 99 id, | 99 id, |
| 100 functionInfo, | 100 functionInfo, |
| 101 rawNodeArray[nodeOffset + allocationCountOffset], | 101 rawNodeArray[nodeOffset + allocationCountOffset], |
| 102 rawNodeArray[nodeOffset + allocationSizeOffset], | 102 rawNodeArray[nodeOffset + allocationSizeOffset], |
| 103 liveCount, | 103 liveCount, |
| 104 liveSize, | 104 liveSize, |
| 105 parent); | 105 parent); |
| 106 functionInfo.addTraceTopNode(result); | 106 functionInfo.addTraceTopNode(result); |
| 107 | 107 |
| 108 var rawChildren = rawNodeArray[nodeOffset + childrenOffset]; | 108 var rawChildren = rawNodeArray[nodeOffset + childrenOffset]; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 | 147 |
| 148 /** | 148 /** |
| 149 * @param {string} nodeId | 149 * @param {string} nodeId |
| 150 * @return {!WebInspector.HeapSnapshotCommon.AllocationNodeCallers} | 150 * @return {!WebInspector.HeapSnapshotCommon.AllocationNodeCallers} |
| 151 */ | 151 */ |
| 152 serializeCallers: function(nodeId) | 152 serializeCallers: function(nodeId) |
| 153 { | 153 { |
| 154 var node = this._idToNode[nodeId]; | 154 var node = this._idToNode[nodeId]; |
| 155 if (!node) { | 155 if (!node) { |
| 156 var functionInfo = this._collapsedTopNodeIdToFunctionInfo[nodeId]; | 156 var functionInfo = this._collapsedTopNodeIdToFunctionInfo[nodeId]; |
| 157 node = functionInfo.tracesWithThisTop(); | 157 node = functionInfo.bottomUpRoot(); |
| 158 delete this._collapsedTopNodeIdToFunctionInfo[nodeId]; | 158 delete this._collapsedTopNodeIdToFunctionInfo[nodeId]; |
| 159 this._idToNode[nodeId] = node; | 159 this._idToNode[nodeId] = node; |
| 160 } | 160 } |
| 161 | 161 |
| 162 var nodesWithSingleCaller = []; | 162 var nodesWithSingleCaller = []; |
| 163 while (node.callers().length === 1) { | 163 while (node.callers().length === 1) { |
| 164 node = node.callers()[0]; | 164 node = node.callers()[0]; |
| 165 nodesWithSingleCaller.push(this._serializeCaller(node)); | 165 nodesWithSingleCaller.push(this._serializeCaller(node)); |
| 166 } | 166 } |
| 167 | 167 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 liveCount, | 210 liveCount, |
| 211 liveSize, | 211 liveSize, |
| 212 hasChildren | 212 hasChildren |
| 213 ); | 213 ); |
| 214 } | 214 } |
| 215 } | 215 } |
| 216 | 216 |
| 217 | 217 |
| 218 /** | 218 /** |
| 219 * @constructor | 219 * @constructor |
| 220 * @param {number} id |
| 221 * @param {!WebInspector.FunctionAllocationInfo} functionInfo |
| 222 * @param {number} count |
| 223 * @param {number} size |
| 224 * @param {number} liveCount |
| 225 * @param {number} liveSize |
| 226 * @param {?WebInspector.TopDownAllocationNode} parent |
| 220 */ | 227 */ |
| 221 WebInspector.AllocationTraceNode = function(id, functionInfo, count, size, liveC
ount, liveSize, parent) | 228 WebInspector.TopDownAllocationNode = function(id, functionInfo, count, size, liv
eCount, liveSize, parent) |
| 222 { | 229 { |
| 223 this.id = id; | 230 this.id = id; |
| 224 this.functionInfo = functionInfo; | 231 this.functionInfo = functionInfo; |
| 225 this.allocationCount = count; | 232 this.allocationCount = count; |
| 226 this.allocationSize = size; | 233 this.allocationSize = size; |
| 227 this.liveCount = liveCount; | 234 this.liveCount = liveCount; |
| 228 this.liveSize = liveSize; | 235 this.liveSize = liveSize; |
| 229 this.parent = parent; | 236 this.parent = parent; |
| 230 this.children = []; | 237 this.children = []; |
| 231 } | 238 } |
| 232 | 239 |
| 233 | 240 |
| 234 /** | 241 /** |
| 235 * @constructor | 242 * @constructor |
| 236 * @param {!WebInspector.FunctionAllocationInfo} functionInfo | 243 * @param {!WebInspector.FunctionAllocationInfo} functionInfo |
| 237 */ | 244 */ |
| 238 WebInspector.AllocationBackTraceNode = function(functionInfo) | 245 WebInspector.BottomUpAllocationNode = function(functionInfo) |
| 239 { | 246 { |
| 240 this.functionInfo = functionInfo; | 247 this.functionInfo = functionInfo; |
| 241 this.allocationCount = 0; | 248 this.allocationCount = 0; |
| 242 this.allocationSize = 0; | 249 this.allocationSize = 0; |
| 243 this.liveCount = 0; | 250 this.liveCount = 0; |
| 244 this.liveSize = 0; | 251 this.liveSize = 0; |
| 245 this._callers = []; | 252 this._callers = []; |
| 246 } | 253 } |
| 247 | 254 |
| 248 | 255 |
| 249 WebInspector.AllocationBackTraceNode.prototype = { | 256 WebInspector.BottomUpAllocationNode.prototype = { |
| 250 /** | 257 /** |
| 251 * @param {!WebInspector.AllocationTraceNode} traceNode | 258 * @param {!WebInspector.TopDownAllocationNode} traceNode |
| 252 * @return {!WebInspector.AllocationTraceNode} | 259 * @return {!WebInspector.TopDownAllocationNode} |
| 253 */ | 260 */ |
| 254 addCaller: function(traceNode) | 261 addCaller: function(traceNode) |
| 255 { | 262 { |
| 256 var functionInfo = traceNode.functionInfo; | 263 var functionInfo = traceNode.functionInfo; |
| 257 var result; | 264 var result; |
| 258 for (var i = 0; i < this._callers.length; i++) { | 265 for (var i = 0; i < this._callers.length; i++) { |
| 259 var caller = this._callers[i]; | 266 var caller = this._callers[i]; |
| 260 if (caller.functionInfo === functionInfo) { | 267 if (caller.functionInfo === functionInfo) { |
| 261 result = caller; | 268 result = caller; |
| 262 break; | 269 break; |
| 263 } | 270 } |
| 264 } | 271 } |
| 265 if (!result) { | 272 if (!result) { |
| 266 result = new WebInspector.AllocationBackTraceNode(functionInfo); | 273 result = new WebInspector.BottomUpAllocationNode(functionInfo); |
| 267 this._callers.push(result); | 274 this._callers.push(result); |
| 268 } | 275 } |
| 269 return result; | 276 return result; |
| 270 }, | 277 }, |
| 271 | 278 |
| 272 /** | 279 /** |
| 273 * @return {!Array.<!WebInspector.AllocationBackTraceNode>} | 280 * @return {!Array.<!WebInspector.BottomUpAllocationNode>} |
| 274 */ | 281 */ |
| 275 callers: function() | 282 callers: function() |
| 276 { | 283 { |
| 277 return this._callers; | 284 return this._callers; |
| 278 }, | 285 }, |
| 279 | 286 |
| 280 /** | 287 /** |
| 281 * @return {boolean} | 288 * @return {boolean} |
| 282 */ | 289 */ |
| 283 hasCallers: function() | 290 hasCallers: function() |
| 284 { | 291 { |
| 285 return this._callers.length > 0; | 292 return this._callers.length > 0; |
| 286 } | 293 } |
| 287 } | 294 } |
| 288 | 295 |
| 289 | 296 |
| 290 /** | 297 /** |
| 291 * @constructor | 298 * @constructor |
| 299 * @param {string} functionName |
| 300 * @param {string} scriptName |
| 301 * @param {number} scriptId |
| 302 * @param {number} line |
| 303 * @param {number} column |
| 292 */ | 304 */ |
| 293 WebInspector.FunctionAllocationInfo = function(functionName, scriptName, scriptI
d, line, column) | 305 WebInspector.FunctionAllocationInfo = function(functionName, scriptName, scriptI
d, line, column) |
| 294 { | 306 { |
| 295 this.functionName = functionName; | 307 this.functionName = functionName; |
| 296 this.scriptName = scriptName; | 308 this.scriptName = scriptName; |
| 297 this.scriptId = scriptId; | 309 this.scriptId = scriptId; |
| 298 this.line = line; | 310 this.line = line; |
| 299 this.column = column; | 311 this.column = column; |
| 300 this.totalCount = 0; | 312 this.totalCount = 0; |
| 301 this.totalSize = 0; | 313 this.totalSize = 0; |
| 302 this.totalLiveCount = 0; | 314 this.totalLiveCount = 0; |
| 303 this.totalLiveSize = 0; | 315 this.totalLiveSize = 0; |
| 304 this._traceTops = []; | 316 this._traceTops = []; |
| 305 } | 317 } |
| 306 | 318 |
| 307 WebInspector.FunctionAllocationInfo.prototype = { | 319 WebInspector.FunctionAllocationInfo.prototype = { |
| 320 /** |
| 321 * @param {!WebInspector.TopDownAllocationNode} node |
| 322 */ |
| 308 addTraceTopNode: function(node) | 323 addTraceTopNode: function(node) |
| 309 { | 324 { |
| 310 if (node.allocationCount === 0) | 325 if (node.allocationCount === 0) |
| 311 return; | 326 return; |
| 312 this._traceTops.push(node); | 327 this._traceTops.push(node); |
| 313 this.totalCount += node.allocationCount; | 328 this.totalCount += node.allocationCount; |
| 314 this.totalSize += node.allocationSize; | 329 this.totalSize += node.allocationSize; |
| 315 this.totalLiveCount += node.liveCount; | 330 this.totalLiveCount += node.liveCount; |
| 316 this.totalLiveSize += node.liveSize; | 331 this.totalLiveSize += node.liveSize; |
| 317 }, | 332 }, |
| 318 | 333 |
| 319 /** | 334 /** |
| 320 * @return {?WebInspector.AllocationBackTraceNode} | 335 * @return {?WebInspector.BottomUpAllocationNode} |
| 321 */ | 336 */ |
| 322 tracesWithThisTop: function() | 337 bottomUpRoot: function() |
| 323 { | 338 { |
| 324 if (!this._traceTops.length) | 339 if (!this._traceTops.length) |
| 325 return null; | 340 return null; |
| 326 if (!this._backTraceTree) | 341 if (!this._bottomUpTree) |
| 327 this._buildAllocationTraceTree(); | 342 this._buildAllocationTraceTree(); |
| 328 return this._backTraceTree; | 343 return this._bottomUpTree; |
| 329 }, | 344 }, |
| 330 | 345 |
| 331 _buildAllocationTraceTree: function() | 346 _buildAllocationTraceTree: function() |
| 332 { | 347 { |
| 333 this._backTraceTree = new WebInspector.AllocationBackTraceNode(this._tra
ceTops[0].functionInfo); | 348 this._bottomUpTree = new WebInspector.BottomUpAllocationNode(this); |
| 334 | 349 |
| 335 for (var i = 0; i < this._traceTops.length; i++) { | 350 for (var i = 0; i < this._traceTops.length; i++) { |
| 336 var node = this._traceTops[i]; | 351 var node = this._traceTops[i]; |
| 337 var backTraceNode = this._backTraceTree; | 352 var bottomUpNode = this._bottomUpTree; |
| 338 var count = node.allocationCount; | 353 var count = node.allocationCount; |
| 339 var size = node.allocationSize; | 354 var size = node.allocationSize; |
| 340 var liveCount = node.liveCount; | 355 var liveCount = node.liveCount; |
| 341 var liveSize = node.liveSize; | 356 var liveSize = node.liveSize; |
| 342 while (true) { | 357 while (true) { |
| 343 backTraceNode.allocationCount += count; | 358 bottomUpNode.allocationCount += count; |
| 344 backTraceNode.allocationSize += size; | 359 bottomUpNode.allocationSize += size; |
| 345 backTraceNode.liveCount += liveCount; | 360 bottomUpNode.liveCount += liveCount; |
| 346 backTraceNode.liveSize += liveSize; | 361 bottomUpNode.liveSize += liveSize; |
| 347 node = node.parent; | 362 node = node.parent; |
| 348 if (node === null) { | 363 if (node === null) { |
| 349 break; | 364 break; |
| 350 } | 365 } |
| 351 backTraceNode = backTraceNode.addCaller(node); | 366 bottomUpNode = bottomUpNode.addCaller(node); |
| 352 } | 367 } |
| 353 } | 368 } |
| 354 } | 369 } |
| 355 } | 370 } |
| OLD | NEW |