Bug 1027131 - Switch to a struct for the StackScopedClone closure. r=gabor
authorBobby Holley <bobbyholley@gmail.com>
Mon, 23 Jun 2014 13:25:08 -0700
changeset 190327 ffed77f6ec4e07210d6ddbe7527826fc838821c5
parent 190326 f3fc9863ef3173cbb9c9c588ceae0e0c522dd664
child 190328 3d1e64043288eb7f66c229d2d9d7c84275940f14
push id27004
push useremorley@mozilla.com
push dateTue, 24 Jun 2014 15:52:34 +0000
treeherdermozilla-central@7b174d47f3cc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgabor
bugs1027131
milestone33.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 1027131 - Switch to a struct for the StackScopedClone closure. r=gabor
js/xpconnect/src/ExportHelpers.cpp
--- a/js/xpconnect/src/ExportHelpers.cpp
+++ b/js/xpconnect/src/ExportHelpers.cpp
@@ -26,30 +26,41 @@ IsReflector(JSObject *obj)
     return IS_WN_REFLECTOR(obj) || dom::IsDOMObject(obj);
 }
 
 enum StackScopedCloneTags {
     SCTAG_BASE = JS_SCTAG_USER_MIN,
     SCTAG_REFLECTOR
 };
 
+class MOZ_STACK_CLASS StackScopedCloneData {
+public:
+    StackScopedCloneData(JSContext *aCx, StackScopedCloneOptions *aOptions)
+        : mOptions(aOptions)
+        , mReflectors(aCx)
+    {}
+
+    StackScopedCloneOptions *mOptions;
+    AutoObjectVector mReflectors;
+};
+
 static JSObject *
 StackScopedCloneRead(JSContext *cx, JSStructuredCloneReader *reader, uint32_t tag,
                      uint32_t data, void *closure)
 {
     MOZ_ASSERT(closure, "Null pointer!");
-    AutoObjectVector *reflectors = static_cast<AutoObjectVector *>(closure);
+    StackScopedCloneData *cloneData = static_cast<StackScopedCloneData *>(closure);
     if (tag == SCTAG_REFLECTOR) {
         MOZ_ASSERT(!data);
 
         size_t idx;
         if (!JS_ReadBytes(reader, &idx, sizeof(size_t)))
             return nullptr;
 
-        RootedObject reflector(cx, (*reflectors)[idx]);
+        RootedObject reflector(cx, cloneData->mReflectors[idx]);
         MOZ_ASSERT(reflector, "No object pointer?");
         MOZ_ASSERT(IsReflector(reflector), "Object pointer must be a reflector!");
 
         if (!JS_WrapObject(cx, &reflector))
             return nullptr;
 
         return reflector;
     }
@@ -58,25 +69,22 @@ StackScopedCloneRead(JSContext *cx, JSSt
     return nullptr;
 }
 
 static bool
 StackScopedCloneWrite(JSContext *cx, JSStructuredCloneWriter *writer,
                       Handle<JSObject *> obj, void *closure)
 {
     MOZ_ASSERT(closure, "Null pointer!");
-
-    // We need to maintain a list of reflectors to make sure all these objects
-    // are properly rooter. Only their indices will be serialized.
-    AutoObjectVector *reflectors = static_cast<AutoObjectVector *>(closure);
-    if (IsReflector(obj)) {
-        if (!reflectors->append(obj))
+    StackScopedCloneData *cloneData = static_cast<StackScopedCloneData *>(closure);
+    if (cloneData->mOptions->wrapReflectors && IsReflector(obj)) {
+        if (!cloneData->mReflectors.append(obj))
             return false;
 
-        size_t idx = reflectors->length()-1;
+        size_t idx = cloneData->mReflectors.length() - 1;
         if (!JS_WriteUint32Pair(writer, SCTAG_REFLECTOR, 0))
             return false;
         if (!JS_WriteBytes(writer, &idx, sizeof(size_t)))
             return false;
         return true;
     }
 
     JS_ReportError(cx, "Encountered unsupported value type writing stack-scoped structured clone");
@@ -102,46 +110,34 @@ static const JSStructuredCloneCallbacks 
  * This function assumes that |cx| is already entered the compartment we want
  * to clone to, and that |val| may not be same-compartment with cx. When the
  * function returns, |val| is set to the result of the clone.
  */
 bool
 StackScopedClone(JSContext *cx, StackScopedCloneOptions &options,
                  MutableHandleValue val)
 {
-    MOZ_ASSERT(options.wrapReflectors); // XXXbholley - This goes away in subsequent patches
     JSAutoStructuredCloneBuffer buffer;
-    AutoObjectVector rootedReflectors(cx);
+    StackScopedCloneData data(cx, &options);
     {
         // For parsing val we have to enter its compartment.
         // (unless it's a primitive)
         Maybe<JSAutoCompartment> ac;
         if (val.isObject()) {
             ac.construct(cx, &val.toObject());
         } else if (val.isString() && !JS_WrapValue(cx, val)) {
             return false;
         }
 
-        if (!buffer.write(cx, val,
-            &gStackScopedCloneCallbacks,
-            &rootedReflectors))
-        {
+        if (!buffer.write(cx, val, &gStackScopedCloneCallbacks, &data))
             return false;
-        }
     }
 
     // Now recreate the clones in the target compartment.
-    if (!buffer.read(cx, val,
-        &gStackScopedCloneCallbacks,
-        &rootedReflectors))
-    {
-        return false;
-    }
-
-    return true;
+    return buffer.read(cx, val, &gStackScopedCloneCallbacks, &data);
 }
 
 /*
  * Forwards the call to the exported function. Clones all the non reflectors, ignores
  * the |this| argument.
  */
 static bool
 CloningFunctionForwarder(JSContext *cx, unsigned argc, Value *vp)