Ejemplo n.º 1
0
handlers[actions.SELECT_SNAPSHOT_FOR_DIFFING] = function (diffing, { snapshot }) {
  assert(diffing,
         "Should never select a snapshot for diffing when we aren't diffing " +
         "anything");
  assert(diffing.state === diffingState.SELECTING,
         "Can't select when not in SELECTING state");
  assert(snapshotIsDiffable(snapshot),
         "snapshot must be in a diffable state");

  if (!diffing.firstSnapshotId) {
    return immutableUpdate(diffing, {
      firstSnapshotId: snapshot.id
    });
  }

  assert(!diffing.secondSnapshotId,
         "If we aren't selecting the first, then we must be selecting the " +
         "second");

  if (snapshot.id === diffing.firstSnapshotId) {
    // Ignore requests to select the same snapshot.
    return diffing;
  }

  return immutableUpdate(diffing, {
    secondSnapshotId: snapshot.id
  });
};
Ejemplo n.º 2
0
  return function* (dispatch, getState) {
    assert(getState().view.state === viewState.INDIVIDUALS,
           "Should be in INDIVIDUALS view.");

    const { individuals } = getState();

    switch (individuals.state) {
      case individualsState.COMPUTING_DOMINATOR_TREE:
      case individualsState.FETCHING:
        // Nothing to do here.
        return;

      case individualsState.FETCHED:
        if (getState().individuals.labelDisplay === getState().labelDisplay) {
          return;
        }
        break;

      case individualsState.ERROR:
        // Doesn't hurt to retry: maybe we won't get an error this time around?
        break;

      default:
        assert(false, `Unexpected individuals state: ${individuals.state}`);
        return;
    }

    yield dispatch(fetchIndividuals(heapWorker,
                                    individuals.id,
                                    individuals.censusBreakdown,
                                    individuals.indices));
  };
Ejemplo n.º 3
0
  return function*(dispatch, getState) {
    const snapshot = getSnapshot(getState(), id);
    assert(dominatorTreeIsComputed(snapshot),
           "Should have dominator tree model and it should be computed");

    let display;
    let root;
    do {
      display = getState().dominatorTreeDisplay;
      assert(display && display.breakdown,
             `Should have a breakdown to describe nodes with, got: ${uneval(display)}`);

      dispatch({ type: actions.FETCH_DOMINATOR_TREE_START, id, display });

      try {
        root = yield heapWorker.getDominatorTree({
          dominatorTreeId: snapshot.dominatorTree.dominatorTreeId,
          breakdown: display.breakdown,
        });
      } catch (error) {
        reportException("actions/snapshot/fetchDominatorTree", error);
        dispatch({ type: actions.DOMINATOR_TREE_ERROR, id, error });
        return null;
      }
    }
    while (display !== getState().dominatorTreeDisplay);

    dispatch({ type: actions.FETCH_DOMINATOR_TREE_END, id, root });
    telemetry.countDominatorTree({ display });
    return root;
  };
Ejemplo n.º 4
0
exports.getStatusTextFull = function (state) {
  assert(!!state, "Must have a state");

  switch (state) {
    case diffingState.ERROR:
      return L10N.getStr("diffing.state.error.full");

    case states.ERROR:
      return L10N.getStr("snapshot.state.error.full");

    case states.SAVING:
      return L10N.getStr("snapshot.state.saving.full");

    case states.IMPORTING:
      return L10N.getStr("snapshot.state.importing");

    case states.SAVED:
    case states.READING:
      return L10N.getStr("snapshot.state.reading.full");

    case censusState.SAVING:
      return L10N.getStr("snapshot.state.saving-census.full");

    case treeMapState.SAVING:
      return L10N.getStr("snapshot.state.saving-tree-map.full");

    case diffingState.TAKING_DIFF:
      return L10N.getStr("diffing.state.taking-diff.full");

    case diffingState.SELECTING:
      return L10N.getStr("diffing.state.selecting.full");

    case dominatorTreeState.COMPUTING:
      return L10N.getStr("dominatorTree.state.computing.full");

    case dominatorTreeState.COMPUTED:
    case dominatorTreeState.FETCHING:
      return L10N.getStr("dominatorTree.state.fetching.full");

    case dominatorTreeState.INCREMENTAL_FETCHING:
      return L10N.getStr("dominatorTree.state.incrementalFetching.full");

    case dominatorTreeState.ERROR:
      return L10N.getStr("dominatorTree.state.error.full");

    // These states do not have any full message to show as other content will
    // be displayed.
    case dominatorTreeState.LOADED:
    case diffingState.TOOK_DIFF:
    case states.READ:
    case censusState.SAVED:
    case treeMapState.SAVED:
      return "";

    default:
      assert(false, `Unexpected state: ${state}`);
      return "";
  }
};
Ejemplo n.º 5
0
 onDominatorTreeFocus: node => {
   assert(view.state === viewState.DOMINATOR_TREE,
          "If focusing dominator tree nodes, " +
          "should be in dominator tree view");
   assert(selectedSnapshot, "...and we should have a selected snapshot");
   assert(selectedSnapshot.dominatorTree,
          "...and that snapshot should have a dominator tree");
   dispatch(focusDominatorTreeNode(selectedSnapshot.id, node));
 },
