LCOV - code coverage report
Current view: top level - tools/profiler/public - GeckoProfiler.h (source / functions) Hit Total Coverage
Test: output.info Lines: 46 55 83.6 %
Date: 2017-07-14 16:53:18 Functions: 9 40 22.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       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             : // The Gecko Profiler is an always-on profiler that takes fast and low overhead
       8             : // samples of the program execution using only userspace functionality for
       9             : // portability. The goal of this module is to provide performance data in a
      10             : // generic cross-platform way without requiring custom tools or kernel support.
      11             : //
      12             : // Samples are collected to form a timeline with optional timeline event
      13             : // (markers) used for filtering. The samples include both native stacks and
      14             : // platform-independent "pseudostacks".
      15             : 
      16             : #ifndef GeckoProfiler_h
      17             : #define GeckoProfiler_h
      18             : 
      19             : #include <functional>
      20             : #include <signal.h>
      21             : #include <stdarg.h>
      22             : #include <stdint.h>
      23             : #include <stdlib.h>
      24             : 
      25             : #include "mozilla/Assertions.h"
      26             : #include "mozilla/Attributes.h"
      27             : #include "mozilla/GuardObjects.h"
      28             : #include "mozilla/Sprintf.h"
      29             : #include "mozilla/ThreadLocal.h"
      30             : #include "mozilla/UniquePtr.h"
      31             : #include "js/TypeDecls.h"
      32             : #include "js/ProfilingStack.h"
      33             : #include "nscore.h"
      34             : 
      35             : // Make sure that we can use std::min here without the Windows headers messing
      36             : // with us.
      37             : #ifdef min
      38             : # undef min
      39             : #endif
      40             : 
      41             : class ProfilerBacktrace;
      42             : class ProfilerMarkerPayload;
      43             : class SpliceableJSONWriter;
      44             : 
      45             : namespace mozilla {
      46             : class MallocAllocPolicy;
      47             : template <class T, size_t MinInlineCapacity, class AllocPolicy> class Vector;
      48             : } // namespace mozilla
      49             : 
      50             : // When the profiler is disabled functions declared with these macros are
      51             : // static inline functions (with a trivial return value if they are non-void)
      52             : // that will be optimized away during compilation.
      53             : #ifdef MOZ_GECKO_PROFILER
      54             : # define PROFILER_FUNC(decl, rv)  decl;
      55             : # define PROFILER_FUNC_VOID(decl) void decl;
      56             : #else
      57             : # define PROFILER_FUNC(decl, rv)  static inline decl { return rv; }
      58             : # define PROFILER_FUNC_VOID(decl) static inline void decl {}
      59             : #endif
      60             : 
      61             : //---------------------------------------------------------------------------
      62             : // Profiler features
      63             : //---------------------------------------------------------------------------
      64             : 
      65             : // Higher-order macro containing all the feature info in one place. Define
      66             : // |macro| appropriately to extract the relevant parts. Note that the number
      67             : // values are used internally only and so can be changed without consequence.
      68             : // Any changes to this list should also be applied to the feature list in
      69             : // browser/components/extensions/schemas/geckoProfiler.json.
      70             : #define PROFILER_FOR_EACH_FEATURE(macro) \
      71             :   /* Dump the display list with the textures. */ \
      72             :   macro(0, "displaylistdump", DisplayListDump) \
      73             :   \
      74             :   /* GPU Profiling (may not be supported by the GL). */ \
      75             :   macro(1, "gpu", GPU) \
      76             :   \
      77             :   /* Profile Java code (Android only). */ \
      78             :   macro(2, "java", Java) \
      79             :   \
      80             :   /* Get the JS engine to emit pseudostack entries in prologues/epilogues */ \
      81             :   macro(3, "js", JS) \
      82             :   \
      83             :   /* Dump the layer tree with the textures. */ \
      84             :   macro(4, "layersdump", LayersDump) \
      85             :   \
      86             :   /* Include the C++ leaf node if not stackwalking. */ \
      87             :   /* The DevTools profiler doesn't want the native addresses. */ \
      88             :   macro(5, "leaf", Leaf) \
      89             :   \
      90             :   /* Add main thread I/O to the profile. */ \
      91             :   macro(6, "mainthreadio", MainThreadIO) \
      92             :   \
      93             :   /* Add memory measurements (e.g. RSS). */ \
      94             :   macro(7, "memory", Memory) \
      95             :   \
      96             :   /* Do not include user-identifiable information. */ \
      97             :   macro(8, "privacy", Privacy) \
      98             :   \
      99             :   /* Restyle profiling. */ \
     100             :   macro(9, "restyle", Restyle) \
     101             :   \
     102             :   /* Walk the C++ stack. Not available on all platforms. */ \
     103             :   macro(10, "stackwalk", StackWalk) \
     104             :   \
     105             :   /* Start profiling with feature TaskTracer. */ \
     106             :   macro(11, "tasktracer", TaskTracer) \
     107             :   \
     108             :   /* Profile the registered secondary threads. */ \
     109             :   macro(12, "threads", Threads)
     110             : 
     111             : struct ProfilerFeature
     112             : {
     113             :   #define DECLARE(n_, str_, Name_) \
     114             :     static const uint32_t Name_ = (1u << n_); \
     115             :     static bool Has##Name_(uint32_t aFeatures) { return aFeatures & Name_; } \
     116             :     static void Set##Name_(uint32_t& aFeatures) { aFeatures |= Name_; } \
     117             :     static void Clear##Name_(uint32_t& aFeatures) { aFeatures &= ~Name_; }
     118             : 
     119             :   // Define a bitfield constant, a getter, and two setters for each feature.
     120           0 :   PROFILER_FOR_EACH_FEATURE(DECLARE)
     121             : 
     122             :   #undef DECLARE
     123             : };
     124             : 
     125             : //---------------------------------------------------------------------------
     126             : // Start and stop the profiler
     127             : //---------------------------------------------------------------------------
     128             : 
     129             : #if !defined(ARCH_ARMV6)
     130             : # define PROFILER_DEFAULT_ENTRIES 1000000
     131             : #else
     132             : # define PROFILER_DEFAULT_ENTRIES 100000
     133             : #endif
     134             : 
     135             : #define PROFILER_DEFAULT_INTERVAL 1
     136             : 
     137             : // Initialize the profiler. If MOZ_PROFILER_STARTUP is set the profiler will
     138             : // also be started. This call must happen before any other profiler calls
     139             : // (except profiler_start(), which will call profiler_init() if it hasn't
     140             : // already run).
     141             : PROFILER_FUNC_VOID(profiler_init(void* stackTop))
     142             : 
     143             : // Clean up the profiler module, stopping it if required. This function may
     144             : // also save a shutdown profile if requested. No profiler calls should happen
     145             : // after this point and all pseudo labels should have been popped.
     146             : PROFILER_FUNC_VOID(profiler_shutdown())
     147             : 
     148             : // Start the profiler -- initializing it first if necessary -- with the
     149             : // selected options. Stops and restarts the profiler if it is already active.
     150             : // After starting the profiler is "active". The samples will be recorded in a
     151             : // circular buffer.
     152             : //   "aEntries" is the number of entries in the profiler's circular buffer.
     153             : //   "aInterval" the sampling interval, measured in millseconds.
     154             : //   "aFeatures" is the feature set. Features unsupported by this
     155             : //               platform/configuration are ignored.
     156             : PROFILER_FUNC_VOID(profiler_start(int aEntries, double aInterval,
     157             :                                   uint32_t aFeatures,
     158             :                                   const char** aFilters, uint32_t aFilterCount))
     159             : 
     160             : // Stop the profiler and discard the profile without saving it. A no-op if the
     161             : // profiler is inactive. After stopping the profiler is "inactive".
     162             : PROFILER_FUNC_VOID(profiler_stop())
     163             : 
     164             : //---------------------------------------------------------------------------
     165             : // Control the profiler
     166             : //---------------------------------------------------------------------------
     167             : 
     168             : // Register/unregister threads with the profiler. Both functions operate the
     169             : // same whether the profiler is active or inactive.
     170             : PROFILER_FUNC_VOID(profiler_register_thread(const char* name,
     171             :                                             void* guessStackTop))
     172             : PROFILER_FUNC_VOID(profiler_unregister_thread())
     173             : 
     174             : // Pause and resume the profiler. No-ops if the profiler is inactive. While
     175             : // paused the profile will not take any samples and will not record any data
     176             : // into its buffers. The profiler remains fully initialized in this state.
     177             : // Timeline markers will still be stored. This feature will keep JavaScript
     178             : // profiling enabled, thus allowing toggling the profiler without invalidating
     179             : // the JIT.
     180             : PROFILER_FUNC_VOID(profiler_pause())
     181             : PROFILER_FUNC_VOID(profiler_resume())
     182             : 
     183             : // These functions tell the profiler that a thread went to sleep so that we can
     184             : // avoid sampling it while it's sleeping. Calling profiler_thread_sleep()
     185             : // twice without an intervening profiler_thread_wake() is an error. All three
     186             : // functions operate the same whether the profiler is active or inactive.
     187             : PROFILER_FUNC_VOID(profiler_thread_sleep())
     188             : PROFILER_FUNC_VOID(profiler_thread_wake())
     189             : 
     190             : // Called by the JSRuntime's operation callback. This is used to start profiling
     191             : // on auxiliary threads. Operates the same whether the profiler is active or
     192             : // not.
     193             : PROFILER_FUNC_VOID(profiler_js_interrupt_callback())
     194             : 
     195             : // Set and clear the current thread's JSContext.
     196             : PROFILER_FUNC_VOID(profiler_set_js_context(JSContext* aCx))
     197             : PROFILER_FUNC_VOID(profiler_clear_js_context())
     198             : 
     199             : //---------------------------------------------------------------------------
     200             : // Get information from the profiler
     201             : //---------------------------------------------------------------------------
     202             : 
     203             : // Is the profiler active? Note: the return value of this function can become
     204             : // immediately out-of-date. E.g. the profile might be active but then
     205             : // profiler_stop() is called immediately afterward. One common and reasonable
     206             : // pattern of usage is the following:
     207             : //
     208             : //   if (profiler_is_active()) {
     209             : //     ExpensiveData expensiveData = CreateExpensiveData();
     210             : //     PROFILER_OPERATION(expensiveData);
     211             : //   }
     212             : //
     213             : // where PROFILER_OPERATION is a no-op if the profiler is inactive. In this
     214             : // case the profiler_is_active() check is just an optimization -- it prevents
     215             : // us calling CreateExpensiveData() unnecessarily in most cases, but the
     216             : // expensive data will end up being created but not used if another thread
     217             : // stops the profiler between the CreateExpensiveData() and PROFILER_OPERATION
     218             : // calls.
     219             : PROFILER_FUNC(bool profiler_is_active(), false)
     220             : 
     221             : // Is the profiler active and paused? Returns false if the profiler is inactive.
     222             : PROFILER_FUNC(bool profiler_is_paused(), false)
     223             : 
     224             : // Is the current thread sleeping?
     225             : PROFILER_FUNC(bool profiler_thread_is_sleeping(), false)
     226             : 
     227             : // Get all the features supported by the profiler that are accepted by
     228             : // profiler_start(). The result is the same whether the profiler is active or
     229             : // not.
     230             : PROFILER_FUNC(uint32_t profiler_get_available_features(), 0)
     231             : 
     232             : // Check if a profiler feature (specified via the ProfilerFeature type) is
     233             : // active. Returns false if the profiler is inactive. Note: the return value
     234             : // can become immediately out-of-date, much like the return value of
     235             : // profiler_is_active().
     236             : PROFILER_FUNC(bool profiler_feature_active(uint32_t aFeature), false)
     237             : 
     238             : // Get the params used to start the profiler. Returns 0 and an empty vector
     239             : // (via outparams) if the profile is inactive. It's possible that the features
     240             : // returned may be slightly different to those requested due to required
     241             : // adjustments.
     242             : PROFILER_FUNC_VOID(
     243             :   profiler_get_start_params(int* aEntrySize, double* aInterval,
     244             :                             uint32_t* aFeatures,
     245             :                             mozilla::Vector<const char*, 0,
     246             :                                             mozilla::MallocAllocPolicy>*
     247             :                               aFilters))
     248             : 
     249             : // The number of milliseconds since the process started. Operates the same
     250             : // whether the profiler is active or inactive.
     251             : PROFILER_FUNC(double profiler_time(), 0)
     252             : 
     253             : // Get the current thread's ID.
     254             : PROFILER_FUNC(int profiler_current_thread_id(), 0)
     255             : 
     256             : // This is the function type of the callback passed to profiler_suspend_and_sample_thread.
     257             : //
     258             : // The callback is passed the following arguments:
     259             : //   void** aPCs         The program counters for the target thread's stack.
     260             : //   size_t aCount       The number of program counters in the aPCs array.
     261             : //   bool aIsMainThread  Whether the target thread was the main thread.
     262             : typedef void ProfilerStackCallback(void** aPCs, size_t aCount, bool aIsMainThread);
     263             : 
     264             : // This method suspends the thread identified by aThreadId, optionally samples
     265             : // it for its native stack, and then calls the callback.
     266             : //
     267             : // WARNING: The target thread is suspended during the callback. Do not try to
     268             : // allocate or acquire any locks, or you could deadlock. The target thread will
     269             : // have resumed by the time this function returns.
     270             : PROFILER_FUNC_VOID(
     271             :   profiler_suspend_and_sample_thread(int aThreadId,
     272             :                                      const std::function<ProfilerStackCallback>& aCallback,
     273             :                                      bool aSampleNative = true))
     274             : 
     275             : struct ProfilerBacktraceDestructor
     276             : {
     277             : #ifdef MOZ_GECKO_PROFILER
     278             :   void operator()(ProfilerBacktrace*);
     279             : #else
     280             :   void operator()(ProfilerBacktrace*) {}
     281             : #endif
     282             : };
     283             : 
     284             : using UniqueProfilerBacktrace =
     285             :   mozilla::UniquePtr<ProfilerBacktrace, ProfilerBacktraceDestructor>;
     286             : 
     287             : // Immediately capture the current thread's call stack and return it. A no-op
     288             : // if the profiler is inactive or in privacy mode.
     289             : PROFILER_FUNC(UniqueProfilerBacktrace profiler_get_backtrace(), nullptr)
     290             : 
     291             : PROFILER_FUNC_VOID(profiler_get_backtrace_noalloc(char* aOutput,
     292             :                                                   size_t aOutputSize))
     293             : 
     294             : // Get information about the current buffer status. A no-op when the profiler
     295             : // is inactive. Do not call this function; call profiler_get_buffer_info()
     296             : // instead.
     297             : PROFILER_FUNC_VOID(profiler_get_buffer_info_helper(uint32_t* aCurrentPosition,
     298             :                                                    uint32_t* aEntries,
     299             :                                                    uint32_t* aGeneration))
     300             : 
     301             : // Get information about the current buffer status. Returns (via outparams) the
     302             : // current write position in the buffer, the total size of the buffer, and the
     303             : // generation of the buffer. Returns zeroes if the profiler is inactive.
     304             : //
     305             : // This information may be useful to a user-interface displaying the current
     306             : // status of the profiler, allowing the user to get a sense for how fast the
     307             : // buffer is being written to, and how much data is visible.
     308           0 : static inline void profiler_get_buffer_info(uint32_t* aCurrentPosition,
     309             :                                             uint32_t* aEntries,
     310             :                                             uint32_t* aGeneration)
     311             : {
     312           0 :   *aCurrentPosition = 0;
     313           0 :   *aEntries = 0;
     314           0 :   *aGeneration = 0;
     315             : 
     316           0 :   profiler_get_buffer_info_helper(aCurrentPosition, aEntries, aGeneration);
     317           0 : }
     318             : 
     319             : // Get the current thread's PseudoStack.
     320             : PROFILER_FUNC(PseudoStack* profiler_get_pseudo_stack(), nullptr)
     321             : 
     322             : //---------------------------------------------------------------------------
     323             : // Put profiling data into the profiler (labels and markers)
     324             : //---------------------------------------------------------------------------
     325             : 
     326             : #define PROFILER_APPEND_LINE_NUMBER_PASTE(id, line) id ## line
     327             : #define PROFILER_APPEND_LINE_NUMBER_EXPAND(id, line) \
     328             :   PROFILER_APPEND_LINE_NUMBER_PASTE(id, line)
     329             : #define PROFILER_APPEND_LINE_NUMBER(id) \
     330             :   PROFILER_APPEND_LINE_NUMBER_EXPAND(id, __LINE__)
     331             : 
     332             : // Insert an RAII object in this scope to enter a pseudo stack frame. Any
     333             : // samples collected in this scope will contain this label in their pseudo
     334             : // stack. The label argument must be a string literal. It is usually of the
     335             : // form "ClassName::FunctionName". (Ideally we'd use the compiler to provide
     336             : // that for us, but __func__ gives us the function name without the class
     337             : // name.) If the label applies to only part of a function, you can qualify it
     338             : // like this: "ClassName::FunctionName:PartName".
     339             : //
     340             : // Use AUTO_PROFILER_LABEL_DYNAMIC if you want to add additional / dynamic
     341             : // information to the pseudo stack frame.
     342             : #define AUTO_PROFILER_LABEL(label, category) \
     343             :   mozilla::AutoProfilerLabel \
     344             :   PROFILER_APPEND_LINE_NUMBER(profiler_raii)( \
     345             :     label, nullptr, __LINE__, js::ProfileEntry::Category::category)
     346             : 
     347             : // Similar to AUTO_PROFILER_LABEL, but with an additional string. The inserted
     348             : // RAII object stores the dynamicStr pointer in a field; it does not copy the
     349             : // string. This means that the string you pass to this macro needs to live at
     350             : // least until the end of the current scope.
     351             : //
     352             : // If the profiler samples the current thread and walks the pseudo stack while
     353             : // this RAII object is on the stack, it will copy the supplied string into the
     354             : // profile buffer. So there's one string copy operation, and it happens at
     355             : // sample time.
     356             : //
     357             : // Compare this to the plain AUTO_PROFILER_LABEL macro, which only accepts
     358             : // literal strings: When the pseudo stack frames generated by
     359             : // AUTO_PROFILER_LABEL are sampled, no string copy needs to be made because the
     360             : // profile buffer can just store the raw pointers to the literal strings.
     361             : // Consequently, AUTO_PROFILER_LABEL frames take up considerably less space in
     362             : // the profile buffer than AUTO_PROFILER_LABEL_DYNAMIC frames.
     363             : #define AUTO_PROFILER_LABEL_DYNAMIC(label, category, dynamicStr) \
     364             :   mozilla::AutoProfilerLabel \
     365             :   PROFILER_APPEND_LINE_NUMBER(profiler_raii)( \
     366             :     label, dynamicStr, __LINE__, js::ProfileEntry::Category::category)
     367             : 
     368             : // Insert a marker in the profile timeline. This is useful to delimit something
     369             : // important happening such as the first paint. Unlike labels, which are only
     370             : // recorded in the profile buffer if a sample is collected while the label is
     371             : // on the pseudostack, markers will always be recorded in the profile buffer.
     372             : // aMarkerName is copied, so the caller does not need to ensure it lives for a
     373             : // certain length of time. A no-op if the profiler is inactive or in privacy
     374             : // mode.
     375             : PROFILER_FUNC_VOID(profiler_add_marker(const char* aMarkerName))
     376             : PROFILER_FUNC_VOID(
     377             :   profiler_add_marker(const char* aMarkerName,
     378             :                       mozilla::UniquePtr<ProfilerMarkerPayload> aPayload))
     379             : 
     380             : enum TracingKind {
     381             :   TRACING_EVENT,
     382             :   TRACING_INTERVAL_START,
     383             :   TRACING_INTERVAL_END,
     384             : };
     385             : 
     386             : 
     387             : // Adds a tracing marker to the PseudoStack. A no-op if the profiler is
     388             : // inactive or in privacy mode.
     389             : PROFILER_FUNC_VOID(profiler_tracing(const char* aCategory,
     390             :                                     const char* aMarkerName,
     391             :                                     TracingKind aKind = TRACING_EVENT))
     392             : PROFILER_FUNC_VOID(profiler_tracing(const char* aCategory,
     393             :                                     const char* aMarkerName,
     394             :                                     UniqueProfilerBacktrace aCause,
     395             :                                     TracingKind aKind = TRACING_EVENT))
     396             : 
     397             : //---------------------------------------------------------------------------
     398             : // Output profiles
     399             : //---------------------------------------------------------------------------
     400             : 
     401             : // Get the profile encoded as a JSON string. A no-op (returning nullptr) if the
     402             : // profiler is inactive.
     403             : PROFILER_FUNC(
     404             :   mozilla::UniquePtr<char[]> profiler_get_profile(double aSinceTime = 0),
     405             :   nullptr)
     406             : 
     407             : // Write the profile for this process (excluding subprocesses) into aWriter.
     408             : // Returns false if the profiler is inactive.
     409             : PROFILER_FUNC(
     410             :   bool profiler_stream_json_for_this_process(SpliceableJSONWriter& aWriter,
     411             :                                              double aSinceTime = 0),
     412             :   false)
     413             : 
     414             : // Get the profile and write it into a file. A no-op if the profile is
     415             : // inactive.
     416             : //
     417             : // This function is 'extern "C"' so that it is easily callable from a debugger
     418             : // in a build without debugging information (a workaround for
     419             : // http://llvm.org/bugs/show_bug.cgi?id=22211).
     420             : extern "C" {
     421             : PROFILER_FUNC_VOID(profiler_save_profile_to_file(const char* aFilename))
     422             : }
     423             : 
     424             : //---------------------------------------------------------------------------
     425             : // RAII classes
     426             : //---------------------------------------------------------------------------
     427             : 
     428             : namespace mozilla {
     429             : 
     430             : class MOZ_RAII AutoProfilerInit
     431             : {
     432             : public:
     433           3 :   explicit AutoProfilerInit(void* stackTop
     434             :                             MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     435           3 :   {
     436           3 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     437           3 :     profiler_init(stackTop);
     438           3 :   }
     439             : 
     440           0 :   ~AutoProfilerInit() { profiler_shutdown(); }
     441             : 
     442             : private:
     443             :   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     444             : };
     445             : 
     446             : // Convenience class to register and unregister a thread with the profiler.
     447             : // Needs to be the first object on the stack of the thread.
     448             : class MOZ_RAII AutoProfilerRegisterThread final
     449             : {
     450             : public:
     451          15 :   explicit AutoProfilerRegisterThread(const char* aName
     452             :                                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     453          15 :   {
     454          15 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     455          15 :     profiler_register_thread(aName, this);
     456          15 :   }
     457             : 
     458           0 :   ~AutoProfilerRegisterThread() { profiler_unregister_thread(); }
     459             : 
     460             : private:
     461             :   AutoProfilerRegisterThread(const AutoProfilerRegisterThread&) = delete;
     462             :   AutoProfilerRegisterThread& operator=(const AutoProfilerRegisterThread&) =
     463             :     delete;
     464             :   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     465             : };
     466             : 
     467             : class MOZ_RAII AutoProfilerThreadSleep
     468             : {
     469             : public:
     470        1390 :   explicit AutoProfilerThreadSleep(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
     471        1390 :   {
     472        1390 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     473        1390 :     profiler_thread_sleep();
     474        1389 :   }
     475             : 
     476        1385 :   ~AutoProfilerThreadSleep() { profiler_thread_wake(); }
     477             : 
     478             : private:
     479             :   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     480             : };
     481             : 
     482             : // Temporarily wake up the profiling of a thread while servicing events such as
     483             : // Asynchronous Procedure Calls (APCs).
     484             : class MOZ_RAII AutoProfilerThreadWake
     485             : {
     486             : public:
     487             :   explicit AutoProfilerThreadWake(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
     488             :     : mIssuedWake(profiler_thread_is_sleeping())
     489             :   {
     490             :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     491             :     if (mIssuedWake) {
     492             :       profiler_thread_wake();
     493             :     }
     494             :   }
     495             : 
     496             :   ~AutoProfilerThreadWake()
     497             :   {
     498             :     if (mIssuedWake) {
     499             :       MOZ_ASSERT(!profiler_thread_is_sleeping());
     500             :       profiler_thread_sleep();
     501             :     }
     502             :   }
     503             : 
     504             : private:
     505             :   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     506             :   bool mIssuedWake;
     507             : };
     508             : 
     509             : // This class creates a non-owning PseudoStack reference. Objects of this class
     510             : // are stack-allocated, and so exist within a thread, and are thus bounded by
     511             : // the lifetime of the thread, which ensures that the references held can't be
     512             : // used after the PseudoStack is destroyed.
     513             : class MOZ_RAII AutoProfilerLabel
     514             : {
     515             : public:
     516       12255 :   AutoProfilerLabel(const char* aLabel, const char* aDynamicString,
     517             :                     uint32_t aLine, js::ProfileEntry::Category aCategory
     518             :                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     519       12255 :   {
     520       12255 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     521             : 
     522             :     // This function runs both on and off the main thread.
     523             : 
     524             : #ifdef MOZ_GECKO_PROFILER
     525       12256 :     mPseudoStack = sPseudoStack.get();
     526       12256 :     if (mPseudoStack) {
     527       12256 :       mPseudoStack->pushCppFrame(aLabel, aDynamicString, this, aLine,
     528       12256 :                                  js::ProfileEntry::Kind::CPP_NORMAL, aCategory);
     529             :     }
     530             : #endif
     531       12258 :   }
     532             : 
     533       12245 :   ~AutoProfilerLabel()
     534       12246 :   {
     535             :     // This function runs both on and off the main thread.
     536             : 
     537             : #ifdef MOZ_GECKO_PROFILER
     538       12245 :     if (mPseudoStack) {
     539       12245 :       mPseudoStack->pop();
     540             :     }
     541             : #endif
     542       12246 :   }
     543             : 
     544             : private:
     545             :   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     546             : 
     547             : #ifdef MOZ_GECKO_PROFILER
     548             :   // We save a PseudoStack pointer in the ctor so we don't have to redo the TLS
     549             :   // lookup in the dtor.
     550             :   PseudoStack* mPseudoStack;
     551             : 
     552             : public:
     553             :   // See the comment on the definition in platform.cpp for details about this.
     554             :   static MOZ_THREAD_LOCAL(PseudoStack*) sPseudoStack;
     555             : #endif
     556             : };
     557             : 
     558             : class MOZ_RAII AutoProfilerTracing
     559             : {
     560             : public:
     561          41 :   AutoProfilerTracing(const char* aCategory, const char* aMarkerName,
     562             :                       UniqueProfilerBacktrace aBacktrace
     563             :                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     564          41 :     : mCategory(aCategory)
     565          41 :     , mMarkerName(aMarkerName)
     566             :   {
     567          41 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     568          82 :     profiler_tracing(mCategory, mMarkerName, Move(aBacktrace),
     569          41 :                      TRACING_INTERVAL_START);
     570          41 :   }
     571             : 
     572         297 :   AutoProfilerTracing(const char* aCategory, const char* aMarkerName
     573             :                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     574         297 :     : mCategory(aCategory)
     575         297 :     , mMarkerName(aMarkerName)
     576             :   {
     577         297 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     578         297 :     profiler_tracing(mCategory, mMarkerName, TRACING_INTERVAL_START);
     579         297 :   }
     580             : 
     581         338 :   ~AutoProfilerTracing()
     582         338 :   {
     583         338 :     profiler_tracing(mCategory, mMarkerName, TRACING_INTERVAL_END);
     584         338 :   }
     585             : 
     586             : protected:
     587             :   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
     588             :   const char* mCategory;
     589             :   const char* mMarkerName;
     590             : };
     591             : 
     592             : } // namespace mozilla
     593             : 
     594             : #endif  // GeckoProfiler_h

Generated by: LCOV version 1.13