Bug 1235677 - Add assertion to catch unsafe concurrent use of AutoEnterOOMUnsafeRegion r=terrence
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 30 Mar 2016 12:33:56 +0100
changeset 291058 6c7e6cf636afde50f2dc72099c75e8b5125b97d3
parent 291057 24b56ce6d8db255d1fbf691753ab07f99c07b3c5
child 291059 2d7bdc3491d54fd7318c5314823d4c6f73ee0717
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1235677
milestone48.0a1
Bug 1235677 - Add assertion to catch unsafe concurrent use of AutoEnterOOMUnsafeRegion r=terrence
js/public/Utility.h
js/src/jsutil.cpp
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -3,16 +3,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #ifndef js_Utility_h
 #define js_Utility_h
 
 #include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Compiler.h"
 #include "mozilla/Move.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/TemplateLib.h"
 #include "mozilla/UniquePtr.h"
 
 #include <stdlib.h>
@@ -207,32 +208,37 @@ struct MOZ_RAII AutoEnterOOMUnsafeRegion
     MOZ_NORETURN MOZ_COLD void crash(const char* reason);
 
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     AutoEnterOOMUnsafeRegion()
       : oomEnabled_(oom::IsThreadSimulatingOOM() && oom::maxAllocations != UINT64_MAX),
         oomAfter_(0)
     {
         if (oomEnabled_) {
+            MOZ_ALWAYS_TRUE(owner_.compareExchange(nullptr, this));
             oomAfter_ = int64_t(oom::maxAllocations) - int64_t(oom::counter);
             oom::maxAllocations = UINT64_MAX;
         }
     }
 
     ~AutoEnterOOMUnsafeRegion() {
         if (oomEnabled_) {
             MOZ_ASSERT(oom::maxAllocations == UINT64_MAX);
             int64_t maxAllocations = int64_t(oom::counter) + oomAfter_;
             MOZ_ASSERT(maxAllocations >= 0,
                        "alloc count + oom limit exceeds range, your oom limit is probably too large");
             oom::maxAllocations = uint64_t(maxAllocations);
+            MOZ_ALWAYS_TRUE(owner_.compareExchange(this, nullptr));
         }
     }
 
   private:
+    // Used to catch concurrent use from other threads.
+    static mozilla::Atomic<AutoEnterOOMUnsafeRegion*> owner_;
+
     bool oomEnabled_;
     int64_t oomAfter_;
 #endif
 };
 
 } /* namespace js */
 
 static inline void* js_malloc(size_t bytes)
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -26,16 +26,19 @@
 using namespace js;
 
 using mozilla::CeilingLog2Size;
 using mozilla::PodArrayZero;
 
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
 /* For OOM testing functionality in Utility.h. */
 namespace js {
+
+mozilla::Atomic<AutoEnterOOMUnsafeRegion*> AutoEnterOOMUnsafeRegion::owner_;
+
 namespace oom {
 
 JS_PUBLIC_DATA(uint32_t) targetThread = 0;
 JS_PUBLIC_DATA(MOZ_THREAD_LOCAL(uint32_t)) threadType;
 JS_PUBLIC_DATA(uint64_t) maxAllocations = UINT64_MAX;
 JS_PUBLIC_DATA(uint64_t) counter = 0;
 JS_PUBLIC_DATA(bool) failAlways = true;