Ejemplo n.º 6
0
  _renderIndividuals(state, individuals, dominatorTree, onViewSourceInDebugger) {
    assert(individuals.state === individualsState.FETCHED,
           "Should have fetched individuals");
    assert(dominatorTree && dominatorTree.root,
           "Should have a dominator tree and its root");

    const tree = dom.div(
      {
        className: "vbox",
        style: {
          overflowY: "auto"
        }
      },
      IndividualsHeader(),
      Individuals({
        individuals,
        dominatorTree,
        onViewSourceInDebugger,
        onFocus: this.props.onFocusIndividual
      })
    );

    const shortestPaths = ShortestPaths({
      graph: individuals.focused
        ? individuals.focused.shortestPaths
        : null
    });

    return this._renderHeapView(
      state,
      dom.div(
        { className: "hbox devtools-toolbar" },
        dom.label(
          { id: "pop-view-button-label" },
          dom.button(
            {
              id: "pop-view-button",
              className: "devtools-button",
              onClick: this.props.onPopView,
            },
            L10N.getStr("toolbar.pop-view")
          ),
          L10N.getStr("toolbar.pop-view.label")
        ),
        L10N.getStr("toolbar.viewing-individuals")
      ),
      HSplitBox({
        start: tree,
        end: shortestPaths,
        startWidth: this.props.sizes.shortestPathsSize,
        onResize: this.props.onShortestPathsResize,
      })
    );
  }
Ejemplo n.º 7
0
 onCensusCollapse: (census, node) => {
   if (diffing) {
     assert(diffing.census === census,
            "Should only collapse active census");
     dispatch(collapseDiffingCensusNode(node));
   } else {
     assert(selectedSnapshot && selectedSnapshot.census === census,
            "If not diffing, " +
            "should be collapsing on selected snapshot's census");
     dispatch(collapseCensusNode(selectedSnapshot.id, node));
   }
 },
Ejemplo n.º 8
0
 onCensusExpand: (census, node) => {
   if (diffing) {
     assert(diffing.census === census,
            "Should only expand active census");
     dispatch(expandDiffingCensusNode(node));
   } else {
     assert(selectedSnapshot && selectedSnapshot.census === census,
            "If not diffing, " +
            "should be expanding on selected snapshot's census");
     dispatch(expandCensusNode(selectedSnapshot.id, node));
   }
 },
Ejemplo n.º 9
0
handlers[actions.COLLAPSE_DIFFING_CENSUS_NODE] = function(diffing, { node }) {
  assert(diffing, "Should be diffing if expanding diffing's census nodes");
  assert(diffing.state === diffingState.TOOK_DIFF,
         "Should have taken the census diff if expanding nodes");
  assert(diffing.census, "Should have a census");
  assert(diffing.census.report, "Should have a census report");
  assert(diffing.census.expanded, "Should have a census's expanded set");

  const expanded = diffing.census.expanded.delete(node.id);
  const census = immutableUpdate(diffing.census, { expanded });
  return immutableUpdate(diffing, { census });
};
Ejemplo n.º 10
0
 onCensusFocus: (census, node) => {
   if (diffing) {
     assert(diffing.census === census,
            "Should only focus nodes in active census");
     dispatch(focusDiffingCensusNode(node));
   } else {
     assert(selectedSnapshot && selectedSnapshot.census === census,
            "If not diffing, " +
            "should be focusing on nodes in selected snapshot's census");
     dispatch(focusCensusNode(selectedSnapshot.id, node));
   }
 },
