Bug 669228 - Don't use the dummy global as a real global. r=jorendorff a=asa
authorBlake Kaplan <mrbkap@gmail.com>
Wed, 27 Jul 2011 12:33:33 -0700
changeset 72775 25b41e0dcd7d872131f2cc8a1c81449c9d15db3d
parent 72774 454007c65ceae9fc4d290cef6fe7010c3a8b106e
child 72776 e18e32c32fa99897c925cb397466b251f9648a26
push id303
push usermrbkap@mozilla.com
push dateThu, 11 Aug 2011 21:53:00 +0000
treeherdermozilla-aurora@25b41e0dcd7d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff, asa
bugs669228
milestone7.0a2
Bug 669228 - Don't use the dummy global as a real global. r=jorendorff a=asa
js/src/jsapi.cpp
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsdbgapi.h
js/src/xpconnect/src/xpcstack.cpp
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1192,42 +1192,51 @@ JS_EnterCrossCompartmentCall(JSContext *
         return NULL;
     if (!call->enter()) {
         Foreground::delete_(call);
         return NULL;
     }
     return reinterpret_cast<JSCrossCompartmentCall *>(call);
 }
 
+// Declared in jscompartment.h
+JSClass js_dummy_class = {
+    "jdummy",
+    JSCLASS_GLOBAL_FLAGS,
+    JS_PropertyStub,  JS_PropertyStub,
+    JS_PropertyStub,  JS_StrictPropertyStub,
+    JS_EnumerateStub, JS_ResolveStub,
+    JS_ConvertStub,   NULL,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
 JS_PUBLIC_API(JSCrossCompartmentCall *)
 JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target)
 {
-    static JSClass dummy_class = {
-        "jdummy",
-        JSCLASS_GLOBAL_FLAGS,
-        JS_PropertyStub,  JS_PropertyStub,
-        JS_PropertyStub,  JS_StrictPropertyStub,
-        JS_EnumerateStub, JS_ResolveStub,
-        JS_ConvertStub,   NULL,
-        JSCLASS_NO_OPTIONAL_MEMBERS
-    };
-
     CHECK_REQUEST(cx);
 
-    JS_ASSERT(target);
     JSObject *scriptObject = target->u.object;
     if (!scriptObject) {
         SwitchToCompartment sc(cx, target->compartment);
-        scriptObject = JS_NewGlobalObject(cx, &dummy_class);
+        scriptObject = JS_NewGlobalObject(cx, &js_dummy_class);
         if (!scriptObject)
             return NULL;
     }
     return JS_EnterCrossCompartmentCall(cx, scriptObject);
 }
 
+JS_PUBLIC_API(JSCrossCompartmentCall *)
+JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target)
+{
+    CHECK_REQUEST(cx);
+
+    StackFrame *frame = Valueify(target);
+    return JS_EnterCrossCompartmentCall(cx, frame->scopeChain().getGlobal());
+}
+
 JS_PUBLIC_API(void)
 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call)
 {
     AutoCompartment *realcall = reinterpret_cast<AutoCompartment *>(call);
     CHECK_REQUEST(realcall->context);
     realcall->leave();
     Foreground::delete_(realcall);
 }
@@ -1259,16 +1268,29 @@ AutoEnterScriptCompartment::enter(JSCont
     if (cx->compartment == target->compartment) {
         call = reinterpret_cast<JSCrossCompartmentCall*>(1);
         return true;
     }
     call = JS_EnterCrossCompartmentCallScript(cx, target);
     return call != NULL;
 }
 
