<!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/ui/base/dom_helpers.html">
<link rel="import" href="/tracing/value/numeric.html">
<link rel="import" href="/tracing/value/ui/scalar_span.html">

<script>
'use strict';

/**
 * @fileoverview Helper code for memory dump sub-views.
 */
tr.exportTo('tr.ui.analysis', function() {

  var NO_BREAK_SPACE = String.fromCharCode(160);
  var RIGHTWARDS_ARROW = String.fromCharCode(8594);

  var COLLATOR = new Intl.Collator(undefined, {numeric: true});

  /**
   * A table column for displaying memory dump row titles.
   *
   * @constructor
   */
  function TitleColumn(title) {
    this.title = title;
  }

  TitleColumn.prototype = {
    supportsCellSelection: false,

    /**
     * Get the title associated with a given row.
     *
     * This method will decorate the title with color and '+++'/'---' prefix if
     * appropriate (as determined by the optional row.contexts field).
     * Examples:
     *
     *   +----------------------+-----------------+--------+--------+
     *   | Contexts provided at | Interpretation  | Prefix | Color  |
     *   +----------------------+-----------------+--------+--------+
     *   | 1111111111           | always present  |        |        |
     *   | 0000111111           | added           | +++    | red    |
     *   | 1111111000           | deleted         | ---    | green  |
     *   | 1100111111*          | flaky           |        | purple |
     *   | 0001001111           | added + flaky   | +++    | purple |
     *   | 1111100010           | deleted + flaky | ---    | purple |
     *   +----------------------+-----------------+--------+--------+
     *
     *   *) This means that, given a selection of 10 memory dumps, a particular
     *      row (e.g. a process) was present in the first 2 and last 6 of them
     *      (but not in the third and fourth dump).
     *
     * This method should therefore NOT be overriden by subclasses. The
     * formatTitle method should be overriden instead when necessary.
     */
    value: function(row) {
      var formattedTitle = this.formatTitle(row);

      var contexts = row.contexts;
      if (contexts === undefined || contexts.length === 0)
        return formattedTitle;

      // Determine if the row was provided in the first and last row and how
      // many times it changed between being provided and not provided.
      var firstContext = contexts[0];
      var lastContext = contexts[contexts.length - 1];
      var changeDefinedContextCount = 0;
      for (var i = 1; i < contexts.length; i++) {
        if ((contexts[i] === undefined) !== (contexts[i - 1] === undefined))
          changeDefinedContextCount++;
      }

      // Determine the color and prefix of the title.
      var color = undefined;
      var prefix = undefined;
      if (!firstContext && lastContext) {
        // The row was added.
        color = 'red';
        prefix = '+++';
      } else if (firstContext && !lastContext) {
        // The row was removed.
        color = 'green';
        prefix = '---';
      }
      if (changeDefinedContextCount > 1) {
        // The row was flaky (added/removed more than once).
        color = 'purple';
      }

      if (color === undefined && prefix === undefined)
        return formattedTitle;

      var titleEl = document.createElement('span');
      if (prefix !== undefined) {
        var prefixEl = tr.ui.b.createSpan({textContent: prefix});
        // Enforce same width of '+++' and '---'.
        prefixEl.style.fontFamily = 'monospace';
        titleEl.appendChild(prefixEl);
        titleEl.appendChild(tr.ui.b.asHTMLOrTextNode(NO_BREAK_SPACE));
      }
      if (color !== undefined)
        titleEl.style.color = color;
      titleEl.appendChild(tr.ui.b.asHTMLOrTextNode(formattedTitle));
      return titleEl;
    },

    /**
     * Format the title associated with a given row. This method is intended to
     * be overriden by subclasses.
     */
    formatTitle: function(row) {
      return row.title;
    },

    cmp: function(rowA, rowB) {
      return COLLATOR.compare(rowA.title, rowB.title);
    }
  };

  /**
   * Abstract table column for displaying memory dump data.
   *
   * @constructor
   */
  function MemoryColumn(name, cellPath, aggregationMode) {
    this.name = name;
    this.cellPath = cellPath;

    // See MemoryColumn.AggregationMode enum in this file.
    this.aggregationMode = aggregationMode;
  }

  /**
   * Construct columns from cells in a hierarchy of rows and a list of rules.
   *
   * The list of rules contains objects with three fields:
   *
   *   condition: Optional string or regular expression matched against the
   *       name of a cell. If omitted, the rule will match any cell.
   *   importance: Mandatory number which determines the final order of the
   *       columns. The column with the highest importance will be first in the
   *       returned array.
   *   columnConstructor: Mandatory memory column constructor.
   *
   * Example:
   *
   *   var importanceRules = [
   *     {
   *       condition: 'page_size',
   *       columnConstructor: NumericMemoryColumn,
   *       importance: 8
   *     },
   *     {
   *       condition: /size/,
   *       columnConstructor: CustomNumericMemoryColumn,
   *       importance: 10
   *     },
   *     {
   *       // No condition: matches all columns.
   *       columnConstructor: NumericMemoryColumn,
   *       importance: 9
   *     }
   *   ];
   *
   * Given a name of a cell, the corresponding column constructor and
   * importance are determined by the first rule whose condition matches the
   * column's name. For example, given a cell with name 'inner_size', the
   * corresponding column will be constructed using CustomNumericMemoryColumn
   * and its importance (for sorting purposes) will be 10 (second rule).
   *
   * After columns are constructed for all cell names, they are sorted in
   * descending order of importance and the resulting list is returned. In the
   * example above, the constructed columns will be sorted into three groups as
   * follows:
   *
   *      [most important, left in the resulting table]
   *   1. columns whose name contains 'size' excluding 'page_size' because it
   *      would have already matched the first rule (Note that string matches
   *      must be exact so a column named 'page_size2' would not match the
   *      first rule and would therefore belong to this group).
   *   2. columns whose name does not contain 'size'.
   *   3. columns whose name is 'page_size'.
   *      [least important, right in the resulting table]
   *
   * where columns will be sorted alphabetically within each group.
   */
  MemoryColumn.fromRows = function(rows, cellKey, aggregationMode, rules) {
    // Recursively find the names of all cells of the rows (and their sub-rows).
    var cellNames = new Set();
    function gatherCellNames(rows) {
      rows.forEach(function(row) {
        if (row === undefined)
          return;
        var fieldCells = row[cellKey];
        if (fieldCells !== undefined) {
          tr.b.iterItems(fieldCells, function(fieldName, fieldCell) {
            if (fieldCell === undefined || fieldCell.fields === undefined)
              return;
            cellNames.add(fieldName);
          });
        }
        var subRows = row.subRows;
        if (subRows !== undefined)
          gatherCellNames(subRows);
      });
    }
    gatherCellNames(rows);

    // Based on the provided list of rules, construct the columns and calculate
    // their importance.
    var positions = [];
    cellNames.forEach(function(cellName) {
      var cellPath = [cellKey, cellName];
      var matchingRule = MemoryColumn.findMatchingRule(cellName, rules);
      var constructor = matchingRule.columnConstructor;
      var column = new constructor(cellName, cellPath, aggregationMode);
      positions.push({
        importance: matchingRule.importance,
        column: column
      });
    });

    positions.sort(function(a, b) {
      // Sort columns with the same importance alphabetically.
      if (a.importance === b.importance)
        return COLLATOR.compare(a.column.name, b.column.name);

      // Sort columns in descending order of importance.
      return b.importance - a.importance;
    });

    return positions.map(function(position) { return position.column });
  };

  MemoryColumn.spaceEqually = function(columns) {
    var columnWidth = (100 / columns.length).toFixed(3) + '%';
    columns.forEach(function(column) {
      column.width = columnWidth;
    });
  };

  MemoryColumn.findMatchingRule = function(name, rules) {
    for (var i = 0; i < rules.length; i++) {
      var rule = rules[i];
      if (MemoryColumn.nameMatchesCondition(name, rule.condition))
        return rule;
    }
    return undefined;
  };

  MemoryColumn.nameMatchesCondition = function(name, condition) {
    // Rules without conditions match all columns.
    if (condition === undefined)
      return true;

    // String conditions must match the column name exactly.
    if (typeof(condition) === 'string')
      return name === condition;

    // If the condition is not a string, assume it is a RegExp.
    return condition.test(name);
  };

  /** @enum */
  MemoryColumn.AggregationMode = {
    DIFF: 0,
    MAX: 1
  };

  MemoryColumn.SOME_TIMESTAMPS_INFO_QUANTIFIER = 'at some selected timestamps';

  MemoryColumn.prototype = {
    get title() {
      return this.name;
    },

    cell: function(row) {
      var cell = row;
      var cellPath = this.cellPath;
      for (var i = 0; i < cellPath.length; i++) {
        if (cell === undefined)
          return undefined;
        cell = cell[cellPath[i]];
      }
      return cell;
    },

    aggregateCells: function(row, subRows) {
      // No generic aggregation.
    },

    fields: function(row) {
      var cell = this.cell(row);
      if (cell === undefined)
        return undefined;
      return cell.fields;
    },

    /**
     * Format a cell associated with this column from the given row. This
     * method is not intended to be overriden.
     */
    value: function(row) {
      var fields = this.fields(row);
      if (this.hasAllRelevantFieldsUndefined(fields))
        return '';

      // Determine the color and infos of the resulting element.
      var contexts = row.contexts;
      var color = this.color(fields, contexts);
      var infos = [];
      this.addInfos(fields, contexts, infos);

      // Format the actual fields.
      var formattedFields = this.formatFields(fields);

      // If no color is specified and there are no infos, there is no need to
      // wrap the value in a span element.#
      if ((color === undefined || formattedFields === '') && infos.length === 0)
        return formattedFields;

      var fieldEl = document.createElement('span');
      fieldEl.style.display = 'flex';
      fieldEl.style.alignItems = 'center';
      fieldEl.appendChild(tr.ui.b.asHTMLOrTextNode(formattedFields));

      // Add info icons with tooltips.
      infos.forEach(function(info) {
        var infoEl = document.createElement('span');
        infoEl.style.paddingLeft = '4px';
        infoEl.style.cursor = 'help';
        infoEl.style.fontWeight = 'bold';
        infoEl.textContent = info.icon;
        if (info.color !== undefined)
          infoEl.style.color = info.color;
        infoEl.title = info.message;
        fieldEl.appendChild(infoEl);
      }, this);

      // Set the color of the element.
      if (color !== undefined)
        fieldEl.style.color = color;

      return fieldEl;
    },

    /**
     * Returns true iff all fields of a row which are relevant for the current
     * aggregation mode (e.g. first and last field for diff mode) are undefined.
     */
    hasAllRelevantFieldsUndefined: function(fields) {
      if (fields === undefined)
        return true;

      switch (this.aggregationMode) {
        case MemoryColumn.AggregationMode.DIFF:
          // Only the first and last field are relevant.
          return fields[0] === undefined &&
              fields[fields.length - 1] === undefined;

        case MemoryColumn.AggregationMode.MAX:
        default:
          // All fields are relevant.
          return fields.every(function(field) { return field === undefined; });
      }
    },

    /**
     * Get the color of the given fields formatted by this column. At least one
     * field relevant for the current aggregation mode is guaranteed to be
     * defined.
     */
    color: function(fields, contexts) {
      return undefined;
    },

    /**
     * Format an arbitrary number of fields. At least one field relevant for
     * the current aggregation mode is guaranteed to be defined.
     */
    formatFields: function(fields) {
      if (fields.length === 1)
        return this.formatSingleField(fields[0]);
      else
        return this.formatMultipleFields(fields);
    },

    /**
     * Format a single defined field.
     *
     * This method is intended to be overriden by field type specific columns
     * (e.g. show '1.0 KiB' instead of '1024' for ScalarNumeric(s) representing
     * bytes).
     */
    formatSingleField: function(field) {
      throw new Error('Not implemented');
    },

    /**
     * Format multiple fields. At least one field relevant for the current
     * aggregation mode is guaranteed to be defined.
     *
     * The aggregation mode specializations of this method (e.g.
     * formatMultipleFieldsDiff) are intended to be overriden by field type
     * specific columns.
     */
    formatMultipleFields: function(fields) {
      switch (this.aggregationMode) {
        case MemoryColumn.AggregationMode.DIFF:
          return this.formatMultipleFieldsDiff(
              fields[0], fields[fields.length - 1]);

        case MemoryColumn.AggregationMode.MAX:
          return this.formatMultipleFieldsMax(fields);

        default:
          return tr.ui.b.createSpan({
            textContent: '(unsupported aggregation mode)',
            italic: true
          });
      }
    },

    formatMultipleFieldsDiff: function(firstField, lastField) {
      throw new Error('Not implemented');
    },

    formatMultipleFieldsMax: function(fields) {
      return this.formatSingleField(this.getMaxField(fields));
    },

    cmp: function(rowA, rowB) {
      var fieldsA = this.fields(rowA);
      var fieldsB = this.fields(rowB);

      // Sanity check.
      if (fieldsA !== undefined && fieldsB !== undefined &&
          fieldsA.length !== fieldsB.length)
        throw new Error('Different number of fields');

      // Handle empty fields.
      var undefinedA = this.hasAllRelevantFieldsUndefined(fieldsA);
      var undefinedB = this.hasAllRelevantFieldsUndefined(fieldsB);
      if (undefinedA && undefinedB)
        return 0;
      if (undefinedA)
        return -1;
      if (undefinedB)
        return 1;

      return this.compareFields(fieldsA, fieldsB);
    },

    /**
     * Compare a pair of single or multiple fields. At least one field relevant
     * for the current aggregation mode is guaranteed to be defined in each of
     * the two lists.
     */
    compareFields: function(fieldsA, fieldsB) {
      if (fieldsA.length === 1)
        return this.compareSingleFields(fieldsA[0], fieldsB[0]);
      else
        return this.compareMultipleFields(fieldsA, fieldsB);
    },

    /**
     * Compare a pair of single defined fields.
     *
     * This method is intended to be overriden by field type specific columns.
     */
    compareSingleFields: function(fieldA, fieldB) {
      throw new Error('Not implemented');
    },

    /**
     * Compare a pair of multiple fields. At least one field relevant for the
     * current aggregation mode is guaranteed to be defined in each of the two
     * lists.
     *
     * The aggregation mode specializations of this method (e.g.
     * compareMultipleFieldsDiff) are intended to be overriden by field type
     * specific columns.
     */
    compareMultipleFields: function(fieldsA, fieldsB) {
      switch (this.aggregationMode) {
        case MemoryColumn.AggregationMode.DIFF:
          return this.compareMultipleFieldsDiff(
              fieldsA[0], fieldsA[fieldsA.length - 1],
              fieldsB[0], fieldsB[fieldsB.length - 1]);

        case MemoryColumn.AggregationMode.MAX:
          return this.compareMultipleFieldsMax(fieldsA, fieldsB);

        default:
          return 0;
      }
    },

    compareMultipleFieldsDiff: function(firstFieldA, lastFieldA, firstFieldB,
        lastFieldB) {
      throw new Error('Not implemented');
    },

    compareMultipleFieldsMax: function(fieldsA, fieldsB) {
      return this.compareSingleFields(
          this.getMaxField(fieldsA), this.getMaxField(fieldsB));
    },

    getMaxField: function(fields) {
      return fields.reduce(function(accumulator, field) {
        if (field === undefined)
          return accumulator;
        if (accumulator === undefined ||
            this.compareSingleFields(field, accumulator) > 0) {
          return field;
        }
        return accumulator;
      }.bind(this), undefined);
    },

    addInfos: function(fields, contexts, infos) {
      // No generic infos.
    },

    getImportance: function(importanceRules) {
      if (importanceRules.length === 0)
        return 0;

      // Find the first matching rule.
      var matchingRule =
          MemoryColumn.findMatchingRule(this.name, importanceRules);
      if (matchingRule !== undefined)
        return matchingRule.importance;

      // No matching rule. Return lower importance than all rules.
      var minImportance = importanceRules[0].importance;
      for (var i = 1; i < importanceRules.length; i++)
        minImportance = Math.min(minImportance, importanceRules[i].importance);
      return minImportance - 1;
    }
  };

  /**
   * @constructor
   */
  function StringMemoryColumn(name, cellPath, aggregationMode) {
    MemoryColumn.call(this, name, cellPath, aggregationMode);
  }

  StringMemoryColumn.prototype = {
    __proto__: MemoryColumn.prototype,

    formatSingleField: function(string) {
      return string;
    },

    formatMultipleFieldsDiff: function(firstString, lastString) {
      if (firstString === undefined) {
        // String was added ("+NEW_VALUE" in red).
        var spanEl = tr.ui.b.createSpan({color: 'red'});
        spanEl.appendChild(tr.ui.b.asHTMLOrTextNode('+'));
        spanEl.appendChild(tr.ui.b.asHTMLOrTextNode(
            this.formatSingleField(lastString)));
        return spanEl;
      } else if (lastString === undefined) {
        // String was removed ("-OLD_VALUE" in green).
        var spanEl = tr.ui.b.createSpan({color: 'green'});
        spanEl.appendChild(tr.ui.b.asHTMLOrTextNode('-'));
        spanEl.appendChild(tr.ui.b.asHTMLOrTextNode(
            this.formatSingleField(firstString)));
        return spanEl;
      } else if (firstString === lastString) {
        // String didn't change ("VALUE" with unchanged color).
        return this.formatSingleField(firstString);
      } else {
        // String changed ("OLD_VALUE -> NEW_VALUE" in orange).
        var spanEl = tr.ui.b.createSpan({color: 'DarkOrange'});
        spanEl.appendChild(tr.ui.b.asHTMLOrTextNode(
            this.formatSingleField(firstString)));
        spanEl.appendChild(tr.ui.b.asHTMLOrTextNode(
            ' ' + RIGHTWARDS_ARROW + ' '));
        spanEl.appendChild(tr.ui.b.asHTMLOrTextNode(
            this.formatSingleField(lastString)));
        return spanEl;
      }
    },

    compareSingleFields: function(stringA, stringB) {
      return COLLATOR.compare(stringA, stringB);
    },

    compareMultipleFieldsDiff: function(firstStringA, lastStringA, firstStringB,
        lastStringB) {
      // If one of the strings was added (and the other one wasn't), mark the
      // corresponding diff as greater.
      if (firstStringA === undefined && firstStringB !== undefined)
        return 1;
      if (firstStringA !== undefined && firstStringB === undefined)
        return -1;

      // If both strings were added, compare the last values (greater last
      // value implies greater diff).
      if (firstStringA === undefined && firstStringB === undefined)
        return this.compareSingleFields(lastStringA, lastStringB);

      // If one of the strings was removed (and the other one wasn't), mark the
      // corresponding diff as lower.
      if (lastStringA === undefined && lastStringB !== undefined)
        return -1;
      if (lastStringA !== undefined && lastStringB === undefined)
        return 1;

      // If both strings were removed, compare the first values (greater first
      // value implies smaller (!) diff).
      if (lastStringA === undefined && lastStringB === undefined)
        return this.compareSingleFields(firstStringB, firstStringA);

      var areStringsAEqual = firstStringA === lastStringA;
      var areStringsBEqual = firstStringB === lastStringB;

      // Consider diffs of strings that did not change to be smaller than diffs
      // of strings that did change.
      if (areStringsAEqual && areStringsBEqual)
        return 0;
      if (areStringsAEqual)
        return -1;
      if (areStringsBEqual)
        return 1;

      // Both strings changed. We are unable to determine the ordering of the
      // diffs.
      return 0;
    }
  };

  /**
   * @constructor
   */
  function NumericMemoryColumn(name, cellPath, aggregationMode) {
    MemoryColumn.call(this, name, cellPath, aggregationMode);
  }

  // Avoid tiny positive/negative diffs (displayed in the UI as '+0.0 B' and
  // '-0.0 B') due to imprecise floating-point arithmetic by treating all diffs
  // within the (-DIFF_EPSILON, DIFF_EPSILON) range as zeros.
  NumericMemoryColumn.DIFF_EPSILON = 0.0001;

  NumericMemoryColumn.prototype = {
    __proto__: MemoryColumn.prototype,

    aggregateCells: function(row, subRows) {
      var subRowCells = subRows.map(this.cell, this);

      // Determine if there is at least one defined numeric in the sub-row
      // cells and the timestamp count.
      var hasDefinedSubRowNumeric = false;
      var timestampCount = undefined;
      subRowCells.forEach(function(subRowCell) {
        if (subRowCell === undefined)
          return;

        var subRowNumerics = subRowCell.fields;
        if (subRowNumerics === undefined)
          return;

        if (timestampCount === undefined)
          timestampCount = subRowNumerics.length;
        else if (timestampCount !== subRowNumerics.length)
          throw new Error('Sub-rows have different numbers of timestamps');

        if (hasDefinedSubRowNumeric)
          return;  // Avoid unnecessary traversals of the numerics.
        hasDefinedSubRowNumeric = subRowNumerics.some(function(numeric) {
          return numeric !== undefined;
        });
      });
      if (!hasDefinedSubRowNumeric)
        return;  // No numeric to aggregate.

      // Get or create the row cell.
      var cellPath = this.cellPath;
      var rowCell = row;
      for (var i = 0; i < cellPath.length; i++) {
        var nextStepName = cellPath[i];
        var nextStep = rowCell[nextStepName];
        if (nextStep === undefined) {
          if (i < cellPath.length - 1)
            nextStep = {};
          else
            nextStep = new MemoryCell(undefined);
          rowCell[nextStepName] = nextStep;
        }
        rowCell = nextStep;
      }
      if (rowCell.fields === undefined) {
        rowCell.fields = new Array(timestampCount);
      } else if (rowCell.fields.length !== timestampCount) {
        throw new Error(
            'Row has a different number of timestamps than sub-rows');
      }

      for (var i = 0; i < timestampCount; i++) {
        if (rowCell.fields[i] !== undefined)
          continue;
        rowCell.fields[i] = tr.model.MemoryAllocatorDump.aggregateNumerics(
            subRowCells.map(function(subRowCell) {
              if (subRowCell === undefined || subRowCell.fields === undefined)
                return undefined;
              return subRowCell.fields[i];
            }));
      }
    },

    formatSingleField: function(numeric) {
      if (numeric === undefined)
        return '';
      return tr.v.ui.createScalarSpan(numeric);
    },

    formatMultipleFieldsDiff: function(firstNumeric, lastNumeric) {
      return this.formatSingleField(
          this.getDiffField_(firstNumeric, lastNumeric));
    },

    compareSingleFields: function(numericA, numericB) {
      return numericA.value - numericB.value;
    },

    compareMultipleFieldsDiff: function(firstNumericA, lastNumericA,
        firstNumericB, lastNumericB) {
      return this.getDiffFieldValue_(firstNumericA, lastNumericA) -
          this.getDiffFieldValue_(firstNumericB, lastNumericB);
    },

    getDiffField_: function(firstNumeric, lastNumeric) {
      var definedNumeric = firstNumeric || lastNumeric;
      return new tr.v.ScalarNumeric(definedNumeric.unit.correspondingDeltaUnit,
          this.getDiffFieldValue_(firstNumeric, lastNumeric));
    },

    getDiffFieldValue_: function(firstNumeric, lastNumeric) {
      var firstValue = firstNumeric === undefined ? 0 : firstNumeric.value;
      var lastValue = lastNumeric === undefined ? 0 : lastNumeric.value;
      var diff = lastValue - firstValue;
      return Math.abs(diff) < NumericMemoryColumn.DIFF_EPSILON ? 0 : diff;
    }
  };

  /**
   * @constructor
   */
  function MemoryCell(fields) {
    this.fields = fields;
  }

  MemoryCell.extractFields = function(cell) {
    if (cell === undefined)
      return undefined;
    return cell.fields;
  };

  /** Limit for the number of sub-rows for recursive table row expansion. */
  var RECURSIVE_EXPANSION_MAX_VISIBLE_ROW_COUNT = 10;

  function expandTableRowsRecursively(table) {
    var currentLevelRows = table.tableRows;
    var totalVisibleRowCount = currentLevelRows.length;

    while (currentLevelRows.length > 0) {
      // Calculate the total number of sub-rows on the current level.
      var nextLevelRowCount = 0;
      currentLevelRows.forEach(function(currentLevelRow) {
        var subRows = currentLevelRow.subRows;
        if (subRows === undefined || subRows.length === 0)
          return;
        nextLevelRowCount += subRows.length;
      });

      // Determine whether expanding all rows on the current level would cause
      // the total number of visible rows go over the limit.
      if (totalVisibleRowCount + nextLevelRowCount >
          RECURSIVE_EXPANSION_MAX_VISIBLE_ROW_COUNT) {
        break;
      }

      // Expand all rows on the current level and gather their sub-rows.
      var nextLevelRows = new Array(nextLevelRowCount);
      var nextLevelRowIndex = 0;
      currentLevelRows.forEach(function(currentLevelRow) {
        var subRows = currentLevelRow.subRows;
        if (subRows === undefined || subRows.length === 0)
          return;
        table.setExpandedForTableRow(currentLevelRow, true);
        subRows.forEach(function(subRow) {
          nextLevelRows[nextLevelRowIndex++] = subRow;
        });
      });

      // Update the total number of visible rows and progress to the next level.
      totalVisibleRowCount += nextLevelRowCount;
      currentLevelRows = nextLevelRows;
    }
  }

  function aggregateTableRowCellsRecursively(row, columns, opt_predicate) {
    var subRows = row.subRows;
    if (subRows === undefined || subRows.length === 0)
      return;

    subRows.forEach(function(subRow) {
      aggregateTableRowCellsRecursively(subRow, columns, opt_predicate);
    });

    if (opt_predicate === undefined || opt_predicate(row.contexts))
      aggregateTableRowCells(row, subRows, columns);
  }

  function aggregateTableRowCells(row, subRows, columns) {
    columns.forEach(function(column) {
      if (!(column instanceof MemoryColumn))
        return;
      column.aggregateCells(row, subRows);
    });
  }

  function createCells(timeToValues, valueFieldsGetter) {
    var fieldNameToFields = tr.b.invertArrayOfDicts(
        timeToValues, valueFieldsGetter);
    return tr.b.mapItems(fieldNameToFields, function(fieldName, fields) {
      return new tr.ui.analysis.MemoryCell(fields);
    });
  }

  function createWarningInfo(message) {
    return {
      message: message,
      icon: String.fromCharCode(9888),
      color: 'red'
    };
  }

  return {
    TitleColumn: TitleColumn,
    MemoryColumn: MemoryColumn,
    StringMemoryColumn: StringMemoryColumn,
    NumericMemoryColumn: NumericMemoryColumn,
    MemoryCell: MemoryCell,
    expandTableRowsRecursively: expandTableRowsRecursively,
    aggregateTableRowCellsRecursively: aggregateTableRowCellsRecursively,
    aggregateTableRowCells: aggregateTableRowCells,
    createCells: createCells,
    createWarningInfo: createWarningInfo
  };
});
</script>
