Bug 1498637 - Use __gcov_flush to implement dumping and resetting instead of __gcov_dump and __gcov_reset. r=froydnj
authorMarco Castelluccio <mcastelluccio@mozilla.com>
Mon, 15 Oct 2018 10:36:45 +0200
changeset 499999 5687061cc8320ab2f339766cb1cf0c0877deee72
parent 499998 399335d39d4c49eec8396aef9c77789bee33e3c2
child 500000 bc4d8d0bf57555a39cf825c91c82fea0843072bc
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1498637
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1498637 - Use __gcov_flush to implement dumping and resetting instead of __gcov_dump and __gcov_reset. r=froydnj
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/PContent.ipdl
testing/talos/talos/talos-powers/api.js
tools/code-coverage/CodeCoverageHandler.cpp
tools/code-coverage/CodeCoverageHandler.h
tools/code-coverage/PerTestCoverageUtils.jsm
tools/code-coverage/nsCodeCoverage.cpp
tools/code-coverage/nsICodeCoverage.idl
tools/code-coverage/tests/xpcshell/test_basic.js
tools/code-coverage/tests/xpcshell/test_basic_child_and_parent.js
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -3800,32 +3800,20 @@ ContentChild::RecvShareCodeCoverageMutex
   CodeCoverageHandler::Init(aHandle);
   return IPC_OK();
 #else
   MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
 #endif
 }
 
 mozilla::ipc::IPCResult
-ContentChild::RecvDumpCodeCoverageCounters(DumpCodeCoverageCountersResolver&& aResolver)
+ContentChild::RecvFlushCodeCoverageCounters(FlushCodeCoverageCountersResolver&& aResolver)
 {
 #ifdef MOZ_CODE_COVERAGE
-  CodeCoverageHandler::DumpCounters();
-  aResolver(/* unused */ true);
-  return IPC_OK();
-#else
-  MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
-#endif
-}
-
-mozilla::ipc::IPCResult
-ContentChild::RecvResetCodeCoverageCounters(ResetCodeCoverageCountersResolver&& aResolver)
-{
-#ifdef MOZ_CODE_COVERAGE
-  CodeCoverageHandler::ResetCounters();
+  CodeCoverageHandler::FlushCounters();
   aResolver(/* unused */ true);
   return IPC_OK();
 #else
   MOZ_CRASH("Shouldn't receive this message in non-code coverage builds!");
 #endif
 }
 
 mozilla::ipc::IPCResult
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -634,20 +634,17 @@ public:
   mozilla::ipc::IPCResult
   RecvSetPermissionsWithKey(const nsCString& aPermissionKey,
                             nsTArray<IPC::Permission>&& aPerms) override;
 
   virtual mozilla::ipc::IPCResult
   RecvShareCodeCoverageMutex(const CrossProcessMutexHandle& aHandle) override;
 
   virtual mozilla::ipc::IPCResult
-  RecvDumpCodeCoverageCounters(DumpCodeCoverageCountersResolver&& aResolver) override;
-
-  virtual mozilla::ipc::IPCResult
-  RecvResetCodeCoverageCounters(ResetCodeCoverageCountersResolver&& aResolver) override;
+  RecvFlushCodeCoverageCounters(FlushCodeCoverageCountersResolver&& aResolver) override;
 
   virtual mozilla::ipc::IPCResult
   RecvSetInputEventQueueEnabled() override;
 
   virtual mozilla::ipc::IPCResult
   RecvFlushInputEventQueue() override;
 
   virtual mozilla::ipc::IPCResult
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -643,18 +643,17 @@ child:
      * plugins changes. The chrome process sends up the last epoch it observed.
      * If the epoch last seen by the content process is the same, the content
      * process ignores the update. Otherwise the content process updates its
      * list and reloads its plugins.
      **/
     async SetPluginList(uint32_t pluginEpoch, PluginTag[] plugins, FakePluginTag[] fakePlugins);
 
     async ShareCodeCoverageMutex(CrossProcessMutexHandle handle);
-    async DumpCodeCoverageCounters() returns (bool unused);
-    async ResetCodeCoverageCounters() returns (bool unused);
+    async FlushCodeCoverageCounters() returns (bool unused);
 
     /*
      * IPC message to enable the input event queue on the main thread of the
      * content process.
      */
     async SetInputEventQueueEnabled();
 
     /*
--- a/testing/talos/talos/talos-powers/api.js
+++ b/testing/talos/talos/talos-powers/api.js
@@ -4,16 +4,17 @@
 
 /* globals ExtensionAPI */
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyModuleGetters(this, {
   BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
   OS: "resource://gre/modules/osfile.jsm",
   Services: "resource://gre/modules/Services.jsm",
+  PerTestCoverageUtils: "resource://testing-common/PerTestCoverageUtils.jsm",
 });
 
 XPCOMUtils.defineLazyServiceGetter(this, "resProto",
                                    "@mozilla.org/network/protocol;1?name=resource",
                                    "nsISubstitutingProtocolHandler");
 
 Cu.importGlobalProperties(["TextEncoder"]);
 
