Bug 614578 - Removal of nsAutoGCRoot. r=mrbkap
authorIgor Bukanov <igor@mir2.org>
Fri, 26 Nov 2010 15:11:14 +0100
changeset 58977 fc0384edf67bc8dbc7c502a1f56481e7dbf98025
parent 58976 e35b70ffed69cf1729e8ba7dff19bbe974e9e52b
child 58978 98adda4dcc9c9e6c6df157bab8e37b3320261d09
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersmrbkap
bugs614578
milestone2.0b8pre
Bug 614578 - Removal of nsAutoGCRoot. r=mrbkap
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/base/src/nsFrameMessageManager.cpp
content/events/src/nsEventListenerService.cpp
content/xbl/src/nsXBLProtoImplField.cpp
content/xbl/src/nsXBLProtoImplMember.h
content/xbl/src/nsXBLProtoImplMethod.cpp
content/xbl/src/nsXBLProtoImplProperty.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
dom/src/jsurl/nsJSProtocolHandler.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/xpconnect/src/XPCDispTearOff.cpp
js/src/xpconnect/src/xpcwrappedjsclass.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1842,58 +1842,16 @@ private:
   nsCOMPtr<nsIScriptContext> mScx;
   PRBool mScriptIsRunning;
   PRBool mPushedSomething;
 #ifdef DEBUG
   JSContext* mPushedContext;
 #endif
 };
 
-class NS_STACK_CLASS nsAutoGCRoot {
-public:
-  // aPtr should be the pointer to the jsval we want to protect
-  nsAutoGCRoot(jsval* aPtr, nsresult* aResult
-               MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM) :
-    mPtr(aPtr), mRootType(RootType_JSVal)
-  {
-    MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
-    mResult = *aResult = AddJSGCRoot(aPtr, RootType_JSVal, "nsAutoGCRoot");
-  }
-
-  // aPtr should be the pointer to the JSObject* we want to protect
-  nsAutoGCRoot(JSObject** aPtr, nsresult* aResult
-               MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM) :
-    mPtr(aPtr), mRootType(RootType_Object)
-  {
-    MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
-    mResult = *aResult = AddJSGCRoot(aPtr, RootType_Object, "nsAutoGCRoot");
-  }
-
-  ~nsAutoGCRoot() {
-    if (NS_SUCCEEDED(mResult)) {
-      RemoveJSGCRoot((jsval *)mPtr, mRootType);
-    }
-  }
-
-  static void Shutdown();
-
-private:
-  enum RootType { RootType_JSVal, RootType_Object };
-  static nsresult AddJSGCRoot(void *aPtr, RootType aRootType, const char* aName);
-  static nsresult RemoveJSGCRoot(void *aPtr, RootType aRootType);
-
-  static nsIJSRuntimeService* sJSRuntimeService;
-  static JSRuntime* sJSScriptRuntime;
-
-  void* mPtr;
-  RootType mRootType;
-  nsresult mResult;
-  MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
-};
-
 class NS_STACK_CLASS nsAutoScriptBlocker {
 public:
   nsAutoScriptBlocker(MOZILLA_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
     MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
     nsContentUtils::AddScriptBlocker();
   }
   ~nsAutoScriptBlocker() {
     nsContentUtils::RemoveScriptBlocker();
@@ -1911,23 +1869,16 @@ public:
 
 private:
   PRUint32 mNestingLevel;
   nsCOMPtr<nsIDocument> mDocument;
   nsCOMPtr<nsIDocumentObserver> mObserver;
   MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
-#define NS_AUTO_GCROOT_PASTE2(tok,line) tok##line
-#define NS_AUTO_GCROOT_PASTE(tok,line) \
-  NS_AUTO_GCROOT_PASTE2(tok,line)
-#define NS_AUTO_GCROOT(ptr, result) \ \
-  nsAutoGCRoot NS_AUTO_GCROOT_PASTE(_autoGCRoot_, __LINE__) \
-  (ptr, result)
-
 #define NS_INTERFACE_MAP_ENTRY_TEAROFF(_interface, _allocator)                \
   if (aIID.Equals(NS_GET_IID(_interface))) {                                  \
     foundInterface = static_cast<_interface *>(_allocator);                   \
     if (!foundInterface) {                                                    \
       *aInstancePtr = nsnull;                                                 \
       return NS_ERROR_OUT_OF_MEMORY;                                          \
     }                                                                         \
   } else
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -255,19 +255,16 @@ nsIBidiKeyboard *nsContentUtils::sBidiKe
 #endif
 PRUint32 nsContentUtils::sScriptBlockerCount = 0;
 PRUint32 nsContentUtils::sRemovableScriptBlockerCount = 0;
 nsCOMArray<nsIRunnable>* nsContentUtils::sBlockedScriptRunners = nsnull;
 PRUint32 nsContentUtils::sRunnersCountAtFirstBlocker = 0;
 PRUint32 nsContentUtils::sScriptBlockerCountWhereRunnersPrevented = 0;
 nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nsnull;
 
-nsIJSRuntimeService *nsAutoGCRoot::sJSRuntimeService;
-JSRuntime *nsAutoGCRoot::sJSScriptRuntime;
-
 PRBool nsContentUtils::sIsHandlingKeyBoardEvent = PR_FALSE;
 PRBool nsContentUtils::sAllowXULXBL_for_file = PR_FALSE;
 
 PRBool nsContentUtils::sInitialized = PR_FALSE;
 
 nsRefPtrHashtable<nsPrefObserverHashKey, nsPrefOldCallback>
   *nsContentUtils::sPrefCallbackTable = nsnull;
 
@@ -1206,18 +1203,16 @@ nsContentUtils::Shutdown()
   NS_ASSERTION(!sBlockedScriptRunners ||
                sBlockedScriptRunners->Count() == 0,
                "How'd this happen?");
   delete sBlockedScriptRunners;
   sBlockedScriptRunners = nsnull;
 
   NS_IF_RELEASE(sSameOriginChecker);
   
-  nsAutoGCRoot::Shutdown();
-
   nsTextEditorState::ShutDown();
 }
 
 // static
 PRBool
 nsContentUtils::IsCallerTrustedForCapability(const char* aCapability)
 {
   // The secman really should handle UniversalXPConnect case, since that
@@ -3271,63 +3266,16 @@ nsContentUtils::GetContentPolicy()
     // It's OK to not have a content policy service
     sTriedToGetContentPolicy = PR_TRUE;
   }
 
   return sContentPolicyService;
 }
 
 // static
