Bug 989528 - Introduce a mechanism to explicitly enter a null compartment. r=luke
authorBobby Holley <bobbyholley@gmail.com>
Mon, 14 Apr 2014 20:26:59 -0700
changeset 178441 b79772297b2e4465643ffc7bc8d9f06c9ed9d45b
parent 178440 81ce5041d5d944ca9c0464cd8703d2e80df64476
child 178442 3c079cc52af9b789e3ef1bf71dbea670d1c3a2cf
push id42280
push userbobbyholley@gmail.com
push dateTue, 15 Apr 2014 03:27:08 +0000
treeherdermozilla-inbound@bcd2cf9e9bdf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs989528
milestone31.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 989528 - Introduce a mechanism to explicitly enter a null compartment. r=luke
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.h
js/src/jscntxtinlines.h
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -979,16 +979,29 @@ JSAutoCompartment::JSAutoCompartment(JSC
     cx_->enterCompartment(target->compartment());
 }
 
 JSAutoCompartment::~JSAutoCompartment()
 {
     cx_->leaveCompartment(oldCompartment_);
 }
 
+JSAutoNullCompartment::JSAutoNullCompartment(JSContext *cx)
+  : cx_(cx),
+    oldCompartment_(cx->compartment())
+{
+    AssertHeapIsIdleOrIterating(cx_);
+    cx_->enterNullCompartment();
+}
+
+JSAutoNullCompartment::~JSAutoNullCompartment()
+{
+    cx_->leaveCompartment(oldCompartment_);
+}
+
 JS_PUBLIC_API(void)
 JS_SetCompartmentPrivate(JSCompartment *compartment, void *data)
 {
     compartment->data = data;
 }
 
 JS_PUBLIC_API(void *)
 JS_GetCompartmentPrivate(JSCompartment *compartment)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1672,16 +1672,25 @@ class JS_PUBLIC_API(JSAutoCompartment)
     JSContext *cx_;
     JSCompartment *oldCompartment_;
   public:
     JSAutoCompartment(JSContext *cx, JSObject *target);
     JSAutoCompartment(JSContext *cx, JSScript *target);
     ~JSAutoCompartment();
 };
 
+class JS_PUBLIC_API(JSAutoNullCompartment)
+{
+    JSContext *cx_;
+    JSCompartment *oldCompartment_;
+  public:
+    JSAutoNullCompartment(JSContext *cx);
+    ~JSAutoNullCompartment();
+};
+
 /* NB: This API is infallible; a nullptr return value does not indicate error. */
 extern JS_PUBLIC_API(JSCompartment *)
 JS_EnterCompartment(JSContext *cx, JSObject *target);
 
 extern JS_PUBLIC_API(void)
 JS_LeaveCompartment(JSContext *cx, JSCompartment *oldCompartment);
 
 typedef void (*JSIterateCompartmentCallback)(JSRuntime *rt, void *data, JSCompartment *compartment);
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -345,16 +345,17 @@ class ExclusiveContext : public ThreadSa
     }
 #ifdef DEBUG
     unsigned getEnterCompartmentDepth() const {
         return enterCompartmentDepth_;
     }
 #endif
 
     inline void enterCompartment(JSCompartment *c);
+    inline void enterNullCompartment();
     inline void leaveCompartment(JSCompartment *oldCompartment);
 
     void setWorkerThread(WorkerThread *workerThread);
     WorkerThread *workerThread() const { return workerThread_; }
 
     // Threads with an ExclusiveContext may freely access any data in their
     // compartment and zone.
     JSCompartment *compartment() const {
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -403,26 +403,34 @@ inline void
 js::ExclusiveContext::enterCompartment(JSCompartment *c)
 {
     enterCompartmentDepth_++;
     c->enter();
     setCompartment(c);
 }
 
 inline void
+js::ExclusiveContext::enterNullCompartment()
+{
+    enterCompartmentDepth_++;
+    setCompartment(nullptr);
+}
+
+inline void
 js::ExclusiveContext::leaveCompartment(JSCompartment *oldCompartment)
 {
     JS_ASSERT(hasEnteredCompartment());
     enterCompartmentDepth_--;
 
     // Only call leave() after we've setCompartment()-ed away from the current
     // compartment.
     JSCompartment *startingCompartment = compartment_;
     setCompartment(oldCompartment);
-    startingCompartment->leave();
+    if (startingCompartment)
+        startingCompartment->leave();
 }
 
 inline void
 js::ExclusiveContext::setCompartment(JSCompartment *comp)
 {
     // ExclusiveContexts can only be in the atoms zone or in exclusive zones.
     JS_ASSERT_IF(!isJSContext() && !runtime_->isAtomsCompartment(comp),
                  comp->zone()->usedByExclusiveThread);