Bug 791445 - Propagate errors correctly in ParallelArray debug options (r=jorendorff)
authorShu-yu Guo <shu@rfrn.org>
Thu, 20 Sep 2012 02:26:53 -0700
changeset 107729 e7164530358f549155ca9c5433c697029af89447
parent 107728 b3e66a4b7c0bb20aacf37878f2e1c7977e9f29da
child 107730 0d016659bfcdb87c618c485f18dd3ac4d4d46c72
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersjorendorff
bugs791445
milestone18.0a1
Bug 791445 - Propagate errors correctly in ParallelArray debug options (r=jorendorff)
js/src/builtin/ParallelArray.cpp
--- a/js/src/builtin/ParallelArray.cpp
+++ b/js/src/builtin/ParallelArray.cpp
@@ -26,16 +26,23 @@ using namespace js::types;
 
 //
 // Utilities
 //
 
 typedef ParallelArrayObject::IndexVector IndexVector;
 typedef ParallelArrayObject::IndexInfo IndexInfo;
 
+static bool
+ReportBadArg(JSContext *cx, const char *s = "")
+{
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_ARG, s);
+    return false;
+}
+
 bool
 ParallelArrayObject::IndexInfo::isInitialized() const
 {
     return (dimensions.length() > 0 &&
             indices.capacity() >= dimensions.length() &&
             partialProducts.length() == dimensions.length());
 }
 
@@ -676,66 +683,61 @@ ParallelArrayObject::ExecutionStatusToSt
         return "success";
     }
     return "(unknown status)";
 }
 
 bool
 ParallelArrayObject::DebugOptions::init(JSContext *cx, const Value &v)
 {
-    if (!v.isObject())
+    RootedObject obj(cx, NonNullObject(cx, v));
+    if (!obj)
         return false;
 
-    RootedObject obj(cx, &v.toObject());
     RootedId id(cx);
     RootedValue propv(cx);
     JSString *propStr;
     JSBool match = false;
+    bool ok;
 
     id = AtomToId(Atomize(cx, "mode", strlen("mode")));
     if (!JSObject::getGeneric(cx, obj, obj, id, &propv))
         return false;
 
     propStr = ToString(cx, propv);
-    if (!JS_StringEqualsAscii(cx, propStr, "par", &match))
+    if (!propStr)
         return false;
-    if (match) {
+
+    if ((ok = JS_StringEqualsAscii(cx, propStr, "par", &match)) && match)
         mode = &parallel;
-    } else {
-        if (!JS_StringEqualsAscii(cx, propStr, "seq", &match))
-            return false;
-        if (match)
-            mode = &sequential;
-        else
-            return false;
-    }
+    else if (ok && (ok = JS_StringEqualsAscii(cx, propStr, "seq", &match)) && match)
+        mode = &sequential;
+    else if (ok)
+        return ReportBadArg(cx);
+    else
+        return false;
 
     id = AtomToId(Atomize(cx, "expect", strlen("expect")));
     if (!JSObject::getGeneric(cx, obj, obj, id, &propv))
         return false;
 
     propStr = ToString(cx, propv);
-    if (!JS_StringEqualsAscii(cx, propStr, "fail", &match))
+    if (!propStr)
         return false;
-    if (match) {
+
+    if ((ok = JS_StringEqualsAscii(cx, propStr, "fail", &match)) && match)
         expect = ExecutionFailed;
-    } else {
-        if (!JS_StringEqualsAscii(cx, propStr, "bail", &match))
-            return false;
-        if (match) {
-            expect = ExecutionCompiled;
-        } else {
-            if (!JS_StringEqualsAscii(cx, propStr, "success", &match))
-                return false;
-            if (match)
-                expect = ExecutionSucceeded;
-            else
-                return false;
-        }
-    }
+    else if (ok && (ok = JS_StringEqualsAscii(cx, propStr, "bail", &match)) && match)
+        expect = ExecutionCompiled;
+    else if (ok && (ok = JS_StringEqualsAscii(cx, propStr, "success", &match)) && match)
+        expect = ExecutionSucceeded;
+    else if (ok)
+        return ReportBadArg(cx);
+    else
+        return false;
 
     return true;
 }
 
 bool
 ParallelArrayObject::DebugOptions::check(JSContext *cx, ExecutionStatus actual)
 {
     if (expect != actual) {
@@ -1098,23 +1100,25 @@ ParallelArrayObject::construct(JSContext
     uint32_t length = iv.scalarLengthOfDimensions();
 
     // Create backing store.
     RootedObject buffer(cx, NewDenseArrayWithType(cx, length));
     if (!buffer)
         return false;
 
 #ifdef DEBUG
-    if (args.length() > 1) {
+    if (args.length() > 2) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->build(cx, iv, elementalFun, buffer)))
-                return false;
-            return create(cx, buffer, 0, iv.dimensions, args.rval());
+        if (!options.init(cx, args[2]) ||
+            !options.check(cx, options.mode->build(cx, iv, elementalFun, buffer)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, 0, iv.dimensions, args.rval());
     }
 #endif
 
     if (fallback.build(cx, iv, elementalFun, buffer) != ExecutionSucceeded)
         return false;
 
     return create(cx, buffer, 0, iv.dimensions, args.rval());
 }
@@ -1137,21 +1141,23 @@ ParallelArrayObject::map(JSContext *cx, 
 
     RootedObject elementalFun(cx, ValueToCallable(cx, &args[0]));
     if (!elementalFun)
         return false;
 
 #ifdef DEBUG
     if (args.length() > 1) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->map(cx, obj, elementalFun, buffer)))
