js/src/devtools/Instruments.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "Instruments.h"
     7 #ifdef __APPLE__
     9 #include <dlfcn.h>
    10 #include <CoreFoundation/CoreFoundation.h>
    11 #include <unistd.h>
    13 // There are now 2 paths to the DTPerformanceSession framework. We try to load
    14 // the one contained in /Applications/Xcode.app first, falling back to the one
    15 // contained in /Library/Developer/4.0/Instruments.
    16 #define DTPerformanceLibraryPath "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/DTPerformanceSession.framework/Versions/Current/DTPerformanceSession"
    17 #define OldDTPerformanceLibraryPath "/Library/Developer/4.0/Instruments/Frameworks/DTPerformanceSession.framework/Versions/Current/DTPerformanceSession"
    19 extern "C" {
    21 typedef CFTypeRef DTPerformanceSessionRef;
    23 #define DTPerformanceSession_TimeProfiler               "com.apple.instruments.dtps.timeprofiler"
    24 // DTPerformanceSession_Option_SamplingInterval is measured in microseconds
    25 #define DTPerformanceSession_Option_SamplingInterval    "com.apple.instruments.dtps.option.samplinginterval"
    27 typedef void (*dtps_errorcallback_t)(CFStringRef, CFErrorRef);
    28 typedef DTPerformanceSessionRef (*DTPerformanceSessionCreateFunction)(CFStringRef, CFStringRef, CFDictionaryRef, CFErrorRef*);
    29 typedef bool (*DTPerformanceSessionAddInstrumentFunction)(DTPerformanceSessionRef, CFStringRef, CFDictionaryRef, dtps_errorcallback_t, CFErrorRef*);
    30 typedef bool (*DTPerformanceSessionIsRecordingFunction)(DTPerformanceSessionRef);
    31 typedef bool (*DTPerformanceSessionStartFunction)(DTPerformanceSessionRef, CFArrayRef, CFErrorRef*);
    32 typedef bool (*DTPerformanceSessionStopFunction)(DTPerformanceSessionRef, CFArrayRef, CFErrorRef*);
    33 typedef bool (*DTPerformanceSessionSaveFunction)(DTPerformanceSessionRef, CFStringRef, CFErrorRef*);
    35 } // extern "C"
    37 namespace Instruments {
    39 static const int kSamplingInterval = 20; // microseconds
    41 template<typename T>
    42 class AutoReleased
    43 {
    44 public:
    45   AutoReleased(T aTypeRef) : mTypeRef(aTypeRef)
    46   {
    47   }
    48   ~AutoReleased()
    49   {
    50     if (mTypeRef) {
    51       CFRelease(mTypeRef);
    52     }
    53   }
    55   operator T()
    56   {
    57     return mTypeRef;
    58   }
    60 private:
    61   T mTypeRef;
    62 };
    64 #define DTPERFORMANCE_SYMBOLS \
    65   SYMBOL(DTPerformanceSessionCreate) \
    66   SYMBOL(DTPerformanceSessionAddInstrument) \
    67   SYMBOL(DTPerformanceSessionIsRecording) \
    68   SYMBOL(DTPerformanceSessionStart) \
    69   SYMBOL(DTPerformanceSessionStop) \
    70   SYMBOL(DTPerformanceSessionSave)
    72 #define SYMBOL(_sym) \
    73   _sym##Function _sym = nullptr;
    75 DTPERFORMANCE_SYMBOLS
    77 #undef SYMBOL
    79 void*
    80 LoadDTPerformanceLibraries(bool dontLoad)
    81 {
    82   int flags = RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE;
    83   if (dontLoad) {
    84     flags |= RTLD_NOLOAD;
    85   }
    87   void *DTPerformanceLibrary = dlopen(DTPerformanceLibraryPath, flags);
    88   if (!DTPerformanceLibrary) {
    89     DTPerformanceLibrary = dlopen(OldDTPerformanceLibraryPath, flags);
    90   }
    91   return DTPerformanceLibrary;
    92 }
    94 bool
    95 LoadDTPerformanceLibrary()
    96 {
    97   void *DTPerformanceLibrary = LoadDTPerformanceLibraries(true);
    98   if (!DTPerformanceLibrary) {
    99     DTPerformanceLibrary = LoadDTPerformanceLibraries(false);
   100     if (!DTPerformanceLibrary) {
   101       return false;
   102     }
   103   }
   105 #define SYMBOL(_sym) \
   106   _sym = reinterpret_cast<_sym##Function>(dlsym(DTPerformanceLibrary, #_sym)); \
   107   if (!_sym) { \
   108     dlclose(DTPerformanceLibrary); \
   109     DTPerformanceLibrary = nullptr; \
   110     return false; \
   111   }
   113   DTPERFORMANCE_SYMBOLS
   115 #undef SYMBOL
   117   dlclose(DTPerformanceLibrary);
   119   return true;
   120 }
   122 static DTPerformanceSessionRef gSession;
   124 bool
   125 Error(CFErrorRef error)
   126 {
   127   if (gSession) {
   128     CFErrorRef unused = nullptr;
   129     DTPerformanceSessionStop(gSession, nullptr, &unused);
   130     CFRelease(gSession);
   131     gSession = nullptr;
   132   }
   133 #ifdef DEBUG
   134   AutoReleased<CFDataRef> data =
   135     CFStringCreateExternalRepresentation(nullptr,
   136                                          CFErrorCopyDescription(error),
   137                                          kCFStringEncodingUTF8, '?');
   138   if (data != nullptr) {
   139     printf("%.*s\n\n", (int)CFDataGetLength(data), CFDataGetBytePtr(data));
   140   }
   141 #endif
   142   return false;
   143 }
   145 bool
   146 Start(pid_t pid)
   147 {
   148   if (gSession) {
   149     return false;
   150   }
   152   if (!LoadDTPerformanceLibrary()) {
   153     return false;
   154   }
   156   AutoReleased<CFStringRef> process =
   157     CFStringCreateWithFormat(kCFAllocatorDefault, nullptr, CFSTR("%d"), pid);
   158   if (!process) {
   159     return false;
   160   }
   161   CFErrorRef error = nullptr;
   162   gSession = DTPerformanceSessionCreate(nullptr, process, nullptr, &error);
   163   if (!gSession) {
   164     return Error(error);
   165   }
   167   AutoReleased<CFNumberRef> interval =
   168     CFNumberCreate(0, kCFNumberIntType, &kSamplingInterval);
   169   if (!interval) {
   170     return false;
   171   }
   172   CFStringRef keys[1] = { CFSTR(DTPerformanceSession_Option_SamplingInterval) };
   173   CFNumberRef values[1] = { interval };
   174   AutoReleased<CFDictionaryRef> options =
   175     CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys,
   176                        (const void**)values, 1, &kCFTypeDictionaryKeyCallBacks,
   177                        &kCFTypeDictionaryValueCallBacks);
   178   if (!options) {
   179     return false;
   180   }
   182   if (!DTPerformanceSessionAddInstrument(gSession,
   183                                          CFSTR(DTPerformanceSession_TimeProfiler),
   184                                          options, nullptr, &error)) {
   185     return Error(error);
   186   }
   188   return Resume();
   189 }
   191 void
   192 Pause()
   193 {
   194   if (gSession && DTPerformanceSessionIsRecording(gSession)) {
   195     CFErrorRef error = nullptr;
   196     if (!DTPerformanceSessionStop(gSession, nullptr, &error)) {
   197       Error(error);
   198     }
   199   }
   200 }
   202 bool
   203 Resume()
   204 {
   205   if (!gSession) {
   206     return false;
   207   }
   209   CFErrorRef error = nullptr;
   210   return DTPerformanceSessionStart(gSession, nullptr, &error) ||
   211          Error(error);
   212 }
   214 void
   215 Stop(const char* profileName)
   216 {
   217   Pause();
   219   CFErrorRef error = nullptr;
   220   AutoReleased<CFStringRef> name =
   221     CFStringCreateWithFormat(kCFAllocatorDefault, nullptr, CFSTR("%s%s"),
   222                              "/tmp/", profileName ? profileName : "mozilla");
   223   if (!DTPerformanceSessionSave(gSession, name, &error)) {
   224     Error(error);
   225     return;
   226   }
   228   CFRelease(gSession);
   229   gSession = nullptr;
   230 }
   232 } // namespace Instruments
   234 #endif /* __APPLE__ */

mercurial