Ejemplo n.º 11
0
  return snapshots.map(snapshot => {
    if (snapshot.id !== id) {
      return snapshot;
    }

    assert(snapshot.dominatorTree, "Should have a dominator tree");
    assert(snapshot.dominatorTree.expanded,
           "Should have the dominator tree's expanded set");

    const expanded = snapshot.dominatorTree.expanded.delete(node.nodeId);
    const dominatorTree = immutableUpdate(snapshot.dominatorTree, { expanded });
    return immutableUpdate(snapshot, { dominatorTree });
  });
Ejemplo n.º 12
0
  return snapshots.map(snapshot => {
    if (snapshot.id !== id) {
      return snapshot;
    }

    assert(snapshot.census, "Should have a census");
    assert(snapshot.census.report, "Should have a census report");
    assert(snapshot.census.expanded, "Should have a census's expanded set");

    const expanded = snapshot.census.expanded.delete(node.id);
    const census = immutableUpdate(snapshot.census, { expanded });
    return immutableUpdate(snapshot, { census });
  });
Ejemplo n.º 13
0
  return snapshots.map(snapshot => {
    if (snapshot.id !== id) {
      return snapshot;
    }

    assert(snapshot.dominatorTree, "Should have a dominator tree model");
    assert(snapshot.dominatorTree.state == dominatorTreeState.COMPUTING,
           "Should be in the COMPUTING state");

    const dominatorTree = immutableUpdate(snapshot.dominatorTree, {
      state: dominatorTreeState.COMPUTED,
      dominatorTreeId,
    });
    return immutableUpdate(snapshot, { dominatorTree });
  });
Ejemplo n.º 14
0
  return snapshots.map(snapshot => {
    if (snapshot.id !== id) {
      return snapshot;
    }

    assert(snapshot.census, "Should have a census");
    assert(snapshot.census.report, "Should have a census report");
    assert(snapshot.census.expanded, "Should have a census's expanded set");

    // Warning: mutable operations couched in an immutable update ahead :'( See
    // above comment in the EXPAND_CENSUS_NODE handler.
    const expanded = snapshot.census.expanded;
    expanded.delete(node.id);
    const census = immutableUpdate(snapshot.census, { expanded });
    return immutableUpdate(snapshot, { census });
  });
Ejemplo n.º 15
0
handlers[actions.FETCH_INDIVIDUALS_START] = function (individuals, action) {
  assert(individuals, "Should have individuals");
  return Object.freeze({
    state: individualsState.FETCHING,
    focused: individuals.focused,
  });
};
Ejemplo n.º 16
0
  return function *(dispatch, getState) {
    assert([states.READ, states.SAVED_CENSUS].includes(snapshot.state),
      `Can only take census of snapshots in READ or SAVED_CENSUS state, found ${snapshot.state}`);

    let census;
    let inverted = getState().inverted;
    let breakdown = getState().breakdown;

    // If breakdown and inversion haven't changed, don't do anything.
    if (inverted === snapshot.inverted && breakdownEquals(breakdown, snapshot.breakdown)) {
      return;
    }

    // Keep taking a census if the breakdown changes during. Recheck
    // that the breakdown used for the census is the same as
    // the state's breakdown.
    do {
      inverted = getState().inverted;
      breakdown = getState().breakdown;
      dispatch({ type: actions.TAKE_CENSUS_START, snapshot, inverted, breakdown });
      let opts = inverted ? { asInvertedTreeNode: true } : { asTreeNode: true };

      try {
        census = yield heapWorker.takeCensus(snapshot.path, { breakdown }, opts);
      } catch(error) {
        reportException("takeCensus", error);
        dispatch({ type: actions.SNAPSHOT_ERROR, snapshot, error });
        return;
      }
    }
    while (inverted !== getState().inverted ||
           !breakdownEquals(breakdown, getState().breakdown));

    dispatch({ type: actions.TAKE_CENSUS_END, snapshot, breakdown, inverted, census });
  };
Ejemplo n.º 17
0
  task: function*(heapWorker, id, removeFromCache, dispatch, getState) {
    console.log("FITZGEN: readSnapshot");

    const snapshot = getSnapshot(getState(), id);
    assert([states.SAVED, states.IMPORTING].includes(snapshot.state),
           `Should only read a snapshot once. Found snapshot in state ${snapshot.state}`);

    let creationTime;

    dispatch({ type: actions.READ_SNAPSHOT_START, id });
    try {
      yield heapWorker.readHeapSnapshot(snapshot.path);
      creationTime = yield heapWorker.getCreationTime(snapshot.path);
    } catch (error) {
      console.log("FITZGEN: readSnapshot: error", error);
      removeFromCache();
      reportException("readSnapshot", error);
      dispatch({ type: actions.SNAPSHOT_ERROR, id, error });
      return;
    }

    console.log("FITZGEN: readSnapshot: done reading");
    removeFromCache();
    dispatch({ type: actions.READ_SNAPSHOT_END, id, creationTime });
  }
