LCOV - code coverage report
Current view: top level - js/src/vm - TraceLogging.h (source / functions) Hit Total Coverage
Test: output.info Lines: 85 181 47.0 %
Date: 2017-07-14 16:53:18 Functions: 20 47 42.6 %
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 TraceLogging_h
       8             : #define TraceLogging_h
       9             : 
      10             : #include "mozilla/GuardObjects.h"
      11             : #include "mozilla/LinkedList.h"
      12             : #include "mozilla/MemoryReporting.h"
      13             : 
      14             : #include "jsalloc.h"
      15             : 
      16             : #include "js/HashTable.h"
      17             : #include "js/TypeDecls.h"
      18             : #include "js/Vector.h"
      19             : #include "vm/MutexIDs.h"
      20             : #include "vm/TraceLoggingGraph.h"
      21             : #include "vm/TraceLoggingTypes.h"
      22             : 
      23             : struct JSRuntime;
      24             : 
      25             : namespace JS {
      26             :     class ReadOnlyCompileOptions;
      27             : } // namespace JS
      28             : 
      29             : namespace js {
      30             : 
      31             : namespace jit {
      32             :     class CompileRuntime;
      33             : } // namespace jit
      34             : 
      35             : /*
      36             :  * Tracelogging overview.
      37             :  *
      38             :  * Tracelogging makes it possible to trace the occurrence of a single event
      39             :  * and/or the start and stop of an event. This is implemented with as low
      40             :  * overhead as possible to not interfere with running.
      41             :  *
      42             :  * Logging something is done in 3 stages.
      43             :  * 1) Get the tracelogger of the current thread. cx may be omitted, in which
      44             :  *    case it will be fetched from TLS.
      45             :  *     - TraceLoggerForCurrentThread(cx);
      46             :  *
      47             :  * 2) Optionally create a TraceLoggerEvent for the text that needs to get logged. This
      48             :  *    step takes some time, so try to do this beforehand, outside the hot
      49             :  *    path and don't do unnecessary repetitions, since it will cripple
      50             :  *    performance.
      51             :  *     - TraceLoggerEvent event(logger, "foo");
      52             :  *
      53             :  *    There are also some predefined events. They are located in
      54             :  *    TraceLoggerTextId. They don't require to create an TraceLoggerEvent and
      55             :  *    can also be used as an argument to these functions.
      56             :  *
      57             :  * 3) Log the occurrence of a single event:
      58             :  *    - TraceLogTimestamp(logger, TraceLoggerTextId);
      59             :  *      Note: it is temporarily not supported to provide an TraceLoggerEvent as
      60             :  *            argument to log the occurrence of a single event.
      61             :  *
      62             :  *    or log the start and stop of an event:
      63             :  *    - TraceLogStartEvent(logger, TraceLoggerTextId);
      64             :  *    - TraceLogStartEvent(logger, TraceLoggerEvent);
      65             :  *    - TraceLogStopEvent(logger, TraceLoggerTextId);
      66             :  *    - TraceLogStopEvent(logger, TraceLoggerEvent);
      67             :  *
      68             :  *    or the start/stop of an event with a RAII class:
      69             :  *    - AutoTraceLog atl(logger, TraceLoggerTextId);
      70             :  *    - AutoTraceLog atl(logger, TraceLoggerEvent);
      71             :  */
      72             : 
      73             : class AutoTraceLog;
      74             : class TraceLoggerEventPayload;
      75             : class TraceLoggerThread;
      76             : 
      77             : /**
      78             :  * An event that can be used to report start/stop events to TraceLogger. It
      79             :  * prepares the given info by requesting a TraceLoggerEventPayload containing
      80             :  * the string to report and an unique id. It also increases the useCount of
      81             :  * this payload, so it cannot get removed.
      82             :  */
      83             : class TraceLoggerEvent {
      84             : #ifdef JS_TRACE_LOGGING
      85             :   private:
      86             :     class EventPayloadOrTextId {
      87             : 
      88             :         /**
      89             :          * Payload can be a pointer to a TraceLoggerEventPayload* or a
      90             :          * TraceLoggerTextId. The last bit decides how to read the payload.
      91             :          *
      92             :          * payload_ = [                   | 0 ]
      93             :          *            ------------------------  = TraceLoggerEventPayload* (incl. last bit)
      94             :          * payload_ = [                   | 1 ]
      95             :          *             -------------------      = TraceLoggerTextId (excl. last bit)
      96             :          */
      97             :         uintptr_t payload_;
      98             : 
      99             :       public:
     100       27044 :         EventPayloadOrTextId()
     101       27044 :           : payload_(0)
     102       27044 :         { }
     103             : 
     104      180089 :         bool isEventPayload() const {
     105      180089 :             return (payload_ & 1) == 0;
     106             :         }
     107         546 :         TraceLoggerEventPayload* eventPayload() const {
     108         546 :             MOZ_ASSERT(isEventPayload());
     109         546 :             return (TraceLoggerEventPayload*) payload_;
     110             :         }
     111           0 :         void setEventPayload(TraceLoggerEventPayload* payload) {
     112           0 :             payload_ = (uintptr_t)payload;
     113           0 :             MOZ_ASSERT((payload_ & 1) == 0);
     114           0 :         }
     115      152586 :         bool isTextId() const {
     116      152586 :             return (payload_ & 1) == 1;
     117             :         }
     118       50862 :         uint32_t textId() const {
     119       50862 :             MOZ_ASSERT(isTextId());
     120       50862 :             return payload_ >> 1;
     121             :         }
     122       26417 :         void setTextId(TraceLoggerTextId textId) {
     123             :             static_assert(TraceLogger_Last < (UINT32_MAX >> 1), "Too many predefined text ids.");
     124       26417 :             payload_ = (((uint32_t)textId) << 1) | 1;
     125       26417 :         }
     126             :     };
     127             : 
     128             :     EventPayloadOrTextId payload_;
     129             : 
     130             :   public:
     131         627 :     TraceLoggerEvent()
     132         627 :       : payload_()
     133         627 :     {}
     134             :     explicit TraceLoggerEvent(TraceLoggerTextId textId);
     135             :     TraceLoggerEvent(TraceLoggerTextId type, JSScript* script);
     136             :     TraceLoggerEvent(TraceLoggerTextId type, const char* filename, size_t line, size_t column);
     137             :     explicit TraceLoggerEvent(const char* text);
     138             :     TraceLoggerEvent(const TraceLoggerEvent& event);
     139             :     TraceLoggerEvent& operator=(const TraceLoggerEvent& other);
     140             :     ~TraceLoggerEvent();
     141             :     uint32_t textId() const;
     142      101724 :     bool hasTextId() const {
     143      101724 :         return hasExtPayload() || payload_.isTextId();
     144             :     }
     145             : 
     146             :   private:
     147           0 :     TraceLoggerEventPayload* extPayload() const {
     148           0 :         MOZ_ASSERT(hasExtPayload());
     149           0 :         return payload_.eventPayload();
     150             :     }
     151      179543 :     bool hasExtPayload() const {
     152      179543 :         return payload_.isEventPayload() && !!payload_.eventPayload();
     153             :     }
     154             : #else
     155             :   public:
     156             :     TraceLoggerEvent() {}
     157             :     explicit TraceLoggerEvent(TraceLoggerTextId textId) {}
     158             :     TraceLoggerEvent(TraceLoggerTextId type, JSScript* script) {}
     159             :     TraceLoggerEvent(TraceLoggerTextId type, const char* filename, size_t line, size_t column) {}
     160             :     explicit TraceLoggerEvent(const char* text) {}
     161             :     TraceLoggerEvent(const TraceLoggerEvent& event) {}
     162             :     TraceLoggerEvent& operator=(const TraceLoggerEvent& other) { return *this; };
     163             :     ~TraceLoggerEvent() {}
     164             :     uint32_t textId() const { return 0; }
     165             :     bool hasTextId() const { return false; }
     166             : #endif
     167             : 
     168             : };
     169             : 
     170             : #ifdef DEBUG
     171             : bool CurrentThreadOwnsTraceLoggerThreadStateLock();
     172             : #endif
     173             : 
     174             : /**
     175             :  * An internal class holding the string information to report, together with an
     176             :  * unique id, a useCount and a pointerCount. Whenever this useCount reaches 0, this event
     177             :  * cannot get started/stopped anymore. Consumers may still request the
     178             :  * string information through maybeEventText below, but this may not succeed:
     179             :  * when the use count becomes zero, a payload may be deleted by any thread
     180             :  * holding the TraceLoggerThreadState lock, after that the pointers have been
     181             :  * cleared out of the pointerMap. That means pointerCount needs to be zero.
     182             :  */
     183             : class TraceLoggerEventPayload {
     184             :     uint32_t textId_;
     185             :     UniqueChars string_;
     186             :     mozilla::Atomic<uint32_t> uses_;
     187             :     mozilla::Atomic<uint32_t> pointerCount_;
     188             : 
     189             :   public:
     190           0 :     TraceLoggerEventPayload(uint32_t textId, char* string)
     191           0 :       : textId_(textId),
     192             :         string_(string),
     193           0 :         uses_(0)
     194           0 :     { }
     195             : 
     196           0 :     ~TraceLoggerEventPayload() {
     197           0 :         MOZ_ASSERT(uses_ == 0);
     198           0 :     }
     199             : 
     200           0 :     uint32_t textId() {
     201           0 :         return textId_;
     202             :     }
     203           0 :     const char* string() {
     204           0 :         return string_.get();
     205             :     }
     206           0 :     uint32_t uses() {
     207           0 :         return uses_;
     208             :     }
     209           0 :     uint32_t pointerCount() {
     210           0 :         return pointerCount_;
     211             :     }
     212             : 
     213             :     // Payloads may have their use count change at any time, *except* the count
     214             :     // can only go from zero to non-zero while the thread state lock is held.
     215             :     // This should only happen under getOrCreateEventPayload below, and avoids
     216             :     // races with purgeUnusedPayloads.
     217           0 :     void use() {
     218           0 :         MOZ_ASSERT_IF(!uses_, CurrentThreadOwnsTraceLoggerThreadStateLock());
     219           0 :         uses_++;
     220           0 :     }
     221           0 :     void release() {
     222           0 :         uses_--;
     223           0 :     }
     224           0 :     void incPointerCount() {
     225           0 :         MOZ_ASSERT(CurrentThreadOwnsTraceLoggerThreadStateLock());
     226           0 :         pointerCount_++;
     227           0 :     }
     228           0 :     void decPointerCount() {
     229           0 :         MOZ_ASSERT(CurrentThreadOwnsTraceLoggerThreadStateLock());
     230           0 :         pointerCount_--;
     231           0 :     }
     232           0 :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
     233           0 :         return mallocSizeOf(string_.get());
     234             :     }
     235           0 :     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
     236           0 :         return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
     237             :     }
     238             : };
     239             : 
     240             : // Per thread trace logger state.
     241             : class TraceLoggerThread : public mozilla::LinkedListElement<TraceLoggerThread>
     242             : {
     243             : #ifdef JS_TRACE_LOGGING
     244             :   private:
     245             :     uint32_t enabled_;
     246             :     bool failed;
     247             : 
     248             :     UniquePtr<TraceLoggerGraph> graph;
     249             : 
     250             :     ContinuousSpace<EventEntry> events;
     251             : 
     252             :     // Every time the events get flushed, this count is increased by one.
     253             :     // Together with events.lastEntryId(), this gives an unique id for every
     254             :     // event.
     255             :     uint32_t iteration_;
     256             : 
     257             : #ifdef DEBUG
     258             :     typedef Vector<uint32_t, 1, js::SystemAllocPolicy > GraphStack;
     259             :     GraphStack graphStack;
     260             : #endif
     261             : 
     262             :   public:
     263             :     AutoTraceLog* top;
     264             : 
     265          22 :     TraceLoggerThread()
     266          22 :       : enabled_(0),
     267             :         failed(false),
     268             :         graph(),
     269             :         iteration_(0),
     270          22 :         top(nullptr)
     271          22 :     { }
     272             : 
     273             :     bool init();
     274             :     ~TraceLoggerThread();
     275             : 
     276             :     bool init(uint32_t loggerId);
     277             :     void initGraph();
     278             : 
     279             :     bool enable();
     280             :     bool enable(JSContext* cx);
     281             :     bool disable(bool force = false, const char* = "");
     282           0 :     bool enabled() { return enabled_ > 0; }
     283             : 
     284             :     void silentFail(const char* error);
     285             : 
     286             :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     287             :     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     288             : 
     289             :   private:
     290             :     bool fail(JSContext* cx, const char* error);
     291             : 
     292             :   public:
     293             :     // Given the previous iteration and size, return an array of events
     294             :     // (there could be lost events). At the same time update the iteration and
     295             :     // size and gives back how many events there are.
     296           0 :     EventEntry* getEventsStartingAt(uint32_t* lastIteration, uint32_t* lastSize, size_t* num) {
     297             :         EventEntry* start;
     298           0 :         if (iteration_ == *lastIteration) {
     299           0 :             MOZ_ASSERT(*lastSize <= events.size());
     300           0 :             *num = events.size() - *lastSize;
     301           0 :             start = events.data() + *lastSize;
     302             :         } else {
     303           0 :             *num = events.size();
     304           0 :             start = events.data();
     305             :         }
     306             : 
     307           0 :         getIterationAndSize(lastIteration, lastSize);
     308           0 :         return start;
     309             :     }
     310             : 
     311           0 :     void getIterationAndSize(uint32_t* iteration, uint32_t* size) const {
     312           0 :         *iteration = iteration_;
     313           0 :         *size = events.size();
     314           0 :     }
     315             : 
     316             :     // Extract the details filename, lineNumber and columnNumber out of a event
     317             :     // containing script information.
     318             :     void extractScriptDetails(uint32_t textId, const char** filename, size_t* filename_len,
     319             :                               const char** lineno, size_t* lineno_len, const char** colno,
     320             :                               size_t* colno_len);
     321             : 
     322           0 :     bool lostEvents(uint32_t lastIteration, uint32_t lastSize) {
     323             :         // If still logging in the same iteration, there are no lost events.
     324           0 :         if (lastIteration == iteration_) {
     325           0 :             MOZ_ASSERT(lastSize <= events.size());
     326           0 :             return false;
     327             :         }
     328             : 
     329             :         // If we are in the next consecutive iteration we are only sure we
     330             :         // didn't lose any events when the lastSize equals the maximum size
     331             :         // 'events' can get.
     332           0 :         if (lastIteration == iteration_ - 1 && lastSize == events.maxSize())
     333           0 :             return false;
     334             : 
     335           0 :         return true;
     336             :     }
     337             : 
     338             :   private:
     339             :     const char* maybeEventText(uint32_t id);
     340             :   public:
     341           0 :     const char* eventText(uint32_t id) {
     342           0 :         const char* text = maybeEventText(id);
     343           0 :         MOZ_ASSERT(text);
     344           0 :         return text;
     345             :     };
     346             :     bool textIdIsScriptEvent(uint32_t id);
     347             : 
     348             :   public:
     349             :     // Log an event (no start/stop, only the timestamp is recorded).
     350             :     void logTimestamp(TraceLoggerTextId id);
     351             : 
     352             :     // Record timestamps for start and stop of an event.
     353             :     void startEvent(TraceLoggerTextId id);
     354             :     void startEvent(const TraceLoggerEvent& event);
     355             :     void stopEvent(TraceLoggerTextId id);
     356             :     void stopEvent(const TraceLoggerEvent& event);
     357             : 
     358             :     // These functions are actually private and shouldn't be used in normal
     359             :     // code. They are made public so they can be used in assembly.
     360             :     void logTimestamp(uint32_t id);
     361             :     void startEvent(uint32_t id);
     362             :     void stopEvent(uint32_t id);
     363             :   private:
     364             :     void stopEvent();
     365             :     void log(uint32_t id);
     366             : 
     367             :   public:
     368           0 :     static unsigned offsetOfEnabled() {
     369           0 :         return offsetof(TraceLoggerThread, enabled_);
     370             :     }
     371             : #endif
     372             : };
     373             : 
     374             : // Process wide trace logger state.
     375             : class TraceLoggerThreadState
     376             : {
     377             : #ifdef JS_TRACE_LOGGING
     378             : #ifdef DEBUG
     379             :     bool initialized;
     380             : #endif
     381             : 
     382             :     bool enabledTextIds[TraceLogger_Last];
     383             :     bool cooperatingThreadEnabled;
     384             :     bool helperThreadEnabled;
     385             :     bool graphSpewingEnabled;
     386             :     bool spewErrors;
     387             :     mozilla::LinkedList<TraceLoggerThread> threadLoggers;
     388             : 
     389             :     typedef HashMap<const void*,
     390             :                     TraceLoggerEventPayload*,
     391             :                     PointerHasher<const void*, 3>,
     392             :                     SystemAllocPolicy> PointerHashMap;
     393             :     typedef HashMap<uint32_t,
     394             :                     TraceLoggerEventPayload*,
     395             :                     DefaultHasher<uint32_t>,
     396             :                     SystemAllocPolicy> TextIdHashMap;
     397             :     PointerHashMap pointerMap;
     398             :     TextIdHashMap textIdPayloads;
     399             :     uint32_t nextTextId;
     400             : 
     401             :   public:
     402             :     uint64_t startupTime;
     403             :     Mutex lock;
     404             : 
     405           3 :     TraceLoggerThreadState()
     406           3 :       :
     407             : #ifdef DEBUG
     408             :         initialized(false),
     409             : #endif
     410             :         cooperatingThreadEnabled(false),
     411             :         helperThreadEnabled(false),
     412             :         graphSpewingEnabled(false),
     413             :         spewErrors(false),
     414             :         nextTextId(TraceLogger_Last),
     415             :         startupTime(0),
     416           3 :         lock(js::mutexid::TraceLoggerThreadState)
     417           3 :     { }
     418             : 
     419             :     bool init();
     420             :     ~TraceLoggerThreadState();
     421             : 
     422             :     TraceLoggerThread* forCurrentThread(JSContext* cx);
     423             :     void destroyLogger(TraceLoggerThread* logger);
     424             : 
     425      168139 :     bool isTextIdEnabled(uint32_t textId) {
     426      168139 :         if (textId < TraceLogger_Last)
     427      168139 :             return enabledTextIds[textId];
     428           0 :         return true;
     429             :     }
     430             :     void enableTextId(JSContext* cx, uint32_t textId);
     431             :     void disableTextId(JSContext* cx, uint32_t textId);
     432           0 :     void maybeSpewError(const char* text) {
     433           0 :         if (spewErrors)
     434           0 :             fprintf(stderr, "%s\n", text);
     435           0 :     }
     436             : 
     437             :     const char* maybeEventText(uint32_t id);
     438             : 
     439             :     void purgeUnusedPayloads();
     440             : 
     441             :     // These functions map a unique input to a logger ID.
     442             :     // This can be used to give start and stop events. Calls to these functions should be
     443             :     // limited if possible, because of the overhead.
     444             :     // Note: it is not allowed to use them in logTimestamp.
     445             :     TraceLoggerEventPayload* getOrCreateEventPayload(const char* text);
     446             :     TraceLoggerEventPayload* getOrCreateEventPayload(JSScript* script);
     447             :     TraceLoggerEventPayload* getOrCreateEventPayload(const char* filename, size_t lineno,
     448             :                                                      size_t colno, const void* p);
     449             : 
     450             :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
     451           0 :     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) {
     452           0 :         return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
     453             :     }
     454             : #endif
     455             : };
     456             : 
     457             : #ifdef JS_TRACE_LOGGING
     458             : void DestroyTraceLoggerThreadState();
     459             : void DestroyTraceLogger(TraceLoggerThread* logger);
     460             : 
     461             : TraceLoggerThread* TraceLoggerForCurrentThread(JSContext* cx = nullptr);
     462             : #else
     463             : inline TraceLoggerThread* TraceLoggerForCurrentThread(JSContext* cx = nullptr) {
     464             :     return nullptr;
     465             : };
     466             : #endif
     467             : 
     468             : inline bool TraceLoggerEnable(TraceLoggerThread* logger) {
     469             : #ifdef JS_TRACE_LOGGING
     470             :     if (logger)
     471             :         return logger->enable();
     472             : #endif
     473             :     return false;
     474             : }
     475           0 : inline bool TraceLoggerEnable(TraceLoggerThread* logger, JSContext* cx) {
     476             : #ifdef JS_TRACE_LOGGING
     477           0 :     if (logger)
     478           0 :         return logger->enable(cx);
     479             : #endif
     480           0 :     return false;
     481             : }
     482           0 : inline bool TraceLoggerDisable(TraceLoggerThread* logger) {
     483             : #ifdef JS_TRACE_LOGGING
     484           0 :     if (logger)
     485           0 :         return logger->disable();
     486             : #endif
     487           0 :     return false;
     488             : }
     489             : inline void TraceLoggerSilentFail(TraceLoggerThread* logger, const char* error) {
     490             : #ifdef JS_TRACE_LOGGING
     491             :     if (logger)
     492             :         logger->silentFail(error);
     493             : #endif
     494             : }
     495             : 
     496             : #ifdef JS_TRACE_LOGGING
     497             : bool TraceLogTextIdEnabled(uint32_t textId);
     498             : void TraceLogEnableTextId(JSContext* cx, uint32_t textId);
     499             : void TraceLogDisableTextId(JSContext* cx, uint32_t textId);
     500             : #else
     501             : inline bool TraceLogTextIdEnabled(uint32_t textId) {
     502             :     return false;
     503             : }
     504             : inline void TraceLogEnableTextId(JSContext* cx, uint32_t textId) {}
     505             : inline void TraceLogDisableTextId(JSContext* cx, uint32_t textId) {}
     506             : #endif
     507           0 : inline void TraceLogTimestamp(TraceLoggerThread* logger, TraceLoggerTextId textId) {
     508             : #ifdef JS_TRACE_LOGGING
     509           0 :     if (logger)
     510           0 :         logger->logTimestamp(textId);
     511             : #endif
     512           0 : }
     513       12442 : inline void TraceLogStartEvent(TraceLoggerThread* logger, TraceLoggerTextId textId) {
     514             : #ifdef JS_TRACE_LOGGING
     515       12442 :     if (logger)
     516       12442 :         logger->startEvent(textId);
     517             : #endif
     518       12442 : }
     519       12299 : inline void TraceLogStartEvent(TraceLoggerThread* logger, const TraceLoggerEvent& event) {
     520             : #ifdef JS_TRACE_LOGGING
     521       12299 :     if (logger)
     522       12299 :         logger->startEvent(event);
     523             : #endif
     524       12299 : }
     525       14266 : inline void TraceLogStopEvent(TraceLoggerThread* logger, TraceLoggerTextId textId) {
     526             : #ifdef JS_TRACE_LOGGING
     527       14266 :     if (logger)
     528       14266 :         logger->stopEvent(textId);
     529             : #endif
     530       14266 : }
     531       10325 : inline void TraceLogStopEvent(TraceLoggerThread* logger, const TraceLoggerEvent& event) {
     532             : #ifdef JS_TRACE_LOGGING
     533       10325 :     if (logger)
     534       10325 :         logger->stopEvent(event);
     535             : #endif
     536       10325 : }
     537             : 
     538             : // Helper functions for assembly. May not be used otherwise.
     539             : inline void TraceLogTimestampPrivate(TraceLoggerThread* logger, uint32_t id) {
     540             : #ifdef JS_TRACE_LOGGING
     541             :     if (logger)
     542             :         logger->logTimestamp(id);
     543             : #endif
     544             : }
     545           0 : inline void TraceLogStartEventPrivate(TraceLoggerThread* logger, uint32_t id) {
     546             : #ifdef JS_TRACE_LOGGING
     547           0 :     if (logger)
     548           0 :         logger->startEvent(id);
     549             : #endif
     550           0 : }
     551           0 : inline void TraceLogStopEventPrivate(TraceLoggerThread* logger, uint32_t id) {
     552             : #ifdef JS_TRACE_LOGGING
     553           0 :     if (logger)
     554           0 :         logger->stopEvent(id);
     555             : #endif
     556           0 : }
     557             : 
     558             : size_t SizeOfTraceLogState(mozilla::MallocSizeOf mallocSizeOf);
     559             : 
     560             : // Automatic logging at the start and end of function call.
     561             : class MOZ_RAII AutoTraceLog
     562             : {
     563             : #ifdef JS_TRACE_LOGGING
     564             :     TraceLoggerThread* logger;
     565             :     union {
     566             :         const TraceLoggerEvent* event;
     567             :         TraceLoggerTextId id;
     568             :     } payload;
     569             :     bool isEvent;
     570             :     bool executed;
     571             :     AutoTraceLog* prev;
     572             : 
     573             :   public:
     574       14119 :     AutoTraceLog(TraceLoggerThread* logger,
     575             :                  const TraceLoggerEvent& event MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     576       14119 :       : logger(logger),
     577             :         isEvent(true),
     578       14119 :         executed(false)
     579             :     {
     580       14119 :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     581       14119 :         payload.event = &event;
     582       14119 :         if (logger) {
     583       14119 :             logger->startEvent(event);
     584             : 
     585       14119 :             prev = logger->top;
     586       14119 :             logger->top = this;
     587             :         }
     588       14119 :     }
     589             : 
     590       28684 :     AutoTraceLog(TraceLoggerThread* logger, TraceLoggerTextId id MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     591       28684 :       : logger(logger),
     592             :         isEvent(false),
     593       28684 :         executed(false)
     594             :     {
     595       28684 :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     596       28684 :         payload.id = id;
     597       28684 :         if (logger) {
     598       28684 :             logger->startEvent(id);
     599             : 
     600       28684 :             prev = logger->top;
     601       28684 :             logger->top = this;
     602             :         }
     603       28684 :     }
     604             : 
     605       42806 :     ~AutoTraceLog()
     606       42806 :     {
     607       42806 :         if (logger) {
     608       42806 :             while (this != logger->top)
     609           0 :                 logger->top->stop();
     610       42806 :             stop();
     611             :         }
     612       42806 :     }
     613             :   private:
     614       42806 :     void stop() {
     615       42806 :         if (!executed) {
     616       42806 :             executed = true;
     617       42806 :             if (isEvent)
     618       14121 :                 logger->stopEvent(*payload.event);
     619             :             else
     620       28685 :                 logger->stopEvent(payload.id);
     621             :         }
     622             : 
     623       42806 :         if (logger->top == this)
     624       42806 :             logger->top = prev;
     625       42806 :     }
     626             : #else
     627             :   public:
     628             :     AutoTraceLog(TraceLoggerThread* logger, uint32_t textId MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     629             :     {
     630             :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     631             :     }
     632             :     AutoTraceLog(TraceLoggerThread* logger,
     633             :                  const TraceLoggerEvent& event MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     634             :     {
     635             :         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     636             :     }
     637             : #endif
     638             : 
     639             :   private:
     640             :     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     641             : };
     642             : 
     643             : } // namespace js
     644             : 
     645             : #endif /* TraceLogging_h */

Generated by: LCOV version 1.13