Bug 880697 - Stop using clunky C API in JSD and start using RAII classes. r=gabor
authorBobby Holley <bobbyholley@gmail.com>
Wed, 12 Jun 2013 14:17:54 -0700
changeset 146359 56c790b9bdcc5b0dc09c4d7ee549831d68332fe3
parent 146358 77b50dfb8b1784f5d616ec4ee21d124aeced05c6
child 146360 d775f43176c84b2fb50dc528c868a9b60daf8cf2
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgabor
bugs880697
milestone24.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 880697 - Stop using clunky C API in JSD and start using RAII classes. r=gabor
js/jsd/jsd_scpt.cpp
js/jsd/jsd_val.cpp
--- a/js/jsd/jsd_scpt.cpp
+++ b/js/jsd/jsd_scpt.cpp
@@ -499,48 +499,47 @@ jsd_GetScriptLineExtent(JSDContext* jsdc
         jsdscript->lineExtent = JS_GetScriptLineExtent(jsdc->dumbContext, jsdscript->script);
     return jsdscript->lineExtent;
 }
 
 uintptr_t
 jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, unsigned line)
 {
     uintptr_t pc;
-    JSCompartment *oldCompartment;
 
     if( !jsdscript )
         return 0;
 #ifdef LIVEWIRE
     if( jsdscript->lwscript )
     {
         unsigned newline;
         jsdlw_RawToProcessedLineNumber(jsdc, jsdscript, line, &newline);
         if( line != newline )
             line = newline;
     }
 #endif
 
-    oldCompartment = JS_EnterCompartmentOfScript(jsdc->dumbContext, jsdscript->script);
-    pc = (uintptr_t) JS_LineNumberToPC(jsdc->dumbContext, jsdscript->script, line );
-    JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
+    JSContext *cx = jsdc->dumbContext;
+    JSAutoCompartment ac(cx, jsdscript->script);
+    pc = (uintptr_t) JS_LineNumberToPC(cx, jsdscript->script, line );
     return pc;
 }
 
 unsigned
 jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, uintptr_t pc)
 {
-    JSCompartment* oldCompartment;
     unsigned first = jsdscript->lineBase;
     unsigned last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1;
     unsigned line = 0;
 
-    oldCompartment = JS_EnterCompartmentOfScript(jsdc->dumbContext, jsdscript->script);
-    if (pc)
+    if (pc) {
+        JSContext *cx = jsdc->dumbContext;
+        JSAutoCompartment ac(cx, jsdscript->script);
         line = JS_PCToLineNumber(jsdc->dumbContext, jsdscript->script, (jsbytecode*)pc);
-    JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
+    }
 
     if( line < first )
         return first;
     if( line > last )
         return last;
 
 #ifdef LIVEWIRE
     if( jsdscript && jsdscript->lwscript )
@@ -554,43 +553,42 @@ jsd_GetClosestLine(JSDContext* jsdc, JSD
     return line;    
 }
 
 JSBool
 jsd_GetLinePCs(JSDContext* jsdc, JSDScript* jsdscript,
                unsigned startLine, unsigned maxLines,
                unsigned* count, unsigned** retLines, uintptr_t** retPCs)
 {
-    JSCompartment* oldCompartment;
     unsigned first = jsdscript->lineBase;
     unsigned last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1;
     JSBool ok;
     jsbytecode **pcs;
     unsigned i;
 
     if (last < startLine)
         return JS_TRUE;
 
-    oldCompartment = JS_EnterCompartmentOfScript(jsdc->dumbContext, jsdscript->script);
+    JSContext *cx = jsdc->dumbContext;
+    JSAutoCompartment ac(cx, jsdscript->script);
 
     ok = JS_GetLinePCs(jsdc->dumbContext, jsdscript->script,
                        startLine, maxLines,
                        count, retLines, &pcs);
 
     if (ok) {
         if (retPCs) {
             for (i = 0; i < *count; ++i) {
                 (*retPCs)[i] = (*pcs)[i];
             }
         }
 
         JS_free(jsdc->dumbContext, pcs);
     }
 
-    JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
     return ok;
 }
 
 JSBool
 jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata)
 {
     JSD_LOCK();
     jsdc->scriptHook = hook;
@@ -609,23 +607,22 @@ jsd_GetScriptHook(JSDContext* jsdc, JSD_
         *callerdata = jsdc->scriptHookData;
     JSD_UNLOCK();
     return JS_TRUE;
 }    
 
 JSBool
 jsd_EnableSingleStepInterrupts(JSDContext* jsdc, JSDScript* jsdscript, JSBool enable)
 {
-    JSCompartment* oldCompartment;
     JSBool rv;
-    oldCompartment = JS_EnterCompartmentOfScript(jsdc->dumbContext, jsdscript->script);
+    JSContext *cx = jsdc->dumbContext;
+    JSAutoCompartment ac(cx, jsdscript->script);
     JSD_LOCK();
     rv = JS_SetSingleStepMode(jsdc->dumbContext, jsdscript->script, enable);
     JSD_UNLOCK();
-    JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
     return rv;
 }
 
 
 /***************************************************************************/
 
 void
 jsd_NewScriptHookProc( 
@@ -825,17 +822,16 @@ JSBool
 jsd_SetExecutionHook(JSDContext*           jsdc, 
                      JSDScript*            jsdscript,
                      uintptr_t             pc,
                      JSD_ExecutionHookProc hook,
                      void*                 callerdata)
 {
     JSDExecHook* jsdhook;
     JSBool rv;
-    JSCompartment* oldCompartment;
 
     JSD_LOCK();
     if( ! hook )
     {
         jsd_ClearExecutionHook(jsdc, jsdscript, pc);
         JSD_UNLOCK();
         return JS_TRUE;
     }
@@ -855,23 +851,23 @@ jsd_SetExecutionHook(JSDContext*        
         JSD_UNLOCK();
         return JS_FALSE;
     }
     jsdhook->jsdscript  = jsdscript;
     jsdhook->pc         = pc;
     jsdhook->hook       = hook;
     jsdhook->callerdata = callerdata;
 
-    oldCompartment = JS_EnterCompartmentOfScript(jsdc->dumbContext, jsdscript->script);
-
-    rv = JS_SetTrap(jsdc->dumbContext, jsdscript->script, 
-                    (jsbytecode*)pc, jsd_TrapHandler,
-                    PRIVATE_TO_JSVAL(jsdhook));
-
-    JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
+    {
+        JSContext *cx = jsdc->dumbContext;
+        JSAutoCompartment ac(cx, jsdscript->script);
+        rv = JS_SetTrap(cx, jsdscript->script, 
+                        (jsbytecode*)pc, jsd_TrapHandler,
+                        PRIVATE_TO_JSVAL(jsdhook));
+    }
 
     if ( ! rv ) {
         free(jsdhook);
         JSD_UNLOCK();
         return JS_FALSE;
     }
 
     JS_APPEND_LINK(&jsdhook->links, &jsdscript->hooks);
@@ -880,34 +876,33 @@ jsd_SetExecutionHook(JSDContext*        
     return JS_TRUE;
 }
 
 JSBool
 jsd_ClearExecutionHook(JSDContext*           jsdc, 
                        JSDScript*            jsdscript,
                        uintptr_t             pc)
 {
-    JSCompartment* oldCompartment;
     JSDExecHook* jsdhook;
 
     JSD_LOCK();
 
     jsdhook = _findHook(jsdc, jsdscript, pc);
     if( ! jsdhook )
     {
         JSD_UNLOCK();
         return JS_FALSE;
     }
 
-    oldCompartment = JS_EnterCompartmentOfScript(jsdc->dumbContext, jsdscript->script);
-
-    JS_ClearTrap(jsdc->dumbContext, jsdscript->script, 
-                 (jsbytecode*)pc, NULL, NULL );
-
-    JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
+    {
+        JSContext *cx = jsdc->dumbContext;
+        JSAutoCompartment ac(cx, jsdscript->script);
+        JS_ClearTrap(jsdc->dumbContext, jsdscript->script, 
+                     (jsbytecode*)pc, NULL, NULL );
+    }
 
     JS_REMOVE_LINK(&jsdhook->links);
     free(jsdhook);
 
     JSD_UNLOCK();
     return JS_TRUE;
 }
 
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -114,32 +114,27 @@ jsd_IsValueFunction(JSDContext* jsdc, JS
     return !JSVAL_IS_PRIMITIVE(jsdval->val) &&
            JS_ObjectIsCallable(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
 }
 
 JSBool
 jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSContext* cx = jsdc->dumbContext;
+    JSAutoRequest ar(cx);
     JS::RootedFunction fun(cx);
-    JSExceptionState* exceptionState;
-    JSCompartment* oldCompartment = NULL;
 
     if(jsd_IsValueFunction(jsdc, jsdval))
     {
+        JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(jsdval->val));
+        AutoSaveExceptionState as(cx);
         JSBool ok = JS_FALSE;
-        JS_BeginRequest(cx);
-        oldCompartment = JS_EnterCompartment(cx, JSVAL_TO_OBJECT(jsdval->val));
-        exceptionState = JS_SaveExceptionState(cx);
         fun = JSD_GetValueFunction(jsdc, jsdval);
-        JS_RestoreExceptionState(cx, exceptionState);
         if(fun)
             ok = JS_GetFunctionScript(cx, fun) ? JS_FALSE : JS_TRUE;
-        JS_LeaveCompartment(cx, oldCompartment);
-        JS_EndRequest(cx);
         JS_ASSERT(fun);
         return ok;
     }
     return !JSVAL_IS_PRIMITIVE(jsdval->val);
 }
 
 /***************************************************************************/
 
@@ -168,83 +163,65 @@ jsd_GetValueDouble(JSDContext* jsdc, JSD
         return 0;
     return JSVAL_TO_DOUBLE(jsdval->val);
 }
 
 JSString*
 jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSContext* cx = jsdc->dumbContext;
-    JSExceptionState* exceptionState;
-    JSCompartment* oldCompartment = NULL;
+    JSAutoRequest ar(cx);
     JS::RootedValue stringval(cx);
     JS::RootedString string(cx);
     JS::RootedObject scopeObj(cx);
 
     if(jsdval->string)
         return jsdval->string;
 
     /* Reuse the string without copying or re-rooting it */
     if(JSVAL_IS_STRING(jsdval->val)) {
         jsdval->string = JSVAL_TO_STRING(jsdval->val);
         return jsdval->string;
     }
 
-    JS_BeginRequest(cx);
-
     /* Objects call JS_ValueToString in their own compartment. */
     scopeObj = !JSVAL_IS_PRIMITIVE(jsdval->val) ? JSVAL_TO_OBJECT(jsdval->val) : jsdc->glob;
-    oldCompartment = JS_EnterCompartment(cx, scopeObj);
-    exceptionState = JS_SaveExceptionState(cx);
-
-    string = JS_ValueToString(cx, jsdval->val);
+    {
+        JSAutoCompartment ac(cx, scopeObj);
+        AutoSaveExceptionState as(cx);
+        string = JS_ValueToString(cx, jsdval->val);
+    }
 
-    JS_RestoreExceptionState(cx, exceptionState);
-    JS_LeaveCompartment(cx, oldCompartment);
-    oldCompartment = NULL;
-
+    JSAutoCompartment ac2(cx, jsdc->glob);
     if(string) {
         stringval = STRING_TO_JSVAL(string);
-        oldCompartment = JS_EnterCompartment(cx, jsdc->glob);
     }
     if(!string || !JS_WrapValue(cx, stringval.address())) {
-        if(oldCompartment)
-            JS_LeaveCompartment(cx, oldCompartment);
-        JS_EndRequest(cx);
         return NULL;
     }
 
     jsdval->string = JSVAL_TO_STRING(stringval);
     if(!JS_AddNamedStringRoot(cx, &jsdval->string, "ValueString"))
         jsdval->string = NULL;
 
-    JS_LeaveCompartment(cx, oldCompartment);
-    JS_EndRequest(cx);
-
     return jsdval->string;
 }
 
 JSString*
 jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSContext* cx = jsdc->dumbContext;
+    JSAutoRequest ar(cx);
     JS::RootedFunction fun(cx);
-    JSExceptionState* exceptionState;
-    JSCompartment* oldCompartment = NULL;
 
     if(!jsdval->funName && jsd_IsValueFunction(jsdc, jsdval))
     {
-        JS_BeginRequest(cx);
-
-        oldCompartment = JS_EnterCompartment(jsdc->dumbContext, JSVAL_TO_OBJECT(jsdval->val));
-        exceptionState = JS_SaveExceptionState(cx);
+        JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(jsdval->val));
+        AutoSaveExceptionState as(cx);
         fun = JSD_GetValueFunction(jsdc, jsdval);
-        JS_RestoreExceptionState(cx, exceptionState);
-        JS_LeaveCompartment(cx, oldCompartment);
-        JS_EndRequest(cx);
         if(!fun)
             return NULL;
         jsdval->funName = JS_GetFunctionId(fun);
 
         /* For compatibility we return "anonymous", not an empty string here. */
         if (!jsdval->funName)
             jsdval->funName = JS_GetAnonymousString(jsdc->jsrt);
     }
