Bug 1024774 - Part 11: Implement a JS::ubi::Node specialization for DeserializedNode; r=jimb

This commit is contained in:
Nick Fitzgerald 2015-05-28 07:37:43 -07:00
parent 8a0ed1b0d0
commit 1fe9f17177
3 changed files with 138 additions and 14 deletions

View File

@ -187,6 +187,21 @@ class Base {
}
bool operator!=(const Base& rhs) const { return !(*this == rhs); }
// An identifier for this node, guaranteed to be stable and unique for as
// long as this ubi::Node's referent is alive and at the same address.
//
// This is probably suitable for use in serializations, as it is an integral
// type. It may also help save memory when constructing HashSets of
// ubi::Nodes: since a uintptr_t will always be smaller than a ubi::Node, a
// HashSet<ubi::Node::Id> will use less space per element than a
// HashSet<ubi::Node>.
//
// (Note that 'unique' only means 'up to equality on ubi::Node'; see the
// caveats about multiple objects allocated at the same address for
// 'ubi::Node::operator=='.)
typedef uintptr_t Id;
virtual Id identifier() const { return reinterpret_cast<Id>(ptr); }
// Returns true if this node is pointing to something on the live heap, as
// opposed to something from a deserialized core dump. Returns false,
// otherwise.
@ -385,20 +400,8 @@ class Node {
return base()->edges(cx, wantNames);
}
// An identifier for this node, guaranteed to be stable and unique for as
// long as this ubi::Node's referent is alive and at the same address.
//
// This is probably suitable for use in serializations, as it is an integral
// type. It may also help save memory when constructing HashSets of
// ubi::Nodes: since a uintptr_t will always be smaller than a ubi::Node, a
// HashSet<ubi::Node::Id> will use less space per element than a
// HashSet<ubi::Node>.
//
// (Note that 'unique' only means 'up to equality on ubi::Node'; see the
// caveats about multiple objects allocated at the same address for
// 'ubi::Node::operator=='.)
typedef uintptr_t Id;
Id identifier() const { return reinterpret_cast<Id>(base()->ptr); }
typedef Base::Id Id;
Id identifier() const { return base()->identifier(); }
// A hash policy for ubi::Nodes.
// This simply uses the stock PointerHasher on the ubi::Node's pointer.

View File

@ -4,6 +4,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/devtools/DeserializedNode.h"
#include "mozilla/devtools/HeapSnapshot.h"
#include "nsCRTGlue.h"
namespace mozilla {
namespace devtools {
@ -107,3 +109,86 @@ DeserializedNode::getEdgeReferent(const DeserializedEdge &edge)
} // namespace devtools
} // namespace mozilla
namespace JS {
namespace ubi {
using mozilla::devtools::DeserializedEdge;
const char16_t Concrete<DeserializedNode>::concreteTypeName[] =
MOZ_UTF16("mozilla::devtools::DeserializedNode");
const char16_t *
Concrete<DeserializedNode>::typeName() const
{
return get().typeName;
}
size_t
Concrete<DeserializedNode>::size(mozilla::MallocSizeOf mallocSizeof) const
{
return get().size;
}
class DeserializedEdgeRange : public EdgeRange
{
SimpleEdgeVector edges;
size_t i;
void settle() {
front_ = i < edges.length() ? &edges[i] : nullptr;
}
public:
explicit DeserializedEdgeRange(JSContext* cx)
: edges(cx)
, i(0)
{
settle();
}
bool init(DeserializedNode &node)
{
if (!edges.reserve(node.edges.length()))
return false;
for (DeserializedEdge *edgep = node.edges.begin();
edgep != node.edges.end();
edgep++)
{
char16_t *name = nullptr;
if (edgep->name) {
name = NS_strdup(edgep->name);
if (!name)
return false;
}
DeserializedNode &referent = node.getEdgeReferent(*edgep);
edges.infallibleAppend(mozilla::Move(SimpleEdge(name, Node(&referent))));
}
settle();
return true;
}
void popFront() override
{
i++;
settle();
}
};
UniquePtr<EdgeRange>
Concrete<DeserializedNode>::edges(JSContext* cx, bool) const
{
UniquePtr<DeserializedEdgeRange, JS::DeletePolicy<DeserializedEdgeRange>> range(
js_new<DeserializedEdgeRange>(cx));
if (!range || !range->init(get()))
return nullptr;
return UniquePtr<EdgeRange>(range.release());
}
} // namespace JS
} // namespace ubi

View File

@ -6,6 +6,7 @@
#ifndef mozilla_devtools_DeserializedNode__
#define mozilla_devtools_DeserializedNode__
#include "js/UbiNode.h"
#include "mozilla/devtools/CoreDump.pb.h"
#include "mozilla/MaybeOneOf.h"
#include "mozilla/Move.h"
@ -88,4 +89,39 @@ private:
} // namespace devtools
} // namespace mozilla
namespace JS {
namespace ubi {
using mozilla::devtools::DeserializedNode;
using mozilla::UniquePtr;
template<>
struct Concrete<DeserializedNode> : public Base
{
protected:
explicit Concrete(DeserializedNode *ptr) : Base(ptr) { }
DeserializedNode &get() const {
return *static_cast<DeserializedNode *>(ptr);
}
public:
static const char16_t concreteTypeName[];
static void construct(void *storage, DeserializedNode *ptr) {
new (storage) Concrete(ptr);
}
Id identifier() const override { return get().id; }
bool isLive() const override { return false; }
const char16_t *typeName() const override;
size_t size(mozilla::MallocSizeOf mallocSizeof) const override;
// We ignore the `bool wantNames` parameter because we can't control whether
// the core dump was serialized with edge names or not.
UniquePtr<EdgeRange> edges(JSContext* cx, bool) const override;
};
} // namespace JS
} // namespace ubi
#endif // mozilla_devtools_DeserializedNode__