DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (c2593a3058af)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
/* 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/. */

#include "nsISupports.idl"

%{C++
#include <stdio.h>

class nsCycleCollectorLogger;
%}

[ptr] native FILE(FILE);
[ptr] native nsCycleCollectorLoggerPtr (nsCycleCollectorLogger);
interface nsIFile;

/**
 * A set of interfaces for recording the cycle collector's work. An instance
 * of nsICycleCollectorListener can be configured to enable various
 * options, then passed to the cycle collector when it runs.
 * Note that additional logging options are available by setting environment
 * variables, as described at the top of nsCycleCollector.cpp.
 */

/**
 * nsICycleCollectorHandler is the interface JS code should implement to
 * receive the results logged by an nsICycleCollectorListener
 * instance. Pass an instance of this to the logger's 'processNext' method
 * after the collection has run. This will describe the objects the cycle
 * collector visited, the edges it found, and the conclusions it reached
 * about the liveness of objects.
 *
 * In more detail:
 * - For each node in the graph:
 *   - a call is made to either |noteRefCountedObject| or |noteGCedObject|, to
 *     describe the node itself; and
 *   - for each edge starting at that node, a call is made to |noteEdge|.
 *
 * - Then, a series of calls are made to:
 *   - |describeRoot|, for reference-counted nodes that the CC has identified as
 *     being alive because there are unknown references to those nodes.
 *   - |describeGarbage|, for nodes the cycle collector has identified as garbage.
 *
 *   Any node not mentioned in a call to |describeRoot| or |describeGarbage| is
 *   neither a root nor garbage. The cycle collector was able to find all of the
 *   edges implied by the node's reference count.
 */
[scriptable, uuid(7f093367-1492-4b89-87af-c01dbc831246)]
interface nsICycleCollectorHandler : nsISupports
{
    void noteRefCountedObject(in ACString aAddress,
                              in unsigned long aRefCount,
                              in ACString aObjectDescription);
    void noteGCedObject(in ACString aAddress,
                        in boolean aMarked,
                        in ACString aObjectDescription,
                        in ACString aCompartmentAddress);
    void noteEdge(in ACString aFromAddress,
                  in ACString aToAddress,
                  in ACString aEdgeName);
    void describeRoot(in ACString aAddress,
                      in unsigned long aKnownEdges);
    void describeGarbage(in ACString aAddress);
};


/**
 * This interface allows replacing the log-writing backend for an
 * nsICycleCollectorListener.  As this interface is also called while
 * the cycle collector is running, it cannot be implemented in JS.
 */
[scriptable, builtinclass, uuid(3ad9875f-d0e4-4ac2-87e3-f127f6c02ce1)]
interface nsICycleCollectorLogSink : nsISupports
{
  [noscript] void open(out FILE aGCLog, out FILE aCCLog);
  void closeGCLog();
  void closeCCLog();

  // This string will appear somewhere in the log's filename.
  attribute AString filenameIdentifier;

  // This is the process ID; it can be changed if logging is on behalf
  // of another process.
  attribute int32_t processIdentifier;

  // The GC log file, if logging to files.
  readonly attribute nsIFile gcLog;

  // The CC log file, if logging to files.
  readonly attribute nsIFile ccLog;
};


/**
 * This interface is used to configure some reporting options for the cycle
 * collector. This interface cannot be implemented by JavaScript code, as it
 * is called while the cycle collector is running.
 *
 * To analyze cycle collection data in JS:
 *
 * - Create an instance of nsICycleCollectorListener, which implements this
 *   interface. In C++, this can be done by calling
 *   nsCycleCollector_createLogger(). In JS, this can be done by calling
 *   Components.utils.createCCLogger().
 *
 * - Set its |disableLog| property to true. This prevents the logger from
 *   printing messages about each method call to a temporary log file.
 *
 * - Set its |wantAfterProcessing| property to true. This tells the logger
 *   to record calls to its methods in memory. The |processNext| method
 *   returns events from this record.
 *
 * - Perform a collection using the logger. For example, call
 *   |nsIDOMWindowUtils|'s |garbageCollect| method, passing the logger as
 *   the |aListener| argument.
 *
 * - When the collection is complete, loop calling the logger's
 *   |processNext| method, passing a JavaScript object that implements
 *   nsICycleCollectorHandler. This JS code is free to allocate and operate
 *   on objects however it pleases: the cycle collector has finished its
 *   work, and the JS code is simply consuming recorded data.
 */
[scriptable, builtinclass, uuid(703b53b6-24f6-40c6-9ea9-aeb2dc53d170)]
interface nsICycleCollectorListener : nsISupports
{
    // Return a listener that directs the cycle collector to traverse
    // objects that it knows won't be collectable.
    //
    // Note that even this listener will not visit every node in the heap;
    // the cycle collector can't see the entire heap. But while this
    // listener is in use, the collector disables some optimizations it
    // normally uses to avoid certain classes of objects that are certainly
    // alive. So, if your purpose is to get a view of the portion of the
    // heap that is of interest to the cycle collector, and not simply find
    // garbage, then you should use the listener this returns.
    //
    // Note that this does not necessarily return a new listener; rather, it may
    // simply set a flag on this listener (a side effect!) and return it.
    nsICycleCollectorListener allTraces();

    // True if this listener will behave like one returned by allTraces().
    readonly attribute boolean wantAllTraces;

    // If true, do not log each method call to a temporary file.
    // Initially false.
    attribute boolean disableLog;

    // If |disableLog| is false, this object will be sent the log text.
    attribute nsICycleCollectorLogSink logSink;

    // If true, record all method calls in memory, to be retrieved later
    // using |processNext|. Initially false.
    attribute boolean wantAfterProcessing;

    // Report the next recorded event to |aHandler|, and remove it from the
    // record. Return false if there isn't anything more to process.
    //
    // Note that we only record events to report here if our
    // |wantAfterProcessing| property is true.
    boolean processNext(in nsICycleCollectorHandler aHandler);

    // Return the current object as an nsCycleCollectorLogger*, which is the
    // only class that should be implementing this interface. We need the
    // concrete implementation type to help the GC rooting analysis.
    [noscript] nsCycleCollectorLoggerPtr asLogger();
};