@@ -257,67 +234,59 @@ jsd_GetValueFunctionId(JSDContext* jsdc,
  * Create a new JSD value referring to a jsval. Copy string values into the
  * JSD compartment. Leave all other GCTHINGs in their native compartments
  * and access them through cross-compartment calls.
  */
 JSDValue*
 jsd_NewValue(JSDContext* jsdc, jsval value)
 {
     JS::RootedValue val(jsdc->dumbContext, value);
+    JSAutoRequest ar(jsdc->dumbContext);
     JSDValue* jsdval;
-    JSCompartment* oldCompartment = NULL;
 
     if(!(jsdval = (JSDValue*) calloc(1, sizeof(JSDValue))))
         return NULL;
 
     if(JSVAL_IS_GCTHING(val))
     {
         JSBool ok;
-        JS_BeginRequest(jsdc->dumbContext);
-
-        oldCompartment = JS_EnterCompartment(jsdc->dumbContext, jsdc->glob);
+        JSAutoCompartment ac(jsdc->dumbContext, jsdc->glob);
 
         ok = JS_AddNamedValueRoot(jsdc->dumbContext, &jsdval->val, "JSDValue");
         if(ok && JSVAL_IS_STRING(val)) {
             if(!JS_WrapValue(jsdc->dumbContext, val.address())) {
                 ok = JS_FALSE;
             }
         }
 
-        JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
-        JS_EndRequest(jsdc->dumbContext);
         if(!ok)
         {
             free(jsdval);
             return NULL;
         }
     }
     jsdval->val  = val;
     jsdval->nref = 1;
     JS_INIT_CLIST(&jsdval->props);
 
     return jsdval;
 }
 
 void
 jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval)
 {
-    JSCompartment* oldCompartment = NULL;
-
     JS_ASSERT(jsdval->nref > 0);
     if(0 == --jsdval->nref)
     {
         jsd_RefreshValue(jsdc, jsdval);
         if(JSVAL_IS_GCTHING(jsdval->val))
         {
-            JS_BeginRequest(jsdc->dumbContext);
-            oldCompartment = JS_EnterCompartment(jsdc->dumbContext, jsdc->glob);
+            JSAutoRequest ar(jsdc->dumbContext);
+            JSAutoCompartment ac(jsdc->dumbContext, jsdc->glob);
             JS_RemoveValueRoot(jsdc->dumbContext, &jsdval->val);
-            JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
-            JS_EndRequest(jsdc->dumbContext);
         }
         free(jsdval);
     }
 }
 
 jsval
 jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval)
 {
@@ -379,76 +348,67 @@ static void _freeProps(JSDContext* jsdc,
     }
     JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
     CLEAR_BIT_FLAG(jsdval->flags, GOT_PROPS);
 }
 
 static JSBool _buildProps(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSContext* cx = jsdc->dumbContext;
+    JSAutoRequest ar(cx);
     JS::RootedObject obj(cx);
     JSPropertyDescArray pda;
     unsigned i;
-    JSCompartment* oldCompartment = NULL;
 
     JS_ASSERT(JS_CLIST_IS_EMPTY(&jsdval->props));
     JS_ASSERT(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PROPS)));
     JS_ASSERT(!JSVAL_IS_PRIMITIVE(jsdval->val));
 
     if(JSVAL_IS_PRIMITIVE(jsdval->val))
         return JS_FALSE;
 
     obj = JSVAL_TO_OBJECT(jsdval->val);
 