-nsresult
-nsAutoGCRoot::AddJSGCRoot(void* aPtr, RootType aRootType, const char* aName)
-{
-  if (!sJSScriptRuntime) {
-    nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
-                                 &sJSRuntimeService);
-    NS_ENSURE_TRUE(sJSRuntimeService, rv);
-
-    sJSRuntimeService->GetRuntime(&sJSScriptRuntime);
-    if (!sJSScriptRuntime) {
-      NS_RELEASE(sJSRuntimeService);
-      NS_WARNING("Unable to get JS runtime from JS runtime service");
-      return NS_ERROR_FAILURE;
-    }
-  }
-
-  PRBool ok;
-  if (aRootType == RootType_JSVal)
-    ok = ::js_AddRootRT(sJSScriptRuntime, (jsval *)aPtr, aName);
-  else
-    ok = ::js_AddGCThingRootRT(sJSScriptRuntime, (void **)aPtr, aName);
-  if (!ok) {
-    NS_WARNING("JS_AddNamedRootRT failed");
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  return NS_OK;
-}
-
-/* static */
-nsresult
-nsAutoGCRoot::RemoveJSGCRoot(void* aPtr, RootType aRootType)
-{
-  if (!sJSScriptRuntime) {
-    NS_NOTREACHED("Trying to remove a JS GC root when none were added");
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  if (aRootType == RootType_JSVal)
-    ::js_RemoveRoot(sJSScriptRuntime, (jsval *)aPtr);
-  else
-    ::js_RemoveRoot(sJSScriptRuntime, (JSObject **)aPtr);
-
-  return NS_OK;
-}
-
-// static
 PRBool
 nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType)
 {
   const PRUnichar* name = aName->GetUTF16String();
   if (name[0] != 'o' || name[1] != 'n')
     return PR_FALSE;
 
   EventNameMapping mapping;
@@ -5180,23 +5128,16 @@ nsContentUtils::EqualsIgnoreASCIICase(co
       }
     }
   }
 
   return PR_TRUE;
 }
 
 /* static */
