xpcom/base/nsICycleCollectorListener.idl

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/base/nsICycleCollectorListener.idl	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,178 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "nsISupports.idl"
     1.9 +
    1.10 +/**
    1.11 + * Interfaces for observing the cycle collector's work, both from C++ and
    1.12 + * from JavaScript.
    1.13 + *
    1.14 + * If given an object implementing nsICycleCollectorListener, the cycle
    1.15 + * collector calls that object's methods as it works, describing the
    1.16 + * objects it visits, the edges it finds, and the conclusions it reaches
    1.17 + * about which objects are live.
    1.18 + *
    1.19 + * Analyzing cycle collection from JS is harder: an nsICycleCollectorListener
    1.20 + * mustn't mess with the object graph while the cycle collector is trying to
    1.21 + * figure it out, which means it can't be implemented by JS code: JS can't do
    1.22 + * much of anything useful within those constraints. Instead, JS code can
    1.23 + * instantiate @mozilla.org/cycle-collector-logger;1, a C++ class implementing
    1.24 + * nsICycleCollectorListener that logs the cycle collector's mumblings and then
    1.25 + * replays them later to an nsICycleCollectorHandler --- which *can* be
    1.26 + * implemented in JS.
    1.27 + */
    1.28 +
    1.29 +/**
    1.30 + * The interface JS code should implement to receive annotations logged by an
    1.31 + * @mozilla.org/cycle-collector-logger;1 instance. Pass an instance of this to
    1.32 + * the logger's 'processNext' method.
    1.33 + *
    1.34 + * The methods are a subset of those in nsICycleCollectorListener; see the
    1.35 + * descriptions there.
    1.36 + */
    1.37 +[scriptable, uuid(39a8f80e-7eee-4141-b9ef-6e2a7d6e466d)]
    1.38 +interface nsICycleCollectorHandler : nsISupports
    1.39 +{
    1.40 +    void noteRefCountedObject(in ACString aAddress,
    1.41 +                              in unsigned long aRefCount,
    1.42 +                              in ACString aObjectDescription);
    1.43 +    void noteGCedObject(in ACString aAddress,
    1.44 +                        in boolean aMarked,
    1.45 +                        in ACString aObjectDescription,
    1.46 +                        in ACString aCompartmentAddress);
    1.47 +    void noteEdge(in ACString aFromAddress,
    1.48 +                  in ACString aToAddress,
    1.49 +                  in ACString aEdgeName);
    1.50 +    void describeRoot(in ACString aAddress,
    1.51 +                      in unsigned long aKnownEdges);
    1.52 +    void describeGarbage(in ACString aAddress);
    1.53 +};
    1.54 +
    1.55 +/**
    1.56 + * Given an instance of this interface, the cycle collector calls the instance's
    1.57 + * methods to report the objects it visits, the edges between them, and its
    1.58 + * conclusions about which objects are roots and which are garbage.
    1.59 + *
    1.60 + * For a single cycle collection pass, the cycle collector calls this
    1.61 + * interface's methods in the following order:
    1.62 + *
    1.63 + * - First, |begin|. If |begin| returns an error, none of the listener's other
    1.64 + *   methods will be called.
    1.65 + *
    1.66 + * - Then, for each node in the graph:
    1.67 + *   - a call to either |noteRefCountedObject| or |noteGCedObject|, to describe
    1.68 + *     the node itself; and
    1.69 + *   - for each edge starting at that node, a call to |noteEdge|.
    1.70 + *
    1.71 + * - Then, zero or more calls to |noteIncrementalRoot|; an "incremental
    1.72 + *   root" is an object that may have had a new reference to it created
    1.73 + *   during an incremental collection, and must therefore be treated as
    1.74 + *   live for safety.
    1.75 + *
    1.76 + * - After all the nodes have been described, a call to |beginResults|.
    1.77 + *
    1.78 + * - A series of calls to:
    1.79 + *   - |describeRoot|, for reference-counted nodes that the CC has identified as
    1.80 + *     roots of collection. (The cycle collector didn't find enough incoming
    1.81 + *     edges to account for these nodes' reference counts, so there must be code
    1.82 + *     holding on to them that the cycle collector doesn't know about.)
    1.83 + *   - |describeGarbage|, for nodes the cycle collector has identified as garbage.
    1.84 + *
    1.85 + *   Any node not mentioned in a call to |describeRoot| or |describeGarbage| is
    1.86 + *   neither a root nor garbage. (The cycle collector was able to find all the
    1.87 + *   edges implied by the node's reference count.)
    1.88 + *
    1.89 + * - Finally, a call to |end|.
    1.90 + *
    1.91 + *
    1.92 + * This interface cannot be implemented by JavaScript code, as it is called
    1.93 + * while the cycle collector works. To analyze cycle collection data in JS:
    1.94 + *
    1.95 + * - Create an instance of @mozilla.org/cycle-collector-logger;1, which
    1.96 + *   implements this interface.
    1.97 + *
    1.98 + * - Set its |disableLog| property to true. This prevents the logger from
    1.99 + *   printing messages about each method call to a temporary log file.
   1.100 + *
   1.101 + * - Set its |wantAfterProcessing| property to true. This tells the logger
   1.102 + *   to record calls to its methods in memory. The |processNext| method
   1.103 + *   returns events from this record.
   1.104 + *
   1.105 + * - Perform a collection using the logger. For example, call
   1.106 + *   |nsIDOMWindowUtils|'s |garbageCollect| method, passing the logger as
   1.107 + *   the |aListener| argument.
   1.108 + *
   1.109 + * - When the collection is complete, loop calling the logger's
   1.110 + *   |processNext| method, passing a JavaScript object that implements
   1.111 + *   nsICycleCollectorHandler. This JS code is free to allocate and operate
   1.112 + *   on objects however it pleases: the cycle collector has finished its
   1.113 + *   work, and the JS code is simply consuming recorded data.
   1.114 + */
   1.115 +[scriptable, builtinclass, uuid(c46e6947-9076-4a0e-bb27-d4aa3706c54d)]
   1.116 +interface nsICycleCollectorListener : nsISupports
   1.117 +{
   1.118 +    // Return a listener that directs the cycle collector to traverse
   1.119 +    // objects that it knows won't be collectable.
   1.120 +    //
   1.121 +    // Note that even this listener will not visit every node in the heap;
   1.122 +    // the cycle collector can't see the entire heap. But while this
   1.123 +    // listener is in use, the collector disables some optimizations it
   1.124 +    // normally uses to avoid certain classes of objects that are certainly
   1.125 +    // alive. So, if your purpose is to get a view of the portion of the
   1.126 +    // heap that is of interest to the cycle collector, and not simply find
   1.127 +    // garbage, then you should use the listener this returns.
   1.128 +    //
   1.129 +    // Note that this does not necessarily return a new listener; rather, it may
   1.130 +    // simply set a flag on this listener (a side effect!) and return it.
   1.131 +    nsICycleCollectorListener allTraces();
   1.132 +
   1.133 +    // True if this listener will behave like one returned by allTraces().
   1.134 +    readonly attribute boolean wantAllTraces;
   1.135 +
   1.136 +    // If true, do not log each method call to a temporary file.
   1.137 +    // Initially false.
   1.138 +    attribute boolean disableLog;
   1.139 +
   1.140 +    // This string will appear somewhere in the log's filename.
   1.141 +    attribute AString filenameIdentifier;
   1.142 +
   1.143 +    // If true, record all method calls in memory, to be retrieved later
   1.144 +    // using |processNext|. Initially false.
   1.145 +    attribute boolean wantAfterProcessing;
   1.146 +
   1.147 +    // This string will indicate the full path of the GC log if enabled.
   1.148 +    readonly attribute AString gcLogPath;
   1.149 +
   1.150 +    // This string will indicate the full path of the CC log if enabled.
   1.151 +    readonly attribute AString ccLogPath;
   1.152 +
   1.153 +    void begin();
   1.154 +    void noteRefCountedObject (in unsigned long long aAddress,
   1.155 +			       in unsigned long aRefCount,
   1.156 +			       in string aObjectDescription);
   1.157 +    void noteGCedObject (in unsigned long long aAddress,
   1.158 +			 in boolean aMarked,
   1.159 +			 in string aObjectDescription,
   1.160 +			 in unsigned long long aCompartmentAddress);
   1.161 +    void noteEdge(in unsigned long long aToAddress,
   1.162 +                  in string aEdgeName);
   1.163 +    void noteWeakMapEntry(in unsigned long long aMap,
   1.164 +                          in unsigned long long aKey,
   1.165 +                          in unsigned long long aKeyDelegate,
   1.166 +                          in unsigned long long aValue);
   1.167 +    void noteIncrementalRoot(in unsigned long long aAddress);
   1.168 +
   1.169 +    void beginResults();
   1.170 +    void describeRoot(in unsigned long long aAddress,
   1.171 +		      in unsigned long aKnownEdges);
   1.172 +    void describeGarbage(in unsigned long long aAddress);
   1.173 +    void end();
   1.174 +
   1.175 +    // Report the next recorded event to |aHandler|, and remove it from the
   1.176 +    // record. Return false if there isn't anything more to process.
   1.177 +    //
   1.178 +    // Note that we only record events to report here if our
   1.179 +    // |wantAfterProcessing| property is true.
   1.180 +    boolean processNext(in nsICycleCollectorHandler aHandler);
   1.181 +};

mercurial