<!DOCTYPE html>
<!--
Copyright (c) 2012 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<link rel="import" href="/tracing/base/base64.html">
<link rel="import" href="/tracing/base/color_scheme.html">
<link rel="import" href="/tracing/base/range.html">
<link rel="import" href="/tracing/base/unit.html">
<link rel="import" href="/tracing/base/utils.html">
<link rel="import" href="/tracing/extras/importer/trace_code_entry.html">
<link rel="import" href="/tracing/extras/importer/trace_code_map.html">
<link rel="import" href="/tracing/extras/importer/v8/codemap.html">
<link rel="import" href="/tracing/importer/context_processor.html">
<link rel="import" href="/tracing/importer/importer.html">
<link rel="import" href="/tracing/model/comment_box_annotation.html">
<link rel="import" href="/tracing/model/constants.html">
<link rel="import" href="/tracing/model/container_memory_dump.html">
<link rel="import" href="/tracing/model/counter_series.html">
<link rel="import" href="/tracing/model/flow_event.html">
<link rel="import" href="/tracing/model/global_memory_dump.html">
<link rel="import" href="/tracing/model/heap_dump.html">
<link rel="import" href="/tracing/model/instant_event.html">
<link rel="import" href="/tracing/model/memory_allocator_dump.html">
<link rel="import" href="/tracing/model/model.html">
<link rel="import" href="/tracing/model/process_memory_dump.html">
<link rel="import" href="/tracing/model/rect_annotation.html">
<link rel="import" href="/tracing/model/scoped_id.html">
<link rel="import" href="/tracing/model/slice_group.html">
<link rel="import" href="/tracing/model/vm_region.html">
<link rel="import" href="/tracing/model/x_marker_annotation.html">
<link rel="import" href="/tracing/value/numeric.html">

<script>
'use strict';

/**
 * @fileoverview TraceEventImporter imports TraceEvent-formatted data
 * into the provided model.
 */
