Bug 684039: Don't use JSArenaPool in nsJSEnvironment. (r=mrbkap)
authorChris Leary <cdleary@mozilla.com>
Thu, 22 Sep 2011 15:13:36 -0700
changeset 78948 ebb656c6410ea49cb5f19e1071f2915e0b569976
parent 78947 c4b5ba89b4b7ae9a7d765ebbdd24b5b9ed15a1a2
child 78949 7f0922f6090db56e809391c2aa4bb3d67686fef3
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs684039
milestone9.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 684039: Don't use JSArenaPool in nsJSEnvironment. (r=mrbkap)
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -194,16 +194,43 @@ nsMemoryPressureObserver::Observe(nsISup
 {
   if (sGCOnMemoryPressure) {
     nsJSContext::GarbageCollectNow();
     nsJSContext::CycleCollectNow();
   }
   return NS_OK;
 }
 
+class nsRootedJSValueArray {
+public:
+  explicit nsRootedJSValueArray(JSContext *cx) : avr(cx, vals.Length(), vals.Elements()) {}
+
+  PRBool SetCapacity(JSContext *cx, size_t capacity) {
+    PRBool ok = vals.SetCapacity(capacity);
+    if (!ok)
+      return PR_FALSE;
+    // Values must be safe for the GC to inspect (they must not contain garbage).
+    memset(vals.Elements(), 0, vals.SizeOf());
+    resetRooter(cx);
+    return PR_TRUE;
+  }
+
+  jsval *Elements() {
+    return vals.Elements();
+  }
+
+private:
+  void resetRooter(JSContext *cx) {
+    avr.changeArray(vals.Elements(), vals.Length());
+  }
+
+  nsAutoTArray<jsval, 16> vals;
+  js::AutoArrayRooter avr;
+};
+
 /****************************************************************
  ************************** AutoFree ****************************
  ****************************************************************/
 
 class AutoFree {
 public:
   AutoFree(void *aPtr) : mPtr(aPtr) {
   }
@@ -213,25 +240,16 @@ public:
   }
   void Invalidate() {
     mPtr = 0;
   }
 private:
   void *mPtr;
 };
 
-class nsAutoPoolRelease {
-public:
-  nsAutoPoolRelease(JSArenaPool *p, void *m) : mPool(p), mMark(m) {}
-  ~nsAutoPoolRelease() { JS_ARENA_RELEASE(mPool, mMark); }
-private:
-  JSArenaPool *mPool;
-  void *mMark;
-};
-
 // A utility function for script languages to call.  Although it looks small,
 // the use of nsIDocShell and nsPresContext triggers a huge number of
 // dependencies that most languages would not otherwise need.
 // XXXmarkh - This function is mis-placed!
 PRBool
 NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
                      nsScriptErrorEvent *aErrorEvent,
                      nsEventStatus *aStatus)