-    JS_BeginRequest(cx);
-    oldCompartment = JS_EnterCompartment(jsdc->dumbContext, obj);
+    JSAutoCompartment ac(cx, obj);
 
     if(!JS_GetPropertyDescArray(cx, obj, &pda))
     {
-        JS_EndRequest(cx);
-        JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
         return JS_FALSE;
     }
 
     for(i = 0; i < pda.length; i++)
     {
         JSDProperty* prop = _newProperty(jsdc, &pda.array[i], 0);
         if(!prop)
         {
             _freeProps(jsdc, jsdval);
             break;
         }
         JS_APPEND_LINK(&prop->links, &jsdval->props);
     }
     JS_PutPropertyDescArray(cx, &pda);
-    JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
-    JS_EndRequest(cx);
     SET_BIT_FLAG(jsdval->flags, GOT_PROPS);
     return !JS_CLIST_IS_EMPTY(&jsdval->props);
 }
 
 #undef  DROP_CLEAR_VALUE
 #define DROP_CLEAR_VALUE(jsdc, x) if(x){jsd_DropValue(jsdc,x); x = NULL;}
 
 void
 jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSContext* cx = jsdc->dumbContext;
-    JSCompartment* oldCompartment = NULL;
-
+    JSAutoRequest ar(cx);
     if(jsdval->string)
     {
         /* if the jsval is a string, then we didn't need to root the string */
         if(!JSVAL_IS_STRING(jsdval->val))
         {
-            JS_BeginRequest(cx);
-            oldCompartment = JS_EnterCompartment(cx, jsdc->glob);
+            JSAutoCompartment ac(cx, jsdc->glob);
             JS_RemoveStringRoot(cx, &jsdval->string);
-            JS_LeaveCompartment(cx, oldCompartment);
-            JS_EndRequest(cx);
         }
         jsdval->string = NULL;
     }
 
     jsdval->funName = NULL;
     jsdval->className = NULL;
     DROP_CLEAR_VALUE(jsdc, jsdval->proto);
     DROP_CLEAR_VALUE(jsdc, jsdval->parent);