tr.exportTo('tr.e.importer', function() {
  var Base64 = tr.b.Base64;
  var deepCopy = tr.b.deepCopy;
  var ColorScheme = tr.b.ColorScheme;

  function getEventColor(event, opt_customName) {
    if (event.cname)
      return ColorScheme.getColorIdForReservedName(event.cname);
    else if (opt_customName || event.name) {
      return ColorScheme.getColorIdForGeneralPurposeString(
          opt_customName || event.name);
    }
  }

  var PRODUCER = 'producer';
  var CONSUMER = 'consumer';
  var STEP = 'step';

  var BACKGROUND = tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;
  var LIGHT = tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;
  var DETAILED = tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;
  var MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER = [undefined, BACKGROUND, LIGHT,
                                           DETAILED];

  var GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX = 'global/';

  var ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX = 'ClockSyncEvent.';

  // Map from raw memory dump byte stat names to model byte stat names. See
  // //base/trace_event/process_memory_maps.cc in Chromium.
  var BYTE_STAT_NAME_MAP = {
    'pc': 'privateCleanResident',
    'pd': 'privateDirtyResident',
    'sc': 'sharedCleanResident',
    'sd': 'sharedDirtyResident',
    'pss': 'proportionalResident',
    'sw': 'swapped'
  };

  // See tr.model.MemoryAllocatorDump 'weak' field and
  // base::trace_event::MemoryAllocatorDump::Flags::WEAK in the Chromium
  // codebase.
  var WEAK_MEMORY_ALLOCATOR_DUMP_FLAG = 1 << 0;

  // Object type name patterns for various compilers.
  var OBJECT_TYPE_NAME_PATTERNS = [
    {
      // Clang.
      prefix: 'const char *WTF::getStringWithTypeName() [T = ',
      suffix: ']'
    },
    {
      // GCC.
      prefix: 'const char* WTF::getStringWithTypeName() [with T = ',
      suffix: ']'
    },
    {
      // Microsoft Visual C++
      prefix: 'const char *__cdecl WTF::getStringWithTypeName<',
      suffix: '>(void)'
    }
  ];

  // The list of fields on the trace that are known to contain subtraces.
  var SUBTRACE_FIELDS = new Set([
    'powerTraceAsString',
    'systemTraceEvents',
  ]);

  // The complete list of fields on the trace that should not be treated as
  // trace metadata.
  var NON_METADATA_FIELDS = new Set([
    'samples',
    'stackFrames',
    'traceAnnotations',
    'traceEvents'
  ]);
  // TODO(charliea): Replace this with the spread (...) operator in literal
  // above once v8 is updated to a sufficiently recent version (>M45).
  for (var subtraceField in SUBTRACE_FIELDS)
    NON_METADATA_FIELDS.add(subtraceField);

  function TraceEventImporter(model, eventData) {
    this.importPriority = 1;
    this.model_ = model;
    this.events_ = undefined;
    this.sampleEvents_ = undefined;
    this.stackFrameEvents_ = undefined;
    this.subtraces_ = [];
    this.eventsWereFromString_ = false;
    this.softwareMeasuredCpuCount_ = undefined;


    this.allAsyncEvents_ = [];
    this.allFlowEvents_ = [];
    this.allObjectEvents_ = [];

    this.contextProcessorPerThread = {};

    this.traceEventSampleStackFramesByName_ = {};

    this.v8ProcessCodeMaps_ = {};
    this.v8ProcessRootStackFrame_ = {};
    this.v8SamplingData_ = [];

    // For tracking async events that is used to create back-compat clock sync
    // event.
    this.asyncClockSyncStart_ = undefined;
    this.asyncClockSyncFinish_ = undefined;

    // Dump ID -> PID -> [process memory dump events].
    this.allMemoryDumpEvents_ = {};

    // PID -> Object type ID -> Object type name.
    this.objectTypeNameMap_ = {};

    // For old Chrome traces with no clock domain metadata, just use a
    // placeholder clock domain.
    this.clockDomainId_ = tr.model.ClockDomainId.UNKNOWN_CHROME_LEGACY;
    // A function able to transform timestamps in |clockDomainId| to timestamps
    // in the model clock domain.
    this.toModelTime_ = undefined;

    if (typeof(eventData) === 'string' || eventData instanceof String) {
      eventData = eventData.trim();
      // If the event data begins with a [, then we know it should end with a ].
      // The reason we check for this is because some tracing implementations
      // cannot guarantee that a ']' gets written to the trace file. So, we are
      // forgiving and if this is obviously the case, we fix it up before
      // throwing the string at JSON.parse.
      if (eventData[0] === '[') {
        eventData = eventData.replace(/\s*,\s*$/, '');
        if (eventData[eventData.length - 1] !== ']')
          eventData = eventData + ']';
      }

      this.events_ = JSON.parse(eventData);
      this.eventsWereFromString_ = true;
    } else {
      this.events_ = eventData;
    }

    this.traceAnnotations_ = this.events_.traceAnnotations;

    // Some trace_event implementations put the actual trace events
    // inside a container. E.g { ... , traceEvents: [ ] }
    // If we see that, just pull out the trace events.
    if (this.events_.traceEvents) {
      var container = this.events_;
      this.events_ = this.events_.traceEvents;

      // Some trace authors store subtraces as specific properties of the trace.
      for (var subtraceField of SUBTRACE_FIELDS)
        if (container[subtraceField])
          this.subtraces_.push(container[subtraceField]);

      // Sampling data.
      this.sampleEvents_ = container.samples;
      this.stackFrameEvents_ = container.stackFrames;

      // Some implementations specify displayTimeUnit
      if (container.displayTimeUnit) {
        var unitName = container.displayTimeUnit;
        var unit = tr.b.TimeDisplayModes[unitName];
        if (unit === undefined) {
          throw new Error('Unit ' + unitName + ' is not supported.');
        }
        this.model_.intrinsicTimeUnit = unit;
      }

      // Any other fields in the container should be treated as metadata.
      for (var fieldName in container) {
        if (NON_METADATA_FIELDS.has(fieldName))
          continue;

        this.model_.metadata.push(
            { name: fieldName, value: container[fieldName] });

        if (fieldName === 'metadata') {
          var metadata = container[fieldName];
          if (metadata['highres-ticks'])
            this.model_.isTimeHighResolution = metadata['highres-ticks'];
          if (metadata['clock-domain'])
            this.clockDomainId_ = metadata['clock-domain'];
        }
      }
    }
  }

  /**
   * @return {boolean} Whether obj is a TraceEvent array.
   */
  TraceEventImporter.canImport = function(eventData) {
    // May be encoded JSON. But we dont want to parse it fully yet.
    // Use a simple heuristic:
    //   - eventData that starts with [ are probably trace_event
    //   - eventData that starts with { are probably trace_event
    // May be encoded JSON. Treat files that start with { as importable by us.
    if (typeof(eventData) === 'string' || eventData instanceof String) {
      eventData = eventData.trim();
      return eventData[0] === '{' || eventData[0] === '[';
    }

    // Might just be an array of events
    if (eventData instanceof Array && eventData.length && eventData[0].ph)
      return true;

    // Might be an object with a traceEvents field in it.
    if (eventData.traceEvents) {
      if (eventData.traceEvents instanceof Array) {
        if (eventData.traceEvents.length && eventData.traceEvents[0].ph)
          return true;
        if (eventData.samples.length && eventData.stackFrames !== undefined)
          return true;
      }
    }

    return false;
  };

  TraceEventImporter.prototype = {
    __proto__: tr.importer.Importer.prototype,

    get importerName() {
      return 'TraceEventImporter';
    },

    extractSubtraces: function() {
      // Because subtraces can be quite large, we need to make sure that we
      // don't hold a reference to the memory.
      var subtraces = this.subtraces_;
      this.subtraces_ = [];
      return subtraces;
    },

    /**
     * Deep copying is only needed if the trace was given to us as events.
     */
    deepCopyIfNeeded_: function(obj) {
      if (obj === undefined)
        obj = {};
      if (this.eventsWereFromString_)
        return obj;
      return deepCopy(obj);
    },

    /**
     * Always perform deep copying.
     */
    deepCopyAlways_: function(obj) {
      if (obj === undefined)
        obj = {};
      return deepCopy(obj);
    },

    /**
     * Helper to process an async event.
     */
    processAsyncEvent: function(event) {
      var thread = this.model_.getOrCreateProcess(event.pid).
          getOrCreateThread(event.tid);
      this.allAsyncEvents_.push({
        sequenceNumber: this.allAsyncEvents_.length,
        event: event,
        thread: thread
      });
    },

    /**
     * Helper to process a flow event.
     */
    processFlowEvent: function(event, opt_slice) {
      var thread = this.model_.getOrCreateProcess(event.pid).
          getOrCreateThread(event.tid);
      this.allFlowEvents_.push({
        refGuid: tr.b.GUID.getLastSimpleGuid(),
        sequenceNumber: this.allFlowEvents_.length,
        event: event,
        slice: opt_slice,  // slice for events that have flow info
        thread: thread
      });
    },

    /**
     * Helper that creates and adds samples to a Counter object based on
     * 'C' phase events.
     */
    processCounterEvent: function(event) {
      var ctr_name;
      if (event.id !== undefined)
        ctr_name = event.name + '[' + event.id + ']';
      else
        ctr_name = event.name;

      var ctr = this.model_.getOrCreateProcess(event.pid)
          .getOrCreateCounter(event.cat, ctr_name);
      var reservedColorId = event.cname ? getEventColor(event) : undefined;

      // Initialize the counter's series fields if needed.
      if (ctr.numSeries === 0) {
        for (var seriesName in event.args) {
          var colorId = reservedColorId ||
              getEventColor(event, ctr.name + '.' + seriesName);
          ctr.addSeries(new tr.model.CounterSeries(seriesName, colorId));
        }

        if (ctr.numSeries === 0) {
          this.model_.importWarning({
            type: 'counter_parse_error',
            message: 'Expected counter ' + event.name +
                ' to have at least one argument to use as a value.'
          });

          // Drop the counter.
          delete ctr.parent.counters[ctr.name];
          return;
        }
      }

      var ts = this.toModelTimeFromUs_(event.ts);
      ctr.series.forEach(function(series) {
        var val = event.args[series.name] ? event.args[series.name] : 0;
        series.addCounterSample(ts, val);
      });
    },

    scopedIdForEvent_: function(event) {
      return new tr.model.ScopedId(
          event.scope || tr.model.OBJECT_DEFAULT_SCOPE, event.id);
    },

    processObjectEvent: function(event) {
      var thread = this.model_.getOrCreateProcess(event.pid).
          getOrCreateThread(event.tid);
      this.allObjectEvents_.push({
        sequenceNumber: this.allObjectEvents_.length,
        event: event,
        thread: thread});
      if (thread.guid in this.contextProcessorPerThread) {
        var processor = this.contextProcessorPerThread[thread.guid];
        var scopedId = this.scopedIdForEvent_(event);
        if (event.ph === 'D')
          processor.destroyContext(scopedId);
        // The context processor maintains a cache of unique context objects and
        // active context sets to reduce memory usage. If an object is modified,
        // we should invalidate this cache, because otherwise context sets from
        // before and after the modification may erroneously point to the same
        // context snapshot (as both are the same set/object instances).
        processor.invalidateContextCacheForSnapshot(scopedId);
      }
    },

    processContextEvent: function(event) {
      var thread = this.model_.getOrCreateProcess(event.pid).
          getOrCreateThread(event.tid);
      if (!(thread.guid in this.contextProcessorPerThread)) {
        this.contextProcessorPerThread[thread.guid] =
            new tr.importer.ContextProcessor(this.model_);
      }
      var scopedId = this.scopedIdForEvent_(event);
      var contextType = event.name;
      var processor = this.contextProcessorPerThread[thread.guid];
      if (event.ph === '(') {
        processor.enterContext(contextType, scopedId);
      } else if (event.ph === ')') {
        processor.leaveContext(contextType, scopedId);
      } else {
        this.model_.importWarning({
          type: 'unknown_context_phase',
          message: 'Unknown context event phase: ' + event.ph + '.'
        });
      }
    },

    setContextsFromThread_: function(thread, slice) {
      if (thread.guid in this.contextProcessorPerThread) {
        slice.contexts =
            this.contextProcessorPerThread[thread.guid].activeContexts;
      }
    },

    processDurationEvent: function(event) {
      var thread = this.model_.getOrCreateProcess(event.pid)
        .getOrCreateThread(event.tid);
      var ts = this.toModelTimeFromUs_(event.ts);
      if (!thread.sliceGroup.isTimestampValidForBeginOrEnd(ts)) {
        this.model_.importWarning({
          type: 'duration_parse_error',
          message: 'Timestamps are moving backward.'
        });
        return;
      }

      if (event.ph === 'B') {
        var slice = thread.sliceGroup.beginSlice(
            event.cat, event.name, this.toModelTimeFromUs_(event.ts),
            this.deepCopyIfNeeded_(event.args),
            this.toModelTimeFromUs_(event.tts), event.argsStripped,
            getEventColor(event));
        slice.startStackFrame = this.getStackFrameForEvent_(event);
        this.setContextsFromThread_(thread, slice);
      } else if (event.ph === 'I' || event.ph === 'i' || event.ph === 'R') {
        if (event.s !== undefined && event.s !== 't')
          throw new Error('This should never happen');

        thread.sliceGroup.beginSlice(event.cat, event.name,
                                     this.toModelTimeFromUs_(event.ts),
                                     this.deepCopyIfNeeded_(event.args),
                                     this.toModelTimeFromUs_(event.tts),
                                     event.argsStripped,
                                     getEventColor(event));
        var slice = thread.sliceGroup.endSlice(
            this.toModelTimeFromUs_(event.ts),
            this.toModelTimeFromUs_(event.tts));
        slice.startStackFrame = this.getStackFrameForEvent_(event);
        slice.endStackFrame = undefined;
      } else {
        if (!thread.sliceGroup.openSliceCount) {
          this.model_.importWarning({
            type: 'duration_parse_error',
            message: 'E phase event without a matching B phase event.'
          });
          return;
        }

        var slice = thread.sliceGroup.endSlice(
            this.toModelTimeFromUs_(event.ts),
            this.toModelTimeFromUs_(event.tts),
            getEventColor(event));
        if (event.name && slice.title != event.name) {
          this.model_.importWarning({
            type: 'title_match_error',
            message: 'Titles do not match. Title is ' +
                slice.title + ' in openSlice, and is ' +
                event.name + ' in endSlice'
          });
        }
        slice.endStackFrame = this.getStackFrameForEvent_(event);

        this.mergeArgsInto_(slice.args, event.args, slice.title);
      }
    },

    mergeArgsInto_: function(dstArgs, srcArgs, eventName) {
      for (var arg in srcArgs) {
        if (dstArgs[arg] !== undefined) {
          this.model_.importWarning({
            type: 'arg_merge_error',
            message: 'Different phases of ' + eventName +
                ' provided values for argument ' + arg + '.' +
                ' The last provided value will be used.'
          });
        }
        dstArgs[arg] = this.deepCopyIfNeeded_(srcArgs[arg]);
      }
    },

    processCompleteEvent: function(event) {
      // Preventing the overhead slices from making it into the model. This
      // only applies to legacy traces, as the overhead traces have been
      // removed from the chromium code.
      if (event.cat !== undefined &&
          event.cat.indexOf('trace_event_overhead') > -1)
        return undefined;

      var thread = this.model_.getOrCreateProcess(event.pid)
          .getOrCreateThread(event.tid);

      if (event.flow_out) {
        if (event.flow_in)
          event.flowPhase = STEP;
        else
          event.flowPhase = PRODUCER;
      } else if (event.flow_in) {
        event.flowPhase = CONSUMER;
      }

      var slice = thread.sliceGroup.pushCompleteSlice(event.cat, event.name,

          this.toModelTimeFromUs_(event.ts),
          this.maybeToModelTimeFromUs_(event.dur),
          this.maybeToModelTimeFromUs_(event.tts),
          this.maybeToModelTimeFromUs_(event.tdur),
          this.deepCopyIfNeeded_(event.args),
          event.argsStripped,
          getEventColor(event),
          event.bind_id);
      slice.startStackFrame = this.getStackFrameForEvent_(event);
      slice.endStackFrame = this.getStackFrameForEvent_(event, true);
      this.setContextsFromThread_(thread, slice);

      return slice;
    },

    processJitCodeEvent: function(event) {
      if (this.v8ProcessCodeMaps_[event.pid] === undefined)
        this.v8ProcessCodeMaps_[event.pid] = new tr.e.importer.TraceCodeMap();
      var map = this.v8ProcessCodeMaps_[event.pid];

      var data = event.args.data;
      // TODO(dsinclair): There are _a lot_ of JitCode events so I'm skipping
      // the display for now. Can revisit later if we want to show them.
      // Handle JitCodeMoved and JitCodeAdded event.
      if (event.name === 'JitCodeMoved')
        map.moveEntry(data.code_start, data.new_code_start, data.code_len);
      else  // event.name === 'JitCodeAdded'
        map.addEntry(data.code_start, data.code_len, data.name, data.script_id);
    },

    processMetadataEvent: function(event) {
      // V8 JIT events are currently logged as phase 'M' so we need to
      // separate them out and handle specially.
      if (event.name === 'JitCodeAdded' || event.name === 'JitCodeMoved') {
        this.v8SamplingData_.push(event);
        return;
      }

      // The metadata events aren't useful without args.
      if (event.argsStripped)
        return;

      if (event.name === 'process_name') {
        var process = this.model_.getOrCreateProcess(event.pid);
        process.name = event.args.name;
      } else if (event.name === 'process_labels') {
        var process = this.model_.getOrCreateProcess(event.pid);
        var labels = event.args.labels.split(',');
        for (var i = 0; i < labels.length; i++)
          process.addLabelIfNeeded(labels[i]);
      } else if (event.name === 'process_sort_index') {
        var process = this.model_.getOrCreateProcess(event.pid);
        process.sortIndex = event.args.sort_index;
      } else if (event.name === 'thread_name') {
        var thread = this.model_.getOrCreateProcess(event.pid).
            getOrCreateThread(event.tid);
        thread.name = event.args.name;
      } else if (event.name === 'thread_sort_index') {
        var thread = this.model_.getOrCreateProcess(event.pid).
            getOrCreateThread(event.tid);
        thread.sortIndex = event.args.sort_index;
      } else if (event.name === 'num_cpus') {
        var n = event.args.number;
        // Not all render processes agree on the cpu count in trace_event. Some
        // processes will report 1, while others will report the actual cpu
        // count. To deal with this, take the max of what is reported.
        if (this.softwareMeasuredCpuCount_ !== undefined)
          n = Math.max(n, this.softwareMeasuredCpuCount_);
        this.softwareMeasuredCpuCount_ = n;
      } else if (event.name === 'stackFrames') {
        var stackFrames = event.args.stackFrames;
        if (stackFrames === undefined) {
          this.model_.importWarning({
            type: 'metadata_parse_error',
            message: 'No stack frames found in a \'' + event.name +
                '\' metadata event'
          });
        } else {
          this.importStackFrames_(stackFrames, 'p' + event.pid + ':');
        }
      } else if (event.name === 'typeNames') {
        var objectTypeNameMap = event.args.typeNames;
        if (objectTypeNameMap === undefined) {
          this.model_.importWarning({
            type: 'metadata_parse_error',
            message: 'No mapping from object type IDs to names found in a \'' +
                event.name + '\' metadata event'
          });
        } else {
          this.importObjectTypeNameMap_(objectTypeNameMap, event.pid);
        }
      } else if (event.name === 'TraceConfig') {
          this.model_.metadata.push(
              {name: 'TraceConfig', value: event.args.value});
      } else {
        this.model_.importWarning({
          type: 'metadata_parse_error',
          message: 'Unrecognized metadata name: ' + event.name
        });
      }
    },

    processInstantEvent: function(event) {
      // V8 JIT events were logged as phase 'I' in the old format,
      // so we need to separate them out and handle specially.
      if (event.name === 'JitCodeAdded' || event.name === 'JitCodeMoved') {
        this.v8SamplingData_.push(event);
        return;
      }

      // Thread-level instant events are treated as zero-duration slices.
      if (event.s === 't' || event.s === undefined) {
        this.processDurationEvent(event);
        return;
      }

      var constructor;
      switch (event.s) {
        case 'g':
          constructor = tr.model.GlobalInstantEvent;
          break;
        case 'p':
          constructor = tr.model.ProcessInstantEvent;
          break;
        default:
          this.model_.importWarning({
            type: 'instant_parse_error',
            message: 'I phase event with unknown "s" field value.'
          });
          return;
      }

      var instantEvent = new constructor(event.cat, event.name,
          getEventColor(event), this.toModelTimeFromUs_(event.ts),
          this.deepCopyIfNeeded_(event.args));

      switch (instantEvent.type) {
        case tr.model.InstantEventType.GLOBAL:
          this.model_.instantEvents.push(instantEvent);
          break;

        case tr.model.InstantEventType.PROCESS:
          var process = this.model_.getOrCreateProcess(event.pid);
          process.instantEvents.push(instantEvent);
          break;

        default:
          throw new Error('Unknown instant event type: ' + event.s);
      }
    },

    processV8Sample: function(event) {
      var data = event.args.data;

      // As-per DevTools, the backend sometimes creates bogus samples. Skip it.
      if (data.vm_state === 'js' && !data.stack.length)
        return;

      var rootStackFrame = this.v8ProcessRootStackFrame_[event.pid];
      if (!rootStackFrame) {
        rootStackFrame = new tr.model.StackFrame(
            undefined /* parent */, 'v8-root-stack-frame' /* id */,
            'v8-root-stack-frame' /* title */, 0 /* colorId */);
        this.v8ProcessRootStackFrame_[event.pid] = rootStackFrame;
      }

      function findChildWithEntryID(stackFrame, entryID) {
        return tr.b.findFirstInArray(stackFrame.children, function(child) {
          return child.entryID === entryID;
        });
      }

      var model = this.model_;
      function addStackFrame(lastStackFrame, entry) {
        var childFrame = findChildWithEntryID(lastStackFrame, entry.id);
        if (childFrame)
          return childFrame;

        var frame = new tr.model.StackFrame(
            lastStackFrame, tr.b.GUID.allocateSimple(), entry.name,
            ColorScheme.getColorIdForGeneralPurposeString(entry.name),
            entry.sourceInfo);

        frame.entryID = entry.id;
        model.addStackFrame(frame);
        return frame;
      }

      var lastStackFrame = rootStackFrame;

      // There are several types of v8 sample events, gc, native, compiler, etc.
      // Some of these types have stacks and some don't, we handle those two
      // cases differently. For types that don't have any stack frames attached
      // we synthesize one based on the type of thing that's happening so when
      // we view all the samples we'll see something like 'external' or 'gc'
      // as a fraction of the time spent.
      if (data.stack.length > 0 && this.v8ProcessCodeMaps_[event.pid]) {
        var map = this.v8ProcessCodeMaps_[event.pid];

        // Stacks have the leaf node first, flip them around so the root
        // comes first.
        data.stack.reverse();

        for (var i = 0; i < data.stack.length; i++) {
          var entry = map.lookupEntry(data.stack[i]);
          if (entry === undefined) {
            entry = {
              id: 'unknown',
              name: 'unknown',
              sourceInfo: undefined
            };
          }

          lastStackFrame = addStackFrame(lastStackFrame, entry);
        }
      } else {
        var entry = {
          id: data.vm_state,
          name: data.vm_state,
          sourceInfo: undefined
        };
        lastStackFrame = addStackFrame(lastStackFrame, entry);
      }

      var thread = this.model_.getOrCreateProcess(event.pid)
        .getOrCreateThread(event.tid);

      var sample = new tr.model.Sample(
          undefined /* cpu */, thread, 'V8 Sample',
          this.toModelTimeFromUs_(event.ts), lastStackFrame, 1 /* weight */,
          this.deepCopyIfNeeded_(event.args));
      this.model_.samples.push(sample);
    },

    processTraceSampleEvent: function(event) {
      if (event.name === 'V8Sample') {
        this.v8SamplingData_.push(event);
        return;
      }

      var stackFrame = this.getStackFrameForEvent_(event);
      if (stackFrame === undefined) {
        stackFrame = this.traceEventSampleStackFramesByName_[
            event.name];
      }
      if (stackFrame === undefined) {
        var id = 'te-' + tr.b.GUID.allocateSimple();
        stackFrame = new tr.model.StackFrame(
            undefined, id, event.name,
            ColorScheme.getColorIdForGeneralPurposeString(event.name));
        this.model_.addStackFrame(stackFrame);
        this.traceEventSampleStackFramesByName_[event.name] = stackFrame;
      }

      var thread = this.model_.getOrCreateProcess(event.pid)
        .getOrCreateThread(event.tid);

      var sample = new tr.model.Sample(
          undefined, thread, 'Trace Event Sample',
          this.toModelTimeFromUs_(event.ts), stackFrame, 1,
          this.deepCopyIfNeeded_(event.args));
      this.setContextsFromThread_(thread, sample);
      this.model_.samples.push(sample);
    },

    processMemoryDumpEvent: function(event) {
      if (event.ph !== 'v')
        throw new Error('Invalid memory dump event phase "' + event.ph + '".');

      var dumpId = event.id;
      if (dumpId === undefined) {
        this.model_.importWarning({
          type: 'memory_dump_parse_error',
          message: 'Memory dump event (phase \'' + event.ph +
              '\') without a dump ID.'
        });
        return;
      }

      var pid = event.pid;
      if (pid === undefined) {
        this.model_.importWarning({
          type: 'memory_dump_parse_error',
          message: 'Memory dump event (phase\'' + event.ph + '\', dump ID \'' +
              dumpId + '\') without a PID.'
        });
        return;
      }

      // Dump ID -> PID -> [process memory dump events].
      var allEvents = this.allMemoryDumpEvents_;

      // PID -> [process memory dump events].
      var dumpIdEvents = allEvents[dumpId];
      if (dumpIdEvents === undefined)
        allEvents[dumpId] = dumpIdEvents = {};

      // [process memory dump events].
      var processEvents = dumpIdEvents[pid];
      if (processEvents === undefined)
        dumpIdEvents[pid] = processEvents = [];

      processEvents.push(event);
    },

    processClockSyncEvent: function(event) {
      if (event.ph !== 'c')
        throw new Error('Invalid clock sync event phase "' + event.ph + '".');

      var syncId = event.args.sync_id;
      if (syncId === undefined) {
        this.model_.importWarning({
          type: 'clock_sync_parse_error',
          message: 'Clock sync at time ' + event.ts + ' without an ID.'
        });
        return;
      }

      if (event.args && event.args.issue_ts !== undefined) {
        // When Chrome is the tracing controller and is the requester of the
        // clock sync, the clock sync event looks like:
        //
        //   {
        //     "args": {
        //       "sync_id": "abc123",
        //       "issue_ts": 12340
        //     }
        //     "ph": "c"
        //     "ts": 12345
        //     ...
        //   }
        this.model_.clockSyncManager.addClockSyncMarker(
            this.clockDomainId_, syncId,
            tr.b.Unit.timestampFromUs(event.args.issue_ts),
            tr.b.Unit.timestampFromUs(event.ts));
      } else {
        // When Chrome is a tracing agent and is the recipient of the clock
        // sync request, the clock sync event looks like:
        //
        //   {
        //     "args": { "sync_id": "abc123" }
        //     "ph": "c"
        //     "ts": 12345
        //     ...
        //   }
        this.model_.clockSyncManager.addClockSyncMarker(
            this.clockDomainId_, syncId, tr.b.Unit.timestampFromUs(event.ts));
      }
    },

    // Because the order of Jit code events and V8 samples are not guaranteed,
    // We store them in an array, sort by timestamp, and then process them.
    processV8Events: function() {
      this.v8SamplingData_.sort(function(a, b) {
        if (a.ts !== b.ts)
          return a.ts - b.ts;
        if (a.ph === 'M' || a.ph === 'I')
          return -1;
        else if (b.ph === 'M' || b.ph === 'I')
          return 1;
        return 0;
      });
      var length = this.v8SamplingData_.length;
      for (var i = 0; i < length; ++i) {
        var event = this.v8SamplingData_[i];
        if (event.ph === 'M' || event.ph === 'I') {
          this.processJitCodeEvent(event);
        } else if (event.ph === 'P') {
          this.processV8Sample(event);
        }
      }
    },

    initBackcompatClockSyncEventTracker_: function(event) {
      if (event.name !== undefined &&
          event.name.startsWith(ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX) &&
          event.ph === 'S')
        this.asyncClockSyncStart_ = event;

      if (event.name !== undefined &&
          event.name.startsWith(ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX) &&
          event.ph === 'F')
          this.asyncClockSyncFinish_ = event;
      if (this.asyncClockSyncStart_ == undefined ||
          this.asyncClockSyncFinish_ == undefined)
        return;

      // Older version of Chrome doesn't support clock sync API, hence
      // telemetry get around it by marking the clock sync events with
      // console.time & console.timeEnd. When we encounter async events
      // with named started with 'ClockSyncEvent.' prefix, create a
      // synthetic clock sync events based on their timestamps.
      var syncId =
          this.asyncClockSyncStart_.name.substring(
              ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX.length);
      if (syncId !==
          this.asyncClockSyncFinish_.name.substring(
              ASYNC_CLOCK_SYNC_EVENT_TITLE_PREFIX.length)) {
         throw new Error('Inconsistent clock sync id of async clock sync ' +
                         'events.');
      }
      var clockSyncEvent = {
          ph: 'c',
          args: {
            sync_id: syncId,
            issue_ts: this.asyncClockSyncStart_.ts
          },
          ts: this.asyncClockSyncFinish_.ts,
      };
      this.asyncClockSyncStart_ = undefined;
      this.asyncClockSyncFinish_ = undefined;
      return clockSyncEvent;
    },

    importClockSyncMarkers: function() {
      var asyncClockSyncStart, asyncClockSyncFinish;
      for (var i = 0; i < this.events_.length; i++) {
        var event = this.events_[i];

        var possibleBackCompatClockSyncEvent =
            this.initBackcompatClockSyncEventTracker_(event);
        if (possibleBackCompatClockSyncEvent)
            this.processClockSyncEvent(possibleBackCompatClockSyncEvent);

        if (event.ph !== 'c')
          continue;

        var eventSizeInBytes =
            this.model_.importOptions.trackDetailedModelStats ?
                JSON.stringify(event).length : undefined;

        this.model_.stats.willProcessBasicTraceEvent(
            'clock_sync', event.cat, event.name, event.ts, eventSizeInBytes);
        this.processClockSyncEvent(event);
      }
    },

    /**
     * Walks through the events_ list and outputs the structures discovered to
     * model_.
     */
    importEvents: function() {
      if (this.stackFrameEvents_)
        this.importStackFrames_(this.stackFrameEvents_, 'g');

      if (this.traceAnnotations_)
        this.importAnnotations_();

      var importOptions = this.model_.importOptions;
      var trackDetailedModelStats = importOptions.trackDetailedModelStats;

      var modelStats = this.model_.stats;

      var events = this.events_;
      for (var eI = 0; eI < events.length; eI++) {
        var event = events[eI];

        if (event.args === '__stripped__') {
          event.argsStripped = true;
          event.args = undefined;
        }

        var eventSizeInBytes;
        if (trackDetailedModelStats)
          eventSizeInBytes = JSON.stringify(event).length;
        else
          eventSizeInBytes = undefined;

        if (event.ph === 'B' || event.ph === 'E') {
          modelStats.willProcessBasicTraceEvent(
              'begin_end (non-compact)', event.cat, event.name, event.ts,
              eventSizeInBytes);
          this.processDurationEvent(event);

        } else if (event.ph === 'X') {
          modelStats.willProcessBasicTraceEvent(
              'begin_end (compact)', event.cat, event.name, event.ts,
              eventSizeInBytes);
          var slice = this.processCompleteEvent(event);
          // TODO(yuhaoz): If Chrome supports creating other events with flow,
          // we will need to call processFlowEvent for them also.
          // https://github.com/catapult-project/catapult/issues/1259
          if (slice !== undefined && event.bind_id !== undefined)
            this.processFlowEvent(event, slice);

        } else if (event.ph === 'b' || event.ph === 'e' || event.ph === 'n' ||
                   event.ph === 'S' || event.ph === 'F' || event.ph === 'T' ||
                   event.ph === 'p') {
          modelStats.willProcessBasicTraceEvent(
              'async', event.cat, event.name, event.ts, eventSizeInBytes);
          this.processAsyncEvent(event);

        // Note, I is historic. The instant event marker got changed, but we
        // want to support loading old trace files so we have both I and i.
        } else if (event.ph === 'I' || event.ph === 'i' || event.ph === 'R') {
          modelStats.willProcessBasicTraceEvent(
              'instant', event.cat, event.name, event.ts, eventSizeInBytes);
          this.processInstantEvent(event);

        } else if (event.ph === 'P') {
          modelStats.willProcessBasicTraceEvent(
              'samples', event.cat, event.name, event.ts, eventSizeInBytes);
          this.processTraceSampleEvent(event);
        } else if (event.ph === 'C') {
          modelStats.willProcessBasicTraceEvent(
              'counters', event.cat, event.name, event.ts, eventSizeInBytes);
          this.processCounterEvent(event);
        } else if (event.ph === 'M') {
          modelStats.willProcessBasicTraceEvent(
              'metadata', event.cat, event.name, event.ts, eventSizeInBytes);
          this.processMetadataEvent(event);

        } else if (event.ph === 'N' || event.ph === 'D' || event.ph === 'O') {
          modelStats.willProcessBasicTraceEvent(
              'objects', event.cat, event.name, event.ts, eventSizeInBytes);
          this.processObjectEvent(event);

        } else if (event.ph === 's' || event.ph === 't' || event.ph === 'f') {
          modelStats.willProcessBasicTraceEvent(
              'flows', event.cat, event.name, event.ts, eventSizeInBytes);
          this.processFlowEvent(event);

        } else if (event.ph === 'v') {
          modelStats.willProcessBasicTraceEvent(
              'memory_dumps', event.cat, event.name, event.ts,
              eventSizeInBytes);
          this.processMemoryDumpEvent(event);

        } else if (event.ph === '(' || event.ph === ')') {
          this.processContextEvent(event);
        } else if (event.ph === 'c') {
          // No-op. Clock sync events have already been processed in
          // importClockSyncMarkers().
        } else {
          modelStats.willProcessBasicTraceEvent(
              'unknown', event.cat, event.name, event.ts, eventSizeInBytes);
          this.model_.importWarning({
            type: 'parse_error',
            message: 'Unrecognized event phase: ' +
                event.ph + ' (' + event.name + ')'
          });
        }
      }
      this.processV8Events();

      // Remove all the root stack frame children as they should
      // already be added.
      tr.b.iterItems(this.v8ProcessRootStackFrame_, function(name, frame) {
        frame.removeAllChildren();
      });
    },

    importStackFrames_: function(rawStackFrames, idPrefix) {
      var model = this.model_;

      for (var id in rawStackFrames) {
        var rawStackFrame = rawStackFrames[id];
        var fullId = idPrefix + id;
        var textForColor = rawStackFrame.category ?
            rawStackFrame.category : rawStackFrame.name;
        var stackFrame = new tr.model.StackFrame(
            undefined /* parentFrame */, fullId, rawStackFrame.name,
            ColorScheme.getColorIdForGeneralPurposeString(textForColor));
        model.addStackFrame(stackFrame);
      }

      for (var id in rawStackFrames) {
        var fullId = idPrefix + id;
        var stackFrame = model.stackFrames[fullId];
        if (stackFrame === undefined)
          throw new Error('Internal error');

        var rawStackFrame = rawStackFrames[id];
        var parentId = rawStackFrame.parent;
        var parentStackFrame;
        if (parentId === undefined) {
          parentStackFrame = undefined;
        } else {
          var parentFullId = idPrefix + parentId;
          parentStackFrame = model.stackFrames[parentFullId];
          if (parentStackFrame === undefined) {
            this.model_.importWarning({
              type: 'metadata_parse_error',
              message: 'Missing parent frame with ID ' + parentFullId +
                  ' for stack frame \'' + stackFrame.name + '\' (ID ' + fullId +
                  ').'
            });
          }
        }
        stackFrame.parentFrame = parentStackFrame;
      }
    },

    importObjectTypeNameMap_: function(rawObjectTypeNameMap, pid) {
      if (pid in this.objectTypeNameMap_) {
        this.model_.importWarning({
          type: 'metadata_parse_error',
          message: 'Mapping from object type IDs to names provided for pid=' +
              pid + ' multiple times.'
        });
        return;
      }

      var objectTypeNamePrefix = undefined;
      var objectTypeNameSuffix = undefined;
      var objectTypeNameMap = {};
      for (var objectTypeId in rawObjectTypeNameMap) {
        var rawObjectTypeName = rawObjectTypeNameMap[objectTypeId];

        // If we haven't figured out yet which compiler the object type names
        // come from, we try to do it now.
        if (objectTypeNamePrefix === undefined) {
          for (var i = 0; i < OBJECT_TYPE_NAME_PATTERNS.length; i++) {
            var pattern = OBJECT_TYPE_NAME_PATTERNS[i];
            if (rawObjectTypeName.startsWith(pattern.prefix) &&
                rawObjectTypeName.endsWith(pattern.suffix)) {
              objectTypeNamePrefix = pattern.prefix;
              objectTypeNameSuffix = pattern.suffix;
              break;
            }
          }
        }

        if (objectTypeNamePrefix !== undefined &&
            rawObjectTypeName.startsWith(objectTypeNamePrefix) &&
            rawObjectTypeName.endsWith(objectTypeNameSuffix)) {
          // With compiler-specific prefix and suffix (automatically annotated
          // object types).
          objectTypeNameMap[objectTypeId] = rawObjectTypeName.substring(
               objectTypeNamePrefix.length,
               rawObjectTypeName.length - objectTypeNameSuffix.length);
        } else {
          // Without compiler-specific prefix and suffix (manually annotated
          // object types and '[unknown]').
          objectTypeNameMap[objectTypeId] = rawObjectTypeName;
        }
      }

      this.objectTypeNameMap_[pid] = objectTypeNameMap;
    },

    importAnnotations_: function() {
      for (var id in this.traceAnnotations_) {
        var annotation = tr.model.Annotation.fromDictIfPossible(
           this.traceAnnotations_[id]);
        if (!annotation) {
          this.model_.importWarning({
            type: 'annotation_warning',
            message: 'Unrecognized traceAnnotation typeName \"' +
                this.traceAnnotations_[id].typeName + '\"'
          });
          continue;
        }
        this.model_.addAnnotation(annotation);
      }
    },

    /**
     * Called by the Model after all other importers have imported their
     * events.
     */
    finalizeImport: function() {
      if (this.softwareMeasuredCpuCount_ !== undefined) {
        this.model_.kernel.softwareMeasuredCpuCount =
            this.softwareMeasuredCpuCount_;
      }
      this.createAsyncSlices_();
      this.createFlowSlices_();
      this.createExplicitObjects_();
      this.createImplicitObjects_();
      this.createMemoryDumps_();
    },

    /* Events can have one or more stack frames associated with them, but
     * that frame might be encoded either as a stack trace of program counters,
     * or as a direct stack frame reference. This handles either case and
     * if found, returns the stackframe.
     */
    getStackFrameForEvent_: function(event, opt_lookForEndEvent) {
      var sf;
      var stack;
      if (opt_lookForEndEvent) {
        sf = event.esf;
        stack = event.estack;
      } else {
        sf = event.sf;
        stack = event.stack;
      }
      if (stack !== undefined && sf !== undefined) {
        this.model_.importWarning({
          type: 'stack_frame_and_stack_error',
          message: 'Event at ' + event.ts +
              ' cannot have both a stack and a stackframe.'
        });
        return undefined;
      }

      if (stack !== undefined)
        return this.model_.resolveStackToStackFrame_(event.pid, stack);
      if (sf === undefined)
        return undefined;

      var stackFrame = this.model_.stackFrames['g' + sf];
      if (stackFrame === undefined) {
        this.model_.importWarning({
          type: 'sample_import_error',
          message: 'No frame for ' + sf
        });
        return;
      }
      return stackFrame;
    },

    resolveStackToStackFrame_: function(pid, stack) {
      // TODO(alph,fmeawad): Add codemap resolution code here.
      return undefined;
    },

    importSampleData: function() {
      if (!this.sampleEvents_)
        return;
      var m = this.model_;

      // If this is the only importer, then fake-create the threads.
      var events = this.sampleEvents_;
      if (this.events_.length === 0) {
        for (var i = 0; i < events.length; i++) {
          var event = events[i];
          m.getOrCreateProcess(event.tid).getOrCreateThread(event.tid);
        }
      }

      var threadsByTid = {};
      m.getAllThreads().forEach(function(t) {
        threadsByTid[t.tid] = t;
      });

      for (var i = 0; i < events.length; i++) {
        var event = events[i];
        var thread = threadsByTid[event.tid];
        if (thread === undefined) {
          m.importWarning({
            type: 'sample_import_error',
            message: 'Thread ' + events.tid + 'not found'
          });
          continue;
        }

        var cpu;
        if (event.cpu !== undefined)
          cpu = m.kernel.getOrCreateCpu(event.cpu);

        var stackFrame = this.getStackFrameForEvent_(event);

        var sample = new tr.model.Sample(
            cpu, thread,
            event.name,
            this.toModelTimeFromUs_(event.ts),
            stackFrame,
            event.weight);
        m.samples.push(sample);
      }
    },

    createAsyncSlices_: function() {
      if (this.allAsyncEvents_.length === 0)
        return;

      this.allAsyncEvents_.sort(function(x, y) {
        var d = x.event.ts - y.event.ts;
        if (d !== 0)
          return d;
        return x.sequenceNumber - y.sequenceNumber;
      });

      var legacyEvents = [];
      // Group nestable async events by ID. Events with the same ID should
      // belong to the same parent async event.
      var nestableAsyncEventsByKey = {};
      var nestableMeasureAsyncEventsByKey = {};
      for (var i = 0; i < this.allAsyncEvents_.length; i++) {
        var asyncEventState = this.allAsyncEvents_[i];
        var event = asyncEventState.event;
        if (event.ph === 'S' || event.ph === 'F' || event.ph === 'T' ||
            event.ph === 'p') {
          legacyEvents.push(asyncEventState);
          continue;
        }
        if (event.cat === undefined) {
          this.model_.importWarning({
            type: 'async_slice_parse_error',
            message: 'Nestable async events (ph: b, e, or n) require a ' +
                'cat parameter.'
          });
          continue;
        }

        if (event.name === undefined) {
          this.model_.importWarning({
            type: 'async_slice_parse_error',
            message: 'Nestable async events (ph: b, e, or n) require a ' +
                'name parameter.'
          });
          continue;
        }

        if (event.id === undefined) {
          this.model_.importWarning({
            type: 'async_slice_parse_error',
            message: 'Nestable async events (ph: b, e, or n) require an ' +
                'id parameter.'
          });
          continue;
        }

        if (event.cat === 'blink.user_timing') {
          var matched = /([^\/:]+):([^\/:]+)\/?(.*)/.exec(event.name);
          if (matched !== null) {
            var key = matched[1] + ':' + event.cat;
            event.args = JSON.parse(Base64.atob(matched[3]) || '{}');
            if (nestableMeasureAsyncEventsByKey[key] === undefined)
              nestableMeasureAsyncEventsByKey[key] = [];
            nestableMeasureAsyncEventsByKey[key].push(asyncEventState);
            continue;
          }
        }

        var key = event.cat + ':' + event.id;
        if (nestableAsyncEventsByKey[key] === undefined)
           nestableAsyncEventsByKey[key] = [];
        nestableAsyncEventsByKey[key].push(asyncEventState);
      }
      // Handle legacy async events.
      this.createLegacyAsyncSlices_(legacyEvents);

      // Parse nestable measure async events into AsyncSlices.
      this.createNestableAsyncSlices_(nestableMeasureAsyncEventsByKey);

      // Parse nestable async events into AsyncSlices.
      this.createNestableAsyncSlices_(nestableAsyncEventsByKey);
    },

    createLegacyAsyncSlices_: function(legacyEvents) {
      if (legacyEvents.length === 0)
        return;

      legacyEvents.sort(function(x, y) {
        var d = x.event.ts - y.event.ts;
        if (d != 0)
          return d;
        return x.sequenceNumber - y.sequenceNumber;
      });

      var asyncEventStatesByNameThenID = {};

      for (var i = 0; i < legacyEvents.length; i++) {
        var asyncEventState = legacyEvents[i];

        var event = asyncEventState.event;
        var name = event.name;
        if (name === undefined) {
          this.model_.importWarning({
            type: 'async_slice_parse_error',
            message: 'Async events (ph: S, T, p, or F) require a name ' +
                ' parameter.'
          });
          continue;
        }

        var id = event.id;
        if (id === undefined) {
          this.model_.importWarning({
            type: 'async_slice_parse_error',
            message: 'Async events (ph: S, T, p, or F) require an id parameter.'
          });
          continue;
        }

        // TODO(simonjam): Add a synchronous tick on the appropriate thread.

        if (event.ph === 'S') {
          if (asyncEventStatesByNameThenID[name] === undefined)
            asyncEventStatesByNameThenID[name] = {};
          if (asyncEventStatesByNameThenID[name][id]) {
            this.model_.importWarning({
              type: 'async_slice_parse_error',
              message: 'At ' + event.ts + ', a slice of the same id ' + id +
                  ' was alrady open.'
            });
            continue;
          }
          asyncEventStatesByNameThenID[name][id] = [];
          asyncEventStatesByNameThenID[name][id].push(asyncEventState);
        } else {
          if (asyncEventStatesByNameThenID[name] === undefined) {
            this.model_.importWarning({
              type: 'async_slice_parse_error',
              message: 'At ' + event.ts + ', no slice named ' + name +
                  ' was open.'
            });
            continue;
          }
          if (asyncEventStatesByNameThenID[name][id] === undefined) {
            this.model_.importWarning({
              type: 'async_slice_parse_error',
              message: 'At ' + event.ts + ', no slice named ' + name +
                  ' with id=' + id + ' was open.'
            });
            continue;
          }
          var events = asyncEventStatesByNameThenID[name][id];
          events.push(asyncEventState);

          if (event.ph === 'F') {
            // Create a slice from start to end.
            var asyncSliceConstructor =
               tr.model.AsyncSlice.subTypes.getConstructor(
                  events[0].event.cat,
                  name);
            var slice = new asyncSliceConstructor(
                events[0].event.cat,
                name,
                getEventColor(events[0].event),
                this.toModelTimeFromUs_(events[0].event.ts),
                tr.b.concatenateObjects(events[0].event.args,
                                      events[events.length - 1].event.args),
                this.toModelTimeFromUs_(event.ts - events[0].event.ts),
                true, undefined, undefined, events[0].event.argsStripped);
            slice.startThread = events[0].thread;
            slice.endThread = asyncEventState.thread;
            slice.id = id;

            var stepType = events[1].event.ph;
            var isValid = true;

            // Create subSlices for each step. Skip the start and finish events,
            // which are always first and last respectively.
            for (var j = 1; j < events.length - 1; ++j) {
              if (events[j].event.ph === 'T' || events[j].event.ph === 'p') {
                isValid = this.assertStepTypeMatches_(stepType, events[j]);
                if (!isValid)
                  break;
              }

              if (events[j].event.ph === 'S') {
                this.model_.importWarning({
                  type: 'async_slice_parse_error',
                  message: 'At ' + event.event.ts + ', a slice named ' +
                      event.event.name + ' with id=' + event.event.id +
                      ' had a step before the start event.'
                });
                continue;
              }

              if (events[j].event.ph === 'F') {
                this.model_.importWarning({
                  type: 'async_slice_parse_error',
                  message: 'At ' + event.event.ts + ', a slice named ' +
                      event.event.name + ' with id=' + event.event.id +
                      ' had a step after the finish event.'
                });
                continue;
              }

              var startIndex = j + (stepType === 'T' ? 0 : -1);
              var endIndex = startIndex + 1;

              var subName = events[j].event.name;
              if (!events[j].event.argsStripped &&
                  (events[j].event.ph === 'T' || events[j].event.ph === 'p'))
                subName = subName + ':' + events[j].event.args.step;

              var asyncSliceConstructor =
                 tr.model.AsyncSlice.subTypes.getConstructor(
                    events[0].event.cat,
                    subName);
              var subSlice = new asyncSliceConstructor(
                  events[0].event.cat,
                  subName,
                  getEventColor(event, subName + j),
                  this.toModelTimeFromUs_(events[startIndex].event.ts),
                  this.deepCopyIfNeeded_(events[j].event.args),
                  this.toModelTimeFromUs_(
                    events[endIndex].event.ts - events[startIndex].event.ts),
                      undefined, undefined,
                      events[startIndex].event.argsStripped);
              subSlice.startThread = events[startIndex].thread;
              subSlice.endThread = events[endIndex].thread;
              subSlice.id = id;

              slice.subSlices.push(subSlice);
            }

            if (isValid) {
              // Add |slice| to the start-thread's asyncSlices.
              slice.startThread.asyncSliceGroup.push(slice);
            }

            delete asyncEventStatesByNameThenID[name][id];
          }
        }
      }
    },

    createNestableAsyncSlices_: function(nestableEventsByKey) {
      for (var key in nestableEventsByKey) {
        var eventStateEntries = nestableEventsByKey[key];
        // Stack of enclosing BEGIN events.
        var parentStack = [];
        for (var i = 0; i < eventStateEntries.length; ++i) {
          var eventStateEntry = eventStateEntries[i];
          // If this is the end of an event, match it to the start.
          if (eventStateEntry.event.ph === 'e') {
            // Walk up the parent stack to find the corresponding BEGIN for
            // this END.
            var parentIndex = -1;
            for (var k = parentStack.length - 1; k >= 0; --k) {
              if (parentStack[k].event.name === eventStateEntry.event.name) {
                parentIndex = k;
                break;
              }
            }
            if (parentIndex === -1) {
              // Unmatched end.
              eventStateEntry.finished = false;
            } else {
              parentStack[parentIndex].end = eventStateEntry;
              // Pop off all enclosing unmatched BEGINs util parentIndex.
              while (parentIndex < parentStack.length) {
                parentStack.pop();
              }
            }
          }
          // Inherit the current parent.
          if (parentStack.length > 0)
            eventStateEntry.parentEntry = parentStack[parentStack.length - 1];
          if (eventStateEntry.event.ph === 'b') {
            parentStack.push(eventStateEntry);
          }
        }
        var topLevelSlices = [];
        for (var i = 0; i < eventStateEntries.length; ++i) {
          var eventStateEntry = eventStateEntries[i];
          // Skip matched END, as its slice will be created when we
          // encounter its corresponding BEGIN.
          if (eventStateEntry.event.ph === 'e' &&
              eventStateEntry.finished === undefined) {
            continue;
          }
          var startState = undefined;
          var endState = undefined;
          var sliceArgs = eventStateEntry.event.args || {};
          var sliceError = undefined;
          if (eventStateEntry.event.ph === 'n') {
            startState = eventStateEntry;
            endState = eventStateEntry;
          } else if (eventStateEntry.event.ph === 'b') {
            if (eventStateEntry.end === undefined) {
              // Unmatched BEGIN. End it when last event with this ID ends.
              eventStateEntry.end =
                eventStateEntries[eventStateEntries.length - 1];
              sliceError =
                'Slice has no matching END. End time has been adjusted.';
              this.model_.importWarning({
                type: 'async_slice_parse_error',
                message: 'Nestable async BEGIN event at ' +
                  eventStateEntry.event.ts + ' with name=' +
                  eventStateEntry.event.name +
                  ' and id=' + eventStateEntry.event.id + ' was unmatched.'
              });
            } else {
              // Include args for both END and BEGIN for a matched pair.
              function concatenateArguments(args1, args2) {
                if (args1.params === undefined || args2.params === undefined)
                  return tr.b.concatenateObjects(args1, args2);
                // Make an argument object to hold the combined params.
                var args3 = {};
                args3.params = tr.b.concatenateObjects(args1.params,
                                                       args2.params);
                return tr.b.concatenateObjects(args1, args2, args3);
              }
              var endArgs = eventStateEntry.end.event.args || {};
              sliceArgs = concatenateArguments(sliceArgs, endArgs);
            }
            startState = eventStateEntry;
            endState = eventStateEntry.end;
          } else {
            // Unmatched END. Start it at the first event with this ID starts.
            sliceError =
              'Slice has no matching BEGIN. Start time has been adjusted.';
            this.model_.importWarning({
              type: 'async_slice_parse_error',
              message: 'Nestable async END event at ' +
                eventStateEntry.event.ts + ' with name=' +
                eventStateEntry.event.name +
                ' and id=' + eventStateEntry.event.id + ' was unmatched.'
            });
            startState = eventStateEntries[0];
            endState = eventStateEntry;
          }

          var isTopLevel = (eventStateEntry.parentEntry === undefined);
          var asyncSliceConstructor =
              tr.model.AsyncSlice.subTypes.getConstructor(
                eventStateEntry.event.cat,
                eventStateEntry.event.name);

          var thread_start = undefined;
          var thread_duration = undefined;
          if (startState.event.tts && startState.event.use_async_tts) {
            thread_start = this.toModelTimeFromUs_(startState.event.tts);
            if (endState.event.tts) {
              var thread_end = this.toModelTimeFromUs_(endState.event.tts);
              thread_duration = thread_end - thread_start;
            }
          }

          var slice = new asyncSliceConstructor(
            eventStateEntry.event.cat,
            eventStateEntry.event.name,
            getEventColor(endState.event),
            this.toModelTimeFromUs_(startState.event.ts),
            sliceArgs,
            this.toModelTimeFromUs_(endState.event.ts - startState.event.ts),
            isTopLevel,
            thread_start,
            thread_duration,
            startState.event.argsStripped);

          slice.startThread = startState.thread;
          slice.endThread = endState.thread;

          slice.startStackFrame = this.getStackFrameForEvent_(startState.event);
          slice.endStackFrame = this.getStackFrameForEvent_(endState.event);

          slice.id = key;
          if (sliceError !== undefined)
            slice.error = sliceError;
          eventStateEntry.slice = slice;
          // Add the slice to the topLevelSlices array if there is no parent.
          // Otherwise, add the slice to the subSlices of its parent.
          if (isTopLevel) {
            topLevelSlices.push(slice);
          } else if (eventStateEntry.parentEntry.slice !== undefined) {
            eventStateEntry.parentEntry.slice.subSlices.push(slice);
          }
        }
        for (var si = 0; si < topLevelSlices.length; si++) {
          topLevelSlices[si].startThread.asyncSliceGroup.push(
            topLevelSlices[si]);
        }
      }
    },

    assertStepTypeMatches_: function(stepType, event) {
      if (stepType != event.event.ph) {
        this.model_.importWarning({
          type: 'async_slice_parse_error',
          message: 'At ' + event.event.ts + ', a slice named ' +
              event.event.name + ' with id=' + event.event.id +
              ' had both begin and end steps, which is not allowed.'
        });
        return false;
      }
      return true;
    },

    createFlowSlices_: function() {
      if (this.allFlowEvents_.length === 0)
        return;

      var that = this;

      function validateFlowEvent() {
        if (event.name === undefined) {
          that.model_.importWarning({
            type: 'flow_slice_parse_error',
            message: 'Flow events (ph: s, t or f) require a name parameter.'
          });
          return false;
        }

        // Support Flow API v1.
        if (event.ph === 's' || event.ph === 'f' || event.ph === 't') {
          if (event.id === undefined) {
            that.model_.importWarning({
              type: 'flow_slice_parse_error',
              message: 'Flow events (ph: s, t or f) require an id parameter.'
            });
            return false;
          }
          return true;
        }

        // Support Flow API v2.
        if (event.bind_id) {
          if (event.flow_in === undefined && event.flow_out === undefined) {
            that.model_.importWarning({
              type: 'flow_slice_parse_error',
              message: 'Flow producer or consumer require flow_in or flow_out.'
            });
            return false;
          }
          return true;
        }

        return false;
      }

      var createFlowEvent = function(thread, event, opt_slice) {
        var startSlice, flowId, flowStartTs;

        if (event.bind_id) {
          // Support Flow API v2.
          startSlice = opt_slice;
          flowId = event.bind_id;
          flowStartTs = this.toModelTimeFromUs_(event.ts + event.dur);
        } else {
          // Support Flow API v1.
          var ts = this.toModelTimeFromUs_(event.ts);
          startSlice = thread.sliceGroup.findSliceAtTs(ts);
          if (startSlice === undefined)
            return undefined;
          flowId = event.id;
          flowStartTs = ts;
        }

        var flowEvent = new tr.model.FlowEvent(
            event.cat,
            flowId,
            event.name,
            getEventColor(event),
            flowStartTs,
            that.deepCopyAlways_(event.args));
        flowEvent.startSlice = startSlice;
        flowEvent.startStackFrame = that.getStackFrameForEvent_(event);
        flowEvent.endStackFrame = undefined;
        startSlice.outFlowEvents.push(flowEvent);
        return flowEvent;
      }.bind(this);

      var finishFlowEventWith = function(
          flowEvent, thread, event, refGuid, bindToParent, opt_slice) {
        var endSlice;

        if (event.bind_id) {
          // Support Flow API v2.
          endSlice = opt_slice;
        } else {
          // Support Flow API v1.
          var ts = this.toModelTimeFromUs_(event.ts);
          if (bindToParent) {
            endSlice = thread.sliceGroup.findSliceAtTs(ts);
          } else {
            endSlice = thread.sliceGroup.findNextSliceAfter(ts, refGuid);
          }
          if (endSlice === undefined)
            return false;
        }

        endSlice.inFlowEvents.push(flowEvent);
        flowEvent.endSlice = endSlice;
        flowEvent.duration =
            this.toModelTimeFromUs_(event.ts) - flowEvent.start;
        flowEvent.endStackFrame = that.getStackFrameForEvent_(event);
        that.mergeArgsInto_(flowEvent.args, event.args, flowEvent.title);
        return true;
      }.bind(this);

      function processFlowConsumer(
          flowIdToEvent, sliceGuidToEvent, event, slice) {
        var flowEvent = flowIdToEvent[event.bind_id];
        if (flowEvent === undefined) {
          that.model_.importWarning({
              type: 'flow_slice_ordering_error',
              message: 'Flow consumer ' + event.bind_id + ' does not have ' +
                  'a flow producer'});
          return false;
        } else if (flowEvent.endSlice) {
          // One flow producer can have more than one flow consumers.
          // In this case, create a new flow event using the flow producer.
          var flowProducer = flowEvent.startSlice;
          flowEvent = createFlowEvent(undefined,
              sliceGuidToEvent[flowProducer.guid], flowProducer);
        }

        var ok = finishFlowEventWith(flowEvent, undefined, event,
                                     refGuid, undefined, slice);
        if (ok) {
          that.model_.flowEvents.push(flowEvent);
        } else {
          that.model_.importWarning({
              type: 'flow_slice_end_error',
              message: 'Flow consumer ' + event.bind_id + ' does not end ' +
                  'at an actual slice, so cannot be created.'});
          return false;
        }

        return true;
      }

      function processFlowProducer(flowIdToEvent, flowStatus, event, slice) {
        if (flowIdToEvent[event.bind_id] &&
            flowStatus[event.bind_id]) {
          // Can't open the same flow again while it's still open.
          // This is essentially the multi-producer case which we don't support
          that.model_.importWarning({
              type: 'flow_slice_start_error',
              message: 'Flow producer ' + event.bind_id + ' already seen'});
          return false;
        }

        var flowEvent = createFlowEvent(undefined, event, slice);
        if (!flowEvent) {
          that.model_.importWarning({
              type: 'flow_slice_start_error',
              message: 'Flow producer ' + event.bind_id + ' does not start' +
                  'a flow'});
          return false;
        }
        flowIdToEvent[event.bind_id] = flowEvent;
      }

      // Actual import.
      this.allFlowEvents_.sort(function(x, y) {
        var d = x.event.ts - y.event.ts;
        if (d != 0)
          return d;
        return x.sequenceNumber - y.sequenceNumber;
      });

      var flowIdToEvent = {};
      var sliceGuidToEvent = {};
      var flowStatus = {}; // true: open; false: closed.
      for (var i = 0; i < this.allFlowEvents_.length; ++i) {
        var data = this.allFlowEvents_[i];
        var refGuid = data.refGuid;
        var event = data.event;
        var thread = data.thread;
        if (!validateFlowEvent(event))
          continue;

        // Support for Flow API v2.
        if (event.bind_id) {
          var slice = data.slice;
          sliceGuidToEvent[slice.guid] = event;

          if (event.flowPhase === PRODUCER) {
            if (!processFlowProducer(flowIdToEvent, flowStatus, event, slice))
              continue;
            flowStatus[event.bind_id] = true; // open the flow.
          }
          else {
            if (!processFlowConsumer(flowIdToEvent, sliceGuidToEvent,
                event, slice))
              continue;
            flowStatus[event.bind_id] = false; // close the flow.

            if (event.flowPhase === STEP) {
              if (!processFlowProducer(flowIdToEvent, flowStatus,
                  event, slice))
                continue;
              flowStatus[event.bind_id] = true; // open the flow again.
            }
          }
          continue;
        }

        // Support for Flow API v1.
        var flowEvent;
        if (event.ph === 's') {
          if (flowIdToEvent[event.id]) {
            this.model_.importWarning({
              type: 'flow_slice_start_error',
              message: 'event id ' + event.id + ' already seen when ' +
                  'encountering start of flow event.'});
            continue;
          }
          flowEvent = createFlowEvent(thread, event);
          if (!flowEvent) {
            this.model_.importWarning({
              type: 'flow_slice_start_error',
              message: 'event id ' + event.id + ' does not start ' +
                  'at an actual slice, so cannot be created.'});
            continue;
          }
          flowIdToEvent[event.id] = flowEvent;

        } else if (event.ph === 't' || event.ph === 'f') {
          flowEvent = flowIdToEvent[event.id];
          if (flowEvent === undefined) {
            this.model_.importWarning({
              type: 'flow_slice_ordering_error',
              message: 'Found flow phase ' + event.ph + ' for id: ' + event.id +
                  ' but no flow start found.'
            });
            continue;
          }

          var bindToParent = event.ph === 't';

          if (event.ph === 'f') {
            if (event.bp === undefined) {
              // TODO(yuhaoz): In flow V2, there is no notion of binding point.
              // Removal of binding point is tracked in
              // https://github.com/google/trace-viewer/issues/991.
              if (event.cat.indexOf('input') > -1)
                bindToParent = true;
              else if (event.cat.indexOf('ipc.flow') > -1)
                bindToParent = true;
            } else {
              if (event.bp !== 'e') {
                this.model_.importWarning({
                 type: 'flow_slice_bind_point_error',
                 message: 'Flow event with invalid binding point (event.bp).'
                });
                continue;
              }
              bindToParent = true;
            }
          }

          var ok = finishFlowEventWith(flowEvent, thread, event,
                                       refGuid, bindToParent);
          if (ok) {
            that.model_.flowEvents.push(flowEvent);
          } else {
            this.model_.importWarning({
              type: 'flow_slice_end_error',
              message: 'event id ' + event.id + ' does not end ' +
                  'at an actual slice, so cannot be created.'});
          }
          flowIdToEvent[event.id] = undefined;

          // If this is a step, then create another flow event.
          if (ok && event.ph === 't') {
            flowEvent = createFlowEvent(thread, event);
            flowIdToEvent[event.id] = flowEvent;
          }
        }
      }
    },

    /**
     * This function creates objects described via the N, D, and O phase
     * events.
     */
    createExplicitObjects_: function() {
      if (this.allObjectEvents_.length === 0)
        return;

      var processEvent = function(objectEventState) {
        var event = objectEventState.event;
        var scopedId = this.scopedIdForEvent_(event);
        var thread = objectEventState.thread;
        if (event.name === undefined) {
          this.model_.importWarning({
            type: 'object_parse_error',
            message: 'While processing ' + JSON.stringify(event) + ': ' +
                'Object events require an name parameter.'
          });
        }

        if (scopedId.id === undefined) {
          this.model_.importWarning({
            type: 'object_parse_error',
            message: 'While processing ' + JSON.stringify(event) + ': ' +
                'Object events require an id parameter.'
          });
        }
        var process = thread.parent;
        var ts = this.toModelTimeFromUs_(event.ts);
        var instance;
        if (event.ph === 'N') {
          try {
            instance = process.objects.idWasCreated(
                scopedId, event.cat, event.name, ts);
          } catch (e) {
            this.model_.importWarning({
              type: 'object_parse_error',
              message: 'While processing create of ' +
                  scopedId + ' at ts=' + ts + ': ' + e
            });
            return;
          }
        } else if (event.ph === 'O') {
          if (event.args.snapshot === undefined) {
            this.model_.importWarning({
              type: 'object_parse_error',
              message: 'While processing ' + scopedId + ' at ts=' + ts + ': ' +
                  'Snapshots must have args: {snapshot: ...}'
            });
            return;
          }
          var snapshot;
          try {
            var args = this.deepCopyIfNeeded_(event.args.snapshot);
            var cat;
            if (args.cat) {
              cat = args.cat;
              delete args.cat;
            } else {
              cat = event.cat;
            }

            var baseTypename;
            if (args.base_type) {
              baseTypename = args.base_type;
              delete args.base_type;
            } else {
              baseTypename = undefined;
            }
            snapshot = process.objects.addSnapshot(
                scopedId, cat, event.name, ts, args, baseTypename);
            snapshot.snapshottedOnThread = thread;
          } catch (e) {
            this.model_.importWarning({
              type: 'object_parse_error',
              message: 'While processing snapshot of ' +
                  scopedId + ' at ts=' + ts + ': ' + e
            });
            return;
          }
          instance = snapshot.objectInstance;
        } else if (event.ph === 'D') {
          try {
            process.objects.idWasDeleted(scopedId, event.cat, event.name, ts);
            var instanceMap = process.objects.getOrCreateInstanceMap_(scopedId);
            instance = instanceMap.lastInstance;
          } catch (e) {
            this.model_.importWarning({
              type: 'object_parse_error',
              message: 'While processing delete of ' +
                  scopedId + ' at ts=' + ts + ': ' + e
            });
            return;
          }
        }

        if (instance)
          instance.colorId = getEventColor(event, instance.typeName);
      }.bind(this);

      this.allObjectEvents_.sort(function(x, y) {
        var d = x.event.ts - y.event.ts;
        if (d != 0)
          return d;
        return x.sequenceNumber - y.sequenceNumber;
      });

      var allObjectEvents = this.allObjectEvents_;
      for (var i = 0; i < allObjectEvents.length; i++) {
        var objectEventState = allObjectEvents[i];
        try {
          processEvent.call(this, objectEventState);
        } catch (e) {
          this.model_.importWarning({
            type: 'object_parse_error',
            message: e.message
          });
        }
      }
    },

    createImplicitObjects_: function() {
      tr.b.iterItems(this.model_.processes, function(pid, process) {
        this.createImplicitObjectsForProcess_(process);
      }, this);
    },

    // Here, we collect all the snapshots that internally contain a
    // Javascript-level object inside their args list that has an "id" field,
    // and turn that into a snapshot of the instance referred to by id.
    createImplicitObjectsForProcess_: function(process) {

      function processField(referencingObject,
                            referencingObjectFieldName,
                            referencingObjectFieldValue,
                            containingSnapshot) {
        if (!referencingObjectFieldValue)
          return;

        if (referencingObjectFieldValue instanceof
            tr.model.ObjectSnapshot)
          return null;
        if (referencingObjectFieldValue.id === undefined)
          return;

        var implicitSnapshot = referencingObjectFieldValue;

        var rawId = implicitSnapshot.id;
        var m = /(.+)\/(.+)/.exec(rawId);
        if (!m)
          throw new Error('Implicit snapshots must have names.');
        delete implicitSnapshot.id;
        var name = m[1];
        var id = m[2];
        var res;

        var cat;
        if (implicitSnapshot.cat !== undefined)
          cat = implicitSnapshot.cat;
        else
          cat = containingSnapshot.objectInstance.category;

        var baseTypename;
        if (implicitSnapshot.base_type)
          baseTypename = implicitSnapshot.base_type;
        else
          baseTypename = undefined;

        var scope = containingSnapshot.objectInstance.scopedId.scope;

        try {
          res = process.objects.addSnapshot(
              new tr.model.ScopedId(scope, id), cat,
              name, containingSnapshot.ts,
              implicitSnapshot, baseTypename);
        } catch (e) {
          this.model_.importWarning({
            type: 'object_snapshot_parse_error',
            message: 'While processing implicit snapshot of ' +
                rawId + ' at ts=' + containingSnapshot.ts + ': ' + e
          });
          return;
        }
        res.objectInstance.hasImplicitSnapshots = true;
        res.containingSnapshot = containingSnapshot;
        res.snapshottedOnThread = containingSnapshot.snapshottedOnThread;
        referencingObject[referencingObjectFieldName] = res;
        if (!(res instanceof tr.model.ObjectSnapshot))
          throw new Error('Created object must be instanceof snapshot');
        return res.args;
      }

      /**
       * Iterates over the fields in the object, calling func for every
       * field/value found.
       *
       * @return {object} If the function does not want the field's value to be
       * iterated, return null. If iteration of the field value is desired, then
       * return either undefined (if the field value did not change) or the new
       * field value if it was changed.
       */
      function iterObject(object, func, containingSnapshot, thisArg) {
        if (!(object instanceof Object))
          return;

        if (object instanceof Array) {
          for (var i = 0; i < object.length; i++) {
            var res = func.call(thisArg, object, i, object[i],
                                containingSnapshot);
            if (res === null)
              continue;
            if (res)
              iterObject(res, func, containingSnapshot, thisArg);
            else
              iterObject(object[i], func, containingSnapshot, thisArg);
          }
          return;
        }

        for (var key in object) {
          var res = func.call(thisArg, object, key, object[key],
                              containingSnapshot);
          if (res === null)
            continue;
          if (res)
            iterObject(res, func, containingSnapshot, thisArg);
          else
            iterObject(object[key], func, containingSnapshot, thisArg);
        }
      }

      // TODO(nduca): We may need to iterate the instances in sorted order by
      // creationTs.
      process.objects.iterObjectInstances(function(instance) {
        instance.snapshots.forEach(function(snapshot) {
          if (snapshot.args.id !== undefined)
            throw new Error('args cannot have an id field inside it');
          iterObject(snapshot.args, processField, snapshot, this);
        }, this);
      }, this);
    },

    createMemoryDumps_: function() {
      for (var dumpId in this.allMemoryDumpEvents_)
        this.createGlobalMemoryDump_(this.allMemoryDumpEvents_[dumpId], dumpId);
    },

    createGlobalMemoryDump_: function(dumpIdEvents, dumpId) {
      // 1. Create a GlobalMemoryDump for the provided process memory dump
      // the events, all of which have the same dump ID.

      // Calculate the range of the global memory dump.
      var globalRange = new tr.b.Range();
      for (var pid in dumpIdEvents) {
        var processEvents = dumpIdEvents[pid];
        for (var i = 0; i < processEvents.length; i++)
          globalRange.addValue(this.toModelTimeFromUs_(processEvents[i].ts));
      }
      if (globalRange.isEmpty)
        throw new Error('Internal error: Global memory dump without events');

      // Create the global memory dump.
      var globalMemoryDump = new tr.model.GlobalMemoryDump(
          this.model_, globalRange.min);
      globalMemoryDump.duration = globalRange.range;
      this.model_.globalMemoryDumps.push(globalMemoryDump);

      var globalMemoryAllocatorDumpsByFullName = {};
      var levelsOfDetail = {};
      var allMemoryAllocatorDumpsByGuid = {};

      // 2. Create a ProcessMemoryDump for each PID in the provided process
      // memory dump events. Everything except for edges between memory
      // allocator dumps is parsed from the process memory dump trace events at
      // this step.
      for (var pid in dumpIdEvents) {
        this.createProcessMemoryDump_(globalMemoryDump,
            globalMemoryAllocatorDumpsByFullName, levelsOfDetail,
            allMemoryAllocatorDumpsByGuid, dumpIdEvents[pid], pid, dumpId);
      }

      // 3. Set the level of detail and memory allocator dumps of the
      // GlobalMemoryDump, which come from the process memory dump trace
      // events parsed in the prebvious step.
      globalMemoryDump.levelOfDetail = levelsOfDetail.global;

      // Find the root allocator dumps and establish the parent links of
      // the global memory dump.
      globalMemoryDump.memoryAllocatorDumps =
          this.inferMemoryAllocatorDumpTree_(
              globalMemoryAllocatorDumpsByFullName);

      // 4. Finally, parse the edges between all memory allocator dumps within
      // the GlobalMemoryDump. This can only be done once all memory allocator
      // dumps have been parsed (i.e. it is necessary to iterate over the
      // process memory dump trace events once more).
      this.parseMemoryDumpAllocatorEdges_(allMemoryAllocatorDumpsByGuid,
          dumpIdEvents, dumpId);
    },

    createProcessMemoryDump_: function(globalMemoryDump,
        globalMemoryAllocatorDumpsByFullName, levelsOfDetail,
        allMemoryAllocatorDumpsByGuid, processEvents, pid, dumpId) {
      // Calculate the range of the process memory dump.
      var processRange = new tr.b.Range();
      for (var i = 0; i < processEvents.length; i++)
        processRange.addValue(this.toModelTimeFromUs_(processEvents[i].ts));
      if (processRange.isEmpty)
        throw new Error('Internal error: Process memory dump without events');

      // Create the process memory dump.
      var process = this.model_.getOrCreateProcess(pid);
      var processMemoryDump = new tr.model.ProcessMemoryDump(
          globalMemoryDump, process, processRange.min);
      processMemoryDump.duration = processRange.range;
      process.memoryDumps.push(processMemoryDump);
      globalMemoryDump.processMemoryDumps[pid] = processMemoryDump;

      var processMemoryAllocatorDumpsByFullName = {};

      // Parse all process memory dump trace events for the newly created
      // ProcessMemoryDump.
      for (var i = 0; i < processEvents.length; i++) {
        var processEvent = processEvents[i];

        var dumps = processEvent.args.dumps;
        if (dumps === undefined) {
          this.model_.importWarning({
            type: 'memory_dump_parse_error',
            message: '\'dumps\' field not found in a process memory dump' +
                ' event for PID=' + pid + ' and dump ID=' + dumpId + '.'
          });
          continue;
        }

        // Totals, VM regions, and heap dumps for the newly created
        // ProcessMemoryDump should be present in at most one event, so they
        // can be added to the ProcessMemoryDump immediately.
        this.parseMemoryDumpTotals_(processMemoryDump, dumps, pid, dumpId);
        this.parseMemoryDumpVmRegions_(processMemoryDump, dumps, pid, dumpId);
        this.parseMemoryDumpHeapDumps_(processMemoryDump, dumps, pid, dumpId);

        // All process memory dump trace events for the newly created
        // ProcessMemoryDump must be processed before level of detail and
        // allocator dumps can be added to it.
        this.parseMemoryDumpLevelOfDetail_(levelsOfDetail, dumps, pid,
            dumpId);
        this.parseMemoryDumpAllocatorDumps_(processMemoryDump, globalMemoryDump,
            processMemoryAllocatorDumpsByFullName,
            globalMemoryAllocatorDumpsByFullName,
            allMemoryAllocatorDumpsByGuid, dumps, pid, dumpId);
      }

      if (levelsOfDetail.process === undefined) {
        // Infer level of detail from the presence of VM regions in legacy
        // traces (where raw process memory dump events don't contain the
        // level_of_detail field). These traces will not have BACKGROUND mode.
        levelsOfDetail.process = processMemoryDump.vmRegions ? DETAILED : LIGHT;
      }
      if (!this.updateMemoryDumpLevelOfDetail_(
          levelsOfDetail, 'global', levelsOfDetail.process)) {
        this.model_.importWarning({
          type: 'memory_dump_parse_error',
          message: 'diffent levels of detail provided for global memory' +
              ' dump (dump ID=' + dumpId + ').'
        });
      }
      processMemoryDump.levelOfDetail = levelsOfDetail.process;
      delete levelsOfDetail.process;  // Reused for all process dumps.

      // Find the root allocator dumps and establish the parent links of
      // the process memory dump.
      processMemoryDump.memoryAllocatorDumps =
          this.inferMemoryAllocatorDumpTree_(
              processMemoryAllocatorDumpsByFullName);
    },

    parseMemoryDumpTotals_: function(processMemoryDump, dumps, pid, dumpId) {
      var rawTotals = dumps.process_totals;
      if (rawTotals === undefined)
        return;

      if (processMemoryDump.totals !== undefined) {
        this.model_.importWarning({
          type: 'memory_dump_parse_error',
          message: 'Process totals provided multiple times for' +
              ' process memory dump for PID=' + pid +
              ' and dump ID=' + dumpId + '.'
        });
        return;
      }

      var totals = {};
      var platformSpecificTotals = undefined;

      for (var rawTotalName in rawTotals) {
        var rawTotalValue = rawTotals[rawTotalName];
        if (rawTotalValue === undefined)
          continue;

        // Total resident bytes.
        if (rawTotalName === 'resident_set_bytes') {
          totals.residentBytes = parseInt(rawTotalValue, 16);
          continue;
        }

        // Peak resident bytes.
        if (rawTotalName === 'peak_resident_set_bytes') {
          totals.peakResidentBytes = parseInt(rawTotalValue, 16);
          continue;
        }
        if (rawTotalName === 'is_peak_rss_resetable') {
          totals.arePeakResidentBytesResettable = !!rawTotalValue;
          continue;
        }

        // OS-specific totals (e.g. private resident on Mac).
        if (platformSpecificTotals === undefined) {
          platformSpecificTotals = {};
          totals.platformSpecific = platformSpecificTotals;
        }
        platformSpecificTotals[rawTotalName] = parseInt(rawTotalValue, 16);
      }

      // Either both peak_resident_set_bytes and is_peak_rss_resetable should
      // be present in the trace, or neither.
      if (totals.peakResidentBytes === undefined &&
          totals.arePeakResidentBytesResettable !== undefined) {
        this.model_.importWarning({
            type: 'memory_dump_parse_error',
            message: 'Optional field peak_resident_set_bytes found' +
                ' but is_peak_rss_resetable not found in' +
                ' process memory dump for PID=' + pid +
                ' and dump ID=' + dumpId + '.'
        });
      }
      if (totals.arePeakResidentBytesResettable !== undefined &&
          totals.peakResidentBytes === undefined) {
        this.model_.importWarning({
            type: 'memory_dump_parse_error',
            message: 'Optional field is_peak_rss_resetable found' +
                ' but peak_resident_set_bytes not found in' +
                ' process memory dump for PID=' + pid +
                ' and dump ID=' + dumpId + '.'
        });
      }

      processMemoryDump.totals = totals;
    },

    parseMemoryDumpVmRegions_: function(processMemoryDump, dumps, pid, dumpId) {
      var rawProcessMmaps = dumps.process_mmaps;
      if (rawProcessMmaps === undefined)
        return;

      var rawVmRegions = rawProcessMmaps.vm_regions;
      if (rawVmRegions === undefined)
        return;

      if (processMemoryDump.vmRegions !== undefined) {
        this.model_.importWarning({
          type: 'memory_dump_parse_error',
          message: 'VM regions provided multiple times for' +
              ' process memory dump for PID=' + pid +
              ' and dump ID=' + dumpId + '.'
        });
        return;
      }

      // See //base/trace_event/process_memory_maps.cc in Chromium.
      var vmRegions = new Array(rawVmRegions.length);
      for (var i = 0; i < rawVmRegions.length; i++) {
        var rawVmRegion = rawVmRegions[i];

        var byteStats = {};
        var rawByteStats = rawVmRegion.bs;
        for (var rawByteStatName in rawByteStats) {
          var rawByteStatValue = rawByteStats[rawByteStatName];
          if (rawByteStatValue === undefined) {
            this.model_.importWarning({
              type: 'memory_dump_parse_error',
              message: 'Byte stat \'' + rawByteStatName + '\' of VM region ' +
                  i + ' (' + rawVmRegion.mf + ') in process memory dump for ' +
                  'PID=' + pid + ' and dump ID=' + dumpId +
                  ' does not have a value.'
            });
            continue;
          }
          var byteStatName = BYTE_STAT_NAME_MAP[rawByteStatName];
          if (byteStatName === undefined) {
            this.model_.importWarning({
              type: 'memory_dump_parse_error',
              message: 'Unknown byte stat name \'' + rawByteStatName + '\' (' +
                  rawByteStatValue + ') of VM region ' + i + ' (' +
                  rawVmRegion.mf + ') in process memory dump for PID=' + pid +
                  ' and dump ID=' + dumpId + '.'
            });
            continue;
          }
          byteStats[byteStatName] = parseInt(rawByteStatValue, 16);
        }

        vmRegions[i] = new tr.model.VMRegion(
            parseInt(rawVmRegion.sa, 16),  // startAddress
            parseInt(rawVmRegion.sz, 16),  // sizeInBytes
            rawVmRegion.pf,  // protectionFlags
            rawVmRegion.mf,  // mappedFile
            byteStats);
      }

      processMemoryDump.vmRegions =
          tr.model.VMRegionClassificationNode.fromRegions(vmRegions);
    },

    parseMemoryDumpHeapDumps_: function(processMemoryDump, dumps, pid, dumpId) {
      var rawHeapDumps = dumps.heaps;
      if (rawHeapDumps === undefined)
        return;

      if (processMemoryDump.heapDumps !== undefined) {
        this.model_.importWarning({
          type: 'memory_dump_parse_error',
          message: 'Heap dumps provided multiple times for' +
              ' process memory dump for PID=' + pid +
              ' and dump ID=' + dumpId + '.'
        });
        return;
      }

      var model = this.model_;
      var idPrefix = 'p' + pid + ':';
      var heapDumps = {};

      var objectTypeNameMap = this.objectTypeNameMap_[pid];
      if (objectTypeNameMap === undefined) {
        this.model_.importWarning({
          type: 'memory_dump_parse_error',
          message: 'Missing mapping from object type IDs to names.'
        });
      }

      for (var allocatorName in rawHeapDumps) {
        var entries = rawHeapDumps[allocatorName].entries;
        if (entries === undefined || entries.length === 0) {
          this.model_.importWarning({
            type: 'memory_dump_parse_error',
            message: 'No heap entries in a ' + allocatorName +
                ' heap dump for PID=' + pid + ' and dump ID=' + dumpId + '.'
          });
          continue;
        }

        // The old format always starts with a {size: <total>} entry.
        // See https://goo.gl/WYStil
        // TODO(petrcermak): Remove support for the old format once the new
        // format has been around long enough.
        var isOldFormat = entries[0].bt === undefined;
        if (!isOldFormat && objectTypeNameMap === undefined) {
          // Mapping from object type IDs to names must be provided in the new
          // format.
          continue;
        }

        var heapDump = new tr.model.HeapDump(processMemoryDump, allocatorName);

        for (var i = 0; i < entries.length; i++) {
          var entry = entries[i];
          var leafStackFrameIndex = entry.bt;
          var leafStackFrame;

          // There are two possible mappings from leaf stack frame indices
          // (provided in the trace) to the corresponding stack frames
          // depending on the format.
          if (isOldFormat) {
            // Old format:
            //   Undefined index        -> / (root)
            //   Defined index for /A/B -> /A/B/<self>
            if (leafStackFrameIndex === undefined) {
              leafStackFrame = undefined /* root */;
            } else {
              // Get the leaf stack frame corresponding to the provided index.
              var leafStackFrameId = idPrefix + leafStackFrameIndex;
              if (leafStackFrameIndex === '') {
                leafStackFrame = undefined /* root */;
              } else {
                leafStackFrame = model.stackFrames[leafStackFrameId];
                if (leafStackFrame === undefined) {
                  this.model_.importWarning({
                    type: 'memory_dump_parse_error',
                    message: 'Missing leaf stack frame (ID ' +
                        leafStackFrameId + ') of heap entry ' + i + ' (size ' +
                        size + ') in a ' + allocatorName +
                        ' heap dump for PID=' + pid + '.'
                  });
                  continue;
                }
              }

              // Inject an artificial <self> leaf stack frame.
              leafStackFrameId += ':self';
              if (model.stackFrames[leafStackFrameId] !== undefined) {
                // The frame might already exist if there are multiple process
                // memory dumps (for the same process) in the trace.
                leafStackFrame = model.stackFrames[leafStackFrameId];
              } else {
                leafStackFrame = new tr.model.StackFrame(
                    leafStackFrame, leafStackFrameId, '<self>',
                    undefined /* colorId */);
                model.addStackFrame(leafStackFrame);
              }
            }
          } else {
            // New format:
            //   Undefined index        -> (invalid value)
            //   Defined index for /A/B -> /A/B
            if (leafStackFrameIndex === undefined) {
              this.model_.importWarning({
                type: 'memory_dump_parse_error',
                message: 'Missing stack frame ID of heap entry ' + i +
                    ' (size ' + size + ') in a ' + allocatorName +
                    ' heap dump for PID=' + pid + '.'
              });
              continue;
            }

            // Get the leaf stack frame corresponding to the provided index.
            var leafStackFrameId = idPrefix + leafStackFrameIndex;
            if (leafStackFrameIndex === '') {
              leafStackFrame = undefined /* root */;
            } else {
              leafStackFrame = model.stackFrames[leafStackFrameId];
              if (leafStackFrame === undefined) {
                this.model_.importWarning({
                  type: 'memory_dump_parse_error',
                  message: 'Missing leaf stack frame (ID ' + leafStackFrameId +
                      ') of heap entry ' + i + ' (size ' + size + ') in a ' +
                      allocatorName + ' heap dump for PID=' + pid + '.'
                });
                continue;
              }
            }
          }

          var objectTypeId = entry.type;
          var objectTypeName;
          if (objectTypeId === undefined) {
            objectTypeName = undefined /* total over all types */;
          } else if (objectTypeNameMap === undefined) {
            // This can only happen when the old format is used.
            continue;
          } else {
            objectTypeName = objectTypeNameMap[objectTypeId];
            if (objectTypeName === undefined) {
              this.model_.importWarning({
                type: 'memory_dump_parse_error',
                message: 'Missing object type name (ID ' + objectTypeId +
                    ') of heap entry ' + i + ' (size ' + size + ') in a ' +
                    allocatorName + ' heap dump for pid=' + pid + '.'
              });
              continue;
            }
          }

          var size = parseInt(entry.size, 16);
          var count = entry.count === undefined ? undefined :
              parseInt(entry.count, 16);
          heapDump.addEntry(leafStackFrame, objectTypeName, size, count);
        }

        // Throw away heap dumps with no entries. This can happen if all raw
        // entries in the trace are skipped for some reason (e.g. invalid leaf
        // stack frame ID).
        if (heapDump.entries.length > 0)
          heapDumps[allocatorName] = heapDump;
      }

      if (Object.keys(heapDumps).length > 0)
        processMemoryDump.heapDumps = heapDumps;
    },

    parseMemoryDumpLevelOfDetail_: function(levelsOfDetail, dumps, pid,
        dumpId) {
      var rawLevelOfDetail = dumps.level_of_detail;
      var level;
      switch (rawLevelOfDetail) {
        case 'background':
          level = BACKGROUND;
          break;
        case 'light':
          level = LIGHT;
          break;
        case 'detailed':
          level = DETAILED;
          break;
        case undefined:
          level = undefined;
          break;
        default:
          this.model_.importWarning({
            type: 'memory_dump_parse_error',
            message: 'unknown raw level of detail \'' + rawLevelOfDetail +
                '\' of process memory dump for PID=' + pid +
                ' and dump ID=' + dumpId + '.'
          });
          return;
      }

      if (!this.updateMemoryDumpLevelOfDetail_(
          levelsOfDetail, 'process', level)) {
        this.model_.importWarning({
          type: 'memory_dump_parse_error',
          message: 'diffent levels of detail provided for process memory' +
              ' dump for PID=' + pid + ' (dump ID=' + dumpId + ').'
        });
      }
    },

    updateMemoryDumpLevelOfDetail_: function(levelsOfDetail, scope, level) {
      // If all process memory dump events have the same level of detail (for
      // the particular 'process' or 'global' scope), return true.
      if (!(scope in levelsOfDetail) || level === levelsOfDetail[scope]) {
        levelsOfDetail[scope] = level;
        return true;
      }

      // If the process memory dump events have different levels of detail (for
      // the particular 'process' or 'global' scope), use the highest level and
      // return false.
      if (MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER.indexOf(level) >
          MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER.indexOf(levelsOfDetail[scope])) {
        levelsOfDetail[scope] = level;
      }
      return false;
    },

    parseMemoryDumpAllocatorDumps_: function(processMemoryDump,
        globalMemoryDump, processMemoryAllocatorDumpsByFullName,
        globalMemoryAllocatorDumpsByFullName, allMemoryAllocatorDumpsByGuid,
        dumps, pid, dumpId) {
      var rawAllocatorDumps = dumps.allocators;
      if (rawAllocatorDumps === undefined)
        return;

      // Construct the MemoryAllocatorDump objects without parent links
      // and add them to the processMemoryAllocatorDumpsByName and
      // globalMemoryAllocatorDumpsByName indices appropriately.
      for (var fullName in rawAllocatorDumps) {
        var rawAllocatorDump = rawAllocatorDumps[fullName];

        // Every memory allocator dump should have a GUID. If not, then
        // it cannot be associated with any edges.
        var guid = rawAllocatorDump.guid;
        if (guid === undefined) {
          this.model_.importWarning({
            type: 'memory_dump_parse_error',
            message: 'Memory allocator dump ' + fullName + ' for PID=' + pid +
                ' and dump ID=' + dumpId + ' does not have a GUID.'
          });
        }

        // A memory allocator dump can have optional flags.
        var flags = rawAllocatorDump.flags || 0;
        var isWeakDump = !!(flags & WEAK_MEMORY_ALLOCATOR_DUMP_FLAG);

        // Determine if this is a global memory allocator dump (check if
        // it's prefixed with 'global/').
        var containerMemoryDump;
        var dstIndex;
        if (fullName.startsWith(GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX)) {
          // Global memory allocator dump.
          fullName = fullName.substring(
              GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX.length);
          containerMemoryDump = globalMemoryDump;
          dstIndex = globalMemoryAllocatorDumpsByFullName;
        } else {
          // Process memory allocator dump.
          containerMemoryDump = processMemoryDump;
          dstIndex = processMemoryAllocatorDumpsByFullName;
        }

        // Construct or retrieve a memory allocator dump with the provided
        // GUID.
        var allocatorDump = allMemoryAllocatorDumpsByGuid[guid];
        if (allocatorDump === undefined) {
          if (fullName in dstIndex) {
            this.model_.importWarning({
              type: 'memory_dump_parse_error',
              message: 'Multiple GUIDs provided for' +
                  ' memory allocator dump ' + fullName + ': ' +
                  dstIndex[fullName].guid + ', ' + guid + ' (ignored) for' +
                  ' PID=' + pid + ' and dump ID=' + dumpId + '.'
            });
            continue;
          }
          allocatorDump = new tr.model.MemoryAllocatorDump(
              containerMemoryDump, fullName, guid);
          allocatorDump.weak = isWeakDump;
          dstIndex[fullName] = allocatorDump;
          if (guid !== undefined)
            allMemoryAllocatorDumpsByGuid[guid] = allocatorDump;
        } else {
          // A memory allocator dump with this GUID has already been
          // dumped (so we will only add new attributes). Check that it
          // belonged to the same process or was also global.
          if (allocatorDump.containerMemoryDump !== containerMemoryDump) {
            this.model_.importWarning({
            type: 'memory_dump_parse_error',
            message: 'Memory allocator dump ' + fullName +
                ' (GUID=' + guid + ') for PID=' + pid + ' and dump ID=' +
                dumpId + ' dumped in different contexts.'
            });
            continue;
          }
          // Check that the names of the memory allocator dumps match.
          if (allocatorDump.fullName !== fullName) {
            this.model_.importWarning({
            type: 'memory_dump_parse_error',
            message: 'Memory allocator dump with GUID=' + guid + ' for PID=' +
                pid + ' and dump ID=' + dumpId + ' has multiple names: ' +
                allocatorDump.fullName + ', ' + fullName + ' (ignored).'
            });
            continue;
          }
          if (!isWeakDump) {
            // A MemoryAllocatorDump is non-weak if at least one process dumped
            // it without WEAK_MEMORY_ALLOCATOR_DUMP_FLAG.
            allocatorDump.weak = false;
          }
        }

        // Add all new attributes to the memory allocator dump.
        var attributes = rawAllocatorDump.attrs;
        if (attributes === undefined) {
          this.model_.importWarning({
            type: 'memory_dump_parse_error',
            message: 'Memory allocator dump ' + fullName + ' (GUID=' + guid +
                ') for PID=' + pid + ' and dump ID=' + dumpId +
                ' does not have attributes.'
          });
          attributes = {};
        }

        for (var attrName in attributes) {
          var attrArgs = attributes[attrName];
          var attrType = attrArgs.type;
          var attrValue = attrArgs.value;

          switch (attrType) {
            case 'scalar':
              if (attrName in allocatorDump.numerics) {
                this.model_.importWarning({
                type: 'memory_dump_parse_error',
                message: 'Multiple values provided for scalar attribute ' +
                    attrName + ' of memory allocator dump ' + fullName +
                    ' (GUID=' + guid + ') for PID=' + pid + ' and dump ID=' +
                    dumpId + '.'
                });
                break;
              }
              var unit = attrArgs.units === 'bytes' ?
                  tr.b.Unit.byName.sizeInBytes_smallerIsBetter :
                  tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
              var value = parseInt(attrValue, 16);
              allocatorDump.addNumeric(attrName,
                  new tr.v.ScalarNumeric(unit, value));
              break;

            case 'string':
              if (attrName in allocatorDump.diagnostics) {
                this.model_.importWarning({
                type: 'memory_dump_parse_error',
                message: 'Multiple values provided for string attribute ' +
                    attrName + ' of memory allocator dump ' + fullName +
                    ' (GUID=' + guid + ') for PID=' + pid + ' and dump ID=' +
                    dumpId + '.'
                });
                break;
              }
              allocatorDump.addDiagnostic(attrName, attrValue);
              break;

            default:
              this.model_.importWarning({
              type: 'memory_dump_parse_error',
              message: 'Unknown type provided for attribute ' + attrName +
                  ' of memory allocator dump ' + fullName + ' (GUID=' + guid +
                  ') for PID=' + pid + ' and dump ID=' + dumpId + ': ' +
                  attrType
              });
              break;
          }
        }
      }
    },

    inferMemoryAllocatorDumpTree_: function(memoryAllocatorDumpsByFullName) {
      var rootAllocatorDumps = [];

      var fullNames = Object.keys(memoryAllocatorDumpsByFullName);
      fullNames.sort();
      for (var i = 0; i < fullNames.length; i++) {
        var fullName = fullNames[i];
        var allocatorDump = memoryAllocatorDumpsByFullName[fullName];

        // This is a loop because we might need to build implicit
        // ancestors in case they were not present in the trace.
        while (true) {
          var lastSlashIndex = fullName.lastIndexOf('/');
          if (lastSlashIndex === -1) {
            // If the dump is a root, add it to the top-level
            // rootAllocatorDumps list.
            rootAllocatorDumps.push(allocatorDump);
            break;
          }

          // If the dump is not a root, find its parent.
          var parentFullName = fullName.substring(0, lastSlashIndex);
          var parentAllocatorDump =
              memoryAllocatorDumpsByFullName[parentFullName];

          // If the parent dump does not exist yet, we build an implicit
          // one and continue up the ancestor chain.
          var parentAlreadyExisted = true;
          if (parentAllocatorDump === undefined) {
            parentAlreadyExisted = false;
            parentAllocatorDump = new tr.model.MemoryAllocatorDump(
                allocatorDump.containerMemoryDump, parentFullName);
            if (allocatorDump.weak !== false) {
              // If we are inferring a parent dump (e.g. 'root/parent') of a
              // current dump (e.g. 'root/parent/current') which is weak (or
              // was also inferred and we don't know yet whether it's weak or
              // not), then we clear the weak flag on the parent dump because
              // we don't know yet whether it should be weak or non-weak:
              //
              //   * We can't mark the parent as non-weak straightaway because
              //     the parent might have no non-weak descendants (in which
              //     case we want the inferred parent to be weak, so that it
              //     would be later removed like the current dump).
              //   * We can't mark the parent as weak immediately either. If we
              //     did and later encounter a non-weak child of the parent
              //     (e.g. 'root/parent/another_child'), then we couldn't
              //     retroactively mark the inferred parent dump as non-weak
              //     because we couldn't tell whether the parent dump was
              //     dumped in the trace as weak (in which case it should stay
              //     weak and be subsequently removed) or whether it was
              //     inferred as weak (in which case it should be changed to
              //     non-weak).
              //
              // Therefore, we defer marking the inferred parent as
              // weak/non-weak. If an inferred parent dump does not have any
              // non-weak child, it will be marked as weak at the end of this
              // method.
              //
              // Note that this should not be confused with the recursive
              // propagation of the weak flag from parent dumps to their
              // children and from owned dumps to their owners, which is
              // performed in GlobalMemoryDump.prototype.removeWeakDumps().
              parentAllocatorDump.weak = undefined;
            }
            memoryAllocatorDumpsByFullName[parentFullName] =
                parentAllocatorDump;
          }

          // Setup the parent <-> children relationships
          allocatorDump.parent = parentAllocatorDump;
          parentAllocatorDump.children.push(allocatorDump);

          // If the parent already existed, then its ancestors were/will be
          // constructed in another iteration of the forEach loop.
          if (parentAlreadyExisted) {
            if (!allocatorDump.weak) {
              // If the current dump is non-weak, then we must ensure that all
              // its inferred ancestors are also non-weak.
              while (parentAllocatorDump !== undefined &&
                     parentAllocatorDump.weak === undefined) {
                parentAllocatorDump.weak = false;
                parentAllocatorDump = parentAllocatorDump.parent;
              }
            }
            break;
          }

          fullName = parentFullName;
          allocatorDump = parentAllocatorDump;
        }
      }

      // All inferred ancestor dumps that have a non-weak child have already
      // been marked as non-weak. We now mark the rest as weak.
      for (var fullName in memoryAllocatorDumpsByFullName) {
        var allocatorDump = memoryAllocatorDumpsByFullName[fullName];
        if (allocatorDump.weak === undefined)
          allocatorDump.weak = true;
      }

      return rootAllocatorDumps;
    },

    parseMemoryDumpAllocatorEdges_: function(allMemoryAllocatorDumpsByGuid,
        dumpIdEvents, dumpId) {
      for (var pid in dumpIdEvents) {
        var processEvents = dumpIdEvents[pid];

        for (var i = 0; i < processEvents.length; i++) {
          var processEvent = processEvents[i];

          var dumps = processEvent.args.dumps;
          if (dumps === undefined)
            continue;

          var rawEdges = dumps.allocators_graph;
          if (rawEdges === undefined)
            continue;

          for (var j = 0; j < rawEdges.length; j++) {
            var rawEdge = rawEdges[j];

            var sourceGuid = rawEdge.source;
            var sourceDump = allMemoryAllocatorDumpsByGuid[sourceGuid];
            if (sourceDump === undefined) {
              this.model_.importWarning({
                type: 'memory_dump_parse_error',
                message: 'Edge for PID=' + pid + ' and dump ID=' + dumpId +
                    ' is missing source memory allocator dump (GUID=' +
                    sourceGuid + ').'
              });
              continue;
            }

            var targetGuid = rawEdge.target;
            var targetDump = allMemoryAllocatorDumpsByGuid[targetGuid];
            if (targetDump === undefined) {
              this.model_.importWarning({
                type: 'memory_dump_parse_error',
                message: 'Edge for PID=' + pid + ' and dump ID=' + dumpId +
                    ' is missing target memory allocator dump (GUID=' +
                    targetGuid + ').'
              });
              continue;
            }

            var importance = rawEdge.importance;
            var edge = new tr.model.MemoryAllocatorDumpLink(
                sourceDump, targetDump, importance);

            switch (rawEdge.type) {
              case 'ownership':
                if (sourceDump.owns !== undefined) {
                  this.model_.importWarning({
                    type: 'memory_dump_parse_error',
                    message: 'Memory allocator dump ' + sourceDump.fullName +
                        ' (GUID=' + sourceGuid + ') already owns a memory' +
                        ' allocator dump (' +
                        sourceDump.owns.target.fullName + ').'
                  });
                } else {
                  sourceDump.owns = edge;
                  targetDump.ownedBy.push(edge);
                }
                break;

              case 'retention':
                sourceDump.retains.push(edge);
                targetDump.retainedBy.push(edge);
                break;

              default:
                this.model_.importWarning({
                  type: 'memory_dump_parse_error',
                  message: 'Invalid edge type: ' + rawEdge.type +
                      ' (PID=' + pid + ', dump ID=' + dumpId +
                      ', source=' + sourceGuid + ', target=' + targetGuid +
                      ', importance=' + importance + ').'
                });
            }
          }
        }
      }
    },

    /**
     * Converts |ts| (in microseconds) to a timestamp in the model clock domain
     * (in milliseconds).
     */
    toModelTimeFromUs_: function(ts) {
      if (!this.toModelTime_) {
        this.toModelTime_ =
            this.model_.clockSyncManager.getModelTimeTransformer(
                this.clockDomainId_);
      }

      return this.toModelTime_(tr.b.Unit.timestampFromUs(ts));
    },

    /**
     * Converts |ts| (in microseconds) to a timestamp in the model clock domain
     * (in milliseconds). If |ts| is undefined, undefined is returned.
     */
    maybeToModelTimeFromUs_: function(ts) {
      if (ts === undefined)
        return undefined;

      return this.toModelTimeFromUs_(ts);
    }
  };

  tr.importer.Importer.register(TraceEventImporter);

  return {
    TraceEventImporter: TraceEventImporter
  };
});
</script>
