Files
palemoon27/js/public/UbiNodeCensus.h
T
roytam1 b5ee72fe09 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1265956 - Assert that no entry is found in HashTable::putNew. (r=terrence) (8770735325)
- Bug 1265483 - Use WeakCache to automate sweeping of ObjectGroupComparment::NewTable; r=jonco (e88fa842ab)
- Bug 1198093 - Part 1: Expose indexedDB to System with [Exposed=System]. r=khuey (2a20a6ecd0)
- Bug 1198093 - Part 2: Set Default Locale Value in ICU Canonicalization Form. r=khuey (1e1cd981ce)
- Bug 1263871 - Fix OOM handling in while resolving function name r=shu (44114a7e8d)
- Bug 1263270 - Sort census reports by smallest node ID counted, rather than number of nodes counted. r=jimb (08d4a431a7)
- Bug 1263218 - Fix possbile race under oomTest involving background threads r=terrence (82c1e3b698)
- Bug 1256488 - Add explicit casts to fix MSVC warning C4365. r=fitzgen (b9bb6b52c5)
- Bug 1235677 - Add assertion to catch unsafe concurrent use of AutoEnterOOMUnsafeRegion r=terrence (2e0876578f)
- Bug 1263902 - check return value from JS_smprintf. r=bbouvier, r=shu (df1d9b5e14)
- Bug 1262208: Generalize the disabled compilation mode message for asm.js; r=luke (9153b2c5ba)
- Bug 1259903: Baldr: unify Select true and false types instead of checking against each other; r=luke (5f89398199)
- Bug 1253344: Remove unused pushPhi/popPhi in WasmIonCompile; r=luke (244967401c)
- Bug 933257 - Part 1: Add a script to import and update fdlibm from FreeBSD. r=jwalden (37c8a85771)
- Bug 933257 - Part 2: Add patches for fdlibm. r=jwalden (bc0dce94a0)
- Bug 933257 - Part 2.1: Import fdlibm from FreeBSD (revision bcea9d50b15e4f0027a5dd526e0e2a612238471e). r=jwalden (223f6d6ce5)
- Bug 933257 - Part 3: Add build scripts for fdlibm. r=jwalden (893f740423)
- Bug 933257 - Part 4: Link fdlibm in SpiderMonkey. r=jwalden (9f1395258a)
- Bug 933257 - Part 5: Use fdlibm in jsmath.cpp. r=jwalden (9d962657ab)
- Bug 933257 - Part 6: Remove unused math polyfill. r=jwalden (cf284ad4e5)
- Bug 1225024 - Allow sloppy tolerance in ecma_6/Math/log10-approx.js. r=jorendorff (7df3bf46dd)
- Bug 933257 - Part 7: Remove or reduce sloppy_tolerance in Math function tests. r=jorendorff (86b978eb14)
- Bug 933257 - Part 8: Add license for k_exp.cpp to about:license. r=gerv (513012fbb9)
- Bug 933257 - Part 9: Use fdlibm in asm.js. r=luke (46bedc10d0)
- Bug 1256490 - Disable C4302 to unblock compilation on VS2015; r=bobowen (7fb6820241)
- Bug 1256499 - Disable C4311 and C4312 to unblock compilation on VS2015; r=bobowen (a9b3b01410)
- Bug 1257036 - Disable C4302 to unblock compilation on VS2015; r=bobowen (307af58682)
- Bug 1124033 - Disable C4311 and C4312 in directories exhibiting warnings; r=ehsan (b6ecd1f8e7)
- Bug 1252931 - Remove INSTALL/PP_TARGETS from js/src/*; r=gps (a1e1d3bb82)
- Bug 1258908: Rename TYPE_MOZILLA_UI to TYPE_MOZILLA_PARENT. r=jld (29aef56b8e)
- Bug 1203835 - Don't ship replace_jemalloc. r=njn (249f927cf5)
- bug 1259753 - fix some C++ unittests to use ScopedXPCOM to init XPCOM. r=ms2ger (a908216277)
2024-04-30 11:53:38 +08:00

250 lines
8.1 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_UbiNodeCensus_h
#define js_UbiNodeCensus_h
#include "mozilla/Move.h"
#include <algorithm>
#include "jsapi.h"
#include "js/UbiNode.h"
#include "js/UbiNodeBreadthFirst.h"
// A census is a ubi::Node traversal that assigns each node to one or more
// buckets, and returns a report with the size of each bucket.
//
// We summarize the results of a census with counts broken down according to
// criteria selected by the API consumer code that is requesting the census. For
// example, the following breakdown might give an interesting overview of the
// heap:
//
// - all nodes
// - objects
// - objects with a specific [[Class]] *
// - strings
// - scripts
// - all other Node types
// - nodes with a specific ubi::Node::typeName *
//
// Obviously, the parts of this tree marked with * represent many separate
// counts, depending on how many distinct [[Class]] values and ubi::Node type
// names we encounter.
//
// The supported types of breakdowns are documented in
// js/src/doc/Debugger/Debugger.Memory.md.
//
// When we parse the 'breakdown' argument to takeCensus, we build a tree of
// CountType nodes. For example, for the breakdown shown in the
// Debugger.Memory.prototype.takeCensus, documentation:
//
// {
// by: "coarseType",
// objects: { by: "objectClass" },
// other: { by: "internalType" }
// }
//
// we would build the following tree of CountType subclasses:
//
// ByCoarseType
// objects: ByObjectClass
// each class: SimpleCount
// scripts: SimpleCount
// strings: SimpleCount
// other: ByUbinodeType
// each type: SimpleCount
//
// The interior nodes are all breakdown types that categorize nodes according to
// one characteristic or another; and the leaf nodes are all SimpleType.
//
// Each CountType has its own concrete C++ type that holds the counts it
// produces. SimpleCount::Count just holds totals. ByObjectClass::Count has a
// hash table whose keys are object class names and whose values are counts of
// some other type (in the example above, SimpleCount).
//
// To keep actual count nodes small, they have no vtable. Instead, each count
// points to its CountType, which knows how to carry out all the operations we
// need on a Count. A CountType can produce new count nodes; process nodes as we
// visit them; build a JS object reporting the results; and destruct count
// nodes.
namespace JS {
namespace ubi {
struct Census;
class CountBase;
struct JS_FRIEND_API(CountDeleter) {
void operator()(CountBase*);
};
using CountBasePtr = js::UniquePtr<CountBase, CountDeleter>;
// Abstract base class for CountType nodes.
struct JS_FRIEND_API(CountType) {
explicit CountType() { }
virtual ~CountType() { }
// Destruct a count tree node that this type instance constructed.
virtual void destructCount(CountBase& count) = 0;
// Return a fresh node for the count tree that categorizes nodes according
// to this type. Return a nullptr on OOM.
virtual CountBasePtr makeCount() = 0;
// Trace |count| and all its children, for garbage collection.
virtual void traceCount(CountBase& count, JSTracer* trc) = 0;
// Implement the 'count' method for counts returned by this CountType
// instance's 'newCount' method.
virtual bool count(CountBase& count,
mozilla::MallocSizeOf mallocSizeOf,
const Node& node) = 0;
// Implement the 'report' method for counts returned by this CountType
// instance's 'newCount' method.
virtual bool report(JSContext* cx, CountBase& count, MutableHandleValue report) = 0;
};
using CountTypePtr = js::UniquePtr<CountType>;
// An abstract base class for count tree nodes.
class JS_FRIEND_API(CountBase) {
// In lieu of a vtable, each CountBase points to its type, which
// carries not only the implementations of the CountBase methods, but also
// additional parameters for the type's behavior, as specified in the
// breakdown argument passed to takeCensus.
CountType& type;
protected:
~CountBase() { }
public:
explicit CountBase(CountType& type)
: type(type)
, total_(0)
, smallestNodeIdCounted_(SIZE_MAX)
{ }
// Categorize and count |node| as appropriate for this count's type.
bool count(mozilla::MallocSizeOf mallocSizeOf, const Node& node) {
total_++;
auto id = node.identifier();
if (id < smallestNodeIdCounted_) {
smallestNodeIdCounted_ = id;
}
#ifdef DEBUG
size_t oldTotal = total_;
#endif
bool ret = type.count(*this, mallocSizeOf, node);
MOZ_ASSERT(total_ == oldTotal,
"CountType::count should not increment total_, CountBase::count handles that");
return ret;
}
// Construct a JavaScript object reporting the counts recorded in this
// count, and store it in |report|. Return true on success, or false on
// failure.
bool report(JSContext* cx, MutableHandleValue report) {
return type.report(cx, *this, report);
}
// Down-cast this CountBase to its true type, based on its 'type' member,
// and run its destructor.
void destruct() { return type.destructCount(*this); }
// Trace this count for garbage collection.
void trace(JSTracer* trc) { type.traceCount(*this, trc); }
size_t total_;
// The smallest JS::ubi::Node::identifier() passed to this instance's
// count() method. This provides a stable way to sort sets.
Node::Id smallestNodeIdCounted_;
};
class RootedCount : JS::CustomAutoRooter {
CountBasePtr count;
void trace(JSTracer* trc) override { count->trace(trc); }
public:
RootedCount(JSContext* cx, CountBasePtr&& count)
: CustomAutoRooter(cx),
count(Move(count))
{ }
CountBase* operator->() const { return count.get(); }
explicit operator bool() const { return count.get(); }
operator CountBasePtr&() { return count; }
};
// Common data for a census traversal, shared across all CountType nodes.
struct JS_FRIEND_API(Census) {
JSContext* const cx;
// If the targetZones set is non-empty, then only consider nodes whose zone
// is an element of the set. If the targetZones set is empty, then nodes in
// all zones are considered.
JS::ZoneSet targetZones;
Zone* atomsZone;
explicit Census(JSContext* cx) : cx(cx), atomsZone(nullptr) { }
bool init();
};
// A BreadthFirst handler type that conducts a census, using a CountBase to
// categorize and count each node.
class JS_FRIEND_API(CensusHandler) {
Census& census;
CountBasePtr& rootCount;
mozilla::MallocSizeOf mallocSizeOf;
public:
CensusHandler(Census& census, CountBasePtr& rootCount, mozilla::MallocSizeOf mallocSizeOf)
: census(census),
rootCount(rootCount),
mallocSizeOf(mallocSizeOf)
{ }
bool report(JSContext* cx, MutableHandleValue report) {
return rootCount->report(cx, report);
}
// This class needs to retain no per-node data.
class NodeData { };
bool operator() (BreadthFirst<CensusHandler>& traversal,
Node origin, const Edge& edge,
NodeData* referentData, bool first);
};
using CensusTraversal = BreadthFirst<CensusHandler>;
// Examine the census options supplied by the API consumer, and (among other
// things) use that to build a CountType tree.
JS_FRIEND_API(bool) ParseCensusOptions(JSContext* cx, Census& census, HandleObject options,
CountTypePtr& outResult);
// Parse the breakdown language (as described in
// js/src/doc/Debugger/Debugger.Memory.md) into a CountTypePtr. A null pointer
// is returned on error and is reported to the cx.
JS_FRIEND_API(CountTypePtr) ParseBreakdown(JSContext* cx, HandleValue breakdownValue);
} // namespace ubi
} // namespace JS
#endif // js_UbiNodeCensus_h