| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium 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 | 5 |
| 6 WebInspector.TimelineJSProfileProcessor = { }; | 6 WebInspector.TimelineJSProfileProcessor = { }; |
| 7 | 7 |
| 8 /** | 8 /** |
| 9 * @param {!ProfilerAgent.CPUProfile} jsProfile | 9 * @param {!ProfilerAgent.CPUProfile} jsProfile |
| 10 * @param {!WebInspector.TracingModel.Thread} thread | 10 * @param {!WebInspector.TracingModel.Thread} thread |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 var entryEndAddress = entry.address + entry.size; | 359 var entryEndAddress = entry.address + entry.size; |
| 360 if (entryEndAddress <= newEntry.address) | 360 if (entryEndAddress <= newEntry.address) |
| 361 break; | 361 break; |
| 362 } | 362 } |
| 363 ++index; | 363 ++index; |
| 364 this._entries.splice(index, lastIndex - index, newEntry); | 364 this._entries.splice(index, lastIndex - index, newEntry); |
| 365 } | 365 } |
| 366 } | 366 } |
| 367 | 367 |
| 368 /** | 368 /** |
| 369 * @param {string} functionName | |
| 370 * @param {string=} url | |
| 371 * @param {string=} scriptId | |
| 372 * @param {number=} line | |
| 373 * @param {number=} column | |
| 374 * @return {!ConsoleAgent.CallFrame} | |
| 375 */ | |
| 376 WebInspector.TimelineJSProfileProcessor._createFrame = function(functionName, ur
l, scriptId, line, column) | |
| 377 { | |
| 378 return /** @type {!ConsoleAgent.CallFrame} */ ({ | |
| 379 "functionName": functionName, | |
| 380 "url": url || "", | |
| 381 "scriptId": scriptId || "0", | |
| 382 "lineNumber": line || 0, | |
| 383 "columnNumber": column || 0 | |
| 384 }); | |
| 385 } | |
| 386 | |
| 387 /** | |
| 388 * @param {string} name | 369 * @param {string} name |
| 389 * @param {number} scriptId | 370 * @param {number} scriptId |
| 390 * @return {!ConsoleAgent.CallFrame} | 371 * @return {!ConsoleAgent.CallFrame} |
| 391 */ | 372 */ |
| 392 WebInspector.TimelineJSProfileProcessor._buildCallFrame = function(name, scriptI
d) | 373 WebInspector.TimelineJSProfileProcessor._buildCallFrame = function(name, scriptI
d) |
| 393 { | 374 { |
| 375 /** |
| 376 * @param {string} functionName |
| 377 * @param {string=} url |
| 378 * @param {string=} scriptId |
| 379 * @param {number=} line |
| 380 * @param {number=} column |
| 381 * @param {boolean=} isNative |
| 382 * @return {!ConsoleAgent.CallFrame} |
| 383 */ |
| 384 function createFrame(functionName, url, scriptId, line, column, isNative) |
| 385 { |
| 386 return /** @type {!ConsoleAgent.CallFrame} */ ({ |
| 387 "functionName": functionName, |
| 388 "url": url || "", |
| 389 "scriptId": scriptId || "0", |
| 390 "lineNumber": line || 0, |
| 391 "columnNumber": column || 0, |
| 392 "isNative": isNative || false |
| 393 }); |
| 394 } |
| 395 |
| 394 // Code states: | 396 // Code states: |
| 395 // (empty) -> compiled | 397 // (empty) -> compiled |
| 396 // ~ -> optimizable | 398 // ~ -> optimizable |
| 397 // * -> optimized | 399 // * -> optimized |
| 398 var rePrefix = /^(\w*:)?[*~]?(.*)$/m; | 400 var rePrefix = /^(\w*:)?[*~]?(.*)$/m; |
| 399 | |
| 400 var tokens = rePrefix.exec(name); | 401 var tokens = rePrefix.exec(name); |
| 401 var prefix = tokens[1]; | 402 var prefix = tokens[1]; |
| 402 var body = tokens[2]; | 403 var body = tokens[2]; |
| 403 var rawName; | 404 var rawName; |
| 404 var rawUrl; | 405 var rawUrl; |
| 405 if (prefix === "Script:") { | 406 if (prefix === "Script:") { |
| 406 rawName = ""; | 407 rawName = ""; |
| 407 rawUrl = body; | 408 rawUrl = body; |
| 408 } else { | 409 } else { |
| 409 var spacePos = body.lastIndexOf(" "); | 410 var spacePos = body.lastIndexOf(" "); |
| 410 rawName = spacePos !== -1 ? body.substr(0, spacePos) : body; | 411 rawName = spacePos !== -1 ? body.substr(0, spacePos) : body; |
| 411 rawUrl = spacePos !== -1 ? body.substr(spacePos + 1) : ""; | 412 rawUrl = spacePos !== -1 ? body.substr(spacePos + 1) : ""; |
| 412 } | 413 } |
| 413 var functionName = rawName; | 414 var nativeSuffix = " native"; |
| 415 var isNative = rawName.endsWith(nativeSuffix); |
| 416 var functionName = isNative ? rawName.slice(0, -nativeSuffix.length) : rawNa
me; |
| 414 var urlData = WebInspector.ParsedURL.splitLineAndColumn(rawUrl); | 417 var urlData = WebInspector.ParsedURL.splitLineAndColumn(rawUrl); |
| 415 var url = urlData.url || ""; | 418 var url = urlData.url || ""; |
| 416 var line = urlData.lineNumber || 0; | 419 var line = urlData.lineNumber || 0; |
| 417 var column = urlData.columnNumber || 0; | 420 var column = urlData.columnNumber || 0; |
| 418 return WebInspector.TimelineJSProfileProcessor._createFrame(functionName, ur
l, String(scriptId), line, column); | 421 return createFrame(functionName, url, String(scriptId), line, column, isNati
ve); |
| 419 } | 422 } |
| 420 | 423 |
| 421 /** | 424 /** |
| 422 * @param {!Array<!WebInspector.TracingModel.Event>} events | 425 * @param {!Array<!WebInspector.TracingModel.Event>} events |
| 423 * @return {!Array<!WebInspector.TracingModel.Event>} | 426 * @return {!Array<!WebInspector.TracingModel.Event>} |
| 424 */ | 427 */ |
| 425 WebInspector.TimelineJSProfileProcessor.processRawV8Samples = function(events) | 428 WebInspector.TimelineJSProfileProcessor.processRawV8Samples = function(events) |
| 426 { | 429 { |
| 427 var missingAddesses = new Set(); | 430 var missingAddesses = new Set(); |
| 428 | 431 |
| 429 /** | 432 /** |
| 430 * @param {string} address | 433 * @param {string} address |
| 431 * @return {!ConsoleAgent.CallFrame} | 434 * @return {?ConsoleAgent.CallFrame} |
| 432 */ | 435 */ |
| 433 function convertRawFrame(address) | 436 function convertRawFrame(address) |
| 434 { | 437 { |
| 435 var entry = codeMap.lookupEntry(address); | 438 var entry = codeMap.lookupEntry(address); |
| 436 if (entry) | 439 if (entry) |
| 437 return entry; | 440 return entry.isNative ? null : entry; |
| 438 if (!missingAddesses.has(address)) { | 441 if (!missingAddesses.has(address)) { |
| 439 missingAddesses.add(address); | 442 missingAddesses.add(address); |
| 440 console.error("Address " + address + " has missing code entry"); | 443 console.error("Address " + address + " has missing code entry"); |
| 441 } | 444 } |
| 442 return WebInspector.TimelineJSProfileProcessor._createFrame(address); | 445 return null; |
| 443 } | 446 } |
| 444 | 447 |
| 445 var recordTypes = WebInspector.TimelineModel.RecordType; | 448 var recordTypes = WebInspector.TimelineModel.RecordType; |
| 446 var samples = []; | 449 var samples = []; |
| 447 var codeMap = new WebInspector.TimelineJSProfileProcessor.CodeMap(); | 450 var codeMap = new WebInspector.TimelineJSProfileProcessor.CodeMap(); |
| 448 for (var i = 0; i < events.length; ++i) { | 451 for (var i = 0; i < events.length; ++i) { |
| 449 var e = events[i]; | 452 var e = events[i]; |
| 450 var data = e.args["data"]; | 453 var data = e.args["data"]; |
| 451 switch (e.name) { | 454 switch (e.name) { |
| 452 case recordTypes.JitCodeAdded: | 455 case recordTypes.JitCodeAdded: |
| 453 var frame = WebInspector.TimelineJSProfileProcessor._buildCallFrame(
data["name"], data["script_id"]); | 456 var frame = WebInspector.TimelineJSProfileProcessor._buildCallFrame(
data["name"], data["script_id"]); |
| 454 codeMap.addEntry(data["code_start"], data["code_len"], frame); | 457 codeMap.addEntry(data["code_start"], data["code_len"], frame); |
| 455 break; | 458 break; |
| 456 case recordTypes.JitCodeMoved: | 459 case recordTypes.JitCodeMoved: |
| 457 codeMap.moveEntry(data["code_start"], data["new_code_start"], data["
code_len"]); | 460 codeMap.moveEntry(data["code_start"], data["new_code_start"], data["
code_len"]); |
| 458 break; | 461 break; |
| 459 case recordTypes.V8Sample: | 462 case recordTypes.V8Sample: |
| 460 var rawStack = data["stack"]; | 463 var rawStack = data["stack"]; |
| 461 // Sometimes backend fails to collect a stack and returns an empty s
tack. | 464 // Sometimes backend fails to collect a stack and returns an empty s
tack. |
| 462 // Skip these bogus samples. | 465 // Skip these bogus samples. |
| 463 if (data["vm_state"] === "js" && !rawStack.length) | 466 if (data["vm_state"] === "js" && !rawStack.length) |
| 464 break; | 467 break; |
| 465 var stack = rawStack.map(convertRawFrame); | 468 var stack = rawStack.map(convertRawFrame); |
| 469 stack.remove(null); |
| 466 var sampleEvent = new WebInspector.TracingModel.Event( | 470 var sampleEvent = new WebInspector.TracingModel.Event( |
| 467 WebInspector.TracingModel.DevToolsTimelineEventCategory, | 471 WebInspector.TracingModel.DevToolsTimelineEventCategory, |
| 468 WebInspector.TimelineModel.RecordType.JSSample, | 472 WebInspector.TimelineModel.RecordType.JSSample, |
| 469 WebInspector.TracingModel.Phase.Instant, e.startTime, e.thread); | 473 WebInspector.TracingModel.Phase.Instant, e.startTime, e.thread); |
| 470 sampleEvent.ordinal = e.ordinal; | 474 sampleEvent.ordinal = e.ordinal; |
| 471 sampleEvent.args = {"data": {"stackTrace": stack }}; | 475 sampleEvent.args = {"data": {"stackTrace": stack }}; |
| 472 samples.push(sampleEvent); | 476 samples.push(sampleEvent); |
| 473 break; | 477 break; |
| 474 } | 478 } |
| 475 } | 479 } |
| 476 | 480 |
| 477 return samples; | 481 return samples; |
| 478 } | 482 } |
| OLD | NEW |