Bug 1022784 - Make all users of AutoGCRooter depend upon its definition, not upon forward declarations of it. r=terrence, a=lmandel
authorJeff Walden <jwalden@mit.edu>
Mon, 09 Jun 2014 10:35:59 -0700
changeset 208197 d7a5852feb92ce528d3c85c0c1a183f0eab4cc29
parent 208196 380fcc352a29809886d049cf49c2366ecb4a330e
child 208198 f9b60c46c1ed454f79dbdd442147b341541109aa
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, lmandel
bugs1022784
milestone32.0a2
Bug 1022784 - Make all users of AutoGCRooter depend upon its definition, not upon forward declarations of it. r=terrence, a=lmandel
js/src/NamespaceImports.h
js/src/builtin/MapObject.h
js/src/frontend/BytecodeCompiler.h
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/gc/RootMarking.cpp
js/src/jit/IonAllocPolicy.h
js/src/jit/IonMacroAssembler.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.h
js/src/jscompartment.h
js/src/jsgc.cpp
js/src/jsonparser.h
js/src/jspubtd.h
--- a/js/src/NamespaceImports.h
+++ b/js/src/NamespaceImports.h
@@ -27,17 +27,16 @@ class TwoByteChars;
 class AutoFunctionVector;
 class AutoIdVector;
 class AutoObjectVector;
 class AutoScriptVector;
 class AutoValueVector;
 
 class AutoIdArray;
 
-class JS_PUBLIC_API(AutoGCRooter);
 template <typename T> class AutoVectorRooter;
 template<typename K, typename V> class AutoHashMapRooter;
 template<typename T> class AutoHashSetRooter;
 template<typename T> class RootedGeneric;
 
 class MOZ_STACK_CLASS SourceBufferHolder;
 
 class HandleValueArray;
@@ -73,17 +72,16 @@ using JS::TwoByteChars;
 using JS::AutoFunctionVector;
 using JS::AutoIdVector;
 using JS::AutoObjectVector;
 using JS::AutoScriptVector;
 using JS::AutoValueVector;
 
 using JS::AutoIdArray;
 
-using JS::AutoGCRooter;
 using JS::AutoHashMapRooter;
 using JS::AutoHashSetRooter;
 using JS::AutoVectorRooter;
 using JS::RootedGeneric;
 
 using JS::CallArgs;
 using JS::CallNonGenericMethod;
 using JS::CallReceiver;
--- a/js/src/builtin/MapObject.h
+++ b/js/src/builtin/MapObject.h
@@ -37,37 +37,37 @@ class HashableValue {
 
     bool setValue(JSContext *cx, HandleValue v);
     HashNumber hash() const;
     bool operator==(const HashableValue &other) const;
     HashableValue mark(JSTracer *trc) const;
     Value get() const { return value.get(); }
 };
 
