tor-browser

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

DeserializedNode.cpp (3911B)


      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/DeserializedNode.h"
      7 #include "mozilla/devtools/HeapSnapshot.h"
      8 #include "nsCRTGlue.h"
      9 
     10 namespace mozilla {
     11 namespace devtools {
     12 
     13 DeserializedEdge::DeserializedEdge(DeserializedEdge&& rhs) {
     14  referent = rhs.referent;
     15  name = rhs.name;
     16 }
     17 
     18 DeserializedEdge& DeserializedEdge::operator=(DeserializedEdge&& rhs) {
     19  MOZ_ASSERT(&rhs != this);
     20  this->~DeserializedEdge();
     21  new (this) DeserializedEdge(std::move(rhs));
     22  return *this;
     23 }
     24 
     25 JS::ubi::Node DeserializedNode::getEdgeReferent(const DeserializedEdge& edge) {
     26  auto ptr = owner->nodes.lookup(edge.referent);
     27  MOZ_ASSERT(ptr);
     28 
     29  // `HashSets` only provide const access to their values, because mutating a
     30  // value might change its hash, rendering it unfindable in the set.
     31  // Unfortunately, the `ubi::Node` constructor requires a non-const pointer to
     32  // its referent.  However, the only aspect of a `DeserializedNode` we hash on
     33  // is its id, which can't be changed via `ubi::Node`, so this cast can't cause
     34  // the trouble `HashSet` is concerned a non-const reference would cause.
     35  return JS::ubi::Node(const_cast<DeserializedNode*>(&*ptr));
     36 }
     37 
     38 JS::ubi::StackFrame DeserializedStackFrame::getParentStackFrame() const {
     39  MOZ_ASSERT(parent.isSome());
     40  auto ptr = owner->frames.lookup(parent.ref());
     41  MOZ_ASSERT(ptr);
     42  // See above comment in DeserializedNode::getEdgeReferent about why this
     43  // const_cast is needed and safe.
     44  return JS::ubi::StackFrame(const_cast<DeserializedStackFrame*>(&*ptr));
     45 }
     46 
     47 }  // namespace devtools
     48 }  // namespace mozilla
     49 
     50 namespace JS {
     51 namespace ubi {
     52 
     53 const char16_t Concrete<DeserializedNode>::concreteTypeName[] =
     54    u"mozilla::devtools::DeserializedNode";
     55 
     56 const char16_t* Concrete<DeserializedNode>::typeName() const {
     57  return get().typeName;
     58 }
     59 
     60 Node::Size Concrete<DeserializedNode>::size(
     61    mozilla::MallocSizeOf mallocSizeof) const {
     62  return get().size;
     63 }
     64 
     65 class DeserializedEdgeRange : public EdgeRange {
     66  DeserializedNode* node;
     67  Edge currentEdge;
     68  size_t i;
     69 
     70  void settle() {
     71    if (i >= node->edges.length()) {
     72      front_ = nullptr;
     73      return;
     74    }
     75 
     76    auto& edge = node->edges[i];
     77    auto referent = node->getEdgeReferent(edge);
     78    currentEdge = Edge(edge.name ? NS_xstrdup(edge.name) : nullptr, referent);
     79    front_ = &currentEdge;
     80  }
     81 
     82 public:
     83  explicit DeserializedEdgeRange(DeserializedNode& node) : node(&node), i(0) {
     84    settle();
     85  }
     86 
     87  void popFront() override {
     88    i++;
     89    settle();
     90  }
     91 };
     92 
     93 StackFrame Concrete<DeserializedNode>::allocationStack() const {
     94  MOZ_ASSERT(hasAllocationStack());
     95  auto id = get().allocationStack.ref();
     96  auto ptr = get().owner->frames.lookup(id);
     97  MOZ_ASSERT(ptr);
     98  // See above comment in DeserializedNode::getEdgeReferent about why this
     99  // const_cast is needed and safe.
    100  return JS::ubi::StackFrame(const_cast<DeserializedStackFrame*>(&*ptr));
    101 }
    102 
    103 js::UniquePtr<EdgeRange> Concrete<DeserializedNode>::edges(JSContext* cx,
    104                                                           bool) const {
    105  js::UniquePtr<DeserializedEdgeRange> range(
    106      js_new<DeserializedEdgeRange>(get()));
    107 
    108  if (!range) return nullptr;
    109 
    110  return js::UniquePtr<EdgeRange>(range.release());
    111 }
    112 
    113 StackFrame ConcreteStackFrame<DeserializedStackFrame>::parent() const {
    114  return get().parent.isNothing() ? StackFrame() : get().getParentStackFrame();
    115 }
    116 
    117 bool ConcreteStackFrame<DeserializedStackFrame>::constructSavedFrameStack(
    118    JSContext* cx, JS::MutableHandle<JSObject*> outSavedFrameStack) const {
    119  StackFrame f(&get());
    120  return ConstructSavedFrameStackSlow(cx, f, outSavedFrameStack);
    121 }
    122 
    123 }  // namespace ubi
    124 }  // namespace JS