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