Ejemplo n.º 18
0
      renderItem: (item, depth, focused, arrow, expanded) => {
        if (item instanceof DominatorTreeLazyChildren) {
          if (item.isFirstChild()) {
            assert(dominatorTree.state === dominatorTreeState.INCREMENTAL_FETCHING,
                   "If we are displaying a throbber for loading a subtree, " +
                   "then we should be INCREMENTAL_FETCHING those children right now");
            return DominatorTreeSubtreeFetching({
              key: item.key(),
              depth,
              focused,
            });
          }

          return DominatorTreeSiblingLink({
            key: item.key(),
            item,
            depth,
            focused,
            onLoadMoreSiblings,
          });
        }

        return DominatorTreeItem({
          item,
          depth,
          focused,
          arrow,
          expanded,
          getPercentSize: size => (size / dominatorTree.root.retainedSize) * 100,
          onViewSourceInDebugger,
        });
      },
Ejemplo n.º 19
0
  return snapshots.map(snapshot => {
    if (snapshot.id !== id) {
      return snapshot;
    }

    assert(snapshot.dominatorTree, "Should have a dominator tree");
    assert(snapshot.dominatorTree.expanded,
           "Should have the dominator tree's expanded set");

    // Warning: mutable operations couched in an immutable update ahead :'( See
    // above comment in the EXPAND_DOMINATOR_TREE_NODE handler.
    const expanded = snapshot.dominatorTree.expanded;
    expanded.delete(node.nodeId);
    const dominatorTree = immutableUpdate(snapshot.dominatorTree, { expanded });
    return immutableUpdate(snapshot, { dominatorTree });
  });
Ejemplo n.º 20
0
/**
 * Get the app state's current state atom.
 *
 * @see the relevant state string constants in `../constants.js`.
 *
 * @param {models.view} view
 * @param {snapshotModel} snapshot
 * @param {diffingModel} diffing
 * @param {individualsModel} individuals
 *
 * @return {snapshotState|diffingState|dominatorTreeState}
 */
function getState(view, snapshot, diffing, individuals) {
  switch (view.state) {
    case viewState.CENSUS:
      return snapshot.census
        ? snapshot.census.state
        : snapshot.state;

    case viewState.DIFFING:
      return diffing.state;

    case viewState.TREE_MAP:
      return snapshot.treeMap
      ? snapshot.treeMap.state
      : snapshot.state;

    case viewState.DOMINATOR_TREE:
      return snapshot.dominatorTree
        ? snapshot.dominatorTree.state
        : snapshot.state;

    case viewState.INDIVIDUALS:
      return individuals.state;
  }

  assert(false, `Unexpected view state: ${view.state}`);
  return null;
}
Ejemplo n.º 21
0
  _renderCensus(state, census, diffing, onViewSourceInDebugger, onViewIndividuals) {
    assert(census.report, "Should not render census that does not have a report");

    if (!census.report.children) {
      const censusFilterMsg = census.filter ? L10N.getStr("heapview.none-match")
                                            : L10N.getStr("heapview.empty");
      const msg = diffing ? L10N.getStr("heapview.no-difference")
                          : censusFilterMsg;
      return this._renderHeapView(state, dom.div({ className: "empty" }, msg));
    }

    const contents = [];

    if (census.display.breakdown.by === "allocationStack"
        && census.report.children
        && census.report.children.length === 1
        && census.report.children[0].name === "noStack") {
      contents.push(dom.div({ className: "error no-allocation-stacks" },
                            L10N.getStr("heapview.noAllocationStacks")));
    }

    contents.push(CensusHeader({ diffing }));
    contents.push(Census({
      onViewSourceInDebugger,
      onViewIndividuals,
      diffing,
      census,
      onExpand: node => this.props.onCensusExpand(census, node),
      onCollapse: node => this.props.onCensusCollapse(census, node),
      onFocus: node => this.props.onCensusFocus(census, node),
    }));

    return this._renderHeapView(state, ...contents);
  }
