1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file.
4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @fileoverview TimelineModel is a parsed representation of the
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * TraceEvents obtained from base/trace_event in which the begin-end
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * tokens are converted into a hierarchy of processes, threads,
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * subrows, and slices.
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * The building block of the model is a slice. A slice is roughly
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * equivalent to function call executing on a specific thread. As a
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * result, slices may have one or more subslices.
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * A thread contains one or more subrows of slices. Row 0 corresponds to
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * the "root" slices, e.g. the topmost slices. Row 1 contains slices that
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * are nested 1 deep in the stack, and so on. We use these subrows to draw
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * nesting tasks.
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsencr.define('gpu', function() {
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  /**
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * A TimelineSlice represents an interval of time on a given thread
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * associated with a specific trace event. For example,
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   *   TRACE_EVENT_BEGIN1("x","myArg", 7) at time=0.1ms
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   *   TRACE_EVENT_END()                  at time=0.3ms
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * Results in a single timeline slice from 0.1 with duration 0.2.
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   *
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * All time units are stored in milliseconds.
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * @constructor
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   */
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  function TimelineSlice(title, colorId, start, args) {
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.title = title;
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.start = start;
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.colorId = colorId;
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.args = args;
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.subSlices = [];
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TimelineSlice.prototype = {
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    selected: false,
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    duration: undefined,
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    get end() {
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return this.start + this.duration;
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  /**
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * A TimelineThread stores all the trace events collected for a particular
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * thread. We organize the slices on a thread by "subrows," where subrow 0
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * has all the root slices, subrow 1 those nested 1 deep, and so on.
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   *
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * @constructor
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   */
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  function TimelineThread(parent, tid) {
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.parent = parent;
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.tid = tid;
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.subRows = [[]];
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TimelineThread.prototype = {
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    getSubrow: function(i) {
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      while (i >= this.subRows.length)
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this.subRows.push([]);
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return this.subRows[i];
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    },
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    updateBounds: function() {
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var slices = this.subRows[0];
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (slices.length != 0) {
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this.minTimestamp = slices[0].start;
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this.maxTimestamp = slices[slices.length - 1].end;
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      } else {
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this.minTimestamp = undefined;
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this.maxTimestamp = undefined;
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  /**
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * The TimelineProcess represents a single process in the
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * trace. Right now, we keep this around purely for bookkeeping
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * reasons.
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * @constructor
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   */
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  function TimelineProcess(pid) {
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.pid = pid;
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.threads = {};
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TimelineProcess.prototype = {
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    getThread: function(tid) {
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!this.threads[tid])
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this.threads[tid] = new TimelineThread(this, tid);
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return this.threads[tid];
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  /**
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * Builds a model from an array of TraceEvent objects.
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * @param {Array} events An array of TraceEvents created by
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   *     TraceEvent.ToJSON().
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   * @constructor
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   */
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  function TimelineModel(events) {
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    this.processes = {};
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (events)
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.importEvents(events);
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  TimelineModel.prototype = {
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    __proto__: cr.EventTarget.prototype,
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    getProcess: function(pid) {
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!this.processes[pid])
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this.processes[pid] = new TimelineProcess(pid);
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return this.processes[pid];
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    },
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    /**
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * The import takes an array of json-ified TraceEvents and adds them into
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * the TimelineModel as processes, threads, and slices.
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     */
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    importEvents: function(events) {
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // A ptid is a pid and tid joined together x:y fashion, eg 1024:130
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // The ptid is a unique key for a thread in the trace.
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Threadstate
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const numColorIds = 12;
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      function ThreadState(tid) {
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        this.openSlices = [];
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var threadStateByPTID = {};
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var nameToColorMap = {};
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      function getColor(name) {
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (!(name in nameToColorMap)) {
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          // Compute a simplistic hashcode of the string so we get consistent
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          // coloring across traces.
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          var hash = 0;
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          for (var i = 0; i < name.length; ++i)
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            hash = (hash + 37 * hash + name.charCodeAt(i)) % 0xFFFFFFFF;
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          nameToColorMap[name] = hash % numColorIds;
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        }
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return nameToColorMap[name];
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Walk through events
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      for (var eI = 0; eI < events.length; eI++) {
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        var event = events[eI];
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        var ptid = event.pid + ':' + event.tid;
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (!(ptid in threadStateByPTID)) {
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          threadStateByPTID[ptid] = new ThreadState();
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        }
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        var state = threadStateByPTID[ptid];
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (event.ph == 'B') {
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          var colorId = getColor(event.name);
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          var slice = new TimelineSlice(event.name, colorId, event.ts,
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                        event.args);
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          state.openSlices.push(slice);
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        } else if (event.ph == 'E') {
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          if (state.openSlices.length == 0) {
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            // Ignore E events that that are unmatched.
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            continue;
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          }
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          var slice = state.openSlices.pop();
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          slice.duration = event.ts - slice.start;
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          // Store the slice on the right subrow.
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          var thread = this.getProcess(event.pid).getThread(event.tid);
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          var subRowIndex = state.openSlices.length;
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          thread.getSubrow(subRowIndex).push(slice);
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          // Add the slice to the subSlices array of its parent.
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          if (state.openSlices.length) {
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            var parentSlice = state.openSlices[state.openSlices.length - 1];
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            parentSlice.subSlices.push(slice);
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          }
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        } else if (event.ph == 'I') {
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          // TODO(nduca): Implement parsing of immediate events.
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          console.log('Parsing of I-type events not implemented.');
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        } else {
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          throw new Error('Unrecognized event phase: ' + event.ph +
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                          '(' + event.name + ')');
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        }
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.updateBounds();
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.shiftWorldToMicroseconds();
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var boost = (this.maxTimestamp - this.minTimestamp) * 0.15;
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.minTimestamp = this.minTimestamp - boost;
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.maxTimestamp = this.maxTimestamp + boost;
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    },
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    updateBounds: function() {
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var wmin = Infinity;
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var wmax = -wmin;
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var threads = this.getAllThreads();
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      for (var tI = 0; tI < threads.length; tI++) {
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        var thread = threads[tI];
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        thread.updateBounds();
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        wmin = Math.min(wmin, thread.minTimestamp);
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        wmax = Math.max(wmax, thread.maxTimestamp);
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.minTimestamp = wmin;
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.maxTimestamp = wmax;
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    },
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    shiftWorldToMicroseconds: function() {
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var timeBase = this.minTimestamp;
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var threads = this.getAllThreads();
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      for (var tI = 0; tI < threads.length; tI++) {
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        var thread = threads[tI];
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        for (var tSR = 0; tSR < thread.subRows.length; tSR++) {
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          var subRow = thread.subRows[tSR];
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          for (var tS = 0; tS < subRow.length; tS++) {
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            var slice = subRow[tS];
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            slice.start = (slice.start - timeBase) / 1000;
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            slice.duration /= 1000;
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          }
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        }
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      this.updateBounds();
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    },
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    getAllThreads: function() {
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      var threads = [];
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      for (var pid in this.processes) {
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        var process = this.processes[pid];
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        for (var tid in process.threads) {
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          threads.push(process.threads[tid]);
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        }
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return threads;
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return {
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TimelineSlice: TimelineSlice,
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TimelineThread: TimelineThread,
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TimelineProcess: TimelineProcess,
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TimelineModel: TimelineModel
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  };
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen});
254