@@ -499,28 +459,28 @@ jsd_IterateProperties(JSDContext* jsdc, 
     jsdprop->nref++;
     return jsdprop;
 }
 
 JSDProperty*
 jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* nameStr)
 {
     JSContext* cx = jsdc->dumbContext;
+    JSAutoRequest ar(cx);
     JSDProperty* jsdprop;
     JSDProperty* iter = NULL;
     JS::RootedObject obj(cx);
     JS::RootedString name(cx, nameStr);
     unsigned  attrs = 0;
     JSBool found;
     JSPropertyDesc pd;
     const jschar * nameChars;
     size_t nameLen;
     JS::RootedValue val(cx), nameval(cx);
     JS::RootedId nameid(cx);
-    JSCompartment* oldCompartment = NULL;
 
     if(!jsd_IsValueObject(jsdc, jsdval))
         return NULL;
 
     /* If we already have the prop, then return it */
     while(NULL != (jsdprop = jsd_IterateProperties(jsdc, jsdval, &iter)))
     {
         JSString* propName = jsd_GetValueString(jsdc, jsdprop->name);
@@ -534,54 +494,48 @@ jsd_GetValueProperty(JSDContext* jsdc, J
     /* Not found in property list, look it up explicitly */
 
     if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
         return NULL;
 
     if (!(nameChars = JS_GetStringCharsZAndLength(cx, name, &nameLen)))
         return NULL;
 
-    JS_BeginRequest(cx);
-    oldCompartment = JS_EnterCompartment(cx, obj);
+    {
+        JSAutoCompartment ac(cx, obj);
 
-    JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
-    if (!found)
-    {
-        JS_LeaveCompartment(cx, oldCompartment);
-        JS_EndRequest(cx);
-        return NULL;
-    }
+        JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
+        if (!found)
+        {
+            return NULL;
+        }
+
+        JS_ClearPendingException(cx);
 
-    JS_ClearPendingException(cx);
-
-    if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, val.address()))
-    {
-        if (JS_IsExceptionPending(cx))
+        if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, val.address()))
         {
-            if (!JS_GetPendingException(cx, &pd.value))
+            if (JS_IsExceptionPending(cx))
             {
-                JS_LeaveCompartment(cx, oldCompartment);
-                JS_EndRequest(cx);
-                return NULL;
+                if (!JS_GetPendingException(cx, &pd.value))
+                {
+                    return NULL;
+                }
+                pd.flags = JSPD_EXCEPTION;
             }
-            pd.flags = JSPD_EXCEPTION;
+            else
+            {
+                pd.flags = JSPD_ERROR;
+                pd.value = JSVAL_VOID;
+            }
         }
         else
         {
-            pd.flags = JSPD_ERROR;
-            pd.value = JSVAL_VOID;
+            pd.value = val;
         }
     }