-class AutoHashableValueRooter : private AutoGCRooter
+class AutoHashableValueRooter : private JS::AutoGCRooter
 {
   public:
     explicit AutoHashableValueRooter(JSContext *cx
                                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-        : AutoGCRooter(cx, HASHABLEVALUE)
+        : JS::AutoGCRooter(cx, HASHABLEVALUE)
         {
             MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         }
 
     bool setValue(JSContext *cx, HandleValue v) {
         return value.setValue(cx, v);
     }
 
     operator const HashableValue & () {
         return value;
     }
 
     Value get() const { return value.get(); }
 
-    friend void AutoGCRooter::trace(JSTracer *trc);
+    friend void JS::AutoGCRooter::trace(JSTracer *trc);
     void trace(JSTracer *trc);
 
   private:
     HashableValue value;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 template <class Key, class Value, class OrderedHashPolicy, class AllocPolicy>
--- a/js/src/frontend/BytecodeCompiler.h
+++ b/js/src/frontend/BytecodeCompiler.h
@@ -63,14 +63,14 @@ bool
 IsIdentifier(JSLinearString *str);
 
 /* True if str is a keyword. Defined in TokenStream.cpp. */
 bool
 IsKeyword(JSLinearString *str);
 
 /* GC marking. Defined in Parser.cpp. */
 void
-MarkParser(JSTracer *trc, AutoGCRooter *parser);
+MarkParser(JSTracer *trc, JS::AutoGCRooter *parser);
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif /* frontend_BytecodeCompiler_h */
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -37,18 +37,21 @@
 
 #include "jsatominlines.h"
 #include "jsscriptinlines.h"
 
 #include "frontend/ParseNode-inl.h"
 
 using namespace js;
 using namespace js::gc;
+
 using mozilla::Maybe;
 
+using JS::AutoGCRooter;
+
 namespace js {
 namespace frontend {
 
 typedef Rooted<StaticBlockObject*> RootedStaticBlockObject;
 typedef Handle<StaticBlockObject*> HandleStaticBlockObject;
 typedef Rooted<NestedScopeObject*> RootedNestedScopeObject;
 typedef Handle<NestedScopeObject*> HandleNestedScopeObject;
 
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -308,17 +308,17 @@ struct BindData;
 
 class CompExprTransplanter;
 
 enum LetContext { LetExpresion, LetStatement };
 enum VarContext { HoistVars, DontHoistVars };
 enum FunctionType { Getter, Setter, Normal };
 
 template <typename ParseHandler>
-class Parser : private AutoGCRooter, public StrictModeGetter
+class Parser : private JS::AutoGCRooter, public StrictModeGetter
 {
   public:
     ExclusiveContext *const context;
     LifoAlloc &alloc;
 
     TokenStream         tokenStream;
     LifoAlloc::Mark     tempPoolMark;
 
@@ -387,17 +387,17 @@ class Parser : private AutoGCRooter, pub
         m.traceListHead = traceListHead;
         return m;
     }
     void release(Mark m) {
         alloc.release(m.mark);
         traceListHead = m.traceListHead;
     }
 
-    friend void js::frontend::MarkParser(JSTracer *trc, AutoGCRooter *parser);
+    friend void js::frontend::MarkParser(JSTracer *trc, JS::AutoGCRooter *parser);
 
     const char *getFilename() const { return tokenStream.getFilename(); }
     JSVersion versionNumber() const { return tokenStream.versionNumber(); }
 
     /*
      * Parse a top-level JS script.
      */
     Node parse(JSObject *chain);
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -31,16 +31,18 @@
 #include "jsgcinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
 using mozilla::ArrayEnd;
 
+using JS::AutoGCRooter;
+
 typedef RootedValueMap::Range RootRange;
 typedef RootedValueMap::Entry RootEntry;
 typedef RootedValueMap::Enum RootEnum;
 
 #ifdef JSGC_USE_EXACT_ROOTING
 
 // Note: the following two functions cannot be static as long as we are using
 // GCC 4.4, since it requires template function parameters to have external
@@ -577,26 +579,26 @@ AutoGCRooter::trace(JSTracer *trc)
     if (Value *vp = static_cast<AutoArrayRooter *>(this)->array)
         MarkValueRootRange(trc, tag_, vp, "JS::AutoArrayRooter.array");
 }
 
 /* static */ void
 AutoGCRooter::traceAll(JSTracer *trc)
 {
     for (ContextIter cx(trc->runtime()); !cx.done(); cx.next()) {
-        for (js::AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down)
+        for (AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down)
             gcr->trace(trc);
     }
 }
 
 /* static */ void
 AutoGCRooter::traceAllWrappers(JSTracer *trc)
 {
     for (ContextIter cx(trc->runtime()); !cx.done(); cx.next()) {
-        for (js::AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down) {
+        for (AutoGCRooter *gcr = cx->autoGCRooters; gcr; gcr = gcr->down) {
             if (gcr->tag_ == WRAPVECTOR || gcr->tag_ == WRAPPER)
                 gcr->trace(trc);
         }
     }
 }
 
 void
 AutoHashableValueRooter::trace(JSTracer *trc)
--- a/js/src/jit/IonAllocPolicy.h
+++ b/js/src/jit/IonAllocPolicy.h
@@ -69,27 +69,27 @@ class TempAllocator
     bool ensureBallast() {
         // Most infallible Ion allocations are small, so we use a ballast of
         // ~16K for now.
         return lifoScope_.alloc().ensureUnusedApproximate(16 * 1024);
     }
 };
 
 // Stack allocated rooter for all roots associated with a TempAllocator
-class AutoTempAllocatorRooter : private AutoGCRooter
+class AutoTempAllocatorRooter : private JS::AutoGCRooter
 {
   public:
     explicit AutoTempAllocatorRooter(JSContext *cx, TempAllocator *temp
                                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-      : AutoGCRooter(cx, IONALLOC), temp(temp)
+      : JS::AutoGCRooter(cx, IONALLOC), temp(temp)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
-    friend void AutoGCRooter::trace(JSTracer *trc);
+    friend void JS::AutoGCRooter::trace(JSTracer *trc);
     void trace(JSTracer *trc);
 
   private:
     TempAllocator *temp;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 class IonAllocPolicy
--- a/js/src/jit/IonMacroAssembler.h
+++ b/js/src/jit/IonMacroAssembler.h
@@ -36,23 +36,23 @@ namespace jit {
 // lifoAlloc use if one will be destroyed before the other.
 class MacroAssembler : public MacroAssemblerSpecific
 {
     MacroAssembler *thisFromCtor() {
         return this;
     }
 
   public:
-    class AutoRooter : public AutoGCRooter
+    class AutoRooter : public JS::AutoGCRooter
     {
         MacroAssembler *masm_;
 
       public:
         AutoRooter(JSContext *cx, MacroAssembler *masm)
-          : AutoGCRooter(cx, IONMASM),
+          : JS::AutoGCRooter(cx, IONMASM),
             masm_(masm)
         { }
 
         MacroAssembler *masm() const {
             return masm_;
         }
     };
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -93,16 +93,18 @@
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 
 using mozilla::Maybe;
 using mozilla::PodCopy;
 using mozilla::PodZero;
 
+using JS::AutoGCRooter;
+
 using js::frontend::Parser;
 
 #ifdef HAVE_VA_LIST_AS_ARRAY
 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
 #else
 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
 #endif
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -69,76 +69,16 @@ class JS_PUBLIC_API(AutoCheckRequestDept
 JS_PUBLIC_API(void)
 AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v);
 #else
 inline void AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v) {
     /* Do nothing */
 }
 #endif /* JS_DEBUG */
 
-class JS_PUBLIC_API(AutoGCRooter) {
-  public:
-    AutoGCRooter(JSContext *cx, ptrdiff_t tag);
-    AutoGCRooter(js::ContextFriendFields *cx, ptrdiff_t tag);
-
-    ~AutoGCRooter() {
-        JS_ASSERT(this == *stackTop);
-        *stackTop = down;
-    }
-
-    /* Implemented in gc/RootMarking.cpp. */
-    inline void trace(JSTracer *trc);
-    static void traceAll(JSTracer *trc);
-    static void traceAllWrappers(JSTracer *trc);
-
-  protected:
-    AutoGCRooter * const down;
-
-    /*
-     * Discriminates actual subclass of this being used.  If non-negative, the
-     * subclass roots an array of values of the length stored in this field.
-     * If negative, meaning is indicated by the corresponding value in the enum
-     * below.  Any other negative value indicates some deeper problem such as
-     * memory corruption.
-     */
-    ptrdiff_t tag_;
-
-    enum {
-        VALARRAY =     -2, /* js::AutoValueArray */
-        PARSER =       -3, /* js::frontend::Parser */
-        SHAPEVECTOR =  -4, /* js::AutoShapeVector */
-        IDARRAY =      -6, /* js::AutoIdArray */
-        DESCVECTOR =   -7, /* js::AutoPropDescVector */
-        VALVECTOR =   -10, /* js::AutoValueVector */
-        IDVECTOR =    -13, /* js::AutoIdVector */
-        OBJVECTOR =   -14, /* js::AutoObjectVector */
-        STRINGVECTOR =-15, /* js::AutoStringVector */
-        SCRIPTVECTOR =-16, /* js::AutoScriptVector */
-        NAMEVECTOR =  -17, /* js::AutoNameVector */
-        HASHABLEVALUE=-18, /* js::HashableValue */
-        IONMASM =     -19, /* js::jit::MacroAssembler */
-        IONALLOC =    -20, /* js::jit::AutoTempAllocatorRooter */
-        WRAPVECTOR =  -21, /* js::AutoWrapperVector */
-        WRAPPER =     -22, /* js::AutoWrapperRooter */
-        OBJOBJHASHMAP=-23, /* js::AutoObjectObjectHashMap */
-        OBJU32HASHMAP=-24, /* js::AutoObjectUnsigned32HashMap */
-        OBJHASHSET =  -25, /* js::AutoObjectHashSet */
-        JSONPARSER =  -26, /* js::JSONParser */
-        CUSTOM =      -27, /* js::CustomAutoRooter */
-        FUNVECTOR =   -28  /* js::AutoFunctionVector */
-    };
-
-  private:
-    AutoGCRooter ** const stackTop;
-
-    /* No copy or assignment semantics. */
-    AutoGCRooter(AutoGCRooter &ida) MOZ_DELETE;
-    void operator=(AutoGCRooter &ida) MOZ_DELETE;
-};
-
 /* AutoValueArray roots an internal fixed-size array of Values. */
 template <size_t N>
 class AutoValueArray : public AutoGCRooter
 {
     const size_t length_;
     Value elements_[N];
 
   public:
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -909,22 +909,22 @@ class AutoObjectHashSet : public AutoHas
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 /* AutoArrayRooter roots an external array of Values. */
-class AutoArrayRooter : private AutoGCRooter
+class AutoArrayRooter : private JS::AutoGCRooter
 {
   public:
     AutoArrayRooter(JSContext *cx, size_t len, Value *vec
                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-      : AutoGCRooter(cx, len), array(vec)
+      : JS::AutoGCRooter(cx, len), array(vec)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         JS_ASSERT(tag_ >= 0);
     }
 
     void changeLength(size_t newLength) {
         tag_ = ptrdiff_t(newLength);
         JS_ASSERT(tag_ >= 0);
@@ -956,17 +956,17 @@ class AutoArrayRooter : private AutoGCRo
         JS_ASSERT(i < size_t(tag_));
         return MutableHandleValue::fromMarkedLocation(&array[i]);
     }
     HandleValue operator[](size_t i) const {
         JS_ASSERT(i < size_t(tag_));
         return HandleValue::fromMarkedLocation(&array[i]);
     }
 
-    friend void AutoGCRooter::trace(JSTracer *trc);
+    friend void JS::AutoGCRooter::trace(JSTracer *trc);
 
   private:
     Value *array;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 class AutoAssertNoException
 {
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -646,30 +646,30 @@ class AutoWrapperVector : public AutoVec
         : AutoVectorRooter<WrapperValue>(cx, WRAPVECTOR)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
-class AutoWrapperRooter : private AutoGCRooter {
+class AutoWrapperRooter : private JS::AutoGCRooter {
   public:
     AutoWrapperRooter(JSContext *cx, WrapperValue v
                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-      : AutoGCRooter(cx, WRAPPER), value(v)
+      : JS::AutoGCRooter(cx, WRAPPER), value(v)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     operator JSObject *() const {
         return value.get().toObjectOrNull();
     }
 
-    friend void AutoGCRooter::trace(JSTracer *trc);
+    friend void JS::AutoGCRooter::trace(JSTracer *trc);
 
   private:
     WrapperValue value;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 } /* namespace js */
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -225,16 +225,18 @@
 using namespace js;
 using namespace js::gc;
 
 using mozilla::ArrayEnd;
 using mozilla::DebugOnly;
 using mozilla::Maybe;
 using mozilla::Swap;
 
+using JS::AutoGCRooter;
+
 /* Perform a Full GC every 20 seconds if MaybeGC is called */
 static const uint64_t GC_IDLE_FULL_SPAN = 20 * 1000 * 1000;
 
 /* Increase the IGC marking slice time if we are in highFrequencyGC mode. */
 static const int IGC_MARK_SLICE_MULTIPLIER = 2;
 
 #if defined(ANDROID) || defined(MOZ_B2G)
 static const int MAX_EMPTY_CHUNK_COUNT = 2;
--- a/js/src/jsonparser.h
+++ b/js/src/jsonparser.h
@@ -4,22 +4,24 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jsonparser_h
 #define jsonparser_h
 
 #include "mozilla/Attributes.h"
 
+#include "jspubtd.h"
+
 #include "ds/IdValuePair.h"
 #include "vm/String.h"
 
 namespace js {
 
-class MOZ_STACK_CLASS JSONParser : private AutoGCRooter
+class MOZ_STACK_CLASS JSONParser : private JS::AutoGCRooter
 {
   public:
     enum ErrorHandling { RaiseError, NoError };
 
   private:
     /* Data members */
 
     JSContext * const cx;
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -6,16 +6,17 @@
 
 #ifndef jspubtd_h
 #define jspubtd_h
 
 /*
  * JS public API typedefs.
  */
 
+#include "mozilla/Assertions.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/NullPtr.h"
 #include "mozilla/PodOperations.h"
 
 #include "jsprototypes.h"
 #include "jstypes.h"
 
 #include "js/TypeDecls.h"
@@ -27,27 +28,29 @@
 namespace JS {
 
 class AutoIdVector;
 class CallArgs;
 
 template <typename T>
 class Rooted;
 
-class JS_PUBLIC_API(AutoGCRooter);
-
 class JS_FRIEND_API(CompileOptions);
 class JS_FRIEND_API(ReadOnlyCompileOptions);
 class JS_FRIEND_API(OwningCompileOptions);
 class JS_PUBLIC_API(CompartmentOptions);
 
 struct Zone;
 
 } /* namespace JS */
 
+namespace js {
+struct ContextFriendFields;
+} // namespace js
+
 /*
  * Run-time version enumeration.  For compile-time version checking, please use
  * the JS_HAS_* macros in jsversion.h, or use MOZJS_MAJOR_VERSION,
  * MOZJS_MINOR_VERSION, MOZJS_PATCH_VERSION, and MOZJS_ALPHA definitions.
  */
 enum JSVersion {
     JSVERSION_ECMA_3  = 148,
     JSVERSION_1_6     = 160,
@@ -241,16 +244,78 @@ template<>
 inline mozilla::LinkedList<PersistentRootedString>
 &Runtime::getPersistentRootedList<JSString *>() { return stringPersistentRooteds; }
 
 template<>
 inline mozilla::LinkedList<PersistentRootedValue>
 &Runtime::getPersistentRootedList<Value>() { return valuePersistentRooteds; }
 
 } /* namespace shadow */
+
+class JS_PUBLIC_API(AutoGCRooter)
+{
+  public:
+    AutoGCRooter(JSContext *cx, ptrdiff_t tag);
+    AutoGCRooter(js::ContextFriendFields *cx, ptrdiff_t tag);
+
+    ~AutoGCRooter() {
+        MOZ_ASSERT(this == *stackTop);
+        *stackTop = down;
+    }
+
+    /* Implemented in gc/RootMarking.cpp. */
+    inline void trace(JSTracer *trc);
+    static void traceAll(JSTracer *trc);
+    static void traceAllWrappers(JSTracer *trc);
+
+  protected:
+    AutoGCRooter * const down;
+
+    /*
+     * Discriminates actual subclass of this being used.  If non-negative, the
+     * subclass roots an array of values of the length stored in this field.
+     * If negative, meaning is indicated by the corresponding value in the enum
+     * below.  Any other negative value indicates some deeper problem such as
+     * memory corruption.
+     */
+    ptrdiff_t tag_;
+
+    enum {
+        VALARRAY =     -2, /* js::AutoValueArray */
+        PARSER =       -3, /* js::frontend::Parser */
+        SHAPEVECTOR =  -4, /* js::AutoShapeVector */
+        IDARRAY =      -6, /* js::AutoIdArray */
+        DESCVECTOR =   -7, /* js::AutoPropDescVector */
+        VALVECTOR =   -10, /* js::AutoValueVector */
+        IDVECTOR =    -13, /* js::AutoIdVector */
+        OBJVECTOR =   -14, /* js::AutoObjectVector */
+        STRINGVECTOR =-15, /* js::AutoStringVector */
+        SCRIPTVECTOR =-16, /* js::AutoScriptVector */
+        NAMEVECTOR =  -17, /* js::AutoNameVector */
+        HASHABLEVALUE=-18, /* js::HashableValue */
+        IONMASM =     -19, /* js::jit::MacroAssembler */
+        IONALLOC =    -20, /* js::jit::AutoTempAllocatorRooter */
+        WRAPVECTOR =  -21, /* js::AutoWrapperVector */
+        WRAPPER =     -22, /* js::AutoWrapperRooter */
+        OBJOBJHASHMAP=-23, /* js::AutoObjectObjectHashMap */
+        OBJU32HASHMAP=-24, /* js::AutoObjectUnsigned32HashMap */
+        OBJHASHSET =  -25, /* js::AutoObjectHashSet */
+        JSONPARSER =  -26, /* js::JSONParser */
+        CUSTOM =      -27, /* js::CustomAutoRooter */
+        FUNVECTOR =   -28  /* js::AutoFunctionVector */
+    };
+
+  private:
+    AutoGCRooter ** const stackTop;
+
+    /* No copy or assignment semantics. */
+    AutoGCRooter(AutoGCRooter &ida) MOZ_DELETE;
+    void operator=(AutoGCRooter &ida) MOZ_DELETE;
+};
+
 } /* namespace JS */
 
 namespace js {
 
 /*
  * Parallel operations in general can have one of three states. They may
  * succeed, fail, or "bail", where bail indicates that the code encountered an
  * unexpected condition and should be re-run sequentially. Different