-                return false;
-            return create(cx, buffer, args.rval());
+        if (!options.init(cx, args[1]) ||
+            !options.check(cx, options.mode->map(cx, obj, elementalFun, buffer)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, args.rval());
     }
 #endif
 
     if (fallback.map(cx, obj, elementalFun, buffer) != ExecutionSucceeded)
         return false;
 
     return create(cx, buffer, args.rval());
 }
@@ -1176,20 +1182,21 @@ ParallelArrayObject::reduce(JSContext *c
 
     RootedObject elementalFun(cx, ValueToCallable(cx, &args[0]));
     if (!elementalFun)
         return false;
 
 #ifdef DEBUG
     if (args.length() > 1) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            return options.check(cx, options.mode->reduce(cx, obj, elementalFun, NullPtr(),
-                                                          args.rval()));
-        }
+        if (!options.init(cx, args[1]))
+            return false;
+
+        return options.check(cx, options.mode->reduce(cx, obj, elementalFun, NullPtr(),
+                                                      args.rval()));
     }
 #endif
 
     // Call reduce with a null destination buffer to not store intermediates.
     return fallback.reduce(cx, obj, elementalFun, NullPtr(), args.rval()) == ExecutionSucceeded;
 }
 
 bool
@@ -1221,21 +1228,23 @@ ParallelArrayObject::scan(JSContext *cx,
 
     // Call reduce with a dummy out value to be discarded and a buffer to
     // store intermediates.
     RootedValue dummy(cx);
 
 #ifdef DEBUG
     if (args.length() > 1) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->reduce(cx, obj, elementalFun, buffer, &dummy)))
-                return false;
-            return create(cx, buffer, args.rval());
+        if (!options.init(cx, args[1]) ||
+            !options.check(cx, options.mode->reduce(cx, obj, elementalFun, buffer, &dummy)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, args.rval());
     }
 #endif
 
     if (fallback.reduce(cx, obj, elementalFun, buffer, &dummy) != ExecutionSucceeded)
         return false;
 
     return create(cx, buffer, args.rval());
 }
@@ -1287,26 +1296,26 @@ ParallelArrayObject::scatter(JSContext *
     }
 
     // Create a destination buffer. Fail if we can't maintain denseness.
     RootedObject buffer(cx, NewDenseArrayWithType(cx, resultLength));
     if (!buffer)
         return false;
 
 #ifdef DEBUG
-    if (args.length() > 1) {
+    if (args.length() > 4) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->scatter(cx, obj, targets, defaultValue,
-                                                         conflictFun, buffer)))
-            {
-                return false;
-            }
-            return create(cx, buffer, args.rval());
+        if (!options.init(cx, args[4]) ||
+            !options.check(cx, options.mode->scatter(cx, obj, targets, defaultValue,
+                                                     conflictFun, buffer)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, args.rval());
     }
 #endif
 
     if (fallback.scatter(cx, obj, targets, defaultValue,
                          conflictFun, buffer) != ExecutionSucceeded)
     {
         return false;
     }
@@ -1336,21 +1345,23 @@ ParallelArrayObject::filter(JSContext *c
 
     RootedObject buffer(cx, NewDenseArrayWithType(cx, 0));
     if (!buffer)
         return false;
 
 #ifdef DEBUG
     if (args.length() > 1) {
         DebugOptions options;
-        if (options.init(cx, args[1])) {
-            if (!options.check(cx, options.mode->filter(cx, obj, filters, buffer)))
-                return false;
-            return create(cx, buffer, args.rval());
+        if (!options.init(cx, args[1]) ||
+            !options.check(cx, options.mode->filter(cx, obj, filters, buffer)))
+        {
+            return false;
         }
+
+        return create(cx, buffer, args.rval());
     }
 #endif
 
     if (fallback.filter(cx, obj, filters, buffer) != ExecutionSucceeded)
         return false;
 
     return create(cx, buffer, args.rval());
 }