12da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// Use of this source code is governed by a BSD-style license that can be
32da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// found in the LICENSE file.
42da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
52da489cd246702bee5938545b18a6f710ed214bcJamie Gennis'use strict';
62da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
72da489cd246702bee5938545b18a6f710ed214bcJamie Gennis/**
866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @fileoverview TraceModel is a parsed representation of the
92da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * TraceEvents obtained from base/trace_event in which the begin-end
102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * tokens are converted into a hierarchy of processes, threads,
112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * subrows, and slices.
122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis *
132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * The building block of the model is a slice. A slice is roughly
142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * equivalent to function call executing on a specific thread. As a
152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * result, slices may have one or more subslices.
162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis *
172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * A thread contains one or more subrows of slices. Row 0 corresponds to
182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * the "root" slices, e.g. the topmost slices. Row 1 contains slices that
192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * are nested 1 deep in the stack, and so on. We use these subrows to draw
202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * nesting tasks.
212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis *
222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */
2366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.require('base.range');
2466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.require('base.events');
2566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.require('tracing.trace_model.process');
2666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.require('tracing.trace_model.kernel');
2766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.require('tracing.filter');
2888448d9ae4dfff1805045790ef5f32495d62abccJeff Brown
292da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.exportTo('tracing', function() {
302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
3166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var Process = tracing.trace_model.Process;
3266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var Kernel = tracing.trace_model.Kernel;
332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  /**
352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * Builds a model from an array of TraceEvent objects.
362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * @param {Object=} opt_eventData Data from a single trace to be imported into
3766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   *     the new model. See TraceModel.importTraces for details on how to
382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   *     import multiple traces at once.
392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * @param {bool=} opt_shiftWorldToZero Whether to shift the world to zero.
402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * Defaults to true.
412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * @constructor
422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   */
4366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  function TraceModel(opt_eventData, opt_shiftWorldToZero) {
4466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    this.kernel = new Kernel(this);
452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    this.processes = {};
462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    this.importErrors = [];
472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    this.metadata = [];
482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    this.categories = [];
4988448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    this.bounds = new base.Range();
506833e18b1d4077bf3a727b4422cc2acdbeee35a7Jamie Gennis    this.instantEvents = [];
512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    if (opt_eventData)
532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.importTraces([opt_eventData], opt_shiftWorldToZero);
542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  }
552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
5666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  TraceModel.importerConstructors_ = [];
572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  /**
592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * Registers an importer. All registered importers are considered
602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * when processing an import request.
612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   *
622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * @param {Function} importerConstructor The importer's constructor function.
632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   */
6466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  TraceModel.registerImporter = function(importerConstructor) {
6566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    TraceModel.importerConstructors_.push(importerConstructor);
662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  };
672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
6866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  TraceModel.prototype = {
692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    __proto__: base.EventTarget.prototype,
702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    get numProcesses() {
722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var n = 0;
732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var p in this.processes)
742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        n++;
752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return n;
762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
7988448d9ae4dfff1805045790ef5f32495d62abccJeff Brown     * @return {Process} Gets a TimlineProcess for a specified pid or
802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * creates one if it does not exist.
812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    getOrCreateProcess: function(pid) {
832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (!this.processes[pid])
8466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        this.processes[pid] = new Process(this, pid);
852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return this.processes[pid];
862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
886833e18b1d4077bf3a727b4422cc2acdbeee35a7Jamie Gennis    pushInstantEvent: function(instantEvent) {
896833e18b1d4077bf3a727b4422cc2acdbeee35a7Jamie Gennis      this.instantEvents.push(instantEvent);
906833e18b1d4077bf3a727b4422cc2acdbeee35a7Jamie Gennis    },
916833e18b1d4077bf3a727b4422cc2acdbeee35a7Jamie Gennis
922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
9388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown     * Generates the set of categories from the slices and counters.
942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    updateCategories_: function() {
9688448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      var categoriesDict = {};
9788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      this.kernel.addCategoriesToDict(categoriesDict);
9888448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      for (var pid in this.processes)
9988448d9ae4dfff1805045790ef5f32495d62abccJeff Brown        this.processes[pid].addCategoriesToDict(categoriesDict);
1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
10188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      this.categories = [];
10288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      for (var category in categoriesDict)
10388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown        if (category != '')
10488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown          this.categories.push(category);
1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    updateBounds: function() {
10888448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      this.bounds.reset();
1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
11088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      this.kernel.updateBounds();
11188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      this.bounds.addRange(this.kernel.bounds);
11288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown
11388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      for (var pid in this.processes) {
11488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown        this.processes[pid].updateBounds();
11588448d9ae4dfff1805045790ef5f32495d62abccJeff Brown        this.bounds.addRange(this.processes[pid].bounds);
1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    shiftWorldToZero: function() {
12088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      if (this.bounds.isEmpty)
1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return;
12288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      var timeBase = this.bounds.min;
12388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      this.kernel.shiftTimestampsForward(-timeBase);
1246833e18b1d4077bf3a727b4422cc2acdbeee35a7Jamie Gennis      for (var id in this.instantEvents)
1256833e18b1d4077bf3a727b4422cc2acdbeee35a7Jamie Gennis        this.instantEvents[id].start -= timeBase;
1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var pid in this.processes)
1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        this.processes[pid].shiftTimestampsForward(-timeBase);
1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.updateBounds();
1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    getAllThreads: function() {
1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var threads = [];
13388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      for (var tid in this.kernel.threads) {
13488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown        threads.push(process.threads[tid]);
13588448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      }
1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var pid in this.processes) {
1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var process = this.processes[pid];
1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for (var tid in process.threads) {
1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          threads.push(process.threads[tid]);
1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return threads;
1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * @return {Array} An array of all processes in the model.
1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    getAllProcesses: function() {
1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var processes = [];
1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var pid in this.processes)
1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        processes.push(this.processes[pid]);
1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return processes;
1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * @return {Array} An array of all the counters in the model.
1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    getAllCounters: function() {
1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var counters = [];
16066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      counters.push.apply(
16166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          counters, base.dictionaryValues(this.kernel.counters));
1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var pid in this.processes) {
1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var process = this.processes[pid];
1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for (var tid in process.counters) {
1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          counters.push(process.counters[tid]);
1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return counters;
1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * @param {String} The name of the thread to find.
1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * @return {Array} An array of all the matched threads.
1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    findAllThreadsNamed: function(name) {
1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var namedThreads = [];
17788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      namedThreads.push.apply(
17866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          namedThreads,
17966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          this.kernel.findAllThreadsNamed(name));
18088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      for (var pid in this.processes) {
18188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown        namedThreads.push.apply(
18266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis            namedThreads,
18366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis            this.processes[pid].findAllThreadsNamed(name));
1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return namedThreads;
1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    createImporter_: function(eventData) {
1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var importerConstructor;
19066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      for (var i = 0; i < TraceModel.importerConstructors_.length; ++i) {
19166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        if (TraceModel.importerConstructors_[i].canImport(eventData)) {
19266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          importerConstructor = TraceModel.importerConstructors_[i];
1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          break;
1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (!importerConstructor)
1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        throw new Error(
1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            'Could not find an importer for the provided eventData.');
1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var importer = new importerConstructor(
2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          this, eventData);
2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return importer;
2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * Imports the provided traces into the model. The eventData type
20788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown     * is undefined and will be passed to all the  importers registered
20866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis     * via TraceModel.registerImporter. The first importer that returns true
2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * for canImport(events) will be used to import the events.
2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     *
2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * The primary trace is provided via the eventData variable. If multiple
2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * traces are to be imported, specify the first one as events, and the
2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * remainder in the opt_additionalEventData array.
2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     *
2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * @param {Array} traces An array of eventData to be imported. Each
2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * eventData should correspond to a single trace file and will be handled by
2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * a separate importer.
2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * @param {bool=} opt_shiftWorldToZero Whether to shift the world to zero.
2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * Defaults to true.
22066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis     * @param {bool=} opt_pruneEmptyContainers Whether to prune empty
22166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis     * containers. Defaults to true.
2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    importTraces: function(traces,
22466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                           opt_shiftWorldToZero,
22566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis                           opt_pruneEmptyContainers) {
2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (opt_shiftWorldToZero === undefined)
2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        opt_shiftWorldToZero = true;
22866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      if (opt_pruneEmptyContainers === undefined)
22966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        opt_pruneEmptyContainers = true;
23066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
23166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      // Copy the traces array, we may mutate it.
23266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      traces = traces.slice(0);
2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // Figure out which importers to use.
2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var importers = [];
2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < traces.length; ++i)
2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        importers.push(this.createImporter_(traces[i]));
2382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
23966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      // Some traces have other traces inside them. Before doing the full
24066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      // import, ask the importer if it has any subtraces, and if so, create an
24166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      // importer for that, also.
24266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      for (var i = 0; i < importers.length; i++) {
24366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        var subTrace = importers[i].extractSubtrace();
24466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        if (!subTrace)
24566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          continue;
24666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        traces.push(subTrace);
24766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        importers.push(this.createImporter_(subTrace));
24866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      }
24966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // Sort them on priority. This ensures importing happens in a predictable
2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // order, e.g. linux_perf_importer before trace_event_importer.
2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      importers.sort(function(x, y) {
2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return x.importPriority - y.importPriority;
2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      });
2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // Run the import.
2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < importers.length; i++)
2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        importers[i].importEvents(i > 0);
2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      // Autoclose open slices.
26188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      this.updateBounds();
26288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      this.kernel.autoCloseOpenSlices(this.bounds.max);
26366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      for (var pid in this.processes)
26488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown        this.processes[pid].autoCloseOpenSlices(this.bounds.max);
2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
26688448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      // Finalize import.
2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < importers.length; i++)
2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        importers[i].finalizeImport();
2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
27066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      // Run preinit.
27166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      for (var pid in this.processes)
27266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        this.processes[pid].preInitializeObjects();
27366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
27488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      // Prune empty containers.
27566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      if (opt_pruneEmptyContainers) {
27666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        this.kernel.pruneEmptyContainers();
27766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        for (var pid in this.processes) {
27866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          this.processes[pid].pruneEmptyContainers();
27966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        }
28088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      }
28188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown
28206db268ddce368501b62bd8999fcf2c3255b6de9Jamie Gennis      // Merge kernel and userland slices on each thread.
28306db268ddce368501b62bd8999fcf2c3255b6de9Jamie Gennis      for (var pid in this.processes) {
28406db268ddce368501b62bd8999fcf2c3255b6de9Jamie Gennis        this.processes[pid].mergeKernelWithUserland();
28506db268ddce368501b62bd8999fcf2c3255b6de9Jamie Gennis      }
28606db268ddce368501b62bd8999fcf2c3255b6de9Jamie Gennis
2872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.updateBounds();
2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.updateCategories_();
2902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (opt_shiftWorldToZero)
2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        this.shiftWorldToZero();
29366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
29466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      // Join refs.
29566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      for (var i = 0; i < importers.length; i++)
29666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        importers[i].joinRefs();
29766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
29866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      // Delete any undeleted objects.
29966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      for (var pid in this.processes)
30066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        this.processes[pid].autoDeleteObjects(this.bounds.max);
30166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
30266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      // Run initializers.
30366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      for (var pid in this.processes)
30466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        this.processes[pid].initializeObjects();
3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    }
3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  };
3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
30888448d9ae4dfff1805045790ef5f32495d62abccJeff Brown  /**
30988448d9ae4dfff1805045790ef5f32495d62abccJeff Brown   * Importer for empty strings and arrays.
31088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown   * @constructor
31188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown   */
31266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  function TraceModelEmptyImporter(events) {
31388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    this.importPriority = 0;
31488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown  };
31588448d9ae4dfff1805045790ef5f32495d62abccJeff Brown
31666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  TraceModelEmptyImporter.canImport = function(eventData) {
31788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    if (eventData instanceof Array && eventData.length == 0)
31888448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      return true;
31988448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    if (typeof(eventData) === 'string' || eventData instanceof String) {
32088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      return eventData.length == 0;
32188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    }
32288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    return false;
3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  };
3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
32566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  TraceModelEmptyImporter.prototype = {
32688448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    __proto__: Object.prototype,
32788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown
32866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    extractSubtrace: function() {
32966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return undefined;
33066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
33188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    importEvents: function() {
33288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    },
33388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    finalizeImport: function() {
33466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
33566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    joinRefs: function() {
33688448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    }
33788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown  };
33888448d9ae4dfff1805045790ef5f32495d62abccJeff Brown
33966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  TraceModel.registerImporter(TraceModelEmptyImporter);
34088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown
34188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown  return {
34266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    TraceModel: TraceModel
34388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown  };
3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis});
345