@@ -315,27 +316,21 @@ TalosPowersService.prototype = {
 
     // arg: handle from startFrameTimeRecording. return: array with composition intervals
     stopFrameTimeRecording(arg, callback, win) {
       var rv = win.windowUtils.stopFrameTimeRecording(arg);
       callback(rv);
     },
 
     requestDumpCoverageCounters(arg, callback, win) {
-      let codeCoverage = Cc["@mozilla.org/tools/code-coverage;1"].
-                         getService(Ci.nsICodeCoverage);
-      codeCoverage.dumpCounters();
-      callback();
+      PerTestCoverageUtils.afterTest().then(callback);
     },
 
     requestResetCoverageCounters(arg, callback, win) {
-      let codeCoverage = Cc["@mozilla.org/tools/code-coverage;1"].
-                         getService(Ci.nsICodeCoverage);
-      codeCoverage.resetCounters();
-      callback();
+      PerTestCoverageUtils.beforeTest().then(callback);
     },
 
     dumpAboutSupport(arg, callback, win) {
       ChromeUtils.import("resource://gre/modules/Troubleshoot.jsm");
       Troubleshoot.snapshot(function(snapshot) {
         dump("about:support\t" + JSON.stringify(snapshot));
       });
       callback();
--- a/tools/code-coverage/CodeCoverageHandler.cpp
+++ b/tools/code-coverage/CodeCoverageHandler.cpp
@@ -13,93 +13,50 @@
 #endif
 #include "mozilla/CodeCoverageHandler.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/DebugOnly.h"
 #include "nsAppRunner.h"
 
 using namespace mozilla;
 
-// The __gcov_dump function writes the coverage counters to gcda files.
-// The __gcov_reset function resets the coverage counters to zero.
-// They are defined at https://github.com/gcc-mirror/gcc/blob/aad93da1a579b9ae23ede6b9cf8523360f0a08b4/libgcc/libgcov-interface.c.
-// __gcov_flush is protected by a mutex, __gcov_dump and __gcov_reset aren't.
-// So we are using a CrossProcessMutex to protect them.
-
-#if defined(__GNUC__) && !defined(__clang__)
-extern "C" void __gcov_dump();
-extern "C" void __gcov_reset();
+// The __gcov_flush function writes the coverage counters to gcda files and then resets them to zero.
+// It is defined at https://github.com/gcc-mirror/gcc/blob/aad93da1a579b9ae23ede6b9cf8523360f0a08b4/libgcc/libgcov-interface.c.
+// __gcov_flush is protected by a mutex in GCC, but not in LLVM, so we are using a CrossProcessMutex to protect it.
 
-void counters_dump() {
-  __gcov_dump();
-}
-
-void counters_reset() {
-  __gcov_reset();
-}
-#else
-void counters_dump() {
-  /* Do nothing */
-}
-
-void counters_reset() {
-  /* Do nothing */
-}
-#endif
+extern "C" void __gcov_flush();
 
 StaticAutoPtr<CodeCoverageHandler> CodeCoverageHandler::instance;
 
-void CodeCoverageHandler::DumpCounters()
+void CodeCoverageHandler::FlushCounters()
 {
-  printf_stderr("[CodeCoverage] Requested dump for %d.\n", getpid());
+  printf_stderr("[CodeCoverage] Requested flush for %d.\n", getpid());
 
   CrossProcessMutexAutoLock lock(*CodeCoverageHandler::Get()->GetMutex());
 
-  counters_dump();
-  printf_stderr("[CodeCoverage] Dump completed.\n");
-}
-
-void CodeCoverageHandler::DumpCountersSignalHandler(int)
-{
-  DumpCounters();
+  __gcov_flush();
+  printf_stderr("[CodeCoverage] flush completed.\n");
 }
 
-void CodeCoverageHandler::ResetCounters()
+void CodeCoverageHandler::FlushCountersSignalHandler(int)
 {
-  printf_stderr("[CodeCoverage] Requested reset for %d.\n", getpid());
-
-  CrossProcessMutexAutoLock lock(*CodeCoverageHandler::Get()->GetMutex());
-
-  counters_reset();
-  printf_stderr("[CodeCoverage] Reset completed.\n");
-}
-
-void CodeCoverageHandler::ResetCountersSignalHandler(int)
-{
-  ResetCounters();
+  FlushCounters();
 }
 
 void CodeCoverageHandler::SetSignalHandlers()
 {
 #ifndef XP_WIN
   printf_stderr("[CodeCoverage] Setting handlers for process %d.\n", getpid());
 
   struct sigaction dump_sa;
-  dump_sa.sa_handler = CodeCoverageHandler::DumpCountersSignalHandler;
+  dump_sa.sa_handler = CodeCoverageHandler::FlushCountersSignalHandler;
   dump_sa.sa_flags = SA_RESTART;
   sigemptyset(&dump_sa.sa_mask);
   DebugOnly<int> r1 = sigaction(SIGUSR1, &dump_sa, nullptr);
   MOZ_ASSERT(r1 == 0, "Failed to install GCOV SIGUSR1 handler");
-
-  struct sigaction reset_sa;
-  reset_sa.sa_handler = CodeCoverageHandler::ResetCountersSignalHandler;
-  reset_sa.sa_flags = SA_RESTART;
-  sigemptyset(&reset_sa.sa_mask);
-  DebugOnly<int> r2 = sigaction(SIGUSR2, &reset_sa, nullptr);
-  MOZ_ASSERT(r2 == 0, "Failed to install GCOV SIGUSR2 handler");
 #endif
 }
 
 CodeCoverageHandler::CodeCoverageHandler()
   : mGcovLock("GcovLock")
 {
   SetSignalHandlers();
 }
--- a/tools/code-coverage/CodeCoverageHandler.h
+++ b/tools/code-coverage/CodeCoverageHandler.h
@@ -13,20 +13,18 @@ namespace mozilla {
 
 class CodeCoverageHandler {
 public:
   static void Init();
   static void Init(const CrossProcessMutexHandle& aHandle);
   static CodeCoverageHandler* Get();
   CrossProcessMutex* GetMutex();
   CrossProcessMutexHandle GetMutexHandle(int aProcId);
-  static void DumpCounters();
-  static void DumpCountersSignalHandler(int);
-  static void ResetCounters();
-  static void ResetCountersSignalHandler(int);
+  static void FlushCounters();
+  static void FlushCountersSignalHandler(int);
 
 private:
   CodeCoverageHandler();
   explicit CodeCoverageHandler(const CrossProcessMutexHandle& aHandle);
 
   static StaticAutoPtr<CodeCoverageHandler> instance;
   CrossProcessMutex mGcovLock;
 
--- a/tools/code-coverage/PerTestCoverageUtils.jsm
+++ b/tools/code-coverage/PerTestCoverageUtils.jsm
@@ -57,40 +57,40 @@ function moveDirectoryContents(src, dst)
 
 var PerTestCoverageUtils = class PerTestCoverageUtilsClass {
   // Resets the counters to 0.
   static async beforeTest() {
     if (!PerTestCoverageUtils.enabled) {
       return;
     }
 
-    // Reset the counters.
+    // Flush the counters.
     let codeCoverageService = Cc["@mozilla.org/tools/code-coverage;1"].getService(Ci.nsICodeCoverage);
-    await codeCoverageService.resetCounters();
+    await codeCoverageService.flushCounters();
 
-    // Remove any gcda file that might have been created between the end of a previous test and the beginning of the next one (e.g. some tests can create a new content process for every sub-test).
+    // Remove gcda files created by the flush, and those that might have been created between the end of a previous test and the beginning of the next one (e.g. some tests can create a new content process for every sub-test).
     removeDirectoryContents(gcovPrefixDir);
 
     // Move gcda files from the GCOV_RESULTS_DIR directory, so we can accumulate the counters.
     moveDirectoryContents(gcovResultsDir, gcovPrefixDir);
   }
 
   static beforeTestSync() {
     awaitPromise(this.beforeTest());
   }
 
   // Dumps counters and moves the gcda files in the directory expected by codecoverage.py.
   static async afterTest() {
     if (!PerTestCoverageUtils.enabled) {
       return;
     }
 
-    // Dump the counters.
+    // Flush the counters.
     let codeCoverageService = Cc["@mozilla.org/tools/code-coverage;1"].getService(Ci.nsICodeCoverage);
-    await codeCoverageService.dumpCounters();
+    await codeCoverageService.flushCounters();
 
     // Move the gcda files in the GCOV_RESULTS_DIR, so that the execution from now to shutdown (or next test) is not counted.
     moveDirectoryContents(gcovPrefixDir, gcovResultsDir);
   }
 
   static afterTestSync() {
     awaitPromise(this.afterTest());
   }
--- a/tools/code-coverage/nsCodeCoverage.cpp
+++ b/tools/code-coverage/nsCodeCoverage.cpp
@@ -19,17 +19,17 @@ NS_IMPL_ISUPPORTS(nsCodeCoverage,
 nsCodeCoverage::nsCodeCoverage()
 {
 }
 
 nsCodeCoverage::~nsCodeCoverage()
 {
 }
 
-enum RequestType { Dump, Reset };
+enum RequestType { Flush };
 
 class ProcessCount final {
   NS_INLINE_DECL_REFCOUNTING(ProcessCount);
 
 public:
   explicit ProcessCount(uint32_t c) : mCount(c) {}
   operator uint32_t() const { return mCount; }
   ProcessCount& operator--() { mCount--; return *this; }
@@ -56,20 +56,18 @@ nsresult Request(JSContext* cx, Promise*
   }
 
   uint32_t processCount = 0;
   for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
     Unused << cp;
     ++processCount;
   }
 
-  if (requestType == RequestType::Dump) {
-    CodeCoverageHandler::DumpCounters();
-  } else if (requestType == RequestType::Reset) {
-    CodeCoverageHandler::ResetCounters();
+  if (requestType == RequestType::Flush) {
+    CodeCoverageHandler::FlushCounters();
   }
 
   if (processCount == 0) {
     promise->MaybeResolveWithUndefined();
   } else {
     RefPtr<ProcessCount> processCountHolder(new ProcessCount(processCount));
 
     auto resolve = [processCountHolder, promise](bool unused) {
@@ -78,29 +76,22 @@ nsresult Request(JSContext* cx, Promise*
       }
     };
 
     auto reject = [promise](ResponseRejectReason aReason) {
       promise->MaybeReject(NS_ERROR_FAILURE);
     };
 
     for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
-      if (requestType == RequestType::Dump) {
-        cp->SendDumpCodeCoverageCounters(resolve, reject);
-      } else if (requestType == RequestType::Reset) {
-        cp->SendResetCodeCoverageCounters(resolve, reject);
+      if (requestType == RequestType::Flush) {
+        cp->SendFlushCodeCoverageCounters(resolve, reject);
       }
     }
   }
 
   promise.forget(aPromise);
   return NS_OK;
 }
 
-NS_IMETHODIMP nsCodeCoverage::DumpCounters(JSContext *cx, Promise** aPromise)
+NS_IMETHODIMP nsCodeCoverage::FlushCounters(JSContext *cx, Promise** aPromise)
 {
-  return Request(cx, aPromise, RequestType::Dump);
+  return Request(cx, aPromise, RequestType::Flush);
 }
-
-NS_IMETHODIMP nsCodeCoverage::ResetCounters(JSContext *cx, Promise** aPromise)
-{
-  return Request(cx, aPromise, RequestType::Reset);
-}
--- a/tools/code-coverage/nsICodeCoverage.idl
+++ b/tools/code-coverage/nsICodeCoverage.idl
@@ -3,28 +3,22 @@
  * 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"
 
 /**
  * The nsICodeCoverage component allows controlling the code coverage counters
  * collected by Firefox during execution.
- * By resetting and dumping the counters, one can analyze the coverage information
+ * By flushing the counters, one can analyze the coverage information
  * for a subset of the program execution (e.g. startup code coverage).
  *
  */
 
 [scriptable, uuid(57d92056-37b4-4d0a-a52f-deb8f6dac8bc)]
 interface nsICodeCoverage : nsISupports
 {
   /**
-   * Write the coverage counters to disk.
+   * Write the coverage counters to disk, and reset them in memory to 0.
    */
   [implicit_jscontext]
-  Promise dumpCounters();
-
-  /**
-   * Reset the coverage counters to 0 (as if nothing was executed).
-   */
-  [implicit_jscontext]
-  Promise resetCounters();
+  Promise flushCounters();
 };
--- a/tools/code-coverage/tests/xpcshell/test_basic.js
+++ b/tools/code-coverage/tests/xpcshell/test_basic.js
@@ -8,14 +8,12 @@ async function run_test() {
   Assert.ok("@mozilla.org/tools/code-coverage;1" in Cc);
 
   let codeCoverageCc = Cc["@mozilla.org/tools/code-coverage;1"];
   Assert.ok(!!codeCoverageCc);
 
   let codeCoverage = codeCoverageCc.getService(Ci.nsICodeCoverage);
   Assert.ok(!!codeCoverage);
 
-  await codeCoverage.dumpCounters();
-
-  await codeCoverage.resetCounters();
+  await codeCoverage.flushCounters();
 
   do_test_finished();
 }
--- a/tools/code-coverage/tests/xpcshell/test_basic_child_and_parent.js
+++ b/tools/code-coverage/tests/xpcshell/test_basic_child_and_parent.js
@@ -4,14 +4,13 @@
 
 function run_test() {
   do_load_child_test_harness();
   do_test_pending();
 
   sendCommand("let v = 'test';", async function() {
       let codeCoverage = Cc["@mozilla.org/tools/code-coverage;1"].getService(Ci.nsICodeCoverage);
 
-      await codeCoverage.dumpCounters();
-      await codeCoverage.resetCounters();
+      await codeCoverage.flushCounters();
 
       do_test_finished();
   });
 }