-    else
-    {
-        pd.value = val;
-    }
-
-    JS_LeaveCompartment(cx, oldCompartment);
-    JS_EndRequest(cx);
 
     nameval = STRING_TO_JSVAL(name);
     if (!JS_ValueToId(cx, nameval, nameid.address()) ||
         !JS_IdToValue(cx, nameid, &pd.id)) {
         return NULL;
     }
 
     pd.spare = 0;
@@ -600,24 +554,22 @@ jsd_GetValueProperty(JSDContext* jsdc, J
 JSFunction*
 jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSContext* cx = jsdc->dumbContext;
 
     JS::RootedObject obj(cx);
     JS::RootedFunction fun(cx);
 
-    JSCompartment* oldCompartment = NULL;
     if (JSVAL_IS_PRIMITIVE(jsdval->val))
         return NULL;
 
     obj = js::UncheckedUnwrap(JSVAL_TO_OBJECT(jsdval->val));
-    oldCompartment = JS_EnterCompartment(cx, obj);
+    JSAutoCompartment ac(cx, obj);
     fun = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj));
-    JS_LeaveCompartment(cx, oldCompartment);
 
     return fun;
 }
 
 JSDValue*
 jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSContext* cx = jsdc->dumbContext;
@@ -639,120 +591,110 @@ jsd_GetValuePrototype(JSDContext* jsdc, 
     if(jsdval->proto)
         jsdval->proto->nref++;
     return jsdval->proto;
 }
 
 JSDValue*
 jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval)
 {
-    JSCompartment* oldCompartment = NULL;
-
     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT)))
     {
         JSContext* cx = jsdc->dumbContext;
+        JSAutoRequest ar(cx);
 
         JS::RootedObject obj(cx);
         JS::RootedObject parent(cx);
         JS_ASSERT(!jsdval->parent);
         SET_BIT_FLAG(jsdval->flags, GOT_PARENT);
         if(JSVAL_IS_PRIMITIVE(jsdval->val))
             return NULL;
         obj = JSVAL_TO_OBJECT(jsdval->val);
-        JS_BeginRequest(jsdc->dumbContext);
-        oldCompartment = JS_EnterCompartment(jsdc->dumbContext, obj);
-        parent = JS_GetParentOrScopeChain(jsdc->dumbContext,obj);
-        JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
-        JS_EndRequest(jsdc->dumbContext);
+        {
+            JSAutoCompartment ac(cx, obj);
+            parent = JS_GetParentOrScopeChain(jsdc->dumbContext,obj);
+        }
         if(!parent)
             return NULL;
         jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent));
     }
     if(jsdval->parent)
         jsdval->parent->nref++;
     return jsdval->parent;
 }
 
 JSDValue*
 jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval)
 {
-    JSCompartment* oldCompartment = NULL;
     JSContext* cx = jsdc->dumbContext;
+    JSAutoRequest ar(cx);
 
     if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_CTOR)))
     {
         JS::RootedObject obj(cx);
         JS::RootedObject proto(cx);
         JS::RootedObject ctor(cx);
         JS_ASSERT(!jsdval->ctor);
         SET_BIT_FLAG(jsdval->flags, GOT_CTOR);
         if(JSVAL_IS_PRIMITIVE(jsdval->val))
             return NULL;
         obj = JSVAL_TO_OBJECT(jsdval->val);
         if(!JS_GetPrototype(cx, obj, proto.address()))
             return NULL;
         if(!proto)
             return NULL;
-        JS_BeginRequest(jsdc->dumbContext);
-        oldCompartment = JS_EnterCompartment(jsdc->dumbContext, obj);
-        ctor = JS_GetConstructor(jsdc->dumbContext,proto);
-        JS_LeaveCompartment(jsdc->dumbContext, oldCompartment);
-        JS_EndRequest(jsdc->dumbContext);
+        {
+            JSAutoCompartment ac(cx, obj);
+            ctor = JS_GetConstructor(jsdc->dumbContext,proto);
+        }
         if(!ctor)
             return NULL;
         jsdval->ctor = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(ctor));
     }
     if(jsdval->ctor)
         jsdval->ctor->nref++;
     return jsdval->ctor;
 }
 
 const char*
 jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval)
 {
     jsval val = jsdval->val;
-    JSCompartment* oldCompartment = NULL;
-
     if(!jsdval->className && !JSVAL_IS_PRIMITIVE(val))
     {
         JSContext* cx = jsdc->dumbContext;
+        JSAutoRequest ar(cx);
 
         JS::RootedObject obj(cx, JSVAL_TO_OBJECT(val));
-        JS_BeginRequest(cx);
-        oldCompartment = JS_EnterCompartment(cx, obj);
+        JSAutoCompartment ac(cx, obj);
         jsdval->className = JS_GetDebugClassName(obj);
-        JS_LeaveCompartment(cx, oldCompartment);
-        JS_EndRequest(cx);
     }
     return jsdval->className;
 }
 
 JSDScript*
 jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSContext* cx = jsdc->dumbContext;
