tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DominatorTree.cpp (4736B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "mozilla/devtools/DominatorTree.h"
      7 #include "mozilla/dom/DominatorTreeBinding.h"
      8 #include "mozilla/ErrorResult.h"
      9 
     10 namespace mozilla {
     11 namespace devtools {
     12 
     13 dom::Nullable<uint64_t> DominatorTree::GetRetainedSize(uint64_t aNodeId,
     14                                                       ErrorResult& aRv) {
     15  JS::ubi::Node::Id id(aNodeId);
     16  auto node = mHeapSnapshot->getNodeById(id);
     17  if (node.isNothing()) return dom::Nullable<uint64_t>();
     18 
     19  auto mallocSizeOf = GetCurrentThreadDebuggerMallocSizeOf();
     20  JS::ubi::Node::Size size = 0;
     21  if (!mDominatorTree.getRetainedSize(*node, mallocSizeOf, size)) {
     22    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     23    return dom::Nullable<uint64_t>();
     24  }
     25 
     26  MOZ_ASSERT(size != 0,
     27             "The node should not have been unknown since we got it from the "
     28             "heap snapshot.");
     29  return dom::Nullable<uint64_t>(size);
     30 }
     31 
     32 struct NodeAndRetainedSize {
     33  JS::ubi::Node mNode;
     34  JS::ubi::Node::Size mSize;
     35 
     36  NodeAndRetainedSize(const JS::ubi::Node& aNode, JS::ubi::Node::Size aSize)
     37      : mNode(aNode), mSize(aSize) {}
     38 
     39  struct Comparator {
     40    static bool Equals(const NodeAndRetainedSize& aLhs,
     41                       const NodeAndRetainedSize& aRhs) {
     42      return aLhs.mSize == aRhs.mSize;
     43    }
     44 
     45    static bool LessThan(const NodeAndRetainedSize& aLhs,
     46                         const NodeAndRetainedSize& aRhs) {
     47      // Use > because we want to sort from greatest to least retained size.
     48      return aLhs.mSize > aRhs.mSize;
     49    }
     50  };
     51 };
     52 
     53 void DominatorTree::GetImmediatelyDominated(
     54    uint64_t aNodeId, dom::Nullable<nsTArray<uint64_t>>& aOutResult,
     55    ErrorResult& aRv) {
     56  MOZ_ASSERT(aOutResult.IsNull());
     57 
     58  JS::ubi::Node::Id id(aNodeId);
     59  Maybe<JS::ubi::Node> node = mHeapSnapshot->getNodeById(id);
     60  if (node.isNothing()) return;
     61 
     62  // Get all immediately dominated nodes and their retained sizes.
     63  MallocSizeOf mallocSizeOf = GetCurrentThreadDebuggerMallocSizeOf();
     64  Maybe<JS::ubi::DominatorTree::DominatedSetRange> range =
     65      mDominatorTree.getDominatedSet(*node);
     66  MOZ_ASSERT(
     67      range.isSome(),
     68      "The node should be known, since we got it from the heap snapshot.");
     69  size_t length = range->length();
     70  nsTArray<NodeAndRetainedSize> dominatedNodes(length);
     71  for (const JS::ubi::Node& dominatedNode : *range) {
     72    JS::ubi::Node::Size retainedSize = 0;
     73    if (NS_WARN_IF(!mDominatorTree.getRetainedSize(dominatedNode, mallocSizeOf,
     74                                                   retainedSize))) {
     75      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     76      return;
     77    }
     78    MOZ_ASSERT(retainedSize != 0,
     79               "retainedSize should not be zero since we know the node is in "
     80               "the dominator tree.");
     81 
     82    dominatedNodes.AppendElement(
     83        NodeAndRetainedSize(dominatedNode, retainedSize));
     84  }
     85 
     86  // Sort them by retained size.
     87  NodeAndRetainedSize::Comparator comparator;
     88  dominatedNodes.Sort(comparator);
     89 
     90  // Fill the result with the nodes' ids.
     91  JS::ubi::Node root = mDominatorTree.root();
     92  aOutResult.SetValue(nsTArray<uint64_t>(length));
     93  for (const NodeAndRetainedSize& entry : dominatedNodes) {
     94    // The root dominates itself, but we don't want to expose that to JS.
     95    if (entry.mNode == root) continue;
     96 
     97    aOutResult.Value().AppendElement(entry.mNode.identifier());
     98  }
     99 }
    100 
    101 dom::Nullable<uint64_t> DominatorTree::GetImmediateDominator(
    102    uint64_t aNodeId) const {
    103  JS::ubi::Node::Id id(aNodeId);
    104  Maybe<JS::ubi::Node> node = mHeapSnapshot->getNodeById(id);
    105  if (node.isNothing()) return dom::Nullable<uint64_t>();
    106 
    107  JS::ubi::Node dominator = mDominatorTree.getImmediateDominator(*node);
    108  if (!dominator || dominator == *node) return dom::Nullable<uint64_t>();
    109 
    110  return dom::Nullable<uint64_t>(dominator.identifier());
    111 }
    112 
    113 /*** Cycle Collection Boilerplate
    114 * *****************************************************************/
    115 
    116 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DominatorTree, mParent, mHeapSnapshot)
    117 
    118 NS_IMPL_CYCLE_COLLECTING_ADDREF(DominatorTree)
    119 NS_IMPL_CYCLE_COLLECTING_RELEASE(DominatorTree)
    120 
    121 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DominatorTree)
    122  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    123  NS_INTERFACE_MAP_ENTRY(nsISupports)
    124 NS_INTERFACE_MAP_END
    125 
    126 /* virtual */
    127 JSObject* DominatorTree::WrapObject(JSContext* aCx,
    128                                    JS::Handle<JSObject*> aGivenProto) {
    129  return dom::DominatorTree_Binding::Wrap(aCx, this, aGivenProto);
    130 }
    131 
    132 }  // namespace devtools
    133 }  // namespace mozilla