Ejemplo n.º 22
0
 return function(dispatch, getState) {
   const { previous } = getState().view;
   assert(previous);
   dispatch({
     type: actions.POP_VIEW,
     previousView: previous,
   });
 };
Ejemplo n.º 23
0
handlers[actions.TAKE_CENSUS_DIFF_START] = function(diffing, action) {
  assert(diffing, "Should be diffing when starting a census diff");
  assert(action.first.id === diffing.firstSnapshotId,
         "First snapshot's id should match");
  assert(action.second.id === diffing.secondSnapshotId,
         "Second snapshot's id should match");

  return immutableUpdate(diffing, {
    state: diffingState.TAKING_DIFF,
    census: {
      report: null,
      inverted: action.inverted,
      filter: action.filter,
      display: action.display,
    },
  });
};
Ejemplo n.º 24
0
var destroy = Task.async(function*() {
  const ok = ReactDOM.unmountComponentAtNode(gRoot);
  assert(ok, "Should successfully unmount the memory tool's top level React component");

  unsubscribe();

  gStore, gRoot, gApp, gProvider, unsubscribe, isHighlighted;
});
Ejemplo n.º 25
0
    catchAndIgnore(function(app) {
      switch (app.view.state) {
        case viewState.INDIVIDUALS:
          assert(app.individuals, "Should have individuals state");
          break;

        case viewState.DIFFING:
        case viewState.CENSUS:
        case viewState.DOMINATOR_TREE:
        case viewState.TREE_MAP:
          assert(!app.individuals, "Should not have individuals state");
          break;

        default:
          assert(false, `Unexpected type of view: ${app.view.state}`);
      }
    })(app);
Ejemplo n.º 26
0
    catchAndIgnore(function(app) {
      switch (app.view.state) {
        case viewState.DIFFING:
          assert(app.diffing, "Should be diffing");
          break;

        case viewState.INDIVIDUALS:
        case viewState.CENSUS:
        case viewState.DOMINATOR_TREE:
        case viewState.TREE_MAP:
          assert(!app.diffing, "Should not be diffing");
          break;

        default:
          assert(false, `Unexpected type of view: ${view.state}`);
      }
    })(app);
Ejemplo n.º 27
0
  return snapshots.map(snapshot => {
    if (snapshot.id !== id) {
      return snapshot;
    }

    assert(snapshot.dominatorTree, "Should have a dominator tree model");
    assert(snapshot.dominatorTree.state == dominatorTreeState.FETCHING,
           "Should be in the FETCHING state");

    const dominatorTree = immutableUpdate(snapshot.dominatorTree, {
      state: dominatorTreeState.LOADED,
      root,
      expanded: Immutable.Set(),
    });

    return immutableUpdate(snapshot, { dominatorTree });
  });
Ejemplo n.º 28
0
  return snapshots.map(snapshot => {
    if (snapshot.id !== id) {
      return snapshot;
    }

    assert(snapshot.dominatorTree, "Should have a dominator tree model");
    assert(snapshot.dominatorTree.state !== dominatorTreeState.COMPUTING &&
           snapshot.dominatorTree.state !== dominatorTreeState.ERROR,
           `Should have already computed the dominator tree, found state = ${snapshot.dominatorTree.state}`);

    const dominatorTree = immutableUpdate(snapshot.dominatorTree, {
      state: dominatorTreeState.FETCHING,
      root: undefined,
      display,
    });
    return immutableUpdate(snapshot, { dominatorTree });
  });
Ejemplo n.º 29
0
handlers[actions.TAKE_CENSUS_DIFF_END] = function (diffing, action) {
  assert(diffing, "Should be diffing when ending a census diff");
  assert(action.first.id === diffing.firstSnapshotId,
         "First snapshot's id should match");
  assert(action.second.id === diffing.secondSnapshotId,
         "Second snapshot's id should match");

  return immutableUpdate(diffing, {
    state: diffingState.TOOK_DIFF,
    census: {
      report: action.report,
      inverted: action.inverted,
      filter: action.filter,
      breakdown: action.breakdown,
    }
  });
};
Ejemplo n.º 30
0
handlers[actions.POP_VIEW] = function(diffing, { previousView }) {
  if (previousView.state === viewState.DIFFING) {
    assert(previousView.diffing, "Should have previousView.diffing");
    return previousView.diffing;
  }

  return null;
};