1<!DOCTYPE html>
2<!--
3Copyright 2015 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel='import' href='/tracing/extras/importer/trace_code_entry.html'>
9
10<script>
11'use strict';
12
13tr.exportTo('tr.e.importer', function() {
14  // This code is a tracification of:
15  // devtools/front_end/timeline/TimelineJSProfile.js
16  function TraceCodeMap() {
17    this.banks_ = new Map();
18  }
19
20  TraceCodeMap.prototype = {
21    addEntry: function(addressHex, size, name, scriptId) {
22      var entry = new tr.e.importer.TraceCodeEntry(
23          this.getAddress_(addressHex), size, name, scriptId);
24
25      this.addEntry_(addressHex, entry);
26    },
27
28    moveEntry: function(oldAddressHex, newAddressHex, size) {
29      var entry = this.getBank_(oldAddressHex)
30          .removeEntry(this.getAddress_(oldAddressHex));
31      if (!entry)
32          return;
33
34      entry.address = this.getAddress_(newAddressHex);
35      entry.size = size;
36      this.addEntry_(newAddressHex, entry);
37    },
38
39    lookupEntry: function(addressHex) {
40      return this.getBank_(addressHex)
41          .lookupEntry(this.getAddress_(addressHex));
42    },
43
44    addEntry_: function(addressHex, entry) {
45      // FIXME: Handle bank spanning addresses ...
46      this.getBank_(addressHex).addEntry(entry);
47    },
48
49    getAddress_: function(addressHex) {
50      // 13 hex digits == 52 bits, double mantissa fits 53 bits.
51      var bankSizeHexDigits = 13;
52      addressHex = addressHex.slice(2);  // cut 0x prefix.
53      return parseInt(addressHex.slice(-bankSizeHexDigits), 16);
54    },
55
56    getBank_: function(addressHex) {
57      addressHex = addressHex.slice(2);  // cut 0x prefix.
58
59      // 13 hex digits == 52 bits, double mantissa fits 53 bits.
60      var bankSizeHexDigits = 13;
61      var maxHexDigits = 16;
62      var bankName = addressHex.slice(-maxHexDigits, -bankSizeHexDigits);
63      var bank = this.banks_.get(bankName);
64      if (!bank) {
65          bank = new TraceCodeBank();
66          this.banks_.set(bankName, bank);
67      }
68      return bank;
69    }
70  };
71
72  function TraceCodeBank() {
73    this.entries_ = [];
74  }
75
76  TraceCodeBank.prototype = {
77    removeEntry: function(address) {
78      // findLowIndexInSortedArray returns 1 for empty. Just handle the
79      // empty list and bail early.
80      if (this.entries_.length === 0)
81        return undefined;
82
83      var index = tr.b.findLowIndexInSortedArray(
84          this.entries_, function(entry) { return entry.address; }, address);
85      var entry = this.entries_[index];
86      if (!entry || entry.address !== address)
87        return undefined;
88
89      this.entries_.splice(index, 1);
90      return entry;
91    },
92
93    lookupEntry: function(address) {
94      var index = tr.b.findHighIndexInSortedArray(
95          this.entries_, function(e) { return address - e.address; }) - 1;
96      var entry = this.entries_[index];
97      return entry &&
98          address < entry.address + entry.size ? entry : undefined;
99    },
100
101    addEntry: function(newEntry) {
102      // findLowIndexInSortedArray returns 1 for empty list. Just push the
103      // new address as it's the only item.
104      if (this.entries_.length === 0)
105        this.entries_.push(newEntry);
106
107      var endAddress = newEntry.address + newEntry.size;
108      var lastIndex = tr.b.findLowIndexInSortedArray(
109          this.entries_, function(entry) { return entry.address; }, endAddress);
110      var index;
111      for (index = lastIndex - 1; index >= 0; --index) {
112          var entry = this.entries_[index];
113          var entryEndAddress = entry.address + entry.size;
114          if (entryEndAddress <= newEntry.address)
115              break;
116      }
117      ++index;
118      this.entries_.splice(index, lastIndex - index, newEntry);
119    }
120  };
121
122  return {
123    TraceCodeMap: TraceCodeMap
124  };
125});
126
127</script>
128