Bug 717059. Add suppport for optional features. r=ehsan
authorBenoit Girard <bgirard@mozilla.com>
Thu, 12 Jan 2012 13:33:32 -0500
changeset 85584 014f28a0543c2e76bc5da916a3e163c81788c453
parent 85583 2c1f1e307171886bf7b93074ef4dfaaf9aedbf09
child 85585 4b0fd441c9c70767a253f2b437b1d2aabb6840e0
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs717059
milestone12.0a1
Bug 717059. Add suppport for optional features. r=ehsan This will let us detect situations where we have different features in the profiler and choose to use them.
tools/profiler/nsProfiler.cpp
tools/profiler/public/nsIProfiler.idl
tools/profiler/sampler.h
tools/profiler/sps/TableTicker.cpp
tools/profiler/sps/sps_sampler.h
--- a/tools/profiler/nsProfiler.cpp
+++ b/tools/profiler/nsProfiler.cpp
@@ -48,19 +48,20 @@ NS_IMPL_ISUPPORTS1(nsProfiler, nsIProfil
 
 
 nsProfiler::nsProfiler()
 {
 }
 
 
 NS_IMETHODIMP
-nsProfiler::StartProfiler(PRUint32 aInterval, PRUint32 aEntries)
+nsProfiler::StartProfiler(PRUint32 aInterval, PRUint32 aEntries,
+                          const char** aFeatures, PRUint32 aFeatureCount)
 {
-  SAMPLER_START(aInterval, aEntries);
+  SAMPLER_START(aInterval, aEntries, aFeatures, aFeatureCount);
 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
   mozilla::InitEventTracing();
 #endif
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsProfiler::StopProfiler()
@@ -106,8 +107,35 @@ nsProfiler::GetResponsivenessTimes(PRUin
                        (nsMemory::Clone(times, len * sizeof(double)));
 
   *aCount = len;
   *aResult = fs;
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsProfiler::GetFeatures(PRUint32 *aCount, char ***aFeatures)
+{
+  PRUint32 len = 0;
+
+  const char **features = SAMPLER_GET_FEATURES();
+  if (!features) {
+    *aCount = 0;
+    *aFeatures = nsnull;
+    return NS_OK;
+  }
+
+  while (features[++len]);
+
+  char **featureList = static_cast<char **>
+                       (nsMemory::Alloc(len * sizeof(char*)));
+
+  for (size_t i = 0; i < len; i++) {
+    PRUint32 strLen = strlen(features[i]);
+    featureList[i] = static_cast<char *>
+                         (nsMemory::Clone(features[i], (strLen + 1) * sizeof(char)));
+  }
+
+  *aFeatures = featureList;
+  *aCount = len;
+  return NS_OK;
+}
--- a/tools/profiler/public/nsIProfiler.idl
+++ b/tools/profiler/public/nsIProfiler.idl
@@ -30,18 +30,21 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
-[scriptable, uuid(97c34690-3ca8-4225-9f7d-bcdbb76f29ed)]
+[scriptable, uuid(e388fded-1321-41af-a988-861a2bc5cfc3)]
 interface nsIProfiler : nsISupports
 {
-  void StartProfiler(in PRUint32 aInterval, in PRUint32 aEntries);
+  void StartProfiler(in PRUint32 aInterval, in PRUint32 aEntries,
+                      [array, size_is(aFeatureCount)] in string aFeatures,
+                      in PRUint32 aFeatureCount);
   void StopProfiler();
   string GetProfile();
   boolean IsActive();
   void GetResponsivenessTimes(out PRUint32 aCount, [retval, array, size_is(aCount)] out double aResult);
+  void GetFeatures(out PRUint32 aCount, [retval, array, size_is(aCount)] out string aFeatures);
 };
 
--- a/tools/profiler/sampler.h
+++ b/tools/profiler/sampler.h
@@ -91,22 +91,23 @@
 #include "sps_sampler.h"
 
 #else
 
 // Initialize the sampler. Any other calls will be silently discarded
 // before the sampler has been initialized (i.e. early start-up code)
 #define SAMPLER_INIT()
 #define SAMPLER_DEINIT()
-#define SAMPLER_START(entries, interval)
+#define SAMPLER_START(entries, interval, features, featureCount)
 #define SAMPLER_STOP()
 #define SAMPLER_IS_ACTIVE() false
 #define SAMPLER_SAVE()
 // Returned string must be free'ed
 #define SAMPLER_GET_PROFILE() NULL
 #define SAMPLER_RESPONSIVENESS(time) NULL
 #define SAMPLER_GET_RESPONSIVENESS() NULL
+#define SAMPLER_GET_FEATURES() NULL
 #define SAMPLE_LABEL(name_space, info)
 #define SAMPLE_MARKER(info)
 
 #endif
 
 #endif // ifndef SAMPLER_H
--- a/tools/profiler/sps/TableTicker.cpp
+++ b/tools/profiler/sps/TableTicker.cpp
@@ -212,19 +212,29 @@ private:
   int mReadPos;  // points to the next entry we will read to
   int mEntrySize;
   bool mNeedsSharedLibraryInfo;
   SharedLibraryInfo mSharedLibraryInfo;
 };
 
 class SaveProfileTask;
 
+static bool
+hasFeature(const char** aFeatures, uint32_t aFeatureCount, const char* aFeature) {
+  for(size_t i = 0; i < aFeatureCount; i++) {
+    if (strcmp(aFeatures[i], aFeature) == 0)
+      return true;
+  }
+  return false;
+}
+
 class TableTicker: public Sampler {
  public:
-  explicit TableTicker(int aInterval, int aEntrySize, Stack *aStack)
+  TableTicker(int aInterval, int aEntrySize, Stack *aStack,
+              const char** aFeatures, uint32_t aFeatureCount)
     : Sampler(aInterval, true)
     , mProfile(aEntrySize)
     , mStack(aStack)
     , mSaveRequested(false)
   {
     mProfile.addTag(ProfileEntry('m', "Start"));
   }
 
@@ -437,16 +447,18 @@ string ProfileEntry::TagToString(Profile
     }
   }
 #endif
   return tag;
 }
 
 #define PROFILE_DEFAULT_ENTRY 100000
 #define PROFILE_DEFAULT_INTERVAL 10
+#define PROFILE_DEFAULT_FEATURES NULL
+#define PROFILE_DEFAULT_FEATURE_COUNT 0
 
 void mozilla_sampler_init()
 {
   // TODO linux port: Use TLS with ifdefs
   if (!mozilla::tls::create(&pkey_stack) ||
       !mozilla::tls::create(&pkey_ticker)) {
     LOG("Failed to init.");
     return;
@@ -459,65 +471,77 @@ void mozilla_sampler_init()
   // We can't open pref so we use an environment variable
   // to know if we should trigger the profiler on startup
   // NOTE: Default
   const char *val = PR_GetEnv("MOZ_PROFILER_STARTUP");
   if (!val || !*val) {
     return;
   }
 
-  mozilla_sampler_start(PROFILE_DEFAULT_ENTRY, PROFILE_DEFAULT_INTERVAL);
+  mozilla_sampler_start(PROFILE_DEFAULT_ENTRY, PROFILE_DEFAULT_INTERVAL,
+                        PROFILE_DEFAULT_FEATURES, PROFILE_DEFAULT_FEATURE_COUNT);
 }
 
 void mozilla_sampler_deinit()
 {
   mozilla_sampler_stop();
   // We can't delete the Stack because we can be between a
   // sampler call_enter/call_exit point.
   // TODO Need to find a safe time to delete Stack
 }
 
-void mozilla_sampler_save() {
+void mozilla_sampler_save()
+{
   TableTicker *t = mozilla::tls::get<TableTicker>(pkey_ticker);
   if (!t) {
     return;
   }
 
   t->RequestSave();
   // We're on the main thread already so we don't
   // have to wait to handle the save request.
   t->HandleSaveRequest();
 }
 
-char* mozilla_sampler_get_profile() {
+char* mozilla_sampler_get_profile()
+{
   TableTicker *t = mozilla::tls::get<TableTicker>(pkey_ticker);
   if (!t) {
     return NULL;
   }
 
   StringBuilder profile;
   t->GetProfile()->ToString(profile);
 
   char *rtn = (char*)malloc( (profile.Length()+1) * sizeof(char) );
   strcpy(rtn, profile.Buffer());
   return rtn;
 }
 
+const char** mozilla_sampler_get_features()
+{
+  static const char* features[] = {""};
+
+  return features;
+}
+
 // Values are only honored on the first start
-void mozilla_sampler_start(int aProfileEntries, int aInterval)
+void mozilla_sampler_start(int aProfileEntries, int aInterval,
+                           const char** aFeatures, uint32_t aFeatureCount)
 {
   Stack *stack = mozilla::tls::get<Stack>(pkey_stack);
   if (!stack) {
     ASSERT(false);
     return;
   }
 
   mozilla_sampler_stop();
 
-  TableTicker *t = new TableTicker(aInterval, aProfileEntries, stack);
+  TableTicker *t = new TableTicker(aInterval, aProfileEntries, stack,
+                                   aFeatures, aFeatureCount);
   mozilla::tls::set(pkey_ticker, t);
   t->Start();
 }
 
 void mozilla_sampler_stop()
 {
   TableTicker *t = mozilla::tls::get<TableTicker>(pkey_ticker);
   if (!t) {
--- a/tools/profiler/sps/sps_sampler.h
+++ b/tools/profiler/sps/sps_sampler.h
@@ -46,23 +46,24 @@ using mozilla::TimeStamp;
 using mozilla::TimeDuration;
 
 extern mozilla::tls::key pkey_stack;
 extern mozilla::tls::key pkey_ticker;
 extern bool stack_key_initialized;
 
 #define SAMPLER_INIT() mozilla_sampler_init()
 #define SAMPLER_DEINIT() mozilla_sampler_deinit()
-#define SAMPLER_START(entries, interval) mozilla_sampler_start(entries, interval)
+#define SAMPLER_START(entries, interval, features, featureCount) mozilla_sampler_start(entries, interval, features, featureCount)
 #define SAMPLER_STOP() mozilla_sampler_stop()
 #define SAMPLER_IS_ACTIVE() mozilla_sampler_is_active()
 #define SAMPLER_RESPONSIVENESS(time) mozilla_sampler_responsiveness(time)
 #define SAMPLER_GET_RESPONSIVENESS() mozilla_sampler_get_responsiveness()
 #define SAMPLER_SAVE() mozilla_sampler_save()
 #define SAMPLER_GET_PROFILE() mozilla_sampler_get_profile()
+#define SAMPLER_GET_FEATURES() mozilla_sampler_get_features()
 #define SAMPLE_LABEL(name_space, info) mozilla::SamplerStackFrameRAII only_one_sampleraii_per_scope(FULLFUNCTION, name_space "::" info)
 #define SAMPLE_MARKER(info) mozilla_sampler_add_marker(info)
 
 /* we duplicate this code here to avoid header dependencies
  * which make it more difficult to include in other places */
 #if defined(_M_X64) || defined(__x86_64__)
 #define V8_HOST_ARCH_X64 1
 #elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
@@ -109,23 +110,24 @@ LinuxKernelMemoryBarrierFunc pLinuxKerne
 #endif
 
 // Returns a handdle to pass on exit. This can check that we are popping the
 // correct callstack.
 inline void* mozilla_sampler_call_enter(const char *aInfo);
 inline void  mozilla_sampler_call_exit(void* handle);
 inline void  mozilla_sampler_add_marker(const char *aInfo);
 
-void mozilla_sampler_start(int aEntries, int aInterval);
+void mozilla_sampler_start(int aEntries, int aInterval, const char** aFeatures, uint32_t aFeatureCount);
 void mozilla_sampler_stop();
 bool mozilla_sampler_is_active();
 void mozilla_sampler_responsiveness(TimeStamp time);
 const double* mozilla_sampler_get_responsiveness();
 void mozilla_sampler_save();
 char* mozilla_sampler_get_profile();
+const char** mozilla_sampler_get_features();
 void mozilla_sampler_init();
 
 namespace mozilla {
 
 class NS_STACK_CLASS SamplerStackFrameRAII {
 public:
   SamplerStackFrameRAII(const char *aFuncName, const char *aInfo) {
     mHandle = mozilla_sampler_call_enter(aInfo);