Backed out 2 changesets (bug 1052139, bug 1105261) for b2g desktop crashes
authorPhil Ringnalda <philringnalda@gmail.com>
Mon, 01 Dec 2014 18:25:53 -0800
changeset 218187 7b8eb088c38082d38ba3b459d8ae7e66696c1575
parent 218186 458fbb343a6d4729c04f2da153e1550888530ed2
child 218188 49f9502a978ed649c888b2ff84bd1581b63657d6
push id52470
push userphilringnalda@gmail.com
push dateTue, 02 Dec 2014 02:26:06 +0000
treeherdermozilla-inbound@7b8eb088c380 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1052139, 1105261
milestone37.0a1
backs out72c672d91f9c2060e169e3e037decd1fc53e7545
e3ce0e3a147c749222e28c1d2fa9137f9d8e0cc0
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
Backed out 2 changesets (bug 1052139, bug 1105261) for b2g desktop crashes CLOSED TREE Backed out changeset 72c672d91f9c (bug 1052139) Backed out changeset e3ce0e3a147c (bug 1105261)
js/src/asmjs/AsmJSLink.cpp
js/src/asmjs/AsmJSValidate.cpp
js/src/frontend/TokenStream.cpp
js/src/jsapi.cpp
js/src/jsreflect.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
js/src/vm/Runtime.h
js/src/vm/SelfHosting.cpp
mfbt/Vector.h
mfbt/tests/TestVector.cpp
mfbt/tests/moz.build
--- a/js/src/asmjs/AsmJSLink.cpp
+++ b/js/src/asmjs/AsmJSLink.cpp
@@ -822,19 +822,17 @@ HandleDynamicLinkFailure(JSContext *cx, 
 
     RootedFunction fun(cx, NewFunction(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED,
                                        cx->global(), name, JSFunction::FinalizeKind,
                                        TenuredObject));
     if (!fun)
         return false;
 
     AutoNameVector formals(cx);
-    if (!formals.reserve(3))
-        return false;
-
+    formals.reserve(3);
     if (module.globalArgumentName())
         formals.infallibleAppend(module.globalArgumentName());
     if (module.importArgumentName())
         formals.infallibleAppend(module.importArgumentName());
     if (module.bufferArgumentName())
         formals.infallibleAppend(module.bufferArgumentName());
 
     CompileOptions options(cx);
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -8323,18 +8323,17 @@ GenerateFFIInterpExit(ModuleCompiler &m,
     MacroAssembler &masm = m.masm();
     MOZ_ASSERT(masm.framePushed() == 0);
 
     // Argument types for InvokeFromAsmJS_*:
     static const MIRType typeArray[] = { MIRType_Pointer,   // exitDatum
                                          MIRType_Int32,     // argc
                                          MIRType_Pointer }; // argv
     MIRTypeVector invokeArgTypes(m.cx());
-    if (!invokeArgTypes.append(typeArray, ArrayLength(typeArray)))
-        return false;
+    invokeArgTypes.infallibleAppend(typeArray, ArrayLength(typeArray));
 
     // At the point of the call, the stack layout shall be (sp grows to the left):
     //   | stack args | padding | Value argv[] | padding | retaddr | caller stack args |
     // The padding between stack args and argv ensures that argv is aligned. The
     // padding between argv and retaddr ensures that sp is aligned.
     unsigned offsetToArgv = AlignBytes(StackArgBytes(invokeArgTypes), sizeof(double));
     unsigned argvBytes = Max<size_t>(1, exit.sig().args().length()) * sizeof(Value);
     unsigned framePushed = StackDecrementForCall(masm, ABIStackAlignment, offsetToArgv + argvBytes);
@@ -8441,19 +8440,17 @@ GenerateFFIIonExit(ModuleCompiler &m, co
     unsigned ionArgBytes = 3 * sizeof(size_t) + (1 + exit.sig().args().length()) * sizeof(Value);
     unsigned totalIonBytes = offsetToIonArgs + ionArgBytes + MaybeSavedGlobalReg;
     unsigned ionFrameSize = StackDecrementForCall(masm, AsmJSStackAlignment, totalIonBytes);
 
     // Coercion calls use the following stack layout (sp grows to the left):
     //   | stack args | padding | Value argv[1] | ...
     // The padding between args and argv ensures that argv is aligned.
     MIRTypeVector coerceArgTypes(m.cx());
-    if (!coerceArgTypes.append(MIRType_Pointer)) // argv
-        return false;
-
+    coerceArgTypes.infallibleAppend(MIRType_Pointer); // argv
     unsigned offsetToCoerceArgv = AlignBytes(StackArgBytes(coerceArgTypes), sizeof(double));
     unsigned totalCoerceBytes = offsetToCoerceArgv + sizeof(Value) + MaybeSavedGlobalReg;
     unsigned coerceFrameSize = StackDecrementForCall(masm, AsmJSStackAlignment, totalCoerceBytes);
 
     unsigned framePushed = Max(ionFrameSize, coerceFrameSize);
 
     Label begin;
     GenerateAsmJSExitPrologue(masm, framePushed, AsmJSExit::JitFFI, &begin);
@@ -8703,19 +8700,16 @@ GenerateFFIExits(ModuleCompiler &m, cons
 //     (coming out) and preserve non-volatile registers.
 static bool
 GenerateBuiltinThunk(ModuleCompiler &m, AsmJSExit::BuiltinKind builtin)
 {
     MacroAssembler &masm = m.masm();
     MOZ_ASSERT(masm.framePushed() == 0);
 
     MIRTypeVector argTypes(m.cx());
-    if (!argTypes.reserve(2))
-        return false;
-
     switch (builtin) {
       case AsmJSExit::Builtin_ToInt32:
         argTypes.infallibleAppend(MIRType_Int32);
         break;
 #if defined(JS_CODEGEN_ARM)
       case AsmJSExit::Builtin_IDivMod:
       case AsmJSExit::Builtin_UDivMod:
         argTypes.infallibleAppend(MIRType_Int32);
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -146,17 +146,17 @@ TokenStream::SourceCoords::SourceCoords(
     // which fixes the GCC/clang error, but causes bustage on Windows.  Sigh.
     //
     uint32_t maxPtr = MAX_PTR;
 
     // The first line begins at buffer offset 0.  MAX_PTR is the sentinel.  The
     // appends cannot fail because |lineStartOffsets_| has statically-allocated
     // elements.
     MOZ_ASSERT(lineStartOffsets_.capacity() >= 2);
-    MOZ_ALWAYS_TRUE(lineStartOffsets_.reserve(2));
+    (void)lineStartOffsets_.reserve(2);
     lineStartOffsets_.infallibleAppend(0);
     lineStartOffsets_.infallibleAppend(maxPtr);
 }
 
 MOZ_ALWAYS_INLINE void
 TokenStream::SourceCoords::add(uint32_t lineNum, uint32_t lineStartOffset)
 {
     uint32_t lineIndex = lineNumToIndex(lineNum);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2303,16 +2303,49 @@ JS_GetConstructor(JSContext *cx, HandleO
     if (!IsFunctionObject(cval)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
                              proto->getClass()->name);
         return nullptr;
     }
     return &cval.toObject();
 }
 
+namespace {
+
+class AutoCompartmentRooter : private JS::CustomAutoRooter
+{
+  public:
+    explicit AutoCompartmentRooter(JSContext *cx, JSCompartment *comp
+                                   MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+      : CustomAutoRooter(cx), compartment(comp)
+    {
+        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    }
+
+    operator JSCompartment *() {
+        return compartment;
+    }
+
+    JSCompartment *operator->() {
+        return compartment;
+    }
+
+  protected:
+    virtual void trace(JSTracer *trc)
+    {
+        compartment->mark();
+    }
+
+  private:
+    JSCompartment *compartment;
+    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+} /* anonymous namespace */
+
 bool
 JS::CompartmentOptions::extraWarnings(JSRuntime *rt) const
 {
     return extraWarningsOverride_.get(rt->options().extraWarnings());
 }
 
 bool
 JS::CompartmentOptions::extraWarnings(JSContext *cx) const
@@ -2354,18 +2387,52 @@ JS::CompartmentOptionsRef(JSContext *cx)
 
 JS_PUBLIC_API(JSObject *)
 JS_NewGlobalObject(JSContext *cx, const JSClass *clasp, JSPrincipals *principals,
                    JS::OnNewGlobalHookOption hookOption,
                    const JS::CompartmentOptions &options /* = JS::CompartmentOptions() */)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-
-    return GlobalObject::new_(cx, Valueify(clasp), principals, hookOption, options);
+    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->isExceptionPending());
+
+    JSRuntime *rt = cx->runtime();
+
+    Zone *zone;
+    if (options.zoneSpecifier() == JS::SystemZone)
+        zone = rt->gc.systemZone;
+    else if (options.zoneSpecifier() == JS::FreshZone)
+        zone = nullptr;
+    else
+        zone = static_cast<Zone *>(options.zonePointer());
+
+    AutoCompartmentRooter compartment(cx, NewCompartment(cx, zone, principals, options));
+    if (!compartment)
+        return nullptr;
+
+    // Lazily create the system zone.
+    if (!rt->gc.systemZone && options.zoneSpecifier() == JS::SystemZone) {
+        rt->gc.systemZone = compartment->zone();
+        rt->gc.systemZone->isSystem = true;
+    }
+
+    Rooted<GlobalObject *> global(cx);
+    {
+        AutoCompartment ac(cx, compartment);
+        global = GlobalObject::create(cx, Valueify(clasp));
+    }
+
+    if (!global)
+        return nullptr;
+
+    if (hookOption == JS::FireOnNewGlobalHook)
+        JS_FireOnNewGlobalObject(cx, global);
+
+    return global;
 }
 
 JS_PUBLIC_API(void)
 JS_GlobalObjectTraceHook(JSTracer *trc, JSObject *global)
 {
     MOZ_ASSERT(global->is<GlobalObject>());
 
     // Off thread parsing and compilation tasks create a dummy global which is then
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -2107,17 +2107,17 @@ ASTSerializer::let(ParseNode *pn, bool e
 bool
 ASTSerializer::importDeclaration(ParseNode *pn, MutableHandleValue dst)
 {
     MOZ_ASSERT(pn->isKind(PNK_IMPORT));
     MOZ_ASSERT(pn->pn_left->isKind(PNK_IMPORT_SPEC_LIST));
     MOZ_ASSERT(pn->pn_right->isKind(PNK_STRING));
 
     NodeVector elts(cx);
-    if (!elts.reserve(pn->pn_left->pn_count))
+    if (!elts.reserve(pn->pn_count))
         return false;
 
     for (ParseNode *next = pn->pn_left->pn_head; next; next = next->pn_next) {
         RootedValue elt(cx);
         if (!importSpecifier(next, &elt))
             return false;
         elts.infallibleAppend(elt);
     }
@@ -2146,17 +2146,17 @@ ASTSerializer::exportDeclaration(ParseNo
     MOZ_ASSERT_IF(pn->isKind(PNK_EXPORT_FROM), pn->pn_right->isKind(PNK_STRING));
 
     RootedValue decl(cx, NullValue());
     NodeVector elts(cx);
 
     ParseNode *kid = pn->isKind(PNK_EXPORT) ? pn->pn_kid : pn->pn_left;
     switch (ParseNodeKind kind = kid->getKind()) {
       case PNK_EXPORT_SPEC_LIST:
-        if (!elts.reserve(pn->pn_left->pn_count))
+        if (!elts.reserve(pn->pn_count))
             return false;
 
         for (ParseNode *next = pn->pn_left->pn_head; next; next = next->pn_next) {
             RootedValue elt(cx);
             if (next->isKind(PNK_EXPORT_SPEC)) {
                 if (!exportSpecifier(next, &elt))
                     return false;
             } else {
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -224,17 +224,17 @@ GlobalObject::initBuiltinConstructor(JSC
     global->setPrototype(key, ObjectValue(*proto));
     global->setConstructorPropertySlot(key, ObjectValue(*ctor));
 
     types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
     return true;
 }
 
 GlobalObject *
-GlobalObject::createInternal(JSContext *cx, const Class *clasp)
+GlobalObject::create(JSContext *cx, const Class *clasp)
 {
     MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
     MOZ_ASSERT(clasp->trace == JS_GlobalObjectTraceHook);
 
     JSObject *obj = NewObjectWithGivenProto(cx, clasp, nullptr, nullptr, SingletonObject);
     if (!obj)
         return nullptr;
 
@@ -252,58 +252,16 @@ GlobalObject::createInternal(JSContext *
     if (!global->setUnqualifiedVarObj(cx))
         return nullptr;
     if (!global->setDelegate(cx))
         return nullptr;
 
     return global;
 }
 
-GlobalObject *
-GlobalObject::new_(JSContext *cx, const Class *clasp, JSPrincipals *principals,
-                   JS::OnNewGlobalHookOption hookOption,
-                   const JS::CompartmentOptions &options)
-{
-    MOZ_ASSERT(!cx->isExceptionPending());
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
-
-    JSRuntime *rt = cx->runtime();
-
-    Zone *zone;
-    if (options.zoneSpecifier() == JS::SystemZone)
-        zone = rt->gc.systemZone;
-    else if (options.zoneSpecifier() == JS::FreshZone)
-        zone = nullptr;
-    else
-        zone = static_cast<Zone *>(options.zonePointer());
-
-    JSCompartment *compartment = NewCompartment(cx, zone, principals, options);
-    if (!compartment)
-        return nullptr;
-
-    // Lazily create the system zone.
-    if (!rt->gc.systemZone && options.zoneSpecifier() == JS::SystemZone) {
-        rt->gc.systemZone = compartment->zone();
-        rt->gc.systemZone->isSystem = true;
-    }
-
-    Rooted<GlobalObject*> global(cx);
-    {
-        AutoCompartment ac(cx, compartment);
-        global = GlobalObject::createInternal(cx, clasp);
-        if (!global)
-            return nullptr;
-    }
-
-    if (hookOption == JS::FireOnNewGlobalHook)
-        JS_FireOnNewGlobalObject(cx, global);
-
-    return global;
-}
-
 /* static */ bool
 GlobalObject::getOrCreateEval(JSContext *cx, Handle<GlobalObject*> global,
                               MutableHandleObject eval)
 {
     if (!global->getOrCreateObjectPrototype(cx))
         return false;
     eval.set(&global->getSlot(EVAL).toObject());
     return true;
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -12,17 +12,16 @@
 #include "jsexn.h"
 #include "jsfun.h"
 #include "jsnum.h"
 
 #include "builtin/RegExp.h"
 #include "js/Vector.h"
 #include "vm/ArrayBufferObject.h"
 #include "vm/ErrorObject.h"
-#include "vm/Runtime.h"
 
 extern JSObject *
 js_InitSharedArrayBufferClass(JSContext *cx, js::HandleObject obj);
 
 namespace js {
 
 class Debugger;
 class TypedObjectModuleObject;
@@ -255,27 +254,18 @@ class GlobalObject : public NativeObject
     void setCreateDataViewForThis(Handle<JSFunction*> fun) {
         MOZ_ASSERT(getSlotRef(CREATE_DATAVIEW_FOR_THIS).isUndefined());
         setSlot(CREATE_DATAVIEW_FOR_THIS, ObjectValue(*fun));
     }
 
     template<typename T>
     inline void setCreateArrayFromBuffer(Handle<JSFunction*> fun);
 
-  private:
-    // Disallow use of unqualified JSObject::create in GlobalObject.
-    static GlobalObject *create(...) MOZ_DELETE;
-
-    friend struct ::JSRuntime;
-    static GlobalObject *createInternal(JSContext *cx, const Class *clasp);
-
   public:
-    static GlobalObject *
-    new_(JSContext *cx, const Class *clasp, JSPrincipals *principals,
-         JS::OnNewGlobalHookOption hookOption, const JS::CompartmentOptions &options);
+    static GlobalObject *create(JSContext *cx, const Class *clasp);
 
     /*
      * Create a constructor function with the specified name and length using
      * ctor, a method which creates objects with the given class.
      */
     JSFunction *
     createConstructor(JSContext *cx, JSNative ctor, JSAtom *name, unsigned length,
                       gc::AllocKind kind = JSFunction::FinalizeKind);
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -836,19 +836,16 @@ struct JSRuntime : public JS::shadow::Ru
     js::jit::JitRuntime *jitRuntime_;
 
     /*
      * Self-hosting state cloned on demand into other compartments. Shared with the parent
      * runtime if there is one.
      */
     js::NativeObject *selfHostingGlobal_;
 
-    static js::GlobalObject *
-    createSelfHostingGlobal(JSContext *cx);
-
     /* Space for interpreter frames. */
     js::InterpreterStack interpreterStack_;
 
     js::jit::ExecutableAllocator *createExecutableAllocator(JSContext *cx);
     js::jit::JitRuntime *createJitRuntime(JSContext *cx);
 
   public:
     js::jit::ExecutableAllocator *getExecAlloc(JSContext *cx) {
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -44,16 +44,26 @@ using namespace js::selfhosted;
 using JS::AutoCheckCannotGC;
 
 static void
 selfHosting_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 {
     PrintError(cx, stderr, message, report, true);
 }
 
+static const JSClass self_hosting_global_class = {
+    "self-hosting-global", JSCLASS_GLOBAL_FLAGS,
+    JS_PropertyStub,  JS_DeletePropertyStub,
+    JS_PropertyStub,  JS_StrictPropertyStub,
+    JS_EnumerateStub, JS_ResolveStub,
+    JS_ConvertStub,   nullptr,
+    nullptr, nullptr, nullptr,
+    JS_GlobalObjectTraceHook
+};
+
 bool
 js::intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedValue val(cx, args[0]);
     RootedObject obj(cx, ToObject(cx, val));
     if (!obj)
         return false;
@@ -1218,109 +1228,81 @@ js::FillSelfHostingCompileOptions(Compil
     options.werrorOption = true;
     options.strictOption = true;
 
 #ifdef DEBUG
     options.extraWarningsOption = true;
 #endif
 }
 
-GlobalObject *
-JSRuntime::createSelfHostingGlobal(JSContext *cx)
-{
-    MOZ_ASSERT(!cx->isExceptionPending());
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
-
-    JS::CompartmentOptions options;
-    options.setDiscardSource(true);
-    options.setZone(JS::FreshZone);
-
-    JSCompartment *compartment = NewCompartment(cx, nullptr, nullptr, options);
-    if (!compartment)
-        return nullptr;
-
-    static const Class shgClass = {
-        "self-hosting-global", JSCLASS_GLOBAL_FLAGS,
-        JS_PropertyStub,  JS_DeletePropertyStub,
-        JS_PropertyStub,  JS_StrictPropertyStub,
-        JS_EnumerateStub, JS_ResolveStub,
-        JS_ConvertStub,   nullptr,
-        nullptr, nullptr, nullptr,
-        JS_GlobalObjectTraceHook
-    };
-
-    AutoCompartment ac(cx, compartment);
-    Rooted<GlobalObject*> shg(cx, GlobalObject::createInternal(cx, &shgClass));
-    if (!shg)
-        return nullptr;
-
-    cx->runtime()->selfHostingGlobal_ = shg;
-    compartment->isSelfHosting = true;
-    compartment->isSystem = true;
-
-    if (!GlobalObject::initSelfHostingBuiltins(cx, shg, intrinsic_functions))
-        return nullptr;
-
-    JS_FireOnNewGlobalObject(cx, shg);
-
-    return shg;
-}
-
 bool
 JSRuntime::initSelfHosting(JSContext *cx)
 {
     MOZ_ASSERT(!selfHostingGlobal_);
 
     if (cx->runtime()->parentRuntime) {
         selfHostingGlobal_ = cx->runtime()->parentRuntime->selfHostingGlobal_;
         return true;
     }
 
     /*
      * Self hosted state can be accessed from threads for other runtimes
      * parented to this one, so cannot include state in the nursery.
      */
     JS::AutoDisableGenerationalGC disable(cx->runtime());
 
-    Rooted<GlobalObject*> shg(cx, JSRuntime::createSelfHostingGlobal(cx));
-    if (!shg)
+    JS::CompartmentOptions compartmentOptions;
+    compartmentOptions.setDiscardSource(true);
+    if (!(selfHostingGlobal_ = MaybeNativeObject(JS_NewGlobalObject(cx, &self_hosting_global_class,
+                                                                    nullptr, JS::DontFireOnNewGlobalHook,
+                                                                    compartmentOptions))))
+    {
+        return false;
+    }
+
+    JSAutoCompartment ac(cx, selfHostingGlobal_);
+    Rooted<GlobalObject*> shg(cx, &selfHostingGlobal_->as<GlobalObject>());
+    selfHostingGlobal_->compartment()->isSelfHosting = true;
+    selfHostingGlobal_->compartment()->isSystem = true;
+
+    if (!GlobalObject::initSelfHostingBuiltins(cx, shg, intrinsic_functions))
         return false;
 
-    JSAutoCompartment ac(cx, shg);
+    JS_FireOnNewGlobalObject(cx, shg);
 
     CompileOptions options(cx);
     FillSelfHostingCompileOptions(options);
 
     /*
      * Set a temporary error reporter printing to stderr because it is too
      * early in the startup process for any other reporter to be registered
      * and we don't want errors in self-hosted code to be silently swallowed.
      */
     JSErrorReporter oldReporter = JS_SetErrorReporter(cx->runtime(), selfHosting_ErrorReporter);
     RootedValue rv(cx);
-    bool ok = true;
+    bool ok = false;
 
     char *filename = getenv("MOZ_SELFHOSTEDJS");
     if (filename) {
         RootedScript script(cx);
         if (Compile(cx, shg, options, filename, &script))
             ok = Execute(cx, script, *shg.get(), rv.address());
     } else {
         uint32_t srcLen = GetRawScriptsSize();
 
         const unsigned char *compressed = compressedSources;
         uint32_t compressedLen = GetCompressedSize();
         ScopedJSFreePtr<char> src(selfHostingGlobal_->zone()->pod_malloc<char>(srcLen));
         if (!src || !DecompressString(compressed, compressedLen,
                                       reinterpret_cast<unsigned char *>(src.get()), srcLen))
         {
-            ok = false;
+            return false;
         }
 
-        ok = ok && Evaluate(cx, shg, options, src, srcLen, &rv);
+        ok = Evaluate(cx, shg, options, src, srcLen, &rv);
     }
     JS_SetErrorReporter(cx->runtime(), oldReporter);
     return ok;
 }
 
 void
 JSRuntime::finishSelfHosting()
 {
--- a/mfbt/Vector.h
+++ b/mfbt/Vector.h
@@ -210,20 +210,16 @@ struct VectorImpl<T, N, AP, ThisVector, 
     }
     aV.mBegin = newbuf;
     /* aV.mLength is unchanged. */
     aV.mCapacity = aNewCap;
     return true;
   }
 };
 
-// A struct for TestVector.cpp to access private internal fields.
-// DO NOT DEFINE IN YOUR OWN CODE.
-struct VectorTesting;
-
 } // namespace detail
 
 /*
  * A CRTP base class for vector-like classes.  Unless you really really want
  * your own vector class -- and you almost certainly don't -- you should use
  * mozilla::Vector instead!
  *
  * See mozilla::Vector for interface requirements.
@@ -232,18 +228,16 @@ template<typename T, size_t N, class All
 class VectorBase : private AllocPolicy
 {
   /* utilities */
 
   static const bool kElemIsPod = IsPod<T>::value;
   typedef detail::VectorImpl<T, N, AllocPolicy, ThisVector, kElemIsPod> Impl;
   friend struct detail::VectorImpl<T, N, AllocPolicy, ThisVector, kElemIsPod>;
 
-  friend struct detail::VectorTesting;
-
   bool growStorageBy(size_t aIncr);
   bool convertToHeapStorage(size_t aNewCap);
 
   /* magic constants */
 
   static const int kMaxInlineBytes = 1024;
 
   /* compute constants */
@@ -328,27 +322,20 @@ class VectorBase : private AllocPolicy
   }
 
   const T* endNoCheck() const
   {
     return mBegin + mLength;
   }
 
 #ifdef DEBUG
-  /**
-   * The amount of explicitly allocated space in this vector that is immediately
-   * available to be filled by appending additional elements.  This value is
-   * always greater than or equal to |length()| -- the vector's actual elements
-   * are implicitly reserved.  This value is always less than or equal to
-   * |capacity()|.  It may be explicitly increased using the |reserve()| method.
-   */
   size_t reserved() const
   {
+    MOZ_ASSERT(mReserved <= mCapacity);
     MOZ_ASSERT(mLength <= mReserved);
-    MOZ_ASSERT(mReserved <= mCapacity);
     return mReserved;
   }
 #endif
 
   /* Append operations guaranteed to succeed due to pre-reserved space. */
   template<typename U> void internalAppend(U&& aU);
   template<typename U, size_t O, class BP, class UV>
   void internalAppendAll(const VectorBase<U, O, BP, UV>& aU);
@@ -458,22 +445,18 @@ public:
 
   /**
    * Given that the vector is empty and has no inline storage, grow to
    * |capacity|.
    */
   bool initCapacity(size_t aRequest);
 
   /**
-   * If reserve(aRequest) succeeds and |aRequest >= length()|, then appending
-   * |aRequest - length()| elements, in any sequence of append/appendAll calls,
-   * is guaranteed to succeed.
-   *
-   * A request to reserve an amount less than the current length does not affect
-   * reserved space.
+   * If reserve(length() + N) succeeds, the N next appends are guaranteed to
+   * succeed.
    */
   bool reserve(size_t aRequest);
 
   /**
    * Destroy elements in the range [end() - aIncr, end()). Does not deallocate
    * or unreserve storage for those elements.
    */
   void shrinkBy(size_t aIncr);
@@ -634,17 +617,17 @@ private:
 
 template<typename T, size_t N, class AP, class TV>
 MOZ_ALWAYS_INLINE
 VectorBase<T, N, AP, TV>::VectorBase(AP aAP)
   : AP(aAP)
   , mLength(0)
   , mCapacity(kInlineCapacity)
 #ifdef DEBUG
-  , mReserved(0)
+  , mReserved(kInlineCapacity)
   , mEntered(false)
 #endif
 {
   mBegin = static_cast<T*>(mStorage.addr());
 }
 
 /* Move constructor. */
 template<typename T, size_t N, class AllocPolicy, class TV>
@@ -674,17 +657,17 @@ VectorBase<T, N, AllocPolicy, TV>::Vecto
      * Take src's buffer, and turn src into an empty vector using
      * in-line storage.
      */
     mBegin = aRhs.mBegin;
     aRhs.mBegin = static_cast<T*>(aRhs.mStorage.addr());
     aRhs.mCapacity = kInlineCapacity;
     aRhs.mLength = 0;
 #ifdef DEBUG
-    aRhs.mReserved = 0;
+    aRhs.mReserved = kInlineCapacity;
 #endif
   }
 }
 
 /* Move assignment. */
 template<typename T, size_t N, class AP, class TV>
 MOZ_ALWAYS_INLINE TV&
 VectorBase<T, N, AP, TV>::operator=(TV&& aRhs)
@@ -953,17 +936,17 @@ VectorBase<T, N, AP, TV>::clearAndFree()
 
   if (usingInlineStorage()) {
     return;
   }
   this->free_(beginNoCheck());
   mBegin = static_cast<T*>(mStorage.addr());
   mCapacity = kInlineCapacity;
 #ifdef DEBUG
-  mReserved = 0;
+  mReserved = kInlineCapacity;
 #endif
 }
 
 template<typename T, size_t N, class AP, class TV>
 inline bool
 VectorBase<T, N, AP, TV>::canAppendWithoutRealloc(size_t aNeeded) const
 {
   return mLength + aNeeded <= mCapacity;
@@ -1167,17 +1150,17 @@ VectorBase<T, N, AP, TV>::extractRawBuff
     /* mBegin, mCapacity are unchanged. */
     mLength = 0;
   } else {
     ret = mBegin;
     mBegin = static_cast<T*>(mStorage.addr());
     mLength = 0;
     mCapacity = kInlineCapacity;
 #ifdef DEBUG
-    mReserved = 0;
+    mReserved = kInlineCapacity;
 #endif
   }
   return ret;
 }
 
 template<typename T, size_t N, class AP, class TV>
 inline void
 VectorBase<T, N, AP, TV>::replaceRawBuffer(T* aP, size_t aLength)
deleted file mode 100644
--- a/mfbt/tests/TestVector.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-#include "mozilla/Move.h"
-#include "mozilla/Vector.h"
-
-using mozilla::detail::VectorTesting;
-using mozilla::Move;
-using mozilla::Vector;
-
-struct mozilla::detail::VectorTesting
-{
-  static void testReserved();
-};
-
-void
-mozilla::detail::VectorTesting::testReserved()
-{
-#ifdef DEBUG
-  Vector<bool> bv;
-  MOZ_RELEASE_ASSERT(bv.reserved() == 0);
-
-  MOZ_RELEASE_ASSERT(bv.append(true));
-  MOZ_RELEASE_ASSERT(bv.reserved() == 1);
-
-  Vector<bool> otherbv;
-  MOZ_RELEASE_ASSERT(otherbv.append(false));
-  MOZ_RELEASE_ASSERT(otherbv.append(true));
-  MOZ_RELEASE_ASSERT(bv.appendAll(otherbv));
-  MOZ_RELEASE_ASSERT(bv.reserved() == 3);
-
-  MOZ_RELEASE_ASSERT(bv.reserve(5));
-  MOZ_RELEASE_ASSERT(bv.reserved() == 5);
-
-  MOZ_RELEASE_ASSERT(bv.reserve(1));
-  MOZ_RELEASE_ASSERT(bv.reserved() == 5);
-
-  Vector<bool> bv2(Move(bv));
-  MOZ_RELEASE_ASSERT(bv.reserved() == 0);
-  MOZ_RELEASE_ASSERT(bv2.reserved() == 5);
-
-  bv2.clearAndFree();
-  MOZ_RELEASE_ASSERT(bv2.reserved() == 0);
-
-  Vector<int, 42> iv;
-  MOZ_RELEASE_ASSERT(iv.reserved() == 0);
-
-  MOZ_RELEASE_ASSERT(iv.append(17));
-  MOZ_RELEASE_ASSERT(iv.reserved() == 1);
-
-  Vector<int, 42> otheriv;
-  MOZ_RELEASE_ASSERT(otheriv.append(42));
-  MOZ_RELEASE_ASSERT(otheriv.append(37));
-  MOZ_RELEASE_ASSERT(iv.appendAll(otheriv));
-  MOZ_RELEASE_ASSERT(iv.reserved() == 3);
-
-  MOZ_RELEASE_ASSERT(iv.reserve(5));
-  MOZ_RELEASE_ASSERT(iv.reserved() == 5);
-
-  MOZ_RELEASE_ASSERT(iv.reserve(1));
-  MOZ_RELEASE_ASSERT(iv.reserved() == 5);
-
-  MOZ_RELEASE_ASSERT(iv.reserve(55));
-  MOZ_RELEASE_ASSERT(iv.reserved() == 55);
-
-  Vector<int, 42> iv2(Move(iv));
-  MOZ_RELEASE_ASSERT(iv.reserved() == 0);
-  MOZ_RELEASE_ASSERT(iv2.reserved() == 55);
-
-  iv2.clearAndFree();
-  MOZ_RELEASE_ASSERT(iv2.reserved() == 0);
-#endif
-}
-
-int
-main()
-{
-  VectorTesting::testReserved();
-}
--- a/mfbt/tests/moz.build
+++ b/mfbt/tests/moz.build
@@ -25,17 +25,16 @@ CppUnitTests([
     'TestPair',
     'TestRefPtr',
     'TestRollingMean',
     'TestSHA1',
     'TestSplayTree',
     'TestTypedEnum',
     'TestTypeTraits',
     'TestUniquePtr',
-    'TestVector',
     'TestWeakPtr',
 ])
 
 if not CONFIG['MOZ_ASAN']:
     CppUnitTests([
         'TestPoisonArea',
     ])