<!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/iteration_helpers.html">
<link rel="import" href="/tracing/model/container_memory_dump.html">
<link rel="import" href="/tracing/model/event_registry.html">
<link rel="import" href="/tracing/model/memory_allocator_dump.html">
<link rel="import" href="/tracing/value/numeric.html">
<link rel="import" href="/tracing/value/unit.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 = {};
  }

  // Size numeric names.
  var SIZE_NUMERIC_NAME = tr.model.MemoryAllocatorDump.SIZE_NUMERIC_NAME;
  var EFFECTIVE_SIZE_NUMERIC_NAME =
      tr.model.MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME;

  // Size numeric info types.
  var MemoryAllocatorDumpInfoType = tr.model.MemoryAllocatorDumpInfoType;
  var PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN =
      MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN;
  var PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER =
      MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER;

  // TODO(petrcermak): Move this to tracing/base/iteration_helpers.html.
  function inPlaceFilter(array, predicate, opt_this) {
    opt_this = opt_this || this;
    var nextPosition = 0;
    for (var i = 0; i < array.length; i++) {
      if (!predicate.call(opt_this, array[i], i))
        continue;
      if (nextPosition < i)
        array[nextPosition] = array[i];  // Move elements only if necessary.
      nextPosition++;
    }

    if (nextPosition < array.length)
      array.length = nextPosition;  // Truncate the array only if necessary.
  }

  function getSize(dump) {
    var numeric = dump.numerics[SIZE_NUMERIC_NAME];
    if (numeric === undefined)
      return 0;
    return numeric.value;
  }

  function hasSize(dump) {
    return dump.numerics[SIZE_NUMERIC_NAME] !== undefined;
  }

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

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

    get userFriendlyName() {
      return 'Global memory dump at ' +
          tr.v.Unit.byName.timeStampInMs.format(this.start);
    },

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

    finalizeGraph: function() {
      // 1. Transitively remove weak memory allocator dumps and all their
      // owners and descendants from the model. This must be performed before
      // any other steps.
      this.removeWeakDumps();

      // 2. 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();

      // 3. Aggregate all other numerics of all MADs (*excluding* sizes and
      // effective sizes) and propagate numerics from global MADs to their
      // owners (*including* sizes and effective sizes). This step must be
      // carried out before the sizes of all MADs are calculated (step 3).
      // Otherwise, the propagated sizes of all MADs would not be aggregated.
      this.aggregateNumerics();

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

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

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

      // 7. The above steps (especially steps 1 and 3) can create new memory
      // allocator dumps, so we force rebuilding the memory allocator dump
      // indices of all container memory dumps.
      this.forceRebuildingMemoryAllocatorDumpByFullNameIndices();
    },

    removeWeakDumps: function() {
      // Mark all transitive owners and children of weak memory allocator dumps
      // as weak.
      this.traverseAllocatorDumpsInDepthFirstPreOrder(function(dump) {
        if (dump.weak)
          return;
        if ((dump.owns !== undefined && dump.owns.target.weak) ||
            (dump.parent !== undefined && dump.parent.weak)) {
          dump.weak = true;
        }
      });

      function removeWeakDumpsFromListRecursively(dumps) {
        inPlaceFilter(dumps, function(dump) {
          if (dump.weak) {
            // The dump is weak, so remove it. This will implicitly remove all
            // its descendants, which are also weak due to the initial marking
            // step.
            return false;
          }

          // This dump is non-weak, so keep it. Recursively remove its weak
          // descendants and ownership links from weak dumps instead.
          removeWeakDumpsFromListRecursively(dump.children);
          inPlaceFilter(dump.ownedBy, function(ownershipLink) {
            return !ownershipLink.source.weak;
          });

          return true;
        });
      }

      this.iterateContainerDumps(function(containerDump) {
        var memoryAllocatorDumps = containerDump.memoryAllocatorDumps;
        if (memoryAllocatorDumps !== undefined)
          removeWeakDumpsFromListRecursively(memoryAllocatorDumps);
      });
    },

    /**
     * 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 numeric provided by
     * MemoryAllocatorDump(s):
     *
     *   - If a MAD provides a size numeric, then its size is assumed to be
     *     equal to it.
     *   - If a MAD does not provide a size numeric, 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 numeric of the current dump should
      // be defined, i.e. if (1) the current dump's size numeric 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 value of the size numeric of the
      // given dependent memory allocator dump. If the numeric 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 numeric = dependencyDump.numerics[SIZE_NUMERIC_NAME];
        if (numeric === undefined)
          return 0;
        shouldDefineSize = true;
        return numeric.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 sizeNumeric = dump.numerics[SIZE_NUMERIC_NAME];
      var size = 0;
      var checkDependencySizeIsConsistent = function() { /* no-op */ };
      if (sizeNumeric !== undefined) {
        size = sizeNumeric.value;
        shouldDefineSize = true;
        if (sizeNumeric.unit !== tr.v.Unit.byName.sizeInBytes_smallerIsBetter) {
          this.model.importWarning({
            type: 'memory_dump_parse_error',
            message: 'Invalid unit of \'size\' numeric of memory allocator ' +
                'dump ' + dump.quantifiedName + ': ' +
                sizeNumeric.unit.unitName + '.'
          });
        }
        checkDependencySizeIsConsistent = function(
            dependencySize, dependencyInfoType, dependencyName) {
          if (size >= dependencySize)
            return;
          this.model.importWarning({
            type: 'memory_dump_parse_error',
            message: 'Size provided by memory allocator dump \'' +
                dump.fullName + '\'' +
                tr.v.Unit.byName.sizeInBytes.format(size) +
                ') is less than ' + dependencyName + ' (' +
                tr.v.Unit.byName.sizeInBytes.format(dependencySize) + ').'
          });
          dump.infos.push({
            type: dependencyInfoType,
            providedSize: size,
            dependencySize: dependencySize
          });
        }.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 ownedChildDump = ownedDumpLink.target;
            while (ownedChildDump.parent !== dump)
              ownedChildDump = ownedChildDump.parent;
            if (childDump !== ownedChildDump) {
              var ownedBySiblingSize = getDependencySize(descendantDump);
              if (ownedBySiblingSize > 0) {
                var previousTotalOwnedBySiblingSize =
                    ownedChildDump.ownedBySiblingSizes.get(childDump) || 0;
                var updatedTotalOwnedBySiblingSize =
                    previousTotalOwnedBySiblingSize + ownedBySiblingSize;
                ownedChildDump.ownedBySiblingSizes.set(
                    childDump, updatedTotalOwnedBySiblingSize);
              }
            }
            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);
      });
      checkDependencySizeIsConsistent(
          aggregatedChildrenSize,
          PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN,
          '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);
      });
      checkDependencySizeIsConsistent(
          largestOwnerSize,
          PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER,
          '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 numeric.
      if (!shouldDefineSize) {
        // The rest of the pipeline relies on size being either a valid
        // ScalarNumeric, or undefined.
        delete dump.numerics[SIZE_NUMERIC_NAME];
        return;
      }

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

      dump.numerics[SIZE_NUMERIC_NAME] = new tr.v.ScalarNumeric(
          tr.v.Unit.byName.sizeInBytes_smallerIsBetter, size);

      // 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.numerics[SIZE_NUMERIC_NAME] = new tr.v.ScalarNumeric(
            tr.v.Unit.byName.sizeInBytes_smallerIsBetter,
            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 ScalarNumeric, or undefined.
        delete dump.numerics[EFFECTIVE_SIZE_NUMERIC_NAME];
        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.numerics[EFFECTIVE_SIZE_NUMERIC_NAME].value;
        });
      }
      dump.numerics[EFFECTIVE_SIZE_NUMERIC_NAME] = new tr.v.ScalarNumeric(
          tr.v.Unit.byName.sizeInBytes_smallerIsBetter, effectiveSize);
    },

    aggregateNumerics: function() {
      // 1. Aggregate numerics in this global memory dump.
      this.iterateRootAllocatorDumps(function(dump) {
        dump.aggregateNumericsRecursively(this.model);
      });

      // 2. Propagate numerics and diagnostics from global memory allocator
      // dumps to their owners.
      this.iterateRootAllocatorDumps(
          this.propagateNumericsAndDiagnosticsRecursively);

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

    propagateNumericsAndDiagnosticsRecursively: function(globalAllocatorDump) {
      ['numerics', 'diagnostics'].forEach(function(field) {
        tr.b.iterItems(globalAllocatorDump[field], function(name, value) {
          globalAllocatorDump.ownedBy.forEach(function(ownershipLink) {
            var processAllocatorDump = ownershipLink.source;
            if (processAllocatorDump[field][name] !== undefined) {
              // Numerics and diagnostics provided by process memory allocator
              // dumps themselves have precedence over numerics and diagnostics
              // propagated from global memory allocator dumps.
              return;
            }
            processAllocatorDump[field][name] = value;
          });
        });
      });

      // Recursively propagate numerics from all child memory allocator dumps.
      globalAllocatorDump.children.forEach(
          this.propagateNumericsAndDiagnosticsRecursively, 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);
    },

    forceRebuildingMemoryAllocatorDumpByFullNameIndices: function() {
      this.iterateContainerDumps(function(containerDump) {
        containerDump.forceRebuildingMemoryAllocatorDumpByFullNameIndex();
      });
    },

    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>
