LCOV - code coverage report
Current view: top level - devtools/shared/heapsnapshot - HeapSnapshot.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 28 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

          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             : #ifndef mozilla_devtools_HeapSnapshot__
       7             : #define mozilla_devtools_HeapSnapshot__
       8             : 
       9             : #include "js/HashTable.h"
      10             : #include "mozilla/ErrorResult.h"
      11             : #include "mozilla/devtools/DeserializedNode.h"
      12             : #include "mozilla/dom/BindingDeclarations.h"
      13             : #include "mozilla/dom/Nullable.h"
      14             : #include "mozilla/HashFunctions.h"
      15             : #include "mozilla/Maybe.h"
      16             : #include "mozilla/RefCounted.h"
      17             : #include "mozilla/RefPtr.h"
      18             : #include "mozilla/TimeStamp.h"
      19             : #include "mozilla/UniquePtr.h"
      20             : 
      21             : #include "CoreDump.pb.h"
      22             : #include "nsCOMPtr.h"
      23             : #include "nsCRTGlue.h"
      24             : #include "nsCycleCollectionParticipant.h"
      25             : #include "nsISupports.h"
      26             : #include "nsWrapperCache.h"
      27             : #include "nsXPCOM.h"
      28             : 
      29             : namespace mozilla {
      30             : namespace devtools {
      31             : 
      32             : class DominatorTree;
      33             : 
      34             : struct NSFreePolicy {
      35           0 :   void operator()(void* ptr) {
      36           0 :     NS_Free(ptr);
      37           0 :   }
      38             : };
      39             : 
      40             : using UniqueTwoByteString = UniquePtr<char16_t[], NSFreePolicy>;
      41             : using UniqueOneByteString = UniquePtr<char[], NSFreePolicy>;
      42             : 
      43             : class HeapSnapshot final : public nsISupports
      44             :                          , public nsWrapperCache
      45             : {
      46             :   friend struct DeserializedNode;
      47             :   friend struct DeserializedEdge;
      48             :   friend struct DeserializedStackFrame;
      49             :   friend class JS::ubi::Concrete<JS::ubi::DeserializedNode>;
      50             : 
      51           0 :   explicit HeapSnapshot(JSContext* cx, nsISupports* aParent)
      52           0 :     : timestamp(Nothing())
      53             :     , rootId(0)
      54             :     , nodes(cx)
      55             :     , frames(cx)
      56           0 :     , mParent(aParent)
      57             :   {
      58           0 :     MOZ_ASSERT(aParent);
      59           0 :   };
      60             : 
      61             :   // Initialize this HeapSnapshot from the given buffer that contains a
      62             :   // serialized core dump. Do NOT take ownership of the buffer, only borrow it
      63             :   // for the duration of the call. Return false on failure.
      64             :   bool init(JSContext* cx, const uint8_t* buffer, uint32_t size);
      65             : 
      66             :   using NodeIdSet = js::HashSet<NodeId>;
      67             : 
      68             :   // Save the given `protobuf::Node` message in this `HeapSnapshot` as a
      69             :   // `DeserializedNode`.
      70             :   bool saveNode(const protobuf::Node& node, NodeIdSet& edgeReferents);
      71             : 
      72             :   // Save the given `protobuf::StackFrame` message in this `HeapSnapshot` as a
      73             :   // `DeserializedStackFrame`. The saved stack frame's id is returned via the
      74             :   // out parameter.
      75             :   bool saveStackFrame(const protobuf::StackFrame& frame,
      76             :                       StackFrameId& outFrameId);
      77             : 
      78             : public:
      79             :   // The maximum number of stack frames that we will serialize into a core
      80             :   // dump. This helps prevent over-recursion in the protobuf library when
      81             :   // deserializing stacks.
      82             :   static const size_t MAX_STACK_DEPTH = 60;
      83             : 
      84             : private:
      85             :   // If present, a timestamp in the same units that `PR_Now` gives.
      86             :   Maybe<uint64_t> timestamp;
      87             : 
      88             :   // The id of the root node for this deserialized heap graph.
      89             :   NodeId rootId;
      90             : 
      91             :   // The set of nodes in this deserialized heap graph, keyed by id.
      92             :   using NodeSet = js::HashSet<DeserializedNode, DeserializedNode::HashPolicy>;
      93             :   NodeSet nodes;
      94             : 
      95             :   // The set of stack frames in this deserialized heap graph, keyed by id.
      96             :   using FrameSet = js::HashSet<DeserializedStackFrame,
      97             :                                DeserializedStackFrame::HashPolicy>;
      98             :   FrameSet frames;
      99             : 
     100             :   Vector<UniqueTwoByteString> internedTwoByteStrings;
     101             :   Vector<UniqueOneByteString> internedOneByteStrings;
     102             : 
     103             :   using StringOrRef = Variant<const std::string*, uint64_t>;
     104             : 
     105             :   template<typename CharT,
     106             :            typename InternedStringSet>
     107             :   const CharT* getOrInternString(InternedStringSet& internedStrings,
     108             :                                  Maybe<StringOrRef>& maybeStrOrRef);
     109             : 
     110             : protected:
     111             :   nsCOMPtr<nsISupports> mParent;
     112             : 
     113           0 :   virtual ~HeapSnapshot() { }
     114             : 
     115             : public:
     116             :   // Create a `HeapSnapshot` from the given buffer that contains a serialized
     117             :   // core dump. Do NOT take ownership of the buffer, only borrow it for the
     118             :   // duration of the call.
     119             :   static already_AddRefed<HeapSnapshot> Create(JSContext* cx,
     120             :                                                dom::GlobalObject& global,
     121             :                                                const uint8_t* buffer,
     122             :                                                uint32_t size,
     123             :                                                ErrorResult& rv);
     124             : 
     125             :   // Creates the `$TEMP_DIR/XXXXXX-XXX.fxsnapshot` core dump file that heap
     126             :   // snapshots are serialized into.
     127             :   static already_AddRefed<nsIFile> CreateUniqueCoreDumpFile(ErrorResult& rv,
     128             :                                                             const TimeStamp& now,
     129             :                                                             nsAString& outFilePath,
     130             :                                                             nsAString& outSnapshotId);
     131             : 
     132             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     133           0 :   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(HeapSnapshot)
     134             :   MOZ_DECLARE_REFCOUNTED_TYPENAME(HeapSnapshot)
     135             : 
     136           0 :   nsISupports* GetParentObject() const { return mParent; }
     137             : 
     138             :   virtual JSObject* WrapObject(JSContext* aCx,
     139             :                                JS::Handle<JSObject*> aGivenProto) override;
     140             : 
     141             :   const char16_t* borrowUniqueString(const char16_t* duplicateString,
     142             :                                      size_t length);
     143             : 
     144             :   // Get the root node of this heap snapshot's graph.
     145           0 :   JS::ubi::Node getRoot() {
     146           0 :     MOZ_ASSERT(nodes.initialized());
     147           0 :     auto p = nodes.lookup(rootId);
     148           0 :     MOZ_ASSERT(p);
     149           0 :     const DeserializedNode& node = *p;
     150           0 :     return JS::ubi::Node(const_cast<DeserializedNode*>(&node));
     151             :   }
     152             : 
     153           0 :   Maybe<JS::ubi::Node> getNodeById(JS::ubi::Node::Id nodeId) {
     154           0 :     auto p = nodes.lookup(nodeId);
     155           0 :     if (!p)
     156           0 :       return Nothing();
     157           0 :     return Some(JS::ubi::Node(const_cast<DeserializedNode*>(&*p)));
     158             :   }
     159             : 
     160             :   void TakeCensus(JSContext* cx, JS::HandleObject options,
     161             :                   JS::MutableHandleValue rval, ErrorResult& rv);
     162             : 
     163             :   void DescribeNode(JSContext* cx, JS::HandleObject breakdown, uint64_t nodeId,
     164             :                     JS::MutableHandleValue rval, ErrorResult& rv);
     165             : 
     166             :   already_AddRefed<DominatorTree> ComputeDominatorTree(ErrorResult& rv);
     167             : 
     168             :   void ComputeShortestPaths(JSContext*cx, uint64_t start,
     169             :                             const dom::Sequence<uint64_t>& targets,
     170             :                             uint64_t maxNumPaths,
     171             :                             JS::MutableHandleObject results,
     172             :                             ErrorResult& rv);
     173             : 
     174           0 :   dom::Nullable<uint64_t> GetCreationTime() {
     175             :     static const uint64_t maxTime = uint64_t(1) << 53;
     176           0 :     if (timestamp.isSome() && timestamp.ref() <= maxTime) {
     177           0 :       return dom::Nullable<uint64_t>(timestamp.ref());
     178             :     }
     179             : 
     180           0 :     return dom::Nullable<uint64_t>();
     181             :   }
     182             : };
     183             : 
     184             : // A `CoreDumpWriter` is given the data we wish to save in a core dump and
     185             : // serializes it to disk, or memory, or a socket, etc.
     186           0 : class CoreDumpWriter
     187             : {
     188             : public:
     189           0 :   virtual ~CoreDumpWriter() { };
     190             : 
     191             :   // Write the given bits of metadata we would like to associate with this core
     192             :   // dump.
     193             :   virtual bool writeMetadata(uint64_t timestamp) = 0;
     194             : 
     195             :   enum EdgePolicy : bool {
     196             :     INCLUDE_EDGES = true,
     197             :     EXCLUDE_EDGES = false
     198             :   };
     199             : 
     200             :   // Write the given `JS::ubi::Node` to the core dump. The given `EdgePolicy`
     201             :   // dictates whether its outgoing edges should also be written to the core
     202             :   // dump, or excluded.
     203             :   virtual bool writeNode(const JS::ubi::Node& node,
     204             :                          EdgePolicy includeEdges) = 0;
     205             : };
     206             : 
     207             : // Serialize the heap graph as seen from `node` with the given `CoreDumpWriter`.
     208             : // If `wantNames` is true, capture edge names. If `zones` is non-null, only
     209             : // capture the sub-graph within the zone set, otherwise capture the whole heap
     210             : // graph. Returns false on failure.
     211             : bool
     212             : WriteHeapGraph(JSContext* cx,
     213             :                const JS::ubi::Node& node,
     214             :                CoreDumpWriter& writer,
     215             :                bool wantNames,
     216             :                JS::CompartmentSet* compartments,
     217             :                JS::AutoCheckCannotGC& noGC,
     218             :                uint32_t& outNodeCount,
     219             :                uint32_t& outEdgeCount);
     220             : inline bool
     221             : WriteHeapGraph(JSContext* cx,
     222             :                const JS::ubi::Node& node,
     223             :                CoreDumpWriter& writer,
     224             :                bool wantNames,
     225             :                JS::CompartmentSet* compartments,
     226             :                JS::AutoCheckCannotGC& noGC)
     227             : {
     228             :   uint32_t ignoreNodeCount;
     229             :   uint32_t ignoreEdgeCount;
     230             :   return WriteHeapGraph(cx, node, writer, wantNames, compartments, noGC,
     231             :                         ignoreNodeCount, ignoreEdgeCount);
     232             : }
     233             : 
     234             : // Get the mozilla::MallocSizeOf for the current thread's JSRuntime.
     235             : MallocSizeOf GetCurrentThreadDebuggerMallocSizeOf();
     236             : 
     237             : } // namespace devtools
     238             : } // namespace mozilla
     239             : 
     240             : #endif // mozilla_devtools_HeapSnapshot__

Generated by: LCOV version 1.13