+    JSAutoRequest ar(cx);
     JS::RootedValue val(cx, jsdval->val);
     JSFunction* fun = NULL;
-    JSExceptionState* exceptionState;
     JS::RootedScript script(cx);
     JSDScript* jsdscript;
-    JSCompartment* oldCompartment = NULL;
 
     if (!jsd_IsValueFunction(jsdc, jsdval))
         return NULL;
 
-    JS_BeginRequest(cx);
-    oldCompartment = JS_EnterCompartment(cx, JSVAL_TO_OBJECT(val));
-    exceptionState = JS_SaveExceptionState(cx);
-    fun = JSD_GetValueFunction(jsdc, jsdval);
-    JS_RestoreExceptionState(cx, exceptionState);
-    if (fun)
-        script = JS_GetFunctionScript(cx, fun);
-    JS_LeaveCompartment(cx, oldCompartment);
-    JS_EndRequest(cx);
+    {
+        JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(val));
+        AutoSaveExceptionState as(cx);
+        fun = JSD_GetValueFunction(jsdc, jsdval);
+        if (fun)
+            script = JS_GetFunctionScript(cx, fun);
+    }
 
     if (!script)
         return NULL;
 
     JSD_LOCK_SCRIPTS(jsdc);
     jsdscript = jsd_FindJSDScript(jsdc, script);
     JSD_UNLOCK_SCRIPTS(jsdc);
     return jsdscript;