Chromium Code Reviews| Index: Source/devtools/front_end/timeline/TimelineJSProfile.js |
| diff --git a/Source/devtools/front_end/timeline/TimelineJSProfile.js b/Source/devtools/front_end/timeline/TimelineJSProfile.js |
| index c49f7f5d7619d555c980bd1eba433e22fd96af48..81235e2e1f9287e1527f4d769f4e25c625679fee 100644 |
| --- a/Source/devtools/front_end/timeline/TimelineJSProfile.js |
| +++ b/Source/devtools/front_end/timeline/TimelineJSProfile.js |
| @@ -204,8 +204,8 @@ WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents = function(events) |
| */ |
| WebInspector.TimelineJSProfileProcessor.CodeMap = function() |
| { |
| - /** @type {!Array<!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry>} */ |
| - this._entries = []; |
| + /** @type {!Map<string, !WebInspector.TimelineJSProfileProcessor.CodeMap.Bank>} */ |
| + this._banks = new Map(); |
| } |
| /** |
| @@ -239,8 +239,8 @@ WebInspector.TimelineJSProfileProcessor.CodeMap.prototype = { |
| */ |
| addEntry: function(addressHex, size, callFrame) |
| { |
| - var address = this._addressStringToNumber(addressHex); |
| - this._addEntry(new WebInspector.TimelineJSProfileProcessor.CodeMap.Entry(address, size, callFrame)); |
| + var entry = new WebInspector.TimelineJSProfileProcessor.CodeMap.Entry(this._getAddress(addressHex), size, callFrame); |
| + this._addEntry(addressHex, entry); |
| }, |
| /** |
| @@ -250,16 +250,14 @@ WebInspector.TimelineJSProfileProcessor.CodeMap.prototype = { |
| */ |
| moveEntry: function(oldAddressHex, newAddressHex, size) |
| { |
| - var oldAddress = this._addressStringToNumber(oldAddressHex); |
| - var newAddress = this._addressStringToNumber(newAddressHex); |
| - var index = this._entries.lowerBound(oldAddress, WebInspector.TimelineJSProfileProcessor.CodeMap.comparator); |
| - var entry = this._entries[index]; |
| - if (!entry || entry.address !== oldAddress) |
| + var entry = this._getBank(oldAddressHex).removeEntry(this._getAddress(oldAddressHex)); |
| + if (!entry) { |
| + console.error("Entry at address " + oldAddressHex + " not found"); |
| return; |
| - this._entries.splice(index, 1); |
| - entry.address = newAddress; |
| + } |
| + entry.address = this._getAddress(newAddressHex); |
| entry.size = size; |
| - this._addEntry(entry); |
| + this._addEntry(newAddressHex, entry); |
| }, |
| /** |
| @@ -268,29 +266,90 @@ WebInspector.TimelineJSProfileProcessor.CodeMap.prototype = { |
| */ |
| lookupEntry: function(addressHex) |
| { |
| - var address = this._addressStringToNumber(addressHex); |
| - var index = this._entries.upperBound(address, WebInspector.TimelineJSProfileProcessor.CodeMap.comparator) - 1; |
| - var entry = this._entries[index]; |
| - return entry && address < entry.address + entry.size ? entry.callFrame : null; |
| + return this._getBank(addressHex).lookupEntry(this._getAddress(addressHex)); |
| + }, |
| + |
| + /** |
| + * @param {string} addressHex |
| + * @param {!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry} entry |
| + */ |
| + _addEntry: function(addressHex, entry) |
| + { |
| + // FIXME: deal with entries that span across [multiple] banks. |
| + this._getBank(addressHex).addEntry(entry); |
| + }, |
| + |
| + /** |
| + * @param {string} addressHex |
| + * @return {!WebInspector.TimelineJSProfileProcessor.CodeMap.Bank} |
| + */ |
| + _getBank: function(addressHex) |
| + { |
| + addressHex = addressHex.slice(2); // cut 0x prefix. |
| + // 13 hex digits == 52 bits, double mantissa fits 53 bits. |
| + var /** @const */ bankSizeHexDigits = 13; |
|
yurys
2015/06/22 16:33:00
Please extract these constants so that they are no
alph
2015/06/23 16:06:28
I'd like to keep them as constants for the sake of
|
| + var /** @const */ maxHexDigits = 16; |
| + var bankName = addressHex.slice(-maxHexDigits, -bankSizeHexDigits); |
| + var bank = this._banks.get(bankName); |
| + if (!bank) { |
| + bank = new WebInspector.TimelineJSProfileProcessor.CodeMap.Bank(); |
| + this._banks.set(bankName, bank); |
| + } |
| + return bank; |
| }, |
| /** |
| * @param {string} addressHex |
| * @return {number} |
| */ |
| - _addressStringToNumber: function(addressHex) |
| + _getAddress: function(addressHex) |
| + { |
| + // 13 hex digits == 52 bits, double mantissa fits 53 bits. |
| + var /** @const */ bankSizeHexDigits = 13; |
| + addressHex = addressHex.slice(2); // cut 0x prefix. |
| + return parseInt(addressHex.slice(-bankSizeHexDigits), 16); |
| + } |
| +} |
| + |
| +/** |
| + * @constructor |
| + */ |
| +WebInspector.TimelineJSProfileProcessor.CodeMap.Bank = function() |
| +{ |
| + /** @type {!Array<!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry>} */ |
| + this._entries = []; |
| +} |
| + |
| +WebInspector.TimelineJSProfileProcessor.CodeMap.Bank.prototype = { |
| + /** |
| + * @param {number} address |
| + * @return {?WebInspector.TimelineJSProfileProcessor.CodeMap.Entry} |
| + */ |
| + removeEntry: function(address) |
| { |
| - // TODO(alph): The addressHex may represent addresses from 0 to 2^64-1, |
| - // whereas address is a double type that has exact representation for |
| - // integers up to 2^53. So it might lose up to 11 bits at the end. |
| - // Do something about it, e.g. introduce banks, or just find and subtract a base. |
| - return parseInt(addressHex, 16); |
| + var index = this._entries.lowerBound(address, WebInspector.TimelineJSProfileProcessor.CodeMap.comparator); |
| + var entry = this._entries[index]; |
| + if (!entry || entry.address !== address) |
| + return null; |
| + this._entries.splice(index, 1); |
| + return entry; |
| + }, |
| + |
| + /** |
| + * @param {number} address |
| + * @return {?ConsoleAgent.CallFrame} |
| + */ |
| + lookupEntry: function(address) |
| + { |
| + var index = this._entries.upperBound(address, WebInspector.TimelineJSProfileProcessor.CodeMap.comparator) - 1; |
| + var entry = this._entries[index]; |
| + return entry && address < entry.address + entry.size ? entry.callFrame : null; |
| }, |
| /** |
| * @param {!WebInspector.TimelineJSProfileProcessor.CodeMap.Entry} newEntry |
| */ |
| - _addEntry: function(newEntry) |
| + addEntry: function(newEntry) |
| { |
| var endAddress = newEntry.address + newEntry.size; |
| var lastIndex = this._entries.lowerBound(endAddress, WebInspector.TimelineJSProfileProcessor.CodeMap.comparator); |