<!DOCTYPE html>
<!--
Copyright (c) 2015 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/units/time_stamp.html">
<link rel="import" href="/tracing/model/attribute.html">
<link rel="import" href="/tracing/model/container_memory_dump.html">
<link rel="import" href="/tracing/model/memory_allocator_dump.html">

<script>
'use strict';

/**
 * @fileoverview Provides the GlobalMemoryDump class.
 */
tr.exportTo('tr.model', function() {
  /**
   * The GlobalMemoryDump represents a simultaneous memory dump of all
   * processes.
   * @constructor
   */
  function GlobalMemoryDump(model, start) {
    tr.model.ContainerMemoryDump.call(this, start);
    this.model = model;
    this.processMemoryDumps = {};
  }

  var SIZE_ATTRIBUTE_NAME = tr.model.MemoryAllocatorDump.SIZE_ATTRIBUTE_NAME;
  var EFFECTIVE_SIZE_ATTRIBUTE_NAME =
      tr.model.MemoryAllocatorDump.EFFECTIVE_SIZE_ATTRIBUTE_NAME;

  function getSize(dump) {
    var attr = dump.attributes[SIZE_ATTRIBUTE_NAME];
    if (attr === undefined)
      return 0;
    return attr.value;
  }

  function hasSize(dump) {
    return dump.attributes[SIZE_ATTRIBUTE_NAME] !== undefined;
  }

  function optional(value, defaultValue) {
    if (value === undefined)
      return defaultValue;
    return value;
  }

  function ownershipToUserFriendlyString(dump, importance) {
    return dump.quantifiedName + ' (importance: ' +
        optional(importance, 0) + ')';
  }

  GlobalMemoryDump.prototype = {
    __proto__: tr.model.ContainerMemoryDump.prototype,

    get userFriendlyName() {
      return 'Global memory dump at ' + tr.b.u.TimeStamp.format(this.start);
    },

    get containerName() {
      return 'global space';
    },

    calculateGraphAttributes: function() {
      // 1. Add ownership links from tracing MADs to descendants of malloc or
      // winheap MADs so that tracing would be automatically discounted from
      // them later (step 3).
      this.setUpTracingOverheadOwnership();

      // 2. Calculate the sizes of all memory allocator dumps (MADs). This step
      // requires that the memory allocator dump graph has been finalized (step
      // 1). Subsequent modifications of the graph will most likely break the
      // calculation invariants.
      this.calculateSizes();

      // 3. Calculate the effective sizes of all MADs. This step requires that
      // the sizes of all MADs have already been calculated (step 2).
      this.calculateEffectiveSizes();

      // 4. Aggregate all other attributes of all MADs. This step must be
      // carried out after the sizes of all MADs were calculated (step 2).
      // Otherwise, the sizes of all MADs would be aggregated as direct sums
      // of their children, which would most likely lead to double-counting.
      this.aggregateAttributes();

      // 5. Discount tracing from VM regions stats. This steps requires that
      // sizes (step 2) and resident sizes (step 4) of the tracing MADs have
      // already been calculated.
      this.discountTracingOverheadFromVmRegions();
    },

    /**
     * Calculate the size of all memory allocator dumps in the dump graph.
     *
     * The size refers to the allocated size of a (sub)component. It is a
     * natural extension of the optional size attribute provided by
     * MemoryAllocatorDump(s):
     *
     *   - If a MAD provides a size attribute, then its size is assumed to be
     *     equal to it.
     *   - If a MAD does not provide a size attribute, then its size is assumed
     *     to be the maximum of (1) the size of the largest owner of the MAD
     *     and (2) the aggregated size of the MAD's children.
     *
     * Metric motivation: "How big is a (sub)system?"
     *
     * Please refer to the Memory Dump Graph Metric Calculation design document
     * for more details (https://goo.gl/fKg0dt).
     */
    calculateSizes: function() {
      this.traverseAllocatorDumpsInDepthFirstPostOrder(
          this.calculateMemoryAllocatorDumpSize_.bind(this));
    },

    /**
     * Calculate the size of the given MemoryAllocatorDump. This method assumes
     * that the size of both the children and owners of the dump has already
     * been calculated.
     */
    calculateMemoryAllocatorDumpSize_: function(dump) {
      // This flag becomes true if the size attribute of the current dump
      // should be defined, i.e. if (1) the current dump's size attribute is
      // defined, (2) the size of at least one of its children is defined or
      // (3) the size of at least one of its owners is defined.
      var shouldDefineSize = false;

      // This helper function returns the numeric value of the size attribute
      // of the given dependent memory allocator dump. If the attribute is
      // defined, the shouldDefineSize flag above is also set to true (because
      // condition (2) or (3) is satisfied). Otherwise, zero is returned (and
      // the flag is left unchanged).
      function getDependencySize(dependencyDump) {
        var attr = dependencyDump.attributes[SIZE_ATTRIBUTE_NAME];
        if (attr === undefined)
          return 0;
        shouldDefineSize = true;
        return attr.value;
      }

      // 1. Get the size provided by the dump. If present, define a function
      // for checking dependent size consistency (a dump must always be bigger
      // than all its children aggregated together and/or its largest owner).
      var sizeAttribute = dump.getValidSizeAttributeOrUndefined(
          SIZE_ATTRIBUTE_NAME, this.model);
      var size = 0;
      var infos = [];
      var checkDependentSizeIsConsistent = function() { /* no-op */ };
      if (sizeAttribute !== undefined) {
        size = sizeAttribute.value;
        shouldDefineSize = true;
        checkDependentSizeIsConsistent = function(dependentSize,
            dependentName) {
          if (size >= dependentSize)
            return;
          var messageSuffix = ' (' + tr.b.u.Units.sizeInBytes.format(size) +
              ') is less than ' + dependentName + ' (' +
                tr.b.u.Units.sizeInBytes.format(dependentSize) + ').';
          this.model.importWarning({
            type: 'memory_dump_parse_error',
            message: 'Size provided by memory allocator dump \'' +
                dump.fullName + '\'' + messageSuffix
          });
          infos.push(new tr.model.AttributeInfo(
              tr.model.AttributeInfoType.WARNING,
              'Size provided by this memory allocator dump' + messageSuffix));
        }.bind(this);
      }

      // 2. Aggregate size of children. The recursive function traverses all
      // descendants and ensures that double-counting due to ownership within a
      // subsystem is avoided.
      var aggregatedChildrenSize = 0;
      // Owned child dump name -> (Owner child dump name -> overlapping size).
      var allOverlaps = {};
      dump.children.forEach(function(childDump) {
        function aggregateDescendantDump(descendantDump) {
          // Don't count this descendant dump if it owns another descendant of
          // the current dump (would cause double-counting).
          var ownedDumpLink = descendantDump.owns;
          if (ownedDumpLink !== undefined &&
              ownedDumpLink.target.isDescendantOf(dump)) {
            // If the target owned dump is a descendant of a *different* child
            // of the the current dump (i.e. not childDump), then we remember
            // the ownership so that we could explain why the size of the
            // current dump is not equal to the sum of its children.
            var ownedDescendantDump = ownedDumpLink.target;
            var ownedChildDump = ownedDescendantDump;
            while (ownedChildDump.parent !== dump)
              ownedChildDump = ownedChildDump.parent;
            if (childDump !== ownedChildDump) {
              var overlap = getDependencySize(descendantDump);
              if (overlap > 0) {
                // Owner child dump -> total overlapping size.
                var ownedChildOverlaps = allOverlaps[ownedChildDump.name];
                if (ownedChildOverlaps === undefined)
                  allOverlaps[ownedChildDump.name] = ownedChildOverlaps = {};
                var previousTotalOverlap =
                    ownedChildOverlaps[childDump.name] || 0;
                var updatedTotalOverlap = previousTotalOverlap + overlap;
                ownedChildOverlaps[childDump.name] = updatedTotalOverlap;
              }
            }
            return;
          }

          // If this descendant dump is a leaf node, add its size to the
          // aggregated size.
          if (descendantDump.children.length === 0) {
            aggregatedChildrenSize += getDependencySize(descendantDump);
            return;
          }

          // If this descendant dump is an intermediate node, recurse down into
          // its children. Note that the dump's size is NOT added because it is
          // an aggregate of its children (would cause double-counting).
          descendantDump.children.forEach(aggregateDescendantDump);
        }
        aggregateDescendantDump(childDump);
      });
      // If the size of the dump is not equal to the sum of its children, add
      // infos to its children explaining the difference.
      dump.children.forEach(function(childDump) {
        var childOverlaps = allOverlaps[childDump.name];
        if (childOverlaps === undefined)
          return;

        var message = tr.b.dictionaryValues(tr.b.mapItems(childOverlaps,
            function(ownerChildName, overlap) {
          return 'overlaps with its sibling \'' + ownerChildName + '\' (' +
              tr.b.u.Units.sizeInBytes.format(overlap) + ')';
        })).join(' ');

        childDump.attributes[SIZE_ATTRIBUTE_NAME].infos.push(
            new tr.model.AttributeInfo(
                tr.model.AttributeInfoType.INFORMATION, message));
      });
      checkDependentSizeIsConsistent(
          aggregatedChildrenSize, 'the aggregated size of its children');

      // 3. Calculate the largest owner size.
      var largestOwnerSize = 0;
      dump.ownedBy.forEach(function(ownershipLink) {
        var owner = ownershipLink.source;
        var ownerSize = getDependencySize(owner);
        largestOwnerSize = Math.max(largestOwnerSize, ownerSize);
      });
      checkDependentSizeIsConsistent(
          largestOwnerSize, 'the size of its largest owner');

      // If neither the dump nor any of its dependencies (children and owners)
      // provide a size, do NOT add a zero size attribute.
      if (!shouldDefineSize) {
        // The rest of the pipeline relies on size being either a valid
        // ScalarAttribute, or undefined.
        dump.attributes[SIZE_ATTRIBUTE_NAME] = undefined;
        return;
      }

      // A dump must always be bigger than all its children aggregated
      // together and/or its largest owner.
      size = Math.max(size, aggregatedChildrenSize, largestOwnerSize);

      var sizeAttribute = new tr.model.ScalarAttribute('bytes', size);
      sizeAttribute.infos = infos;
      dump.attributes[SIZE_ATTRIBUTE_NAME] = sizeAttribute;

      // Add a virtual child to make up for extra size of the dump with
      // respect to its children (if applicable).
      if (aggregatedChildrenSize < size &&
          dump.children !== undefined && dump.children.length > 0) {
        var virtualChild = new tr.model.MemoryAllocatorDump(
            dump.containerMemoryDump, dump.fullName + '/<unspecified>');
        virtualChild.parent = dump;
        dump.children.unshift(virtualChild);
        virtualChild.attributes[SIZE_ATTRIBUTE_NAME] =
            new tr.model.ScalarAttribute(
                'bytes', size - aggregatedChildrenSize);
      }
    },

    /**
     * Calculate the effective size of all memory allocator dumps in the dump
     * graph.
     *
     * The effective size refers to the amount of memory a particular component
     * is using/consuming. In other words, every (reported) byte of used memory
     * is uniquely attributed to exactly one component. Consequently, unlike
     * size, effective size is cumulative, i.e. the sum of the effective sizes
     * of (top-level) components is equal to the total amount of (reported)
     * used memory.
     *
     * Metric motivation: "How much memory does a (sub)system use?" or "For how
     * much memory should a (sub)system be 'charged'?"
     *
     * Please refer to the Memory Dump Graph Metric Calculation design document
     * for more details (https://goo.gl/fKg0dt).
     *
     * This method assumes that the size of all contained memory allocator
     * dumps has already been calculated [see calculateSizes()].
     */
    calculateEffectiveSizes: function() {
      // 1. Calculate not-owned and not-owning sub-sizes of all MADs
      // (depth-first post-order traversal).
      this.traverseAllocatorDumpsInDepthFirstPostOrder(
          this.calculateDumpSubSizes_.bind(this));

      // 2. Calculate owned and owning coefficients of owned and owner MADs
      // respectively (arbitrary traversal).
      this.traverseAllocatorDumpsInDepthFirstPostOrder(
          this.calculateDumpOwnershipCoefficient_.bind(this));

      // 3. Calculate cumulative owned and owning coefficients of all MADs
      // (depth-first pre-order traversal).
      this.traverseAllocatorDumpsInDepthFirstPreOrder(
          this.calculateDumpCumulativeOwnershipCoefficient_.bind(this));

      // 4. Calculate the effective sizes of all MADs (depth-first post-order
      // traversal).
      this.traverseAllocatorDumpsInDepthFirstPostOrder(
          this.calculateDumpEffectiveSize_.bind(this));
    },

    /**
     * Calculate not-owned and not-owning sub-sizes of a memory allocator dump
     * from its children's (sub-)sizes.
     *
     * Not-owned sub-size refers to the aggregated memory of all children which
     * is not owned by other MADs. Conversely, not-owning sub-size is the
     * aggregated memory of all children which do not own another MAD. The
     * diagram below illustrates these two concepts:
     *
     *     ROOT 1                         ROOT 2
     *     size: 4                        size: 5
     *     not-owned sub-size: 4          not-owned sub-size: 1 (!)
     *     not-owning sub-size: 0 (!)     not-owning sub-size: 5
     *
     *      ^                              ^
     *      |                              |
     *
     *     PARENT 1   ===== owns =====>   PARENT 2
     *     size: 4                        size: 5
     *     not-owned sub-size: 4          not-owned sub-size: 5
     *     not-owning sub-size: 4         not-owning sub-size: 5
     *
     *      ^                              ^
     *      |                              |
     *
     *     CHILD 1                        CHILD 2
     *     size [given]: 4                size [given]: 5
     *     not-owned sub-size: 4          not-owned sub-size: 5
     *     not-owning sub-size: 4         not-owning sub-size: 5
     *
     * This method assumes that (1) the size of the dump, its children, and its
     * owners [see calculateSizes()] and (2) the not-owned and not-owning
     * sub-sizes of both the children and owners of the dump have already been
     * calculated [depth-first post-order traversal].
     */
    calculateDumpSubSizes_: function(dump) {
      // Completely skip dumps with undefined size.
      if (!hasSize(dump))
        return;

      // If the dump is a leaf node, then both sub-sizes are equal to the size.
      if (dump.children === undefined || dump.children.length === 0) {
        var size = getSize(dump);
        dump.notOwningSubSize_ = size;
        dump.notOwnedSubSize_ = size;
        return;
      }

      // Calculate this dump's not-owning sub-size by summing up the not-owning
      // sub-sizes of children MADs which do not own another MAD.
      var notOwningSubSize = 0;
      dump.children.forEach(function(childDump) {
        if (childDump.owns !== undefined)
          return;
        notOwningSubSize += optional(childDump.notOwningSubSize_, 0);
      });
      dump.notOwningSubSize_ = notOwningSubSize;

      // Calculate this dump's not-owned sub-size.
      var notOwnedSubSize = 0;
      dump.children.forEach(function(childDump) {
        // If the child dump is not owned, then add its not-owned sub-size.
        if (childDump.ownedBy.length === 0) {
          notOwnedSubSize += optional(childDump.notOwnedSubSize_, 0);
          return;
        }
        // If the child dump is owned, then add the difference between its size
        // and the largest owner.
        var largestChildOwnerSize = 0;
        childDump.ownedBy.forEach(function(ownershipLink) {
          largestChildOwnerSize = Math.max(
              largestChildOwnerSize, getSize(ownershipLink.source));
        });
        notOwnedSubSize += getSize(childDump) - largestChildOwnerSize;
      });
      dump.notOwnedSubSize_ = notOwnedSubSize;
    },

    /**
     * Calculate owned and owning coefficients of a memory allocator dump and
     * its owners.
     *
     * The owning coefficient refers to the proportion of a dump's not-owning
     * sub-size which is attributed to the dump (only relevant to owning MADs).
     * Conversely, the owned coefficient is the proportion of a dump's
     * not-owned sub-size, which is attributed to it (only relevant to owned
     * MADs).
     *
     * The not-owned size of the owned dump is split among its owners in the
     * order of the ownership importance as demonstrated by the following
     * example:
     *
     *                                          memory allocator dumps
     *                                   OWNED  OWNER1  OWNER2  OWNER3  OWNER4
     *       not-owned sub-size [given]     10       -       -       -       -
     *      not-owning sub-size [given]      -       6       7       5       8
     *               importance [given]      -       2       2       1       0
     *    attributed not-owned sub-size      2       -       -       -       -
     *   attributed not-owning sub-size      -       3       4       0       1
     *                owned coefficient   2/10       -       -       -       -
     *               owning coefficient      -     3/6     4/7     0/5     1/8
     *
     * Explanation: Firstly, 6 bytes are split equally among OWNER1 and OWNER2
     * (highest importance). OWNER2 owns one more byte, so its attributed
     * not-owning sub-size is 6/2 + 1 = 4 bytes. OWNER3 is attributed no size
     * because it is smaller than the owners with higher priority. However,
     * OWNER4 is larger, so it's attributed the difference 8 - 7 = 1 byte.
     * Finally, 2 bytes remain unattributed and are hence kept in the OWNED
     * dump as attributed not-owned sub-size. The coefficients are then
     * directly calculated as fractions of the sub-sizes and corresponding
     * attributed sub-sizes.
     *
     * Note that we always assume that all ownerships of a dump overlap (e.g.
     * OWNER3 is subsumed by both OWNER1 and OWNER2). Hence, the table could
     * be alternatively represented as follows:
     *
     *                                 owned memory range
     *              0   1   2    3    4    5    6        7        8   9  10
     *   Priority 2 |  OWNER1 + OWNER2 (split)  | OWNER2 |
     *   Priority 1 | (already attributed) |
     *   Priority 0 | - - -  (already attributed)  - - - | OWNER4 |
     *    Remainder | - - - - - (already attributed) - - - - - -  | OWNED |
     *
     * This method assumes that (1) the size of the dump [see calculateSizes()]
     * and (2) the not-owned size of the dump and not-owning sub-sizes of its
     * owners [see the first step of calculateEffectiveSizes()] have already
     * been calculated. Note that the method doesn't make any assumptions about
     * the order in which dumps are visited.
     */
    calculateDumpOwnershipCoefficient_: function(dump) {
      // Completely skip dumps with undefined size.
      if (!hasSize(dump))
        return;

      // We only need to consider owned dumps.
      if (dump.ownedBy.length === 0)
        return;

      // Sort the owners in decreasing order of ownership importance and
      // increasing order of not-owning sub-size (in case of equal importance).
      var owners = dump.ownedBy.map(function(ownershipLink) {
        return {
          dump: ownershipLink.source,
          importance: optional(ownershipLink.importance, 0),
          notOwningSubSize: optional(ownershipLink.source.notOwningSubSize_, 0)
        };
      });
      owners.sort(function(a, b) {
        if (a.importance === b.importance)
          return a.notOwningSubSize - b.notOwningSubSize;
        return b.importance - a.importance;
      });

      // Loop over the list of owners and distribute the owned dump's not-owned
      // sub-size among them according to their ownership importance and
      // not-owning sub-size.
      var currentImportanceStartPos = 0;
      var alreadyAttributedSubSize = 0;
      while (currentImportanceStartPos < owners.length) {
        var currentImportance = owners[currentImportanceStartPos].importance;

        // Find the position of the first owner with lower priority.
        var nextImportanceStartPos = currentImportanceStartPos + 1;
        while (nextImportanceStartPos < owners.length &&
               owners[nextImportanceStartPos].importance ===
                  currentImportance) {
          nextImportanceStartPos++;
        }

        // Visit the owners with the same importance in increasing order of
        // not-owned sub-size, split the owned memory among them appropriately,
        // and calculate their owning coefficients.
        var attributedNotOwningSubSize = 0;
        for (var pos = currentImportanceStartPos; pos < nextImportanceStartPos;
             pos++) {
          var owner = owners[pos];
          var notOwningSubSize = owner.notOwningSubSize;
          if (notOwningSubSize > alreadyAttributedSubSize) {
            attributedNotOwningSubSize +=
                (notOwningSubSize - alreadyAttributedSubSize) /
                (nextImportanceStartPos - pos);
            alreadyAttributedSubSize = notOwningSubSize;
          }

          var owningCoefficient = 0;
          if (notOwningSubSize !== 0)
            owningCoefficient = attributedNotOwningSubSize / notOwningSubSize;
          owner.dump.owningCoefficient_ = owningCoefficient;
        }

        currentImportanceStartPos = nextImportanceStartPos;
      }

      // Attribute the remainder of the owned dump's not-owned sub-size to
      // the dump itself and calculate its owned coefficient.
      var notOwnedSubSize = optional(dump.notOwnedSubSize_, 0);
      var remainderSubSize = notOwnedSubSize - alreadyAttributedSubSize;
      var ownedCoefficient = 0;
      if (notOwnedSubSize !== 0)
        ownedCoefficient = remainderSubSize / notOwnedSubSize;
      dump.ownedCoefficient_ = ownedCoefficient;
    },

    /**
     * Calculate cumulative owned and owning coefficients of a memory allocator
     * dump from its (non-cumulative) owned and owning coefficients and the
     * cumulative coefficients of its parent and/or owned dump.
     *
     * The cumulative coefficients represent the total effect of all
     * (non-strict) ancestor ownerships on a memory allocator dump. The
     * cumulative owned coefficient of a MAD can be calculated simply as:
     *
     *   cumulativeOwnedC(M) = ownedC(M) * cumulativeOwnedC(parent(M))
     *
     * This reflects the assumption that if a parent of a child MAD is
     * (partially) owned, then the parent's owner also indirectly owns (a part
     * of) the child MAD.
     *
     * The cumulative owning coefficient of a MAD depends on whether the MAD
     * owns another dump:
     *
     *                           [if M doesn't own another MAD]
     *                         / cumulativeOwningC(parent(M))
     *   cumulativeOwningC(M) =
     *                         \ [if M owns another MAD]
     *                           owningC(M) * cumulativeOwningC(owned(M))
     *
     * The reasoning behind the first case is similar to the one for cumulative
     * owned coefficient above. The only difference is that we don't need to
     * include the dump's (non-cumulative) owning coefficient because it is
     * implicitly 1.
     *
     * The formula for the second case is derived as follows: Since the MAD
     * owns another dump, its memory is not included in its parent's not-owning
     * sub-size and hence shouldn't be affected by the parent's corresponding
     * cumulative coefficient. Instead, the MAD indirectly owns everything
     * owned by its owned dump (and so it should be affected by the
     * corresponding coefficient).
     *
     * Note that undefined coefficients (and coefficients of non-existent
     * dumps) are implicitly assumed to be 1.
     *
     * This method assumes that (1) the size of the dump [see calculateSizes()],
     * (2) the (non-cumulative) owned and owning coefficients of the dump [see
     * the second step of calculateEffectiveSizes()], and (3) the cumulative
     * coefficients of the dump's parent and owned MADs (if present)
     * [depth-first pre-order traversal] have already been calculated.
     */
    calculateDumpCumulativeOwnershipCoefficient_: function(dump) {
      // Completely skip dumps with undefined size.
      if (!hasSize(dump))
        return;

      var cumulativeOwnedCoefficient = optional(dump.ownedCoefficient_, 1);
      var parent = dump.parent;
      if (dump.parent !== undefined)
        cumulativeOwnedCoefficient *= dump.parent.cumulativeOwnedCoefficient_;
      dump.cumulativeOwnedCoefficient_ = cumulativeOwnedCoefficient;

      var cumulativeOwningCoefficient;
      if (dump.owns !== undefined) {
        cumulativeOwningCoefficient = dump.owningCoefficient_ *
            dump.owns.target.cumulativeOwningCoefficient_;
      } else if (dump.parent !== undefined) {
        cumulativeOwningCoefficient = dump.parent.cumulativeOwningCoefficient_;
      } else {
        cumulativeOwningCoefficient = 1;
      }
      dump.cumulativeOwningCoefficient_ = cumulativeOwningCoefficient;
    },

    /**
     * Calculate the effective size of a memory allocator dump.
     *
     * In order to simplify the (already complex) calculation, we use the fact
     * that effective size is cumulative (unlike regular size), i.e. the
     * effective size of a non-leaf node is equal to the sum of effective sizes
     * of its children. The effective size of a leaf MAD is calculated as:
     *
     *   effectiveSize(M) = size(M) * cumulativeOwningC(M) * cumulativeOwnedC(M)
     *
     * This method assumes that (1) the size of the dump and its children [see
     * calculateSizes()] and (2) the cumulative owning and owned coefficients
     * of the dump (if it's a leaf node) [see the third step of
     * calculateEffectiveSizes()] or the effective sizes of its children (if
     * it's a non-leaf node) [depth-first post-order traversal] have already
     * been calculated.
     */
    calculateDumpEffectiveSize_: function(dump) {
      // Completely skip dumps with undefined size. As a result, each dump will
      // have defined effective size if and only if it has defined size.
      if (!hasSize(dump)) {
        // The rest of the pipeline relies on effective size being either a
        // valid ScalarAttribute, or undefined.
        dump.attributes[EFFECTIVE_SIZE_ATTRIBUTE_NAME] = undefined;
        return;
      }

      var effectiveSize;
      if (dump.children === undefined || dump.children.length === 0) {
        // Leaf dump.
        effectiveSize = getSize(dump) * dump.cumulativeOwningCoefficient_ *
            dump.cumulativeOwnedCoefficient_;
      } else {
        // Non-leaf dump.
        effectiveSize = 0;
        dump.children.forEach(function(childDump) {
          if (!hasSize(childDump))
            return;
          effectiveSize +=
              childDump.attributes[EFFECTIVE_SIZE_ATTRIBUTE_NAME].value;
        });
      }
      var attribute = new tr.model.ScalarAttribute('bytes', effectiveSize);
      dump.attributes[EFFECTIVE_SIZE_ATTRIBUTE_NAME] = attribute;

      // Add attribute infos regarding ownership (if applicable).
      // TODO(petrcermak): This belongs to the corresponding analysis UI code.
      if (dump.ownedBy.length > 0) {
        var message = 'shared by:' +
            dump.ownedBy.map(function(ownershipLink) {
              return '\n  - ' + ownershipToUserFriendlyString(
                  ownershipLink.source, ownershipLink.importance);
            }).join();
        attribute.infos.push(new tr.model.AttributeInfo(
            tr.model.AttributeInfoType.MEMORY_OWNED, message));
      }
      if (dump.owns !== undefined) {
        var target = dump.owns.target;
        var message = 'shares ' +
            ownershipToUserFriendlyString(target, dump.owns.importance) +
            ' with';

        var otherOwnershipLinks = target.ownedBy.filter(
            function(ownershipLink) {
          return ownershipLink.source !== dump;
        });
        if (otherOwnershipLinks.length > 0) {
          message += ':';
          message += otherOwnershipLinks.map(function(ownershipLink) {
            return '\n  - ' + ownershipToUserFriendlyString(
                ownershipLink.source, ownershipLink.importance);
          }).join();
        } else {
          message += ' no other dumps';
        }

        attribute.infos.push(new tr.model.AttributeInfo(
            tr.model.AttributeInfoType.MEMORY_OWNER, message));
      }
    },

    aggregateAttributes: function() {
      // 1. Aggregate attributes in this global memory dump.
      this.iterateRootAllocatorDumps(function(dump) {
        dump.aggregateAttributes(this.model);
      });

      // 2. Propagate attributes from global memory allocator dumps to their
      // owners.
      this.iterateRootAllocatorDumps(this.propagateAttributesRecursively);

      // 3. Aggregate attributes in the associated process memory dumps.
      tr.b.iterItems(this.processMemoryDumps, function(pid, processMemoryDump) {
        processMemoryDump.iterateRootAllocatorDumps(function(dump) {
          dump.aggregateAttributes(this.model);
        }, this);
      }, this);
    },

    propagateAttributesRecursively: function(globalAllocatorDump) {
      tr.b.iterItems(globalAllocatorDump.attributes, function(attrName, attr) {
        if (attrName === SIZE_ATTRIBUTE_NAME ||
            attrName === EFFECTIVE_SIZE_ATTRIBUTE_NAME) {
          // We cannot propagate size and effective_size attributes because it
          // would break the complex maths [see calculateSizes() and
          // calculateEffectiveSizes()].
          return;
        }
        globalAllocatorDump.ownedBy.forEach(function(ownershipLink) {
          var processAllocatorDump = ownershipLink.source;
          if (processAllocatorDump.attributes[attrName] !== undefined) {
            // Attributes provided by process memory allocator dumps themselves
            // have precedence over attributes propagated from global memory
            // allocator dumps.
            return;
          }
          processAllocatorDump.attributes[attrName] = attr;
        });
      });
      // Recursively propagate attributes from all child memory allocator dumps.
      globalAllocatorDump.children.forEach(
          this.propagateAttributesRecursively, this);
    },

    setUpTracingOverheadOwnership: function() {
      tr.b.iterItems(this.processMemoryDumps, function(pid, dump) {
        dump.setUpTracingOverheadOwnership(this.model);
      }, this);
    },

    discountTracingOverheadFromVmRegions: function() {
      // TODO(petrcermak): Consider factoring out all the finalization code and
      // constants to a single file.
      tr.b.iterItems(this.processMemoryDumps, function(pid, dump) {
        dump.discountTracingOverheadFromVmRegions(this.model);
      }, this);
    },

    iterateContainerDumps: function(fn) {
      fn.call(this, this);
      tr.b.iterItems(this.processMemoryDumps, function(pid, processDump) {
        fn.call(this, processDump);
      }, this);
    },

    iterateAllRootAllocatorDumps: function(fn) {
      this.iterateContainerDumps(function(containerDump) {
        containerDump.iterateRootAllocatorDumps(fn, this);
      });
    },

    /**
     * Traverse the memory dump graph in a depth first post-order, i.e.
     * children and owners of a memory allocator dump are visited before the
     * dump itself. This method will throw an exception if the graph contains
     * a cycle.
     */
    traverseAllocatorDumpsInDepthFirstPostOrder: function(fn) {
      var visitedDumps = new WeakSet();
      var openDumps = new WeakSet();

      function visit(dump) {
        if (visitedDumps.has(dump))
          return;

        if (openDumps.has(dump))
          throw new Error(dump.userFriendlyName + ' contains a cycle');
        openDumps.add(dump);

        // Visit owners before the dumps they own.
        dump.ownedBy.forEach(function(ownershipLink) {
          visit.call(this, ownershipLink.source);
        }, this);

        // Visit children before parents.
        dump.children.forEach(visit, this);

        // Actually visit the current memory allocator dump.
        fn.call(this, dump);
        visitedDumps.add(dump);

        openDumps.delete(dump);
      }

      this.iterateAllRootAllocatorDumps(visit);
    },

    /**
     * Traverse the memory dump graph in a depth first pre-order, i.e.
     * children and owners of a memory allocator dump are visited after the
     * dump itself. This method will not visit some dumps if the graph contains
     * a cycle.
     */
    traverseAllocatorDumpsInDepthFirstPreOrder: function(fn) {
      var visitedDumps = new WeakSet();

      function visit(dump) {
        if (visitedDumps.has(dump))
          return;

        // If this dumps owns another dump which hasn't been visited yet, then
        // wait for this dump to be visited later.
        if (dump.owns !== undefined && !visitedDumps.has(dump.owns.target))
          return;

        // If this dump's parent hasn't been visited yet, then wait for this
        // dump to be visited later.
        if (dump.parent !== undefined && !visitedDumps.has(dump.parent))
          return;

        // Actually visit the current memory allocator dump.
        fn.call(this, dump);
        visitedDumps.add(dump);

        // Visit owners after the dumps they own.
        dump.ownedBy.forEach(function(ownershipLink) {
          visit.call(this, ownershipLink.source);
        }, this);

        // Visit children after parents.
        dump.children.forEach(visit, this);
      }

      this.iterateAllRootAllocatorDumps(visit);
    }
  };

  tr.model.EventRegistry.register(
      GlobalMemoryDump,
      {
        name: 'globalMemoryDump',
        pluralName: 'globalMemoryDumps',
        singleViewElementName: 'tr-ui-a-container-memory-dump-sub-view',
        multiViewElementName: 'tr-ui-a-container-memory-dump-sub-view'
      });

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