-void
-nsAutoGCRoot::Shutdown()
-{
-  NS_IF_RELEASE(sJSRuntimeService);
-}
-
-/* static */
 nsIInterfaceRequestor*
 nsContentUtils::GetSameOriginChecker()
 {
   if (!sSameOriginChecker) {
     sSameOriginChecker = new nsSameOriginChecker();
     NS_IF_ADDREF(sSameOriginChecker);
   }
   return sSameOriginChecker;
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -208,18 +208,16 @@ nsFrameMessageManager::GetParamsForMessa
   JSAutoRequest ar(ctx);
   JSString* str;
   if (argc && (str = JS_ValueToString(ctx, argv[0])) && str) {
     aMessageName.Assign(nsDependentJSString(str));
   }
 
   if (argc >= 2) {
     jsval v = argv[1];
-    nsAutoGCRoot root(&v, &rv);
-    NS_ENSURE_SUCCESS(rv, JS_FALSE);
     if (JS_TryJSON(ctx, &v)) {
       JS_Stringify(ctx, &v, nsnull, JSVAL_NULL, JSONCreator, &aJSON);
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -359,43 +357,34 @@ nsFrameMessageManager::ReceiveMessage(ns
         NS_ENSURE_STATE(pusher.Push(ctx, PR_FALSE));
 
         JSAutoRequest ar(ctx);
 
         // The parameter for the listener function.
         JSObject* param = JS_NewObject(ctx, NULL, NULL, NULL);
         NS_ENSURE_TRUE(param, NS_ERROR_OUT_OF_MEMORY);
 
-        nsresult rv;
-        nsAutoGCRoot resultGCRoot(&param, &rv);
-        NS_ENSURE_SUCCESS(rv, rv);
-
         jsval targetv;
-        nsAutoGCRoot resultGCRoot2(&targetv, &rv);
-        NS_ENSURE_SUCCESS(rv, rv);
         nsContentUtils::WrapNative(ctx,
                                    JS_GetGlobalObject(ctx),
                                    aTarget, &targetv);
 
         // To keep compatibility with e10s message manager,
         // define empty objects array.
         if (!aObjectsArray) {
           // Because we want JS messages to have always the same properties,
           // create array even if len == 0.
           aObjectsArray = JS_NewArrayObject(ctx, 0, NULL);
           if (!aObjectsArray) {
             return false;
           }
         }
-        nsAutoGCRoot arrayGCRoot(&aObjectsArray, &rv);
-        NS_ENSURE_SUCCESS(rv, rv);
 
         jsval json = JSVAL_NULL;
-        nsAutoGCRoot root(&json, &rv);
-        if (NS_SUCCEEDED(rv) && !aJSON.IsEmpty()) {
+        if (!aJSON.IsEmpty()) {
           JSONParser* parser = JS_BeginJSONParse(ctx, &json);
           if (parser) {
             JSBool ok = JS_ConsumeJSONText(ctx, parser,
                                            (jschar*)nsString(aJSON).get(),
                                            (uint32)aJSON.Length());
             ok = JS_FinishJSONParse(ctx, parser, JSVAL_NULL) && ok;
             if (!ok) {
               json = JSVAL_NULL;
@@ -412,18 +401,16 @@ nsFrameMessageManager::ReceiveMessage(ns
                           STRING_TO_JSVAL(jsMessage), NULL, NULL, JSPROP_ENUMERATE);
         JS_DefineProperty(ctx, param, "sync",
                           BOOLEAN_TO_JSVAL(aSync), NULL, NULL, JSPROP_ENUMERATE);
         JS_DefineProperty(ctx, param, "json", json, NULL, NULL, JSPROP_ENUMERATE);
         JS_DefineProperty(ctx, param, "objects", OBJECT_TO_JSVAL(aObjectsArray),
                           NULL, NULL, JSPROP_ENUMERATE);
 
         jsval thisValue = JSVAL_VOID;
-        nsAutoGCRoot resultGCRoot3(&thisValue, &rv);
-        NS_ENSURE_SUCCESS(rv, rv);
 
         JSAutoEnterCompartment ac;
 
         if (!ac.enter(ctx, object))
           return PR_FALSE;
 
         jsval funval = JSVAL_VOID;
         if (JS_ObjectIsFunction(ctx, object)) {
@@ -449,18 +436,16 @@ nsFrameMessageManager::ReceiveMessage(ns
                           JSVAL_IS_OBJECT(funval) &&
                           !JSVAL_IS_NULL(funval));
           JSObject* funobject = JSVAL_TO_OBJECT(funval);
           NS_ENSURE_STATE(JS_ObjectIsFunction(ctx, funobject));
           thisValue = OBJECT_TO_JSVAL(object);
         }
 
         jsval rval = JSVAL_VOID;
-        nsAutoGCRoot resultGCRoot4(&rval, &rv);
-        NS_ENSURE_SUCCESS(rv, rv);
 
         js::AutoValueRooter argv(ctx);
         argv.set(OBJECT_TO_JSVAL(param));
 
         {
           JSAutoEnterCompartment tac;
 
           JSObject* thisObject = JSVAL_TO_OBJECT(thisValue);
--- a/content/events/src/nsEventListenerService.cpp
+++ b/content/events/src/nsEventListenerService.cpp
@@ -122,67 +122,74 @@ nsEventListenerInfo::GetJSVal(jsval* aJS
   return PR_FALSE;
 }
 
 NS_IMETHODIMP
 nsEventListenerInfo::ToSource(nsAString& aResult)
 {
   aResult.SetIsVoid(PR_TRUE);
 
-  nsresult rv;
-  jsval v = JSVAL_NULL;
-  nsAutoGCRoot root(&v, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (GetJSVal(&v)) {
-    nsCOMPtr<nsIThreadJSContextStack> stack =
-      nsContentUtils::ThreadJSContextStack();
-    if (stack) {
-      JSContext* cx = nsnull;
-      stack->GetSafeJSContext(&cx);
-      if (cx && NS_SUCCEEDED(stack->Push(cx))) {
-        {
-          // Extra block to finish the auto request before calling pop
-          JSAutoRequest ar(cx);
+  nsCOMPtr<nsIThreadJSContextStack> stack =
+    nsContentUtils::ThreadJSContextStack();
+  if (stack) {
+    JSContext* cx = nsnull;
+    stack->GetSafeJSContext(&cx);
+    if (cx && NS_SUCCEEDED(stack->Push(cx))) {
+      {
+        // Extra block to finish the auto request before calling pop
+        JSAutoRequest ar(cx);
+        jsval v = JSVAL_NULL;
+        if (GetJSVal(&v)) {
           JSString* str = JS_ValueToSource(cx, v);
           if (str) {
             aResult.Assign(nsDependentJSString(str));
           }
         }
-        stack->Pop(&cx);
       }
+      stack->Pop(&cx);
     }
   }
-
+  
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEventListenerInfo::GetDebugObject(nsISupports** aRetVal)
 {
   *aRetVal = nsnull;
 
 #ifdef MOZ_JSDEBUGGER
   nsresult rv = NS_OK;
-  jsval v = JSVAL_NULL;
-  nsAutoGCRoot root(&v, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (GetJSVal(&v)) {
-    nsCOMPtr<jsdIDebuggerService> jsd =
-      do_GetService("@mozilla.org/js/jsd/debugger-service;1", &rv);
-    NS_ENSURE_SUCCESS(rv, NS_OK);
+  nsCOMPtr<jsdIDebuggerService> jsd =
+    do_GetService("@mozilla.org/js/jsd/debugger-service;1", &rv);
+  NS_ENSURE_SUCCESS(rv, NS_OK);
+  
+  PRBool isOn = PR_FALSE;
+  jsd->GetIsOn(&isOn);
+  NS_ENSURE_TRUE(isOn, NS_OK);
 
-    PRBool isOn = PR_FALSE;
-    jsd->GetIsOn(&isOn);
-    NS_ENSURE_TRUE(isOn, NS_OK);
+  nsCOMPtr<nsIThreadJSContextStack> stack =
+    nsContentUtils::ThreadJSContextStack();
+  if (stack) {
+    JSContext* cx = nsnull;
+    stack->GetSafeJSContext(&cx);
+    if (cx && NS_SUCCEEDED(stack->Push(cx))) {
+      {
+        // Extra block to finish the auto request before calling pop
+        JSAutoRequest ar(cx);
 
-    nsCOMPtr<jsdIValue> jsdValue;
-    jsd->WrapJSValue(v, getter_AddRefs(jsdValue));
-    *aRetVal = jsdValue.forget().get();
-    return NS_OK;
+        jsval v = JSVAL_NULL;
+        if (GetJSVal(&v)) {
+          nsCOMPtr<jsdIValue> jsdValue;
+          jsd->WrapJSValue(v, getter_AddRefs(jsdValue));
+          *aRetVal = jsdValue.forget().get();
+          return NS_OK;
+        }
+      }
+    }
   }
 #endif
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEventListenerService::GetListenerInfoFor(nsIDOMEventTarget* aEventTarget,
--- a/content/xbl/src/nsXBLProtoImplField.cpp
+++ b/content/xbl/src/nsXBLProtoImplField.cpp
@@ -105,51 +105,48 @@ nsXBLProtoImplField::InstallField(nsIScr
                   "happen");
 
   *aDidInstall = PR_FALSE;
 
   if (mFieldTextLength == 0) {
     return NS_OK;
   }
 
-  jsval result = JSVAL_NULL;
-  
   // EvaluateStringWithValue and JS_DefineUCProperty can both trigger GC, so
   // protect |result| here.
   nsresult rv;
-  nsAutoGCRoot root(&result, &rv);
-  if (NS_FAILED(rv))
-    return rv;
 
   nsCAutoString uriSpec;
   aBindingDocURI->GetSpec(uriSpec);
   
   JSContext* cx = (JSContext*) aContext->GetNativeContext();
   NS_ASSERTION(!::JS_IsExceptionPending(cx),
                "Shouldn't get here when an exception is pending!");
   
   // compile the literal string
   PRBool undefined;
   nsCOMPtr<nsIScriptContext> context = aContext;
+
+  JSAutoRequest ar(cx);
+  jsval result = JSVAL_NULL;
   rv = context->EvaluateStringWithValue(nsDependentString(mFieldText,
                                                           mFieldTextLength), 
                                         aBoundNode,
                                         aPrincipal, uriSpec.get(),
                                         mLineNumber, JSVERSION_LATEST,
                                         (void*) &result, &undefined);
   if (NS_FAILED(rv))
     return rv;
 
   if (undefined) {
     result = JSVAL_VOID;
   }
 
   // Define the evaluated result as a JS property
   nsDependentString name(mName);
-  JSAutoRequest ar(cx);
   if (!::JS_DefineUCProperty(cx, aBoundNode,
                              reinterpret_cast<const jschar*>(mName), 
                              name.Length(), result, nsnull, nsnull,
                              mJSAttributes)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   *aDidInstall = PR_TRUE;
--- a/content/xbl/src/nsXBLProtoImplMember.h
+++ b/content/xbl/src/nsXBLProtoImplMember.h
@@ -115,15 +115,13 @@ public:
                                  const nsCString& aClassStr) = 0;
   virtual nsresult CompileMember(nsIScriptContext* aContext,
                                  const nsCString& aClassStr,
                                  void* aClassObject)=0;
 
   virtual void Trace(TraceCallback aCallback, void *aClosure) const = 0;
 
 protected:
-  friend class nsAutoGCRoot;
-  
   nsXBLProtoImplMember* mNext;  // The members of an implementation are chained.
   PRUnichar* mName;               // The name of the field, method, or property.
 };
 
 #endif // nsXBLProtoImplMember_h__
--- a/content/xbl/src/nsXBLProtoImplMethod.cpp
+++ b/content/xbl/src/nsXBLProtoImplMethod.cpp
@@ -155,20 +155,16 @@ nsXBLProtoImplMethod::InstallMember(nsIS
       return NS_ERROR_UNEXPECTED;
     }
 
     JSObject * method = ::JS_CloneFunctionObject(cx, mJSMethodObject, globalObject);
     if (!method) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    nsresult rv;
-    nsAutoGCRoot root(&method, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-    
     if (!::JS_DefineUCProperty(cx, targetClassObject,
                                reinterpret_cast<const jschar*>(mName), 
                                name.Length(), OBJECT_TO_JSVAL(method),
                                NULL, NULL, JSPROP_ENUMERATE)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
   return NS_OK;
--- a/content/xbl/src/nsXBLProtoImplProperty.cpp
+++ b/content/xbl/src/nsXBLProtoImplProperty.cpp
@@ -180,28 +180,21 @@ nsXBLProtoImplProperty::InstallMember(ns
 
     if (!ac.enter(cx, globalObject))
       return NS_ERROR_UNEXPECTED;
 
     if (mJSGetterObject)
       if (!(getter = ::JS_CloneFunctionObject(cx, mJSGetterObject, globalObject)))
         return NS_ERROR_OUT_OF_MEMORY;
 
-    nsresult rv;
-    nsAutoGCRoot getterroot(&getter, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-    
     JSObject * setter = nsnull;
     if (mJSSetterObject)
       if (!(setter = ::JS_CloneFunctionObject(cx, mJSSetterObject, globalObject)))
         return NS_ERROR_OUT_OF_MEMORY;
 
-    nsAutoGCRoot setterroot(&setter, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-    
     nsDependentString name(mName);
     if (!::JS_DefineUCProperty(cx, targetClassObject,
                                reinterpret_cast<const jschar*>(mName),
                                name.Length(), JSVAL_VOID,
                                JS_DATA_TO_FUNC_PTR(JSPropertyOp, getter),
                                JS_DATA_TO_FUNC_PTR(JSPropertyOp, setter),
                                mJSAttributes))
       return NS_ERROR_OUT_OF_MEMORY;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -6735,19 +6735,16 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
     JSFunction *fun = ::JS_NewFunction(cx, ContentWindowGetter, 0, 0,
                                        windowObj, "_content");
     if (!fun) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     JSObject *funObj = ::JS_GetFunctionObject(fun);
 
-    nsAutoGCRoot root(&funObj, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
     if (!::JS_DefinePropertyById(cx, windowObj, id, JSVAL_VOID,
                                  JS_DATA_TO_FUNC_PTR(JSPropertyOp, funObj),
                                  nsnull,
                                  JSPROP_ENUMERATE | JSPROP_GETTER |
                                  JSPROP_SHARED)) {
       return NS_ERROR_FAILURE;
     }
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7579,24 +7579,24 @@ nsGlobalWindow::DispatchSyncPopState()
     nsIScriptGlobalObject *sgo = document->GetScopeObject();
     NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
 
     nsIScriptContext *scx = sgo->GetContext();
     NS_ENSURE_TRUE(scx, NS_ERROR_FAILURE);
 
     JSContext *cx = (JSContext*) scx->GetNativeContext();
 
+    // Make sure we in the request while we have jsval on the native stack.
+    JSAutoRequest ar(cx);
+
     // If our json call triggers a JS-to-C++ call, we want that call to use cx
     // as the context.  So we push cx onto the context stack.
     nsCxPusher cxPusher;
 
     jsval jsStateObj = JSVAL_NULL;
-    // Root the container which will hold our decoded state object.
-    nsAutoGCRoot root(&jsStateObj, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
 
     // Deserialize the state object into an nsIVariant.
     nsCOMPtr<nsIJSON> json = do_GetService("@mozilla.org/dom/json;1");
     NS_ENSURE_TRUE(cxPusher.Push(cx), NS_ERROR_FAILURE);
     rv = json->DecodeToJSVal(stateObjJSON, cx, &jsStateObj);
     NS_ENSURE_SUCCESS(rv, rv);
     cxPusher.Pop();
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2214,27 +2214,25 @@ nsresult
 nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, void *aScope,
                                       nsIAtom *aName,
                                       void *aHandler)
 {
   NS_ENSURE_ARG(aHandler);
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
-  nsresult rv;
+
+  JSAutoRequest ar(mContext);
 
   // Get the jsobject associated with this target
   JSObject *target = nsnull;
-  nsAutoGCRoot root(&target, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = JSObjectFromInterface(aTarget, aScope, &target);
+  nsresult rv = JSObjectFromInterface(aTarget, aScope, &target);
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSObject *funobj = (JSObject*) aHandler;
-  JSAutoRequest ar(mContext);
 
 #ifdef DEBUG
   {
     JSAutoEnterCompartment ac;
     if (!ac.enter(mContext, funobj)) {
       return NS_ERROR_FAILURE;
     }
 
@@ -2285,22 +2283,19 @@ nsJSContext::BindCompiledEventHandler(ns
 
 nsresult
 nsJSContext::GetBoundEventHandler(nsISupports* aTarget, void *aScope,
                                   nsIAtom* aName,
                                   nsScriptObjectHolder &aHandler)
 {
     NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
 
-    nsresult rv;
+    JSAutoRequest ar(mContext);
     JSObject *obj = nsnull;
-    nsAutoGCRoot root(&obj, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-    JSAutoRequest ar(mContext);
-    rv = JSObjectFromInterface(aTarget, aScope, &obj);
+    nsresult rv = JSObjectFromInterface(aTarget, aScope, &obj);
     NS_ENSURE_SUCCESS(rv, rv);
 
     JSAutoEnterCompartment ac;
     if (!ac.enter(mContext, obj)) {
       return NS_ERROR_FAILURE;
     }
 
     jsval funval;
--- a/dom/src/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/src/jsurl/nsJSProtocolHandler.cpp
@@ -303,20 +303,16 @@ nsresult nsJSThunk::EvaluateScript(nsICh
 
         nsIXPConnect *xpc = nsContentUtils::XPConnect();
 
         nsCOMPtr<nsIXPConnectJSObjectHolder> sandbox;
         rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(sandbox));
         NS_ENSURE_SUCCESS(rv, rv);
 
         jsval rval = JSVAL_VOID;
-        nsAutoGCRoot root(&rval, &rv);
-        if (NS_FAILED(rv)) {
-            return rv;
-        }
 
         // Push our JSContext on the context stack so the JS_ValueToString call (and
         // JS_ReportPendingException, if relevant) will use the principal of cx.
         // Note that we do this as late as possible to make popping simpler.
         nsCOMPtr<nsIJSContextStack> stack =
             do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
         if (NS_SUCCEEDED(rv)) {
             rv = stack->Push(cx);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -936,16 +936,25 @@ JS_ResumeRequest(JSContext *cx, jsrefcou
     JS_ASSERT(!t->data.requestDepth);
     JS_ASSERT(t->suspendCount);
     StartRequest(cx);
     t->data.requestDepth = saveDepth;
     t->suspendCount--;
 #endif
 }
 
+JS_PUBLIC_API(JSBool)
+JS_IsInRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+    JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
+    return JS_THREAD_DATA(cx)->requestDepth != 0;
+#endif
+}
+
 JS_PUBLIC_API(void)
 JS_Lock(JSRuntime *rt)
 {
     JS_LOCK_RUNTIME(rt);
 }
 
 JS_PUBLIC_API(void)
 JS_Unlock(JSRuntime *rt)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -750,16 +750,19 @@ extern JS_PUBLIC_API(void)
 JS_YieldRequest(JSContext *cx);
 
 extern JS_PUBLIC_API(jsrefcount)
 JS_SuspendRequest(JSContext *cx);
 
 extern JS_PUBLIC_API(void)
 JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth);
 
+extern JS_PUBLIC_API(JSBool)
+JS_IsInRequest(JSContext *cx);
+
 #ifdef __cplusplus
 JS_END_EXTERN_C
 
 class JSAutoRequest {
   public:
     JSAutoRequest(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
         : mContext(cx), mSaveDepth(0) {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
@@ -815,16 +818,40 @@ class JSAutoSuspendRequest {
 
 #if 0
   private:
     static void *operator new(size_t) CPP_THROW_NEW { return 0; };
     static void operator delete(void *, size_t) { };
 #endif
 };
 
+class JSAutoCheckRequest {
+  public:
+    JSAutoCheckRequest(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM) {
+#if defined JS_THREADSAFE && defined DEBUG
+        mContext = cx;
+        JS_ASSERT(JS_IsInRequest(cx));
+#endif
+        JS_GUARD_OBJECT_NOTIFIER_INIT;
+    }
+    
+    ~JSAutoCheckRequest() {
+#if defined JS_THREADSAFE && defined DEBUG
+        JS_ASSERT(JS_IsInRequest(mContext));
+#endif
+    }
+
+
+  private:
+#if defined JS_THREADSAFE && defined DEBUG
+    JSContext *mContext;
+#endif
+    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
 JS_BEGIN_EXTERN_C
 #endif
 
 extern JS_PUBLIC_API(void)
 JS_Lock(JSRuntime *rt);
 
 extern JS_PUBLIC_API(void)
 JS_Unlock(JSRuntime *rt);
--- a/js/src/xpconnect/src/XPCDispTearOff.cpp
+++ b/js/src/xpconnect/src/XPCDispTearOff.cpp
@@ -348,18 +348,17 @@ STDMETHODIMP XPCDispatchTearOff::Invoke(
         scriptEval.StartEvaluating(xpcWrappedJSErrorReporter);
 
         xpcc->SetPendingResult(pending_result);
         xpcc->SetException(nsnull);
         ccx.GetThreadData()->SetException(nsnull);
 
         // We use js_Invoke so that the gcthings we use as args will be rooted
         // by the engine as we do conversions and prepare to do the function
-        // call. This adds a fair amount of complexity, but it's a good
-        // optimization compared to calling JS_AddRoot for each item.
+        // call.
 
         js::LeaveTrace(cx);
 
         // In the xpidl [function] case we are making sure now that the 
         // JSObject is callable. If it is *not* callable then we silently 
         // fallback to looking up the named property...
         // (because jst says he thinks this fallback is 'The Right Thing'.)
         //
--- a/js/src/xpconnect/src/xpcwrappedjsclass.cpp
+++ b/js/src/xpconnect/src/xpcwrappedjsclass.cpp
@@ -1344,18 +1344,16 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWra
 
                 principalGuard.principalPushed(ssm);
             }
         }
     }
 
     // We use js_Invoke so that the gcthings we use as args will be rooted by
     // the engine as we do conversions and prepare to do the function call.
-    // This adds a fair amount of complexity, but it's a good optimization
-    // compared to calling JS_AddRoot for each item.
 
     js::LeaveTrace(cx);
 
     // setup stack
 
     // if this isn't a function call then we don't need to push extra stuff
     if (!(XPT_MD_IS_SETTER(info->flags) || XPT_MD_IS_GETTER(info->flags)))
     {