LCOV - code coverage report
Current view: top level - js/public - UbiNodeCensus.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 37 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef js_UbiNodeCensus_h
       8             : #define js_UbiNodeCensus_h
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : #include "mozilla/Move.h"
      12             : 
      13             : #include <algorithm>
      14             : 
      15             : #include "jsapi.h"
      16             : 
      17             : #include "js/UbiNode.h"
      18             : #include "js/UbiNodeBreadthFirst.h"
      19             : 
      20             : // A census is a ubi::Node traversal that assigns each node to one or more
      21             : // buckets, and returns a report with the size of each bucket.
      22             : //
      23             : // We summarize the results of a census with counts broken down according to
      24             : // criteria selected by the API consumer code that is requesting the census. For
      25             : // example, the following breakdown might give an interesting overview of the
      26             : // heap:
      27             : //
      28             : //   - all nodes
      29             : //     - objects
      30             : //       - objects with a specific [[Class]] *
      31             : //     - strings
      32             : //     - scripts
      33             : //     - all other Node types
      34             : //       - nodes with a specific ubi::Node::typeName *
      35             : //
      36             : // Obviously, the parts of this tree marked with * represent many separate
      37             : // counts, depending on how many distinct [[Class]] values and ubi::Node type
      38             : // names we encounter.
      39             : //
      40             : // The supported types of breakdowns are documented in
      41             : // js/src/doc/Debugger/Debugger.Memory.md.
      42             : //
      43             : // When we parse the 'breakdown' argument to takeCensus, we build a tree of
      44             : // CountType nodes. For example, for the breakdown shown in the
      45             : // Debugger.Memory.prototype.takeCensus, documentation:
      46             : //
      47             : //    {
      48             : //      by: "coarseType",
      49             : //      objects: { by: "objectClass" },
      50             : //      other:    { by: "internalType" }
      51             : //    }
      52             : //
      53             : // we would build the following tree of CountType subclasses:
      54             : //
      55             : //    ByCoarseType
      56             : //      objects: ByObjectClass
      57             : //        each class: SimpleCount
      58             : //      scripts: SimpleCount
      59             : //      strings: SimpleCount
      60             : //      other: ByUbinodeType
      61             : //        each type: SimpleCount
      62             : //
      63             : // The interior nodes are all breakdown types that categorize nodes according to
      64             : // one characteristic or another; and the leaf nodes are all SimpleType.
      65             : //
      66             : // Each CountType has its own concrete C++ type that holds the counts it
      67             : // produces. SimpleCount::Count just holds totals. ByObjectClass::Count has a
      68             : // hash table whose keys are object class names and whose values are counts of
      69             : // some other type (in the example above, SimpleCount).
      70             : //
      71             : // To keep actual count nodes small, they have no vtable. Instead, each count
      72             : // points to its CountType, which knows how to carry out all the operations we
      73             : // need on a Count. A CountType can produce new count nodes; process nodes as we
      74             : // visit them; build a JS object reporting the results; and destruct count
      75             : // nodes.
      76             : 
      77             : 
      78             : namespace JS {
      79             : namespace ubi {
      80             : 
      81             : struct Census;
      82             : 
      83             : class CountBase;
      84             : 
      85             : struct CountDeleter {
      86             :     JS_PUBLIC_API(void) operator()(CountBase*);
      87             : };
      88             : 
      89             : using CountBasePtr = js::UniquePtr<CountBase, CountDeleter>;
      90             : 
      91             : // Abstract base class for CountType nodes.
      92             : struct CountType {
      93           0 :     explicit CountType() { }
      94           0 :     virtual ~CountType() { }
      95             : 
      96             :     // Destruct a count tree node that this type instance constructed.
      97             :     virtual void destructCount(CountBase& count) = 0;
      98             : 
      99             :     // Return a fresh node for the count tree that categorizes nodes according
     100             :     // to this type. Return a nullptr on OOM.
     101             :     virtual CountBasePtr makeCount() = 0;
     102             : 
     103             :     // Trace |count| and all its children, for garbage collection.
     104             :     virtual void traceCount(CountBase& count, JSTracer* trc) = 0;
     105             : 
     106             :     // Implement the 'count' method for counts returned by this CountType
     107             :     // instance's 'newCount' method.
     108             :     virtual MOZ_MUST_USE bool count(CountBase& count,
     109             :                                     mozilla::MallocSizeOf mallocSizeOf,
     110             :                                     const Node& node) = 0;
     111             : 
     112             :     // Implement the 'report' method for counts returned by this CountType
     113             :     // instance's 'newCount' method.
     114             :     virtual MOZ_MUST_USE bool report(JSContext* cx, CountBase& count,
     115             :                                      MutableHandleValue report) = 0;
     116             : };
     117             : 
     118             : using CountTypePtr = js::UniquePtr<CountType>;
     119             : 
     120             : // An abstract base class for count tree nodes.
     121             : class CountBase {
     122             :     // In lieu of a vtable, each CountBase points to its type, which
     123             :     // carries not only the implementations of the CountBase methods, but also
     124             :     // additional parameters for the type's behavior, as specified in the
     125             :     // breakdown argument passed to takeCensus.
     126             :     CountType& type;
     127             : 
     128             :   protected:
     129           0 :     ~CountBase() { }
     130             : 
     131             :   public:
     132           0 :     explicit CountBase(CountType& type)
     133           0 :       : type(type)
     134             :       , total_(0)
     135           0 :       , smallestNodeIdCounted_(SIZE_MAX)
     136           0 :     { }
     137             : 
     138             :     // Categorize and count |node| as appropriate for this count's type.
     139           0 :     MOZ_MUST_USE bool count(mozilla::MallocSizeOf mallocSizeOf, const Node& node) {
     140           0 :         total_++;
     141             : 
     142           0 :         auto id = node.identifier();
     143           0 :         if (id < smallestNodeIdCounted_) {
     144           0 :             smallestNodeIdCounted_ = id;
     145             :         }
     146             : 
     147             : #ifdef DEBUG
     148           0 :         size_t oldTotal = total_;
     149             : #endif
     150             : 
     151           0 :         bool ret = type.count(*this, mallocSizeOf, node);
     152             : 
     153           0 :         MOZ_ASSERT(total_ == oldTotal,
     154             :                    "CountType::count should not increment total_, CountBase::count handles that");
     155             : 
     156           0 :         return ret;
     157             :     }
     158             : 
     159             :     // Construct a JavaScript object reporting the counts recorded in this
     160             :     // count, and store it in |report|. Return true on success, or false on
     161             :     // failure.
     162           0 :     MOZ_MUST_USE bool report(JSContext* cx, MutableHandleValue report) {
     163           0 :         return type.report(cx, *this, report);
     164             :     }
     165             : 
     166             :     // Down-cast this CountBase to its true type, based on its 'type' member,
     167             :     // and run its destructor.
     168           0 :     void destruct() { return type.destructCount(*this); }
     169             : 
     170             :     // Trace this count for garbage collection.
     171           0 :     void trace(JSTracer* trc) { type.traceCount(*this, trc); }
     172             : 
     173             :     size_t total_;
     174             : 
     175             :     // The smallest JS::ubi::Node::identifier() passed to this instance's
     176             :     // count() method. This provides a stable way to sort sets.
     177             :     Node::Id smallestNodeIdCounted_;
     178             : };
     179             : 
     180           0 : class RootedCount : JS::CustomAutoRooter {
     181             :     CountBasePtr count;
     182             : 
     183           0 :     void trace(JSTracer* trc) override { count->trace(trc); }
     184             : 
     185             :   public:
     186           0 :     RootedCount(JSContext* cx, CountBasePtr&& count)
     187           0 :         : CustomAutoRooter(cx),
     188           0 :           count(Move(count))
     189           0 :           { }
     190           0 :     CountBase* operator->() const { return count.get(); }
     191           0 :     explicit operator bool() const { return count.get(); }
     192           0 :     operator CountBasePtr&() { return count; }
     193             : };
     194             : 
     195             : // Common data for a census traversal, shared across all CountType nodes.
     196           0 : struct Census {
     197             :     JSContext* const cx;
     198             :     // If the targetZones set is non-empty, then only consider nodes whose zone
     199             :     // is an element of the set. If the targetZones set is empty, then nodes in
     200             :     // all zones are considered.
     201             :     JS::ZoneSet targetZones;
     202             :     Zone* atomsZone;
     203             : 
     204           0 :     explicit Census(JSContext* cx) : cx(cx), atomsZone(nullptr) { }
     205             : 
     206             :     MOZ_MUST_USE JS_PUBLIC_API(bool) init();
     207             : };
     208             : 
     209             : // A BreadthFirst handler type that conducts a census, using a CountBase to
     210             : // categorize and count each node.
     211             : class CensusHandler {
     212             :     Census& census;
     213             :     CountBasePtr& rootCount;
     214             :     mozilla::MallocSizeOf mallocSizeOf;
     215             : 
     216             :   public:
     217           0 :     CensusHandler(Census& census, CountBasePtr& rootCount, mozilla::MallocSizeOf mallocSizeOf)
     218           0 :       : census(census),
     219             :         rootCount(rootCount),
     220           0 :         mallocSizeOf(mallocSizeOf)
     221           0 :     { }
     222             : 
     223           0 :     MOZ_MUST_USE bool report(JSContext* cx, MutableHandleValue report) {
     224           0 :         return rootCount->report(cx, report);
     225             :     }
     226             : 
     227             :     // This class needs to retain no per-node data.
     228             :     class NodeData { };
     229             : 
     230             :     MOZ_MUST_USE JS_PUBLIC_API(bool) operator() (BreadthFirst<CensusHandler>& traversal,
     231             :                                                  Node origin, const Edge& edge,
     232             :                                                  NodeData* referentData, bool first);
     233             : };
     234             : 
     235             : using CensusTraversal = BreadthFirst<CensusHandler>;
     236             : 
     237             : // Examine the census options supplied by the API consumer, and (among other
     238             : // things) use that to build a CountType tree.
     239             : MOZ_MUST_USE JS_PUBLIC_API(bool) ParseCensusOptions(JSContext* cx,
     240             :                                                     Census& census, HandleObject options,
     241             :                                                     CountTypePtr& outResult);
     242             : 
     243             : // Parse the breakdown language (as described in
     244             : // js/src/doc/Debugger/Debugger.Memory.md) into a CountTypePtr. A null pointer
     245             : // is returned on error and is reported to the cx.
     246             : JS_PUBLIC_API(CountTypePtr) ParseBreakdown(JSContext* cx, HandleValue breakdownValue);
     247             : 
     248             : 
     249             : } // namespace ubi
     250             : } // namespace JS
     251             : 
     252             : #endif // js_UbiNodeCensus_h

Generated by: LCOV version 1.13