Bug 669228 - Don't use the dummy global as a real global. r=jorendorff
authorBlake Kaplan <mrbkap@gmail.com>
Wed, 27 Jul 2011 12:33:33 -0700
changeset 73448 26e80814276e521a4df7e70b50b9fb26605d1c5d
parent 73447 83535f44db38b2a5504a8b95fb1048b65659e1f8
child 73449 3d3f25a67e2418d8989844870bbee849976e3f5a
push id20871
push usereakhgari@mozilla.com
push dateThu, 28 Jul 2011 14:37:48 +0000
treeherdermozilla-central@fe48bbfeff94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs669228
milestone8.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 669228 - Don't use the dummy global as a real global. r=jorendorff
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
@@ -1196,42 +1196,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);
 }
@@ -1263,16 +1272,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
@@ -283,17 +283,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));
                     }