@@ -1907,26 +1925,24 @@ nsJSContext::CallEventHandler(nsISupport
     JSAutoEnterCompartment ac;
     js::ForceFrame ff(mContext, funobj);
     if (!ac.enter(mContext, funobj) || !ff.enter() ||
         !JS_WrapObject(mContext, &target)) {
       sSecurityManager->PopContextPrincipal(mContext);
       return NS_ERROR_FAILURE;
     }
 
-    Maybe<nsAutoPoolRelease> poolRelease;
-    Maybe<js::AutoArrayRooter> tvr;
+    Maybe<nsRootedJSValueArray> tempStorage;
 
     // Use |target| as the scope for wrapping the arguments, since aScope is
     // the safe scope in many cases, which isn't very useful.  Wrapping aTarget
     // was OK because those typically have PreCreate methods that give them the
     // right scope anyway, and we want to make sure that the arguments end up
     // in the same scope as aTarget.
-    rv = ConvertSupportsTojsvals(aargv, target, &argc,
-                                 &argv, poolRelease, tvr);
+    rv = ConvertSupportsTojsvals(aargv, target, &argc, &argv, tempStorage);
     NS_ENSURE_SUCCESS(rv, rv);
 
     ++mExecuteDepth;
     PRBool ok = ::JS_CallFunctionValue(mContext, target,
                                        funval, argc, argv, &rval);
     --mExecuteDepth;
 
     if (!ok) {
@@ -2338,22 +2354,20 @@ nsJSContext::InitializeExternalClasses()
 nsresult
 nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArgs)
 {
   PRUint32  argc;
   jsval    *argv = nsnull;
 
   JSAutoRequest ar(mContext);
 
-  Maybe<nsAutoPoolRelease> poolRelease;
-  Maybe<js::AutoArrayRooter> tvr;
+  Maybe<nsRootedJSValueArray> tempStorage;
 
   nsresult rv;
-  rv = ConvertSupportsTojsvals(aArgs, GetNativeGlobal(), &argc,
-                               &argv, poolRelease, tvr);
+  rv = ConvertSupportsTojsvals(aArgs, GetNativeGlobal(), &argc, &argv, tempStorage);
   NS_ENSURE_SUCCESS(rv, rv);
 
   jsval vargs;
 
   // got the arguments, now attach them.
 
   // window.dialogArguments is supposed to be an array if a JS array
   // was passed to showModalDialog(), deal with that here.
@@ -2379,18 +2393,17 @@ nsJSContext::SetProperty(void *aTarget, 
   return rv;
 }
 
 nsresult
 nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs,
                                      void *aScope,
                                      PRUint32 *aArgc,
                                      jsval **aArgv,
-                                     Maybe<nsAutoPoolRelease> &aPoolRelease,
-                                     Maybe<js::AutoArrayRooter> &aRooter)
+                                     Maybe<nsRootedJSValueArray> &aTempStorage)
 {
   nsresult rv = NS_OK;
 
   // If the array implements nsIJSArgArray, just grab the values directly.
   nsCOMPtr<nsIJSArgArray> fastArray = do_QueryInterface(aArgs);
   if (fastArray != nsnull)
     return fastArray->GetArgs(aArgc, reinterpret_cast<void **>(aArgv));
 
@@ -2415,26 +2428,21 @@ nsJSContext::ConvertSupportsTojsvals(nsI
     rv = argsArray->GetLength(&argCount);
     NS_ENSURE_SUCCESS(rv, rv);
     if (argCount == 0)
       return NS_OK;
   } else {
     argCount = 1; // the nsISupports which is not an array
   }
 
-  void *mark = JS_ARENA_MARK(&mContext->tempPool);
-  jsval *argv;
-  size_t nbytes = argCount * sizeof(jsval);
-  JS_ARENA_ALLOCATE_CAST(argv, jsval *, &mContext->tempPool, nbytes);
-  NS_ENSURE_TRUE(argv, NS_ERROR_OUT_OF_MEMORY);
-  memset(argv, 0, nbytes);  /* initialize so GC-able */
-
   // Use the caller's auto guards to release and unroot.
-  aPoolRelease.construct(&mContext->tempPool, mark);
-  aRooter.construct(mContext, argCount, argv);
+  aTempStorage.construct(mContext);
+  PRBool ok = aTempStorage.ref().SetCapacity(mContext, argCount);
+  NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
+  jsval *argv = aTempStorage.ref().Elements();
 
   if (argsArray) {
     for (argCtr = 0; argCtr < argCount && NS_SUCCEEDED(rv); argCtr++) {
       nsCOMPtr<nsISupports> arg;
       jsval *thisval = argv + argCtr;
       argsArray->QueryElementAt(argCtr, NS_GET_IID(nsISupports),
                                 getter_AddRefs(arg));
       if (!arg) {
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -43,17 +43,17 @@
 #include "jsapi.h"
 #include "nsIObserver.h"
 #include "nsIXPCScriptNotify.h"
 #include "prtime.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsScriptNameSpaceManager.h"
 
 class nsIXPConnectJSObjectHolder;
-class nsAutoPoolRelease;
+class nsRootedJSValueArray;
 namespace js {
 class AutoArrayRooter;
 }
 namespace mozilla {
 template <class> class Maybe;
 }
 
 class nsJSContext : public nsIScriptContext,
@@ -199,18 +199,17 @@ public:
 protected:
   nsresult InitializeExternalClasses();
 
   // Helper to convert xpcom datatypes to jsvals.
   nsresult ConvertSupportsTojsvals(nsISupports *aArgs,
                                    void *aScope,
                                    PRUint32 *aArgc,
                                    jsval **aArgv,
-                                   mozilla::Maybe<nsAutoPoolRelease> &aPoolRelease,
-                                   mozilla::Maybe<js::AutoArrayRooter> &aRooter);
+                                   mozilla::Maybe<nsRootedJSValueArray> &aPoolRelease);
 
   nsresult AddSupportsPrimitiveTojsvals(nsISupports *aArg, jsval *aArgv);
 
   // given an nsISupports object (presumably an event target or some other
   // DOM object), get (or create) the JSObject wrapping it.
   nsresult JSObjectFromInterface(nsISupports *aSup, void *aScript, 
                                  JSObject **aRet);