+bool
+AutoEnterFrameCompartment::enter(JSContext *cx, JSStackFrame *target)
+{
+    JS_ASSERT(!call);
+    js::StackFrame *fp = Valueify(target);
+    if (cx->compartment == fp->scopeChain().compartment()) {
+        call = reinterpret_cast<JSCrossCompartmentCall*>(1);
+        return true;
+    }
+    call = JS_EnterCrossCompartmentCallStackFrame(cx, target);
+    return call != NULL;
+}
+
 } /* namespace JS */
 
 JS_PUBLIC_API(void *)
 JS_SetCompartmentPrivate(JSContext *cx, JSCompartment *compartment, void *data)
 {
     CHECK_REQUEST(cx);
     void *old = compartment->data;
     compartment->data = data;
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -281,17 +281,17 @@ JSCompartment::wrap(JSContext *cx, Value
     }
 
     /* If we already have a wrapper for this value, use it. */
     if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(*vp)) {
         *vp = p->value;
         if (vp->isObject()) {
             JSObject *obj = &vp->toObject();
             JS_ASSERT(IsCrossCompartmentWrapper(obj));
-            if (obj->getParent() != global) {
+            if (global->getJSClass() != &js_dummy_class && obj->getParent() != global) {
                 do {
                     obj->setParent(global);
                     obj = obj->getProto();
                 } while (obj && IsCrossCompartmentWrapper(obj));
             }
         }
         return true;
     }
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -288,16 +288,19 @@ struct TraceMonitor {
     JS_FRIEND_API(size_t) getVMAllocatorsReserveSize() const;
 };
 
 namespace mjit {
 class JaegerCompartment;
 }
 }
 
+/* Defined in jsapi.cpp */
+extern JSClass js_dummy_class;
+
 /* Number of potentially reusable scriptsToGC to search for the eval cache. */
 #ifndef JS_EVAL_CACHE_SHIFT
 # define JS_EVAL_CACHE_SHIFT        6
 #endif
 #define JS_EVAL_CACHE_SIZE          JS_BIT(JS_EVAL_CACHE_SHIFT)
 
 namespace js {
 
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -47,38 +47,48 @@
 #include "jsopcode.h"
 #include "jsprvtd.h"
 
 JS_BEGIN_EXTERN_C
 
 extern JS_PUBLIC_API(JSCrossCompartmentCall *)
 JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target);
 
+extern JS_PUBLIC_API(JSCrossCompartmentCall *)
+JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target);
+
 #ifdef __cplusplus
 JS_END_EXTERN_C
 
 namespace JS {
 
 class JS_PUBLIC_API(AutoEnterScriptCompartment)
 {
+  protected:
     JSCrossCompartmentCall *call;
 
   public:
     AutoEnterScriptCompartment() : call(NULL) {}
 
     bool enter(JSContext *cx, JSScript *target);
 
     bool entered() const { return call != NULL; }
 
     ~AutoEnterScriptCompartment() {
         if (call && call != reinterpret_cast<JSCrossCompartmentCall*>(1))
             JS_LeaveCrossCompartmentCall(call);
     }
 };
 
+class JS_PUBLIC_API(AutoEnterFrameCompartment) : public AutoEnterScriptCompartment
+{
+  public:
+    bool enter(JSContext *cx, JSStackFrame *target);
+};
+
 } /* namespace JS */
 
 JS_BEGIN_EXTERN_C
 #endif
 
 extern JS_PUBLIC_API(JSScript *)
 JS_GetScriptFromObject(JSObject *scriptObject);
 
--- a/js/src/xpconnect/src/xpcstack.cpp
+++ b/js/src/xpconnect/src/xpcstack.cpp
@@ -143,18 +143,18 @@ XPCJSStackFrame::CreateStack(JSContext* 
         }
         else
         {
             self->mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
             JSScript* script = JS_GetFrameScript(cx, fp);
             jsbytecode* pc = JS_GetFramePC(cx, fp);
             if(script && pc)
             {
-                JS::AutoEnterScriptCompartment ac;
-                if(ac.enter(cx, script))
+                JS::AutoEnterFrameCompartment ac;
+                if(ac.enter(cx, fp))
                 {
                     const char* filename = JS_GetScriptFilename(cx, script);
                     if(filename)
                     {
                         self->mFilename = (char*)
                             nsMemory::Clone(filename,
                                             sizeof(char)*(strlen(filename)+1));
                     }