Bug 913586 (Part 6) - Update Maybe users in js. r=luke
authorSeth Fowler <seth@mozilla.com>
Wed, 13 Aug 2014 15:42:00 -0700
changeset 222293 0f2f47600849a2520163c4ccff31fee272887415
parent 222292 59b1637dc740e8e6e8bcbff8f12549ba6710be76
child 222294 3d08e60f8991aaf5ee4f472dac13617e4dee12ca
push id583
push userbhearsum@mozilla.com
push dateMon, 24 Nov 2014 19:04:58 +0000
treeherdermozilla-release@c107e74250f4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs913586
milestone34.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 913586 (Part 6) - Update Maybe users in js. r=luke
extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
js/src/asmjs/AsmJSFrameIterator.cpp
js/src/asmjs/AsmJSValidate.cpp
js/src/frontend/BytecodeCompiler.cpp
js/src/gc/Zone.h
js/src/irregexp/RegExpEngine.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/IonMacroAssembler.h
js/src/jit/MIR.cpp
js/src/jit/shared/CodeGenerator-shared.cpp
js/src/jsgc.cpp
js/src/json.cpp
js/src/jsproxy.cpp
js/src/jswrapper.cpp
js/src/jswrapper.h
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/src/vm/HelperThreads.cpp
js/src/vm/RegExpObject.cpp
js/src/vm/Shape-inl.h
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/ExportHelpers.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/nsCxPusher.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -31,17 +31,17 @@ using mozilla::AutoSafeJSContext;
 
 static mozilla::Maybe<JS::PersistentRooted<JSObject *> > autoconfigSb;
 
 nsresult CentralizedAdminPrefManagerInit()
 {
     nsresult rv;
 
     // If the sandbox is already created, no need to create it again.
-    if (!autoconfigSb.empty())
+    if (autoconfigSb)
         return NS_OK;
 
     // Grab XPConnect.
     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
     if (NS_FAILED(rv)) {
         return rv;
     }
 
@@ -53,26 +53,26 @@ nsresult CentralizedAdminPrefManagerInit
     // Create a sandbox.
     AutoSafeJSContext cx;
     nsCOMPtr<nsIXPConnectJSObjectHolder> sandbox;
     rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(sandbox));
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Unwrap, store and root the sandbox.
     NS_ENSURE_STATE(sandbox->GetJSObject());
-    autoconfigSb.construct(cx, js::UncheckedUnwrap(sandbox->GetJSObject()));
+    autoconfigSb.emplace(cx, js::UncheckedUnwrap(sandbox->GetJSObject()));
 
     return NS_OK;
 }
 
 nsresult CentralizedAdminPrefManagerFinish()
 {
-    if (!autoconfigSb.empty()) {
+    if (autoconfigSb) {
         AutoSafeJSContext cx;
-        autoconfigSb.destroy();
+        autoconfigSb.reset();
         JS_MaybeGC(cx);
     }
     return NS_OK;
 }
 
 nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
                                    const char *filename, bool bGlobalContext,
                                    bool bCallbacks, bool skipFirstLine)
@@ -103,19 +103,19 @@ nsresult EvaluateAdminConfigScript(const
 
     // Grab XPConnect.
     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
     if (NS_FAILED(rv)) {
         return rv;
     }
 
     AutoSafeJSContext cx;
-    JSAutoCompartment ac(cx, autoconfigSb.ref());
+    JSAutoCompartment ac(cx, *autoconfigSb);
 
     nsAutoCString script(js_buffer, length);
     JS::RootedValue v(cx);
     rv = xpc->EvalInSandboxObject(NS_ConvertASCIItoUTF16(script), filename, cx,
-                                  autoconfigSb.ref(), &v);
+                                  *autoconfigSb, &v);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
 }
 
--- a/js/src/asmjs/AsmJSFrameIterator.cpp
+++ b/js/src/asmjs/AsmJSFrameIterator.cpp
@@ -266,19 +266,19 @@ js::GenerateAsmJSFunctionPrologue(MacroA
 
     // Prologue join point, body begin:
     masm.bind(&body);
     masm.setFramePushed(framePushed);
 
     // Overflow checks are omitted by CodeGenerator in some cases (leaf
     // functions with small framePushed). Perform overflow-checking after
     // pushing framePushed to catch cases with really large frames.
-    if (!labels->overflowThunk.empty()) {
+    if (labels->overflowThunk) {
         // If framePushed is zero, we don't need a thunk to adjust StackPointer.
-        Label *target = framePushed ? labels->overflowThunk.addr() : &labels->overflowExit;
+        Label *target = framePushed ? labels->overflowThunk.ptr() : &labels->overflowExit;
         masm.branchPtr(Assembler::AboveOrEqual,
                        AsmJSAbsoluteAddress(AsmJSImm_StackLimit),
                        StackPointer,
                        target);
     }
 }
 
 // Similar to GenerateAsmJSFunctionPrologue (see comment), we generate both a
@@ -325,21 +325,21 @@ js::GenerateAsmJSFunctionEpilogue(MacroA
     masm.addPtr(Imm32(framePushed + AsmJSFrameBytesAfterReturnAddress), StackPointer);
     masm.ret();
     masm.setFramePushed(0);
 
     // Profiling epilogue:
     masm.bind(&labels->profilingEpilogue);
     GenerateProfilingEpilogue(masm, framePushed, AsmJSExit::None, &labels->profilingReturn);
 
-    if (!labels->overflowThunk.empty() && labels->overflowThunk.ref().used()) {
+    if (labels->overflowThunk && labels->overflowThunk->used()) {
         // The general throw stub assumes that only sizeof(AsmJSFrame) bytes
         // have been pushed. The overflow check occurs after incrementing by
         // framePushed, so pop that before jumping to the overflow exit.
-        masm.bind(labels->overflowThunk.addr());
+        masm.bind(labels->overflowThunk.ptr());
         masm.addPtr(Imm32(framePushed), StackPointer);
         masm.jump(&labels->overflowExit);
     }
 }
 
 void
 js::GenerateAsmJSStackOverflowExit(MacroAssembler &masm, Label *overflowExit, Label *throwLabel)
 {
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -1954,17 +1954,17 @@ class FunctionCompiler
         return varInitializers_.append(TypedValue(type, init));
     }
 
     bool prepareToEmitMIR(const VarTypeVector &argTypes)
     {
         JS_ASSERT(locals_.count() == argTypes.length() + varInitializers_.length());
 
         alloc_  = lifo_.new_<TempAllocator>(&lifo_);
-        ionContext_.construct(m_.cx(), alloc_);
+        ionContext_.emplace(m_.cx(), alloc_);
 
         graph_  = lifo_.new_<MIRGraph>(alloc_);
         info_   = lifo_.new_<CompileInfo>(locals_.count(), SequentialExecution);
         const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_AsmJS);
         const JitCompileOptions options;
         mirGen_ = lifo_.new_<MIRGenerator>(CompileCompartment::get(cx()->compartment()),
                                            options, alloc_,
                                            graph_, info_, optimizationInfo);
@@ -1990,25 +1990,25 @@ class FunctionCompiler
         }
         maybeAddInterruptCheck(fn_);
         return true;
     }
 
     /******************************* For consistency of returns in a function */
 
     bool hasAlreadyReturned() const {
-        return !alreadyReturned_.empty();
+        return alreadyReturned_.isSome();
     }
 
     RetType returnedType() const {
-        return alreadyReturned_.ref();
+        return *alreadyReturned_;
     }
 
     void setReturnedType(RetType retType) {
-        alreadyReturned_.construct(retType);
+        alreadyReturned_.emplace(retType);
     }
 
     /************************* Read-only interface (after local scope setup) */
 
     MIRGenerator & mirGen() const     { JS_ASSERT(mirGen_); return *mirGen_; }
     MIRGraph &     mirGraph() const   { JS_ASSERT(graph_); return *graph_; }
     CompileInfo &  info() const       { JS_ASSERT(info_); return *info_; }
 
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -255,25 +255,25 @@ frontend::CompileScript(ExclusiveContext
         else if (!ss->setSourceCopy(cx, srcBuf, false, sct))
             return nullptr;
     }
 
     bool canLazilyParse = CanLazilyParse(cx, options);
 
     Maybe<Parser<SyntaxParseHandler> > syntaxParser;
     if (canLazilyParse) {
-        syntaxParser.construct(cx, alloc, options, srcBuf.get(), srcBuf.length(),
-                               /* foldConstants = */ false,
-                               (Parser<SyntaxParseHandler> *) nullptr,
-                               (LazyScript *) nullptr);
+        syntaxParser.emplace(cx, alloc, options, srcBuf.get(), srcBuf.length(),
+                             /* foldConstants = */ false,
+                             (Parser<SyntaxParseHandler> *) nullptr,
+                             (LazyScript *) nullptr);
     }
 
     Parser<FullParseHandler> parser(cx, alloc, options, srcBuf.get(), srcBuf.length(),
                                     /* foldConstants = */ true,
-                                    canLazilyParse ? &syntaxParser.ref() : nullptr, nullptr);
+                                    canLazilyParse ? syntaxParser.ptr() : nullptr, nullptr);
     parser.sct = sct;
     parser.ss = ss;
 
     Directives directives(options.strictOption);
     GlobalSharedContext globalsc(cx, scopeChain, directives, options.extraWarningsOption);
 
     bool savedCallerFun = options.compileAndGo &&
                           evalCaller && evalCaller->functionOrCallerFunction();
@@ -296,20 +296,20 @@ frontend::CompileScript(ExclusiveContext
     if (!bce.init())
         return nullptr;
 
     // Syntax parsing may cause us to restart processing of top level
     // statements in the script. Use Maybe<> so that the parse context can be
     // reset when this occurs.
     Maybe<ParseContext<FullParseHandler> > pc;
 
-    pc.construct(&parser, (GenericParseContext *) nullptr, (ParseNode *) nullptr, &globalsc,
-                 (Directives *) nullptr, staticLevel, /* bodyid = */ 0,
-                 /* blockScopeDepth = */ 0);
-    if (!pc.ref().init(parser.tokenStream))
+    pc.emplace(&parser, (GenericParseContext *) nullptr, (ParseNode *) nullptr, &globalsc,
+               (Directives *) nullptr, staticLevel, /* bodyid = */ 0,
+               /* blockScopeDepth = */ 0);
+    if (!pc->init(parser.tokenStream))
         return nullptr;
 
     /* If this is a direct call to eval, inherit the caller's strictness.  */
     if (evalCaller && evalCaller->strict())
         globalsc.strict = true;
 
     if (options.compileAndGo) {
         if (source) {
@@ -326,17 +326,17 @@ frontend::CompileScript(ExclusiveContext
         if (evalCaller && evalCaller->functionOrCallerFunction()) {
             /*
              * An eval script in a caller frame needs to have its enclosing
              * function captured in case it refers to an upvar, and someone
              * wishes to decompile it while it's running.
              */
             JSFunction *fun = evalCaller->functionOrCallerFunction();
             Directives directives(/* strict = */ fun->strict());
-            ObjectBox *funbox = parser.newFunctionBox(/* fn = */ nullptr, fun, pc.addr(),
+            ObjectBox *funbox = parser.newFunctionBox(/* fn = */ nullptr, fun, pc.ptr(),
                                                       directives, fun->generatorKind());
             if (!funbox)
                 return nullptr;
             bce.objectList.add(funbox);
         }
     }
 
     bool canHaveDirectives = true;
@@ -360,39 +360,39 @@ frontend::CompileScript(ExclusiveContext
                 // level statement. Restart the parse; syntax parsing has
                 // already been disabled for the parser and the result will not
                 // be ambiguous.
                 parser.clearAbortedSyntaxParse();
                 parser.tokenStream.seek(pos);
 
                 // Destroying the parse context will destroy its free
                 // variables, so check if any deoptimization is needed.
-                if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, pc.ref()))
+                if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, *pc))
                     return nullptr;
 
-                pc.destroy();
-                pc.construct(&parser, (GenericParseContext *) nullptr, (ParseNode *) nullptr,
-                             &globalsc, (Directives *) nullptr, staticLevel, /* bodyid = */ 0,
-                             script->bindings.numBlockScoped());
-                if (!pc.ref().init(parser.tokenStream))
+                pc.reset();
+                pc.emplace(&parser, (GenericParseContext *) nullptr, (ParseNode *) nullptr,
+                           &globalsc, (Directives *) nullptr, staticLevel, /* bodyid = */ 0,
+                           script->bindings.numBlockScoped());
+                if (!pc->init(parser.tokenStream))
                     return nullptr;
-                JS_ASSERT(parser.pc == pc.addr());
+                JS_ASSERT(parser.pc == pc.ptr());
 
                 pn = parser.statement();
             }
             if (!pn) {
                 JS_ASSERT(!parser.hadAbortedSyntaxParse());
                 return nullptr;
             }
         }
 
         // Accumulate the maximum block scope depth, so that EmitTree can assert
         // when emitting JSOP_GETLOCAL that the local is indeed within the fixed
         // part of the stack frame.
-        script->bindings.updateNumBlockScoped(pc.ref().blockScopeDepth);
+        script->bindings.updateNumBlockScoped(pc->blockScopeDepth);
 
         if (canHaveDirectives) {
             if (!parser.maybeParseDirective(/* stmtList = */ nullptr, pn, &canHaveDirectives))
                 return nullptr;
         }
 
         if (!FoldConstants(cx, &pn, &parser))
             return nullptr;
@@ -401,17 +401,17 @@ frontend::CompileScript(ExclusiveContext
             return nullptr;
 
         if (!EmitTree(cx, &bce, pn))
             return nullptr;
 
         parser.handler.freeTree(pn);
     }
 
-    if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, pc.ref()))
+    if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, *pc))
         return nullptr;
 
     if (!SetDisplayURL(cx, parser.tokenStream, ss))
         return nullptr;
 
     if (!SetSourceMap(cx, parser.tokenStream, ss))
         return nullptr;
 
@@ -432,17 +432,17 @@ frontend::CompileScript(ExclusiveContext
         return nullptr;
 
     // Global/eval script bindings are always empty (all names are added to the
     // scope dynamically via JSOP_DEFFUN/VAR).  They may have block-scoped
     // locals, however, which are allocated to the fixed part of the stack
     // frame.
     InternalHandle<Bindings*> bindings(script, &script->bindings);
     if (!Bindings::initWithTemporaryStorage(cx, bindings, 0, 0, nullptr,
-                                            pc.ref().blockScopeDepth))
+                                            pc->blockScopeDepth))
         return nullptr;
 
     if (!JSScript::fullyInitFromEmitter(cx, script, &bce))
         return nullptr;
 
     // Note that this marking must happen before we tell Debugger
     // about the new script, in case Debugger delazifies the script's
     // inner functions.
@@ -550,29 +550,29 @@ CompileFunctionBody(JSContext *cx, Mutab
         if (!ss->setSourceCopy(cx, srcBuf, true, &sct))
             return false;
     }
 
     bool canLazilyParse = CanLazilyParse(cx, options);
 
     Maybe<Parser<SyntaxParseHandler> > syntaxParser;
     if (canLazilyParse) {
-        syntaxParser.construct(cx, &cx->tempLifoAlloc(),
-                               options, srcBuf.get(), srcBuf.length(),
-                               /* foldConstants = */ false,
-                               (Parser<SyntaxParseHandler> *) nullptr,
-                               (LazyScript *) nullptr);
+        syntaxParser.emplace(cx, &cx->tempLifoAlloc(),
+                             options, srcBuf.get(), srcBuf.length(),
+                             /* foldConstants = */ false,
+                             (Parser<SyntaxParseHandler> *) nullptr,
+                             (LazyScript *) nullptr);
     }
 
     JS_ASSERT(!options.forEval);
 
     Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
                                     options, srcBuf.get(), srcBuf.length(),
                                     /* foldConstants = */ true,
-                                    canLazilyParse ? &syntaxParser.ref() : nullptr, nullptr);
+                                    canLazilyParse ? syntaxParser.ptr() : nullptr, nullptr);
     parser.sct = &sct;
     parser.ss = ss;
 
     JS_ASSERT(fun);
     JS_ASSERT(fun->isTenured());
 
     fun->setArgCount(formals.length());
 
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -394,47 +394,47 @@ class CompartmentsIterT
     ZonesIterT zone;
     mozilla::Maybe<CompartmentsInZoneIter> comp;
 
   public:
     explicit CompartmentsIterT(JSRuntime *rt)
       : zone(rt)
     {
         if (zone.done())
-            comp.construct();
+            comp.emplace();
         else
-            comp.construct(zone);
+            comp.emplace(zone);
     }
 
     CompartmentsIterT(JSRuntime *rt, ZoneSelector selector)
       : zone(rt, selector)
     {
         if (zone.done())
-            comp.construct();
+            comp.emplace();
         else
-            comp.construct(zone);
+            comp.emplace(zone);
     }
 
     bool done() const { return zone.done(); }
 
     void next() {
         JS_ASSERT(!done());
-        JS_ASSERT(!comp.ref().done());
-        comp.ref().next();
-        if (comp.ref().done()) {
-            comp.destroy();
+        JS_ASSERT(!comp->done());
+        comp->next();
+        if (comp->done()) {
+            comp.reset();
             zone.next();
             if (!zone.done())
-                comp.construct(zone);
+                comp.emplace(zone);
         }
     }
 
     JSCompartment *get() const {
         JS_ASSERT(!done());
-        return comp.ref();
+        return *comp;
     }
 
     operator JSCompartment *() const { return get(); }
     JSCompartment *operator->() const { return get(); }
 };
 
 typedef CompartmentsIterT<ZonesIter> CompartmentsIter;
 
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1656,22 +1656,22 @@ irregexp::CompilePattern(JSContext *cx, 
     Maybe<InterpretedRegExpMacroAssembler> interpreted_assembler;
 
     RegExpMacroAssembler *assembler;
     if (IsNativeRegExpEnabled(cx)) {
         NativeRegExpMacroAssembler::Mode mode =
             is_ascii ? NativeRegExpMacroAssembler::ASCII
                      : NativeRegExpMacroAssembler::JSCHAR;
 
-        ctx.construct(cx, (jit::TempAllocator *) nullptr);
-        native_assembler.construct(&alloc, shared, cx->runtime(), mode, (data->capture_count + 1) * 2);
-        assembler = native_assembler.addr();
+        ctx.emplace(cx, (jit::TempAllocator *) nullptr);
+        native_assembler.emplace(&alloc, shared, cx->runtime(), mode, (data->capture_count + 1) * 2);
+        assembler = native_assembler.ptr();
     } else {
-        interpreted_assembler.construct(&alloc, shared, (data->capture_count + 1) * 2);
-        assembler = interpreted_assembler.addr();
+        interpreted_assembler.emplace(&alloc, shared, (data->capture_count + 1) * 2);
+        assembler = interpreted_assembler.ptr();
     }
 
     // Inserted here, instead of in Assembler, because it depends on information
     // in the AST that isn't replicated in the Node structure.
     static const int kMaxBacksearchLimit = 1024;
     if (is_end_anchored &&
         !is_start_anchored &&
         max_length < kMaxBacksearchLimit) {
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3379,35 +3379,35 @@ CodeGenerator::generateBody()
 
         IonSpew(IonSpew_Codegen, "# block%lu%s:", i,
                 current->mir()->isLoopHeader() ? " (loop header)" : "");
 
         masm.bind(current->label());
 
         mozilla::Maybe<ScriptCountBlockState> blockCounts;
         if (counts) {
-            blockCounts.construct(&counts->block(i), &masm);
-            if (!blockCounts.ref().init())
+            blockCounts.emplace(&counts->block(i), &masm);
+            if (!blockCounts->init())
                 return false;
         }
 
 #if defined(JS_ION_PERF)
         perfSpewer->startBasicBlock(current->mir(), masm);
 #endif
 
         for (LInstructionIterator iter = current->begin(); iter != current->end(); iter++) {
             IonSpewStart(IonSpew_Codegen, "instruction %s", iter->opName());
 #ifdef DEBUG
             if (const char *extra = iter->extraName())
                 IonSpewCont(IonSpew_Codegen, ":%s", extra);
 #endif
             IonSpewFin(IonSpew_Codegen);
 
             if (counts)
-                blockCounts.ref().visitInstruction(*iter);
+                blockCounts->visitInstruction(*iter);
 
             if (iter->safepoint() && pushedArgumentSlots_.length()) {
                 if (!markArgumentSlots(iter->safepoint()))
                     return false;
             }
 
 #ifdef CHECK_OSIPOINT_REGISTERS
             if (iter->safepoint())
@@ -4846,20 +4846,20 @@ CodeGenerator::visitIsNullOrLikeUndefine
         Label *notNullOrLikeUndefined;
         if (lir->mir()->operandMightEmulateUndefined()) {
             ool = new(alloc()) OutOfLineTestObjectWithLabels();
             if (!addOutOfLineCode(ool, lir->mir()))
                 return false;
             nullOrLikeUndefined = ool->label1();
             notNullOrLikeUndefined = ool->label2();
         } else {
-            label1.construct();
-            label2.construct();
-            nullOrLikeUndefined = label1.addr();
-            notNullOrLikeUndefined = label2.addr();
+            label1.emplace();
+            label2.emplace();
+            nullOrLikeUndefined = label1.ptr();
+            notNullOrLikeUndefined = label2.ptr();
         }
 
         Register tag = masm.splitTagForTest(value);
 
         masm.branchTestNull(Assembler::Equal, tag, nullOrLikeUndefined);
         masm.branchTestUndefined(Assembler::Equal, tag, nullOrLikeUndefined);
 
         if (ool) {
@@ -5556,20 +5556,20 @@ CodeGenerator::visitNotV(LNotV *lir)
     // object.
     if (lir->mir()->operandMightEmulateUndefined() && operand->mightBeType(MIRType_Object)) {
         ool = new(alloc()) OutOfLineTestObjectWithLabels();
         if (!addOutOfLineCode(ool, lir->mir()))
             return false;
         ifTruthy = ool->label1();
         ifFalsy = ool->label2();
     } else {
-        ifTruthyLabel.construct();
-        ifFalsyLabel.construct();
-        ifTruthy = ifTruthyLabel.addr();
-        ifFalsy = ifFalsyLabel.addr();
+        ifTruthyLabel.emplace();
+        ifFalsyLabel.emplace();
+        ifTruthy = ifTruthyLabel.ptr();
+        ifFalsy = ifFalsyLabel.ptr();
     }
 
     testValueTruthyKernel(ToValue(lir, LNotV::Input), lir->temp1(), lir->temp2(),
                           ToFloatRegister(lir->tempFloat()),
                           ifTruthy, ifFalsy, ool, operand);
 
     Label join;
     Register output = ToRegister(lir->output());
@@ -6544,17 +6544,17 @@ bool
 CodeGenerator::generateAsmJS(AsmJSFunctionLabels *labels)
 {
     IonSpew(IonSpew_Codegen, "# Emitting asm.js code");
 
     // AsmJS doesn't do SPS instrumentation.
     sps_.disable();
 
     if (!omitOverRecursedCheck())
-        labels->overflowThunk.construct();
+        labels->overflowThunk.emplace();
 
     GenerateAsmJSFunctionPrologue(masm, frameSize(), labels);
 
     if (!generateBody())
         return false;
 
     masm.bind(&returnLabel_);
     GenerateAsmJSFunctionEpilogue(masm, frameSize(), labels);
--- a/js/src/jit/IonMacroAssembler.h
+++ b/js/src/jit/IonMacroAssembler.h
@@ -205,17 +205,17 @@ class MacroAssembler : public MacroAssem
     {
         IonContext *icx = GetIonContext();
         JSContext *cx = icx->cx;
         if (cx)
             constructRoot(cx);
 
         if (!icx->temp) {
             JS_ASSERT(cx);
-            alloc_.construct(cx);
+            alloc_.emplace(cx);
         }
 
         moveResolver_.setAllocator(*icx->temp);
 #ifdef JS_CODEGEN_ARM
         initWithAllocator();
         m_buffer.id = icx->getNextAssemblerId();
 #endif
     }
@@ -223,31 +223,31 @@ class MacroAssembler : public MacroAssem
     // This constructor should only be used when there is no IonContext active
     // (for example, Trampoline-$(ARCH).cpp and IonCaches.cpp).
     explicit MacroAssembler(JSContext *cx, IonScript *ion = nullptr,
                             JSScript *script = nullptr, jsbytecode *pc = nullptr)
       : embedsNurseryPointers_(false),
         sps_(nullptr)
     {
         constructRoot(cx);
-        ionContext_.construct(cx, (js::jit::TempAllocator *)nullptr);
-        alloc_.construct(cx);
-        moveResolver_.setAllocator(*ionContext_.ref().temp);
+        ionContext_.emplace(cx, (js::jit::TempAllocator *)nullptr);
+        alloc_.emplace(cx);
+        moveResolver_.setAllocator(*ionContext_->temp);
 #ifdef JS_CODEGEN_ARM
         initWithAllocator();
         m_buffer.id = GetIonContext()->getNextAssemblerId();
 #endif
         if (ion) {
             setFramePushed(ion->frameSize());
             if (pc && cx->runtime()->spsProfiler.enabled()) {
                 // We have to update the SPS pc when this IC stub calls into
                 // the VM.
                 spsPc_ = pc;
-                spsInstrumentation_.construct(&cx->runtime()->spsProfiler, &spsPc_);
-                sps_ = spsInstrumentation_.addr();
+                spsInstrumentation_.emplace(&cx->runtime()->spsProfiler, &spsPc_);
+                sps_ = spsInstrumentation_.ptr();
                 sps_->setPushed(script);
             }
         }
     }
 
     // asm.js compilation handles its own IonContext-pushing
     struct AsmJSToken {};
     explicit MacroAssembler(AsmJSToken)
@@ -266,17 +266,17 @@ class MacroAssembler : public MacroAssem
 
     void resetForNewCodeGenerator(TempAllocator &alloc) {
         setFramePushed(0);
         moveResolver_.clearTempObjectPool();
         moveResolver_.setAllocator(alloc);
     }
 
     void constructRoot(JSContext *cx) {
-        autoRooter_.construct(cx, this);
+        autoRooter_.emplace(cx, this);
     }
 
     MoveResolver &moveResolver() {
         return moveResolver_;
     }
 
     size_t instructionsSize() const {
         return size();
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -3839,30 +3839,30 @@ TryAddTypeBarrierForWrite(TempAllocator 
         if (TypeSetIncludes(property.maybeTypes(), (*pvalue)->type(), (*pvalue)->resultTypeSet()))
             return false;
 
         // This freeze is not required for correctness, but ensures that we
         // will recompile if the property types change and the barrier can
         // potentially be removed.
         property.freeze(constraints);
 
-        if (aggregateProperty.empty()) {
-            aggregateProperty.construct(property);
+        if (!aggregateProperty) {
+            aggregateProperty.emplace(property);
         } else {
-            if (!aggregateProperty.ref().maybeTypes()->isSubset(property.maybeTypes()) ||
-                !property.maybeTypes()->isSubset(aggregateProperty.ref().maybeTypes()))
+            if (!aggregateProperty->maybeTypes()->isSubset(property.maybeTypes()) ||
+                !property.maybeTypes()->isSubset(aggregateProperty->maybeTypes()))
             {
                 return false;
             }
         }
     }
 
-    JS_ASSERT(!aggregateProperty.empty());
-
-    MIRType propertyType = aggregateProperty.ref().knownMIRType(constraints);
+    JS_ASSERT(aggregateProperty);
+
+    MIRType propertyType = aggregateProperty->knownMIRType(constraints);
     switch (propertyType) {
       case MIRType_Boolean:
       case MIRType_Int32:
       case MIRType_Double:
       case MIRType_String:
       case MIRType_Symbol: {
         // The property is a particular primitive type, guard by unboxing the
         // value before the write.
@@ -3878,17 +3878,17 @@ TryAddTypeBarrierForWrite(TempAllocator 
         return true;
       }
       default:;
     }
 
     if ((*pvalue)->type() != MIRType_Value)
         return false;
 
-    types::TemporaryTypeSet *types = aggregateProperty.ref().maybeTypes()->clone(alloc.lifoAlloc());
+    types::TemporaryTypeSet *types = aggregateProperty->maybeTypes()->clone(alloc.lifoAlloc());
     if (!types)
         return false;
 
     // If all possible objects can be stored without a barrier, we don't have to
     // guard on the specific object types.
     BarrierKind kind = BarrierKind::TypeSet;
     if ((*pvalue)->resultTypeSet() && (*pvalue)->resultTypeSet()->objectsAreSubset(types))
         kind = BarrierKind::TypeTagOnly;
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -28,18 +28,18 @@ using mozilla::DebugOnly;
 namespace js {
 namespace jit {
 
 MacroAssembler &
 CodeGeneratorShared::ensureMasm(MacroAssembler *masmArg)
 {
     if (masmArg)
         return *masmArg;
-    maybeMasm_.construct();
-    return maybeMasm_.ref();
+    maybeMasm_.emplace();
+    return *maybeMasm_;
 }
 
 CodeGeneratorShared::CodeGeneratorShared(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masmArg)
   : oolIns(nullptr),
     maybeMasm_(),
     masm(ensureMasm(masmArg)),
     gen(gen),
     graph(*graph),
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2232,17 +2232,17 @@ ArenaLists::refillFreeList(ThreadSafeCon
              * return whatever value we get. If we aren't in a ForkJoin
              * session (i.e. we are in a helper thread async with the main
              * thread), we need to first ensure the main thread is not in a GC
              * session.
              */
             mozilla::Maybe<AutoLockHelperThreadState> lock;
             JSRuntime *rt = zone->runtimeFromAnyThread();
             if (rt->exclusiveThreadsPresent()) {
-                lock.construct();
+                lock.emplace();
                 while (rt->isHeapBusy())
                     HelperThreadState().wait(GlobalHelperThreadState::PRODUCER);
             }
 
             void *thing = cx->allocator()->arenas.allocateFromArenaInline(zone, thingKind,
                                                                           maybeStartBackgroundAllocation);
             if (thing)
                 return thing;
@@ -2524,17 +2524,17 @@ GCRuntime::decommitArenasFromAvailableLi
             {
                 /*
                  * If the main thread waits for the decommit to finish, skip
                  * potentially expensive unlock/lock pair on the contested
                  * lock.
                  */
                 Maybe<AutoUnlockGC> maybeUnlock;
                 if (!isHeapBusy())
-                    maybeUnlock.construct(rt);
+                    maybeUnlock.emplace(rt);
                 ok = MarkPagesUnused(aheader->getArena(), ArenaSize);
             }
 
             if (ok) {
                 ++chunk->info.numArenasFree;
                 chunk->decommittedArenas.set(arenaIndex);
             } else {
                 chunk->addArenaToFreeList(rt, aheader);
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -324,20 +324,20 @@ JO(JSContext *cx, HandleObject obj, Stri
     /* Steps 5-7. */
     Maybe<AutoIdVector> ids;
     const AutoIdVector *props;
     if (scx->replacer && !scx->replacer->isCallable()) {
         JS_ASSERT(JS_IsArrayObject(cx, scx->replacer));
         props = &scx->propertyList;
     } else {
         JS_ASSERT_IF(scx->replacer, scx->propertyList.length() == 0);
-        ids.construct(cx);
-        if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, ids.addr()))
+        ids.emplace(cx);
+        if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, ids.ptr()))
             return false;
-        props = ids.addr();
+        props = ids.ptr();
     }
 
     /* My kingdom for not-quite-initialized-from-the-start references. */
     const AutoIdVector &propertyList = *props;
 
     /* Steps 8-10, 13. */
     bool wroteMember = false;
     RootedId id(cx);
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -49,41 +49,41 @@ js::AutoEnterPolicy::reportErrorIfExcept
 }
 
 #ifdef DEBUG
 void
 js::AutoEnterPolicy::recordEnter(JSContext *cx, HandleObject proxy, HandleId id, Action act)
 {
     if (allowed()) {
         context = cx;
-        enteredProxy.construct(proxy);
-        enteredId.construct(id);
+        enteredProxy.emplace(proxy);
+        enteredId.emplace(id);
         enteredAction = act;
         prev = cx->runtime()->enteredPolicy;
         cx->runtime()->enteredPolicy = this;
     }
 }
 
 void
 js::AutoEnterPolicy::recordLeave()
 {
-    if (!enteredProxy.empty()) {
+    if (enteredProxy) {
         JS_ASSERT(context->runtime()->enteredPolicy == this);
         context->runtime()->enteredPolicy = prev;
     }
 }
 
 JS_FRIEND_API(void)
 js::assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id,
                         BaseProxyHandler::Action act)
 {
     MOZ_ASSERT(proxy->is<ProxyObject>());
     MOZ_ASSERT(cx->runtime()->enteredPolicy);
-    MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredProxy.ref().get() == proxy);
-    MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredId.ref().get() == id);
+    MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredProxy->get() == proxy);
+    MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredId->get() == id);
     MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredAction & act);
 }
 #endif
 
 BaseProxyHandler::BaseProxyHandler(const void *family, bool hasPrototype, bool hasSecurityPolicy)
   : mFamily(family),
     mHasPrototype(hasPrototype),
     mHasSecurityPolicy(hasSecurityPolicy)
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -42,19 +42,19 @@ JSObject *
 Wrapper::New(JSContext *cx, JSObject *obj, JSObject *parent, const Wrapper *handler,
              const WrapperOptions *options)
 {
     JS_ASSERT(parent);
 
     RootedValue priv(cx, ObjectValue(*obj));
     mozilla::Maybe<WrapperOptions> opts;
     if (!options) {
-        opts.construct();
-        opts.ref().selectDefaultClass(obj->isCallable());
-        options = opts.addr();
+        opts.emplace();
+        opts->selectDefaultClass(obj->isCallable());
+        options = opts.ptr();
     }
     return NewProxyObject(cx, handler, priv, options->proto(), parent, *options);
 }
 
 JSObject *
 Wrapper::Renew(JSContext *cx, JSObject *existing, JSObject *obj, const Wrapper *handler)
 {
     JS_ASSERT(!obj->isCallable());
@@ -147,22 +147,22 @@ js::TransparentObjectWrapper(JSContext *
 {
     // Allow wrapping outer window proxies.
     JS_ASSERT(!obj->is<WrapperObject>() || obj->getClass()->ext.innerObject);
     return Wrapper::New(cx, obj, parent, &CrossCompartmentWrapper::singleton);
 }
 
 ErrorCopier::~ErrorCopier()
 {
-    JSContext *cx = ac.ref().context()->asJSContext();
-    if (ac.ref().origin() != cx->compartment() && cx->isExceptionPending()) {
+    JSContext *cx = ac->context()->asJSContext();
+    if (ac->origin() != cx->compartment() && cx->isExceptionPending()) {
         RootedValue exc(cx);
         if (cx->getPendingException(&exc) && exc.isObject() && exc.toObject().is<ErrorObject>()) {
             cx->clearPendingException();
-            ac.destroy();
+            ac.reset();
             Rooted<ErrorObject*> errObj(cx, &exc.toObject().as<ErrorObject>());
             JSObject *copyobj = js_CopyErrorObject(cx, errObj);
             if (copyobj)
                 cx->setPendingException(ObjectValue(*copyobj));
         }
     }
 }
 
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -25,23 +25,23 @@ class MOZ_STACK_CLASS WrapperOptions : p
   public:
     WrapperOptions() : ProxyOptions(false, nullptr),
                        proto_()
     {}
 
     explicit WrapperOptions(JSContext *cx) : ProxyOptions(false, nullptr),
                                              proto_()
     {
-        proto_.construct(cx);
+        proto_.emplace(cx);
     }
 
     inline JSObject *proto() const;
     WrapperOptions &setProto(JSObject *protoArg) {
-        JS_ASSERT(!proto_.empty());
-        proto_.ref() = protoArg;
+        JS_ASSERT(proto_);
+        *proto_ = protoArg;
         return *this;
     }
 
   private:
     mozilla::Maybe<JS::RootedObject> proto_;
 };
 
 /*
@@ -91,17 +91,17 @@ class JS_FRIEND_API(Wrapper) : public Di
     static const Wrapper singletonWithPrototype;
 
     static JSObject *defaultProto;
 };
 
 inline JSObject *
 WrapperOptions::proto() const
 {
-    return proto_.empty() ? Wrapper::defaultProto : proto_.ref();
+    return proto_ ? *proto_ : Wrapper::defaultProto;
 }
 
 /* Base class for all cross compartment wrapper handlers. */
 class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
 {
   public:
     explicit CrossCompartmentWrapper(unsigned flags, bool hasPrototype = false,
                                      bool hasSecurityPolicy = false);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -345,17 +345,17 @@ GetContextData(JSContext *cx)
 
 static bool
 ShellInterruptCallback(JSContext *cx)
 {
     if (!gServiceInterrupt)
         return true;
 
     bool result;
-    RootedValue interruptFunc(cx, gInterruptFunc.ref());
+    RootedValue interruptFunc(cx, *gInterruptFunc);
     if (!interruptFunc.isNull()) {
         JS::AutoSaveExceptionState savedExc(cx);
         JSAutoCompartment ac(cx, &interruptFunc.toObject());
         RootedValue rval(cx);
         if (!JS_CallFunctionValue(cx, JS::NullPtr(), interruptFunc,
                                   JS::HandleValueArray::empty(), &rval))
         {
             return false;
@@ -955,31 +955,31 @@ class AutoNewContext
         JS_ASSERT(!JS_IsExceptionPending(cx));
         oldcx = cx;
         newcx = NewContext(JS_GetRuntime(cx));
         if (!newcx)
             return false;
         JS::ContextOptionsRef(newcx).setDontReportUncaught(true);
         js::SetDefaultObjectForContext(newcx, JS::CurrentGlobalOrNull(cx));
 
-        newRequest.construct(newcx);
-        newCompartment.construct(newcx, JS::CurrentGlobalOrNull(cx));
+        newRequest.emplace(newcx);
+        newCompartment.emplace(newcx, JS::CurrentGlobalOrNull(cx));
         return true;
     }
 
     JSContext *get() { return newcx; }
 
     ~AutoNewContext() {
         if (newcx) {
             RootedValue exc(oldcx);
             bool throwing = JS_IsExceptionPending(newcx);
             if (throwing)
                 JS_GetPendingException(newcx, &exc);
-            newCompartment.destroy();
-            newRequest.destroy();
+            newCompartment.reset();
+            newRequest.reset();
             if (throwing)
                 JS_SetPendingException(oldcx, exc);
             DestroyContext(newcx, false);
         }
     }
 };
 
 static const uint32_t CacheEntry_SOURCE = 0;
@@ -2421,17 +2421,17 @@ Clone(JSContext *cx, unsigned argc, jsva
     }
 
     {
         Maybe<JSAutoCompartment> ac;
         RootedObject obj(cx, args[0].isPrimitive() ? nullptr : &args[0].toObject());
 
         if (obj && obj->is<CrossCompartmentWrapperObject>()) {
             obj = UncheckedUnwrap(obj);
-            ac.construct(cx, obj);
+            ac.emplace(cx, obj);
             args[0].setObject(*obj);
         }
         if (obj && obj->is<JSFunction>()) {
             funobj = obj;
         } else {
             JSFunction *fun = JS_ValueToFunction(cx, args[0]);
             if (!fun)
                 return false;
@@ -2603,17 +2603,17 @@ EvalInContext(JSContext *cx, unsigned ar
 
     DescribeScriptedCaller(cx, &filename, &lineno);
     {
         Maybe<JSAutoCompartment> ac;
         unsigned flags;
         JSObject *unwrapped = UncheckedUnwrap(sobj, true, &flags);
         if (flags & Wrapper::CROSS_COMPARTMENT) {
             sobj = unwrapped;
-            ac.construct(cx, sobj);
+            ac.emplace(cx, sobj);
         }
 
         sobj = GetInnerObject(sobj);
         if (!sobj)
             return false;
         if (!(sobj->getClass()->flags & JSCLASS_IS_GLOBAL)) {
             JS_ReportError(cx, "Invalid scope argument to evalcx");
             return false;
@@ -2661,17 +2661,17 @@ EvalInFrame(JSContext *cx, unsigned argc
             break;
     }
 
     AutoSaveFrameChain sfc(cx);
     mozilla::Maybe<AutoCompartment> ac;
     if (saveCurrent) {
         if (!sfc.save())
             return false;
-        ac.construct(cx, DefaultObjectForContextOrNull(cx));
+        ac.emplace(cx, DefaultObjectForContextOrNull(cx));
     }
 
     AutoStableStringChars stableChars(cx);
     if (!stableChars.initTwoByte(cx, str))
         return JSTRAP_ERROR;
 
     AbstractFramePtr frame = fi.abstractFramePtr();
     RootedScript fpscript(cx, frame.script());
@@ -3105,17 +3105,17 @@ ScheduleWatchdog(JSRuntime *rt, double t
 }
 
 static void
 CancelExecution(JSRuntime *rt)
 {
     gServiceInterrupt = true;
     JS_RequestInterruptCallback(rt);
 
-    if (!gInterruptFunc.ref().get().isNull()) {
+    if (!gInterruptFunc->get().isNull()) {
         static const char msg[] = "Script runs for too long, terminating.\n";
         fputs(msg, stderr);
     }
 }
 
 static bool
 SetTimeoutValue(JSContext *cx, double t)
 {
@@ -3152,17 +3152,17 @@ Timeout(JSContext *cx, unsigned argc, Va
         return false;
 
     if (args.length() > 1) {
         RootedValue value(cx, args[1]);
         if (!value.isObject() || !value.toObject().is<JSFunction>()) {
             JS_ReportError(cx, "Second argument must be a timeout function");
             return false;
         }
-        gInterruptFunc.ref() = value;
+        *gInterruptFunc = value;
     }
 
     args.rval().setUndefined();
     return SetTimeoutValue(cx, t);
 }
 
 static bool
 InterruptIf(JSContext *cx, unsigned argc, Value *vp)
@@ -3223,17 +3223,17 @@ SetInterruptCallback(JSContext *cx, unsi
         return false;
     }
 
     RootedValue value(cx, args[0]);
     if (!value.isObject() || !value.toObject().is<JSFunction>()) {
         JS_ReportError(cx, "Argument must be a function");
         return false;
     }
-    gInterruptFunc.ref() = value;
+    *gInterruptFunc = value;
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 StackDump(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -6208,23 +6208,23 @@ main(int argc, char **argv, char **envp)
     rt = JS_NewRuntime(JS::DefaultHeapMaxBytes, nurseryBytes);
     if (!rt)
         return 1;
 
     JS::SetOutOfMemoryCallback(rt, my_OOMCallback, nullptr);
     if (!SetRuntimeOptions(rt, op))
         return 1;
 
-    gInterruptFunc.construct(rt, NullValue());
+    gInterruptFunc.emplace(rt, NullValue());
 
     JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff);
 #ifdef JSGC_GENERATIONAL
     Maybe<JS::AutoDisableGenerationalGC> noggc;
     if (op.getBoolOption("no-ggc"))
-        noggc.construct(rt);
+        noggc.emplace(rt);
 #endif
 
     size_t availMem = op.getIntOption("available-memory");
     if (availMem > 0)
         JS_SetGCParametersBasedOnAvailableMemory(rt, availMem);
 
     JS_SetTrustedPrincipals(rt, &ShellPrincipals::fullyTrusted);
     JS_SetSecurityCallbacks(rt, &ShellPrincipals::securityCallbacks);
@@ -6256,23 +6256,22 @@ main(int argc, char **argv, char **envp)
     if (OOM_printAllocationCount)
         printf("OOM max count: %u\n", OOM_counter);
 #endif
 
     DestroyContext(cx, true);
 
     KillWatchdog();
 
-    gInterruptFunc.destroy();
+    gInterruptFunc.reset();
 
     MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty());
     for (size_t i = 0; i < workerThreads.length(); i++)
         PR_JoinThread(workerThreads[i]);
 
 #ifdef JSGC_GENERATIONAL
-    if (!noggc.empty())
-        noggc.destroy();
+    noggc.reset();
 #endif
 
     JS_DestroyRuntime(rt);
     JS_ShutDown();
     return result;
 }
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -553,17 +553,17 @@ Debugger::slowPathOnLeaveFrame(JSContext
         RootedObject frameobj(cx, *p);
         Debugger *dbg = Debugger::fromChildJSObject(frameobj);
 
         if (dbg->enabled &&
             !frameobj->getReservedSlot(JSSLOT_DEBUGFRAME_ONPOP_HANDLER).isUndefined()) {
             RootedValue handler(cx, frameobj->getReservedSlot(JSSLOT_DEBUGFRAME_ONPOP_HANDLER));
 
             Maybe<AutoCompartment> ac;
-            ac.construct(cx, dbg->object);
+            ac.emplace(cx, dbg->object);
 
             RootedValue completion(cx);
             if (!dbg->newCompletionValue(cx, status, value, &completion)) {
                 status = dbg->handleUncaughtException(ac, false);
                 break;
             }
 
             /* Call the onPop handler. */
@@ -829,17 +829,17 @@ Debugger::unwrapPropDescInto(JSContext *
 
     return true;
 }
 
 JSTrapStatus
 Debugger::handleUncaughtExceptionHelper(Maybe<AutoCompartment> &ac,
                                         MutableHandleValue *vp, bool callHook)
 {
-    JSContext *cx = ac.ref().context()->asJSContext();
+    JSContext *cx = ac->context()->asJSContext();
     if (cx->isExceptionPending()) {
         if (callHook && uncaughtExceptionHook) {
             RootedValue exc(cx);
             if (!cx->getPendingException(&exc))
                 return JSTRAP_ERROR;
             cx->clearPendingException();
             RootedValue fval(cx, ObjectValue(*uncaughtExceptionHook));
             RootedValue rv(cx);
@@ -847,17 +847,17 @@ Debugger::handleUncaughtExceptionHelper(
                 return vp ? parseResumptionValue(ac, true, rv, *vp, false) : JSTRAP_CONTINUE;
         }
 
         if (cx->isExceptionPending()) {
             JS_ReportPendingException(cx);
             cx->clearPendingException();
         }
     }
-    ac.destroy();
+    ac.reset();
     return JSTRAP_ERROR;
 }
 
 JSTrapStatus
 Debugger::handleUncaughtException(Maybe<AutoCompartment> &ac, MutableHandleValue vp, bool callHook)
 {
     return handleUncaughtExceptionHelper(ac, &vp, callHook);
 }
@@ -932,43 +932,43 @@ Debugger::newCompletionValue(JSContext *
     return true;
 }
 
 bool
 Debugger::receiveCompletionValue(Maybe<AutoCompartment> &ac, bool ok,
                                  HandleValue val,
                                  MutableHandleValue vp)
 {
-    JSContext *cx = ac.ref().context()->asJSContext();
+    JSContext *cx = ac->context()->asJSContext();
 
     JSTrapStatus status;
     RootedValue value(cx);
     resultToCompletion(cx, ok, val, &status, &value);
-    ac.destroy();
+    ac.reset();
     return newCompletionValue(cx, status, value, vp);
 }
 
 JSTrapStatus
 Debugger::parseResumptionValue(Maybe<AutoCompartment> &ac, bool ok, const Value &rv, MutableHandleValue vp,
                                bool callHook)
 {
     vp.setUndefined();
     if (!ok)
         return handleUncaughtException(ac, vp, callHook);
     if (rv.isUndefined()) {
-        ac.destroy();
+        ac.reset();
         return JSTRAP_CONTINUE;
     }
     if (rv.isNull()) {
-        ac.destroy();
+        ac.reset();
         return JSTRAP_ERROR;
     }
 
     /* Check that rv is {return: val} or {throw: val}. */
-    JSContext *cx = ac.ref().context()->asJSContext();
+    JSContext *cx = ac->context()->asJSContext();
     Rooted<JSObject*> obj(cx);
     RootedShape shape(cx);
     RootedId returnId(cx, NameToId(cx->names().return_));
     RootedId throwId(cx, NameToId(cx->names().throw_));
     bool okResumption = rv.isObject();
     if (okResumption) {
         obj = &rv.toObject();
         okResumption = obj->is<JSObject>();
@@ -984,17 +984,17 @@ Debugger::parseResumptionValue(Maybe<Aut
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_RESUMPTION);
         return handleUncaughtException(ac, vp, callHook);
     }
 
     RootedValue v(cx, vp.get());
     if (!NativeGet(cx, obj, obj, shape, &v) || !unwrapDebuggeeValue(cx, &v))
         return handleUncaughtException(ac, &v, callHook);
 
-    ac.destroy();
+    ac.reset();
     if (!cx->compartment()->wrap(cx, &v)) {
         vp.setUndefined();
         return JSTRAP_ERROR;
     }
     vp.set(v);
 
     return shape->propid() == returnId ? JSTRAP_RETURN : JSTRAP_THROW;
 }
@@ -1017,17 +1017,17 @@ CallMethodIfPresent(JSContext *cx, Handl
 JSTrapStatus
 Debugger::fireDebuggerStatement(JSContext *cx, MutableHandleValue vp)
 {
     RootedObject hook(cx, getHook(OnDebuggerStatement));
     JS_ASSERT(hook);
     JS_ASSERT(hook->isCallable());
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     ScriptFrameIter iter(cx);
 
     RootedValue scriptFrame(cx);
     if (!getScriptFrame(cx, iter, &scriptFrame))
         return handleUncaughtException(ac, false);
 
     RootedValue rv(cx);
@@ -1043,17 +1043,17 @@ Debugger::fireExceptionUnwind(JSContext 
     JS_ASSERT(hook->isCallable());
 
     RootedValue exc(cx);
     if (!cx->getPendingException(&exc))
         return JSTRAP_ERROR;
     cx->clearPendingException();
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     JS::AutoValueArray<2> argv(cx);
     argv[0].setUndefined();
     argv[1].set(exc);
 
     ScriptFrameIter iter(cx);
     if (!getScriptFrame(cx, iter, argv[0]) || !wrapDebuggeeValue(cx, argv[1]))
         return handleUncaughtException(ac, false);
@@ -1069,17 +1069,17 @@ Debugger::fireExceptionUnwind(JSContext 
 JSTrapStatus
 Debugger::fireEnterFrame(JSContext *cx, AbstractFramePtr frame, MutableHandleValue vp)
 {
     RootedObject hook(cx, getHook(OnEnterFrame));
     JS_ASSERT(hook);
     JS_ASSERT(hook->isCallable());
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     RootedValue scriptFrame(cx);
     if (!getScriptFrame(cx, frame, &scriptFrame))
         return handleUncaughtException(ac, false);
 
     RootedValue rv(cx);
     bool ok = Invoke(cx, ObjectValue(*object), ObjectValue(*hook), 1, scriptFrame.address(), &rv);
     return parseResumptionValue(ac, ok, rv, vp);
@@ -1088,17 +1088,17 @@ Debugger::fireEnterFrame(JSContext *cx, 
 void
 Debugger::fireNewScript(JSContext *cx, HandleScript script)
 {
     RootedObject hook(cx, getHook(OnNewScript));
     JS_ASSERT(hook);
     JS_ASSERT(hook->isCallable());
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     JSObject *dsobj = wrapScript(cx, script);
     if (!dsobj) {
         handleUncaughtException(ac, false);
         return;
     }
 
     RootedValue scriptObject(cx, ObjectValue(*dsobj));
@@ -1243,17 +1243,17 @@ Debugger::onTrap(JSContext *cx, MutableH
          *
          * The other has to do with non-compile-and-go scripts, which have no
          * specific global--until they are executed. Only now do we know which
          * global the script is running against.
          */
         Debugger *dbg = bp->debugger;
         if (dbg->enabled && dbg->debuggees.lookup(scriptGlobal)) {
             Maybe<AutoCompartment> ac;
-            ac.construct(cx, dbg->object);
+            ac.emplace(cx, dbg->object);
 
             RootedValue scriptFrame(cx);
             if (!dbg->getScriptFrame(cx, iter, &scriptFrame))
                 return dbg->handleUncaughtException(ac, false);
             RootedValue rv(cx);
             Rooted<JSObject*> handler(cx, bp->handler);
             bool ok = CallMethodIfPresent(cx, handler, "hit", 1, scriptFrame.address(), &rv);
             JSTrapStatus st = dbg->parseResumptionValue(ac, ok, rv, vp, true);
@@ -1354,17 +1354,17 @@ Debugger::onSingleStep(JSContext *cx, Mu
     PreserveIterValue piv(cx);
 
     /* Call all the onStep handlers we found. */
     for (JSObject **p = frames.begin(); p != frames.end(); p++) {
         RootedObject frame(cx, *p);
         Debugger *dbg = Debugger::fromChildJSObject(frame);
 
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, dbg->object);
+        ac.emplace(cx, dbg->object);
 
         const Value &handler = frame->getReservedSlot(JSSLOT_DEBUGFRAME_ONSTEP_HANDLER);
         RootedValue rval(cx);
         bool ok = Invoke(cx, ObjectValue(*frame), handler, 0, nullptr, &rval);
         JSTrapStatus st = dbg->parseResumptionValue(ac, ok, rval, vp);
         if (st != JSTRAP_CONTINUE)
             return st;
     }
@@ -1378,17 +1378,17 @@ Debugger::onSingleStep(JSContext *cx, Mu
 JSTrapStatus
 Debugger::fireNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global, MutableHandleValue vp)
 {
     RootedObject hook(cx, getHook(OnNewGlobalObject));
     JS_ASSERT(hook);
     JS_ASSERT(hook->isCallable());
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, object);
+    ac.emplace(cx, object);
 
     RootedValue wrappedGlobal(cx, ObjectValue(*global));
     if (!wrapDebuggeeValue(cx, &wrappedGlobal))
         return handleUncaughtException(ac, false);
 
     RootedValue rv(cx);
 
     // onNewGlobalObject is infallible, and thus is only allowed to return
@@ -4384,30 +4384,30 @@ CheckThisFrame(JSContext *cx, const Call
     }
 
 #define THIS_FRAME_ITER(cx, argc, vp, fnname, args, thisobj, maybeIter, iter)  \
     THIS_FRAME_THISOBJ(cx, argc, vp, fnname, args, thisobj);                   \
     Maybe<ScriptFrameIter> maybeIter;                                          \
     {                                                                          \
         AbstractFramePtr f = AbstractFramePtr::FromRaw(thisobj->getPrivate()); \
         if (f.isScriptFrameIterData()) {                                       \
-            maybeIter.construct(*(ScriptFrameIter::Data *)(f.raw()));          \
+            maybeIter.emplace(*(ScriptFrameIter::Data *)(f.raw()));            \
         } else {                                                               \
-            maybeIter.construct(cx, ScriptFrameIter::ALL_CONTEXTS,             \
-                                ScriptFrameIter::GO_THROUGH_SAVED);            \
-            ScriptFrameIter &iter = maybeIter.ref();                           \
+            maybeIter.emplace(cx, ScriptFrameIter::ALL_CONTEXTS,               \
+                              ScriptFrameIter::GO_THROUGH_SAVED);              \
+            ScriptFrameIter &iter = *maybeIter;                                \
             while (iter.isIon() || iter.abstractFramePtr() != f)               \
                 ++iter;                                                        \
             AbstractFramePtr data = iter.copyDataAsAbstractFramePtr();         \
             if (!data)                                                         \
                 return false;                                                  \
             thisobj->setPrivate(data.raw());                                   \
         }                                                                      \
     }                                                                          \
-    ScriptFrameIter &iter = maybeIter.ref()
+    ScriptFrameIter &iter = *maybeIter
 
 #define THIS_FRAME_OWNER(cx, argc, vp, fnname, args, thisobj, frame, dbg)      \
     THIS_FRAME(cx, argc, vp, fnname, args, thisobj, frame);                    \
     Debugger *dbg = Debugger::fromChildJSObject(thisobj)
 
 #define THIS_FRAME_OWNER_ITER(cx, argc, vp, fnname, args, thisobj, maybeIter, iter, dbg) \
     THIS_FRAME_ITER(cx, argc, vp, fnname, args, thisobj, maybeIter, iter);               \
     Debugger *dbg = Debugger::fromChildJSObject(thisobj)
@@ -4896,19 +4896,19 @@ DebuggerGenericEval(JSContext *cx, const
             if (!ToUint32(cx, v, &lineno))
                 return false;
             lineNumber = lineno;
         }
     }
 
     Maybe<AutoCompartment> ac;
     if (iter)
-        ac.construct(cx, iter->scopeChain());
+        ac.emplace(cx, iter->scopeChain());
     else
-        ac.construct(cx, scope);
+        ac.emplace(cx, scope);
 
     RootedValue thisv(cx);
     Rooted<Env *> env(cx);
     if (iter) {
         /* ExecuteInEnv requires 'fp' to have a computed 'this" value. */
         if (!iter->computeThis(cx))
             return false;
         thisv = iter->computedThisValue();
@@ -5393,17 +5393,17 @@ DebuggerObject_getOwnPropertyDescriptor(
     RootedId id(cx);
     if (!ValueToId<CanGC>(cx, args.get(0), &id))
         return false;
 
     /* Bug: This can cause the debuggee to run! */
     Rooted<PropertyDescriptor> desc(cx);
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, obj);
+        ac.emplace(cx, obj);
 
         ErrorCopier ec(ac);
         if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
             return false;
     }
 
     if (desc.object()) {
         /* Rewrap the debuggee values in desc for the debugger. */
@@ -5430,17 +5430,17 @@ DebuggerObject_getOwnPropertyDescriptor(
 static bool
 DebuggerObject_getOwnPropertyNames(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "getOwnPropertyNames", args, obj);
 
     AutoIdVector keys(cx);
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, obj);
+        ac.emplace(cx, obj);
         ErrorCopier ec(ac);
         if (!GetPropertyNames(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &keys))
             return false;
     }
 
     AutoValueVector vals(cx);
     if (!vals.resize(keys.length()))
         return false;
@@ -5483,17 +5483,17 @@ DebuggerObject_defineProperty(JSContext 
 
     if (!dbg->unwrapPropDescInto(cx, obj, desc, &desc))
         return false;
     if (!desc.checkGetter(cx) || !desc.checkSetter(cx))
         return false;
 
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, obj);
+        ac.emplace(cx, obj);
         if (!cx->compartment()->wrap(cx, &desc))
             return false;
 
         ErrorCopier ec(ac);
         bool dummy;
         if (!DefineProperty(cx, obj, id, desc, true, &dummy))
             return false;
     }
@@ -5524,17 +5524,17 @@ DebuggerObject_defineProperties(JSContex
         if (!dbg->unwrapPropDescInto(cx, obj, descs[i], descs[i]))
             return false;
         if (!descs[i].checkGetter(cx) || !descs[i].checkSetter(cx))
             return false;
     }
 
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, obj);
+        ac.emplace(cx, obj);
         for (size_t i = 0; i < n; i++) {
             if (!cx->compartment()->wrap(cx, descs[i]))
                 return false;
         }
 
         ErrorCopier ec(ac);
         for (size_t i = 0; i < n; i++) {
             bool dummy;
@@ -5555,17 +5555,17 @@ static bool
 DebuggerObject_deleteProperty(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "deleteProperty", args, obj);
     RootedId id(cx);
     if (!ValueToId<CanGC>(cx, args.get(0), &id))
         return false;
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
     ErrorCopier ec(ac);
 
     bool succeeded;
     if (!JSObject::deleteGeneric(cx, obj, id, &succeeded))
         return false;
     args.rval().setBoolean(succeeded);
     return true;
 }
@@ -5573,17 +5573,17 @@ DebuggerObject_deleteProperty(JSContext 
 enum SealHelperOp { Seal, Freeze, PreventExtensions };
 
 static bool
 DebuggerObject_sealHelper(JSContext *cx, unsigned argc, Value *vp, SealHelperOp op, const char *name)
 {
     THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, name, args, obj);
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
     ErrorCopier ec(ac);
     bool ok;
     if (op == Seal) {
         ok = JSObject::seal(cx, obj);
     } else if (op == Freeze) {
         ok = JSObject::freeze(cx, obj);
     } else {
         JS_ASSERT(op == PreventExtensions);
@@ -5622,17 +5622,17 @@ DebuggerObject_preventExtensions(JSConte
 
 static bool
 DebuggerObject_isSealedHelper(JSContext *cx, unsigned argc, Value *vp, SealHelperOp op,
                               const char *name)
 {
     THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, name, args, obj);
 
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
     ErrorCopier ec(ac);
     bool r;
     if (op == Seal) {
         if (!JSObject::isSealed(cx, obj, &r))
             return false;
     } else if (op == Freeze) {
         if (!JSObject::isFrozen(cx, obj, &r))
             return false;
@@ -5716,17 +5716,17 @@ ApplyOrCall(JSContext *cx, unsigned argc
             return false;
     }
 
     /*
      * Enter the debuggee compartment and rewrap all input value for that compartment.
      * (Rewrapping always takes place in the destination compartment.)
      */
     Maybe<AutoCompartment> ac;
-    ac.construct(cx, obj);
+    ac.emplace(cx, obj);
     if (!cx->compartment()->wrap(cx, &calleev) || !cx->compartment()->wrap(cx, &thisv))
         return false;
 
     RootedValue arg(cx);
     for (unsigned i = 0; i < callArgc; i++) {
         if (!cx->compartment()->wrap(cx, callArgvRooter.handleAt(i)))
              return false;
     }
@@ -6122,17 +6122,17 @@ DebuggerEnv_getInspectable(JSContext *cx
 static bool
 DebuggerEnv_names(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGENV(cx, argc, vp, "names", args, envobj, env);
 
     AutoIdVector keys(cx);
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, env);
+        ac.emplace(cx, env);
         ErrorCopier ec(ac);
         if (!GetPropertyNames(cx, env, JSITER_HIDDEN, &keys))
             return false;
     }
 
     RootedObject arr(cx, NewDenseEmptyArray(cx));
     if (!arr)
         return false;
@@ -6156,17 +6156,17 @@ DebuggerEnv_find(JSContext *cx, unsigned
         return false;
 
     RootedId id(cx);
     if (!ValueToIdentifier(cx, args[0], &id))
         return false;
 
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, env);
+        ac.emplace(cx, env);
 
         /* This can trigger resolve hooks. */
         ErrorCopier ec(ac);
         RootedShape prop(cx);
         RootedObject pobj(cx);
         for (; env && !prop; env = env->enclosingScope()) {
             if (!JSObject::lookupGeneric(cx, env, id, &pobj, &prop))
                 return false;
@@ -6187,17 +6187,17 @@ DebuggerEnv_getVariable(JSContext *cx, u
 
     RootedId id(cx);
     if (!ValueToIdentifier(cx, args[0], &id))
         return false;
 
     RootedValue v(cx);
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, env);
+        ac.emplace(cx, env);
 
         /* This can trigger getters. */
         ErrorCopier ec(ac);
 
         // For DebugScopeObjects, we get sentinel values for optimized out
         // slots and arguments instead of throwing (the default behavior).
         //
         // See wrapDebuggeeValue for how the sentinel values are wrapped.
@@ -6228,17 +6228,17 @@ DebuggerEnv_setVariable(JSContext *cx, u
         return false;
 
     RootedValue v(cx, args[1]);
     if (!dbg->unwrapDebuggeeValue(cx, &v))
         return false;
 
     {
         Maybe<AutoCompartment> ac;
-        ac.construct(cx, env);
+        ac.emplace(cx, env);
         if (!cx->compartment()->wrap(cx, &v))
             return false;
 
         /* This can trigger setters. */
         ErrorCopier ec(ac);
 
         /* Make sure the environment actually has the specified binding. */
         bool has;
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -418,21 +418,21 @@ GlobalHelperThreadState::ensureInitializ
         return;
 
     threads = js_pod_calloc<HelperThread>(threadCount);
     if (!threads)
         CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
 
     for (size_t i = 0; i < threadCount; i++) {
         HelperThread &helper = threads[i];
-        helper.threadData.construct(static_cast<JSRuntime *>(nullptr));
+        helper.threadData.emplace(static_cast<JSRuntime *>(nullptr));
         helper.thread = PR_CreateThread(PR_USER_THREAD,
                                         HelperThread::ThreadMain, &helper,
                                         PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, HELPER_STACK_SIZE);
-        if (!helper.thread || !helper.threadData.ref().init())
+        if (!helper.thread || !helper.threadData->init())
             CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
     }
 
     resetAsmJSFailureState();
 }
 
 GlobalHelperThreadState::GlobalHelperThreadState()
 {
@@ -808,18 +808,17 @@ HelperThread::destroy()
 
             /* Notify all helpers, to ensure that this thread wakes up. */
             HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
         }
 
         PR_JoinThread(thread);
     }
 
-    if (!threadData.empty())
-        threadData.destroy();
+    threadData.reset();
 }
 
 #ifdef MOZ_NUWA_PROCESS
 extern "C" {
 MFBT_API bool IsNuwaProcess();
 MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void *), void *arg);
 }
 #endif
@@ -847,17 +846,17 @@ HelperThread::handleAsmJSWorkload()
     JS_ASSERT(HelperThreadState().canStartAsmJSCompile());
     JS_ASSERT(idle());
 
     asmData = HelperThreadState().asmJSWorklist().popCopy();
     bool success = false;
 
     do {
         AutoUnlockHelperThreadState unlock;
-        PerThreadData::AutoEnterRuntime enter(threadData.addr(), asmData->runtime);
+        PerThreadData::AutoEnterRuntime enter(threadData.ptr(), asmData->runtime);
 
         jit::IonContext icx(asmData->mir->compartment->runtime(),
                             asmData->mir->compartment,
                             &asmData->mir->alloc());
 
         int64_t before = PRMJ_Now();
 
         if (!OptimizeMIR(asmData->mir))
@@ -917,17 +916,17 @@ HelperThread::handleIonWorkload()
     TraceLogger *logger = TraceLoggerForCurrentThread();
     AutoTraceLog logScript(logger, TraceLogCreateTextId(logger, ionBuilder->script()));
     AutoTraceLog logCompile(logger, TraceLogger::IonCompilation);
 
     JSRuntime *rt = ionBuilder->script()->compartment()->runtimeFromAnyThread();
 
     {
         AutoUnlockHelperThreadState unlock;
-        PerThreadData::AutoEnterRuntime enter(threadData.addr(),
+        PerThreadData::AutoEnterRuntime enter(threadData.ptr(),
                                               ionBuilder->script()->runtimeFromAnyThread());
         jit::IonContext ictx(jit::CompileRuntime::get(rt),
                              jit::CompileCompartment::get(ionBuilder->script()->compartment()),
                              &ionBuilder->alloc());
         ionBuilder->setBackgroundCodegen(jit::CompileBackEnd(ionBuilder));
     }
 
     FinishOffThreadIonCompile(ionBuilder);
@@ -993,17 +992,17 @@ js::PauseCurrentHelperThread()
     while (thread->pause)
         HelperThreadState().wait(GlobalHelperThreadState::PAUSE);
 }
 
 void
 ExclusiveContext::setHelperThread(HelperThread *thread)
 {
     helperThread_ = thread;
-    perThreadData = thread->threadData.addr();
+    perThreadData = thread->threadData.ptr();
 }
 
 frontend::CompileError &
 ExclusiveContext::addPendingCompileError()
 {
     frontend::CompileError *error = js_new<frontend::CompileError>();
     if (!error)
         MOZ_CRASH();
@@ -1026,17 +1025,17 @@ HelperThread::handleParseWorkload()
     JS_ASSERT(HelperThreadState().canStartParseTask());
     JS_ASSERT(idle());
 
     parseTask = HelperThreadState().parseWorklist().popCopy();
     parseTask->cx->setHelperThread(this);
 
     {
         AutoUnlockHelperThreadState unlock;
-        PerThreadData::AutoEnterRuntime enter(threadData.addr(),
+        PerThreadData::AutoEnterRuntime enter(threadData.ptr(),
                                               parseTask->exclusiveContextGlobal->runtimeFromAnyThread());
         SourceBufferHolder srcBuf(parseTask->chars, parseTask->length,
                                   SourceBufferHolder::NoOwnership);
         parseTask->script = frontend::CompileScript(parseTask->cx, &parseTask->alloc,
                                                     NullPtr(), NullPtr(),
                                                     parseTask->options,
                                                     srcBuf);
     }
@@ -1182,27 +1181,27 @@ HelperThread::handleGCHelperWorkload()
 void
 HelperThread::threadLoop()
 {
     JS_ASSERT(CanUseExtraThreads());
 
     JS::AutoSuppressGCAnalysis nogc;
     AutoLockHelperThreadState lock;
 
-    js::TlsPerThreadData.set(threadData.addr());
+    js::TlsPerThreadData.set(threadData.ptr());
 
     // Compute the thread's stack limit, for over-recursed checks.
     uintptr_t stackLimit = GetNativeStackBase();
 #if JS_STACK_GROWTH_DIRECTION > 0
     stackLimit += HELPER_STACK_QUOTA;
 #else
     stackLimit -= HELPER_STACK_QUOTA;
 #endif
-    for (size_t i = 0; i < ArrayLength(threadData.ref().nativeStackLimit); i++)
-        threadData.ref().nativeStackLimit[i] = stackLimit;
+    for (size_t i = 0; i < ArrayLength(threadData->nativeStackLimit); i++)
+        threadData->nativeStackLimit[i] = stackLimit;
 
     while (true) {
         JS_ASSERT(idle());
 
         // Block until a task is available. Save the value of whether we are
         // going to do an Ion compile, in case the value returned by the method
         // changes.
         bool ionCompile = false;
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -299,21 +299,21 @@ RegExpObject::createNoStatics(ExclusiveC
 
 RegExpObject *
 RegExpObject::createNoStatics(ExclusiveContext *cx, HandleAtom source, RegExpFlag flags,
                               TokenStream *tokenStream, LifoAlloc &alloc)
 {
     Maybe<CompileOptions> dummyOptions;
     Maybe<TokenStream> dummyTokenStream;
     if (!tokenStream) {
-        dummyOptions.construct(cx->asJSContext());
-        dummyTokenStream.construct(cx, dummyOptions.ref(),
+        dummyOptions.emplace(cx->asJSContext());
+        dummyTokenStream.emplace(cx, *dummyOptions,
                                    (const jschar *) nullptr, 0,
                                    (frontend::StrictModeGetter *) nullptr);
-        tokenStream = dummyTokenStream.addr();
+        tokenStream = dummyTokenStream.ptr();
     }
 
     if (!irregexp::ParsePatternSyntax(*tokenStream, alloc, source))
         return nullptr;
 
     RegExpObjectBuilder builder(cx);
     return builder.build(source, flags);
 }
--- a/js/src/vm/Shape-inl.h
+++ b/js/src/vm/Shape-inl.h
@@ -197,17 +197,17 @@ AutoRooterGetterSetter::Inner::Inner(Thr
 }
 
 inline
 AutoRooterGetterSetter::AutoRooterGetterSetter(ThreadSafeContext *cx, uint8_t attrs,
                                                PropertyOp *pgetter, StrictPropertyOp *psetter
                                                MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
 {
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
-        inner.construct(cx, attrs, pgetter, psetter);
+        inner.emplace(cx, attrs, pgetter, psetter);
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 }
 
 static inline uint8_t
 GetShapeAttributes(JSObject *obj, Shape *shape)
 {
     JS_ASSERT(obj->isNative());
 
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -336,21 +336,21 @@ class MOZ_STACK_CLASS ComponentLoaderInf
     }
 
     nsIURI* ResolvedURI() { MOZ_ASSERT(mResolvedURI); return mResolvedURI; }
     nsresult EnsureResolvedURI() {
         BEGIN_ENSURE(ResolvedURI, ScriptChannel);
         return mScriptChannel->GetURI(getter_AddRefs(mResolvedURI));
     }
 
-    nsAutoCString& Key() { return mKey.ref(); }
+    nsAutoCString& Key() { return *mKey; }
     nsresult EnsureKey() {
         ENSURE_DEPS(ResolvedURI);
-        mKey.construct();
-        return mResolvedURI->GetSpec(mKey.ref());
+        mKey.emplace();
+        return mResolvedURI->GetSpec(*mKey);
     }
 
   private:
     const nsACString& mLocation;
     nsCOMPtr<nsIIOService> mIOService;
     nsCOMPtr<nsIURI> mURI;
     nsCOMPtr<nsIChannel> mScriptChannel;
     nsCOMPtr<nsIURI> mResolvedURI;
@@ -1108,17 +1108,17 @@ mozJSComponentLoader::Import(const nsACS
         }
     } else {
         nsresult rv = FindTargetObject(cx, &targetObject);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     Maybe<JSAutoCompartment> ac;
     if (targetObject) {
-        ac.construct(cx, targetObject);
+        ac.emplace(cx, targetObject);
     }
 
     RootedObject global(cx);
     nsresult rv = ImportInto(registryLocation, targetObject, cx, &global);
 
     if (global) {
         if (!JS_WrapObject(cx, &global)) {
             NS_ERROR("can't wrap return value");
--- a/js/xpconnect/src/ExportHelpers.cpp
+++ b/js/xpconnect/src/ExportHelpers.cpp
@@ -180,17 +180,17 @@ StackScopedClone(JSContext *cx, StackSco
 {
     JSAutoStructuredCloneBuffer buffer;
     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());
+            ac.emplace(cx, &val.toObject());
         } else if (val.isString() && !JS_WrapValue(cx, val)) {
             return false;
         }
 
         if (!buffer.write(cx, val, &gStackScopedCloneCallbacks, &data))
             return false;
     }
 
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3186,17 +3186,17 @@ nsXPCComponents_Utils::Dispatch(HandleVa
 {
     RootedValue runnable(cx, runnableArg);
     // Enter the given compartment, if any, and rewrap runnable.
     Maybe<JSAutoCompartment> ac;
     if (scope.isObject()) {
         JSObject *scopeObj = js::UncheckedUnwrap(&scope.toObject());
         if (!scopeObj)
             return NS_ERROR_FAILURE;
-        ac.construct(cx, scopeObj);
+        ac.emplace(cx, scopeObj);
         if (!JS_WrapValue(cx, &runnable))
             return NS_ERROR_FAILURE;
     }
 
     // Get an XPCWrappedJS for |runnable|.
     if (!runnable.isObject())
         return NS_ERROR_INVALID_ARG;
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1182,17 +1182,17 @@ class WatchdogManager : public nsIObserv
     // the lock in each case).
     void
     RecordRuntimeActivity(bool active)
     {
         // The watchdog reads this state, so acquire the lock before writing it.
         MOZ_ASSERT(NS_IsMainThread());
         Maybe<AutoLockWatchdog> lock;
         if (mWatchdog)
-            lock.construct(mWatchdog);
+            lock.emplace(mWatchdog);
 
         // Write state.
         mTimestamps[TimestampRuntimeStateChange] = PR_Now();
         mRuntimeState = active ? RUNTIME_ACTIVE : RUNTIME_INACTIVE;
 
         // The watchdog may be hibernating, waiting for the runtime to go
         // active. Wake it up if necessary.
         if (active && mWatchdog && mWatchdog->Hibernating())
@@ -1206,25 +1206,25 @@ class WatchdogManager : public nsIObserv
 
     // Note - Because of the runtime activity timestamp, these are read and
     // written from both threads.
     void RecordTimestamp(WatchdogTimestampCategory aCategory)
     {
         // The watchdog thread always holds the lock when it runs.
         Maybe<AutoLockWatchdog> maybeLock;
         if (NS_IsMainThread() && mWatchdog)
-            maybeLock.construct(mWatchdog);
+            maybeLock.emplace(mWatchdog);
         mTimestamps[aCategory] = PR_Now();
     }
     PRTime GetTimestamp(WatchdogTimestampCategory aCategory)
     {
         // The watchdog thread always holds the lock when it runs.
         Maybe<AutoLockWatchdog> maybeLock;
         if (NS_IsMainThread() && mWatchdog)
-            maybeLock.construct(mWatchdog);
+            maybeLock.emplace(mWatchdog);
         return mTimestamps[aCategory];
     }
 
     XPCJSRuntime* Runtime() { return mRuntime; }
     Watchdog* GetWatchdog() { return mWatchdog; }
 
     void RefreshWatchdog()
     {
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -643,18 +643,18 @@ File(JSContext *cx, unsigned argc, Value
   return true;
 }
 
 static Maybe<PersistentRootedValue> sScriptedInterruptCallback;
 
 static bool
 XPCShellInterruptCallback(JSContext *cx)
 {
-    MOZ_ASSERT(!sScriptedInterruptCallback.empty());
-    RootedValue callback(cx, sScriptedInterruptCallback.ref());
+    MOZ_ASSERT(sScriptedInterruptCallback);
+    RootedValue callback(cx, *sScriptedInterruptCallback);
 
     // If no interrupt callback was set by script, no-op.
     if (callback.isUndefined())
         return true;
 
     JSAutoCompartment ac(cx, &callback.toObject());
     RootedValue rv(cx);
     if (!JS_CallFunctionValue(cx, JS::NullPtr(), callback, JS::HandleValueArray::empty(), &rv) ||
@@ -666,38 +666,38 @@ XPCShellInterruptCallback(JSContext *cx)
     }
 
     return rv.toBoolean();
 }
 
 static bool
 SetInterruptCallback(JSContext *cx, unsigned argc, jsval *vp)
 {
-    MOZ_ASSERT(!sScriptedInterruptCallback.empty());
+    MOZ_ASSERT(sScriptedInterruptCallback);
 
     // Sanity-check args.
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
     if (args.length() != 1) {
         JS_ReportError(cx, "Wrong number of arguments");
         return false;
     }
 
     // Allow callers to remove the interrupt callback by passing undefined.
     if (args[0].isUndefined()) {
-        sScriptedInterruptCallback.ref() = UndefinedValue();
+        *sScriptedInterruptCallback = UndefinedValue();
         return true;
     }
 
     // Otherwise, we should have a callable object.
     if (!args[0].isObject() || !JS_ObjectIsCallable(cx, &args[0].toObject())) {
         JS_ReportError(cx, "Argument must be callable");
         return false;
     }
 
-    sScriptedInterruptCallback.ref() = args[0];
+    *sScriptedInterruptCallback = args[0];
 
     return true;
 }
 
 static bool
 SimulateActivityCallback(JSContext *cx, unsigned argc, jsval *vp)
 {
     // Sanity-check args.
@@ -1454,17 +1454,17 @@ XRE_XPCShellMain(int argc, char **argv, 
             return 1;
         }
 
         rtsvc->RegisterContextCallback(ContextCallback);
 
         // Override the default XPConnect interrupt callback. We could store the
         // old one and restore it before shutting down, but there's not really a
         // reason to bother.
-        sScriptedInterruptCallback.construct(rt, UndefinedValue());
+        sScriptedInterruptCallback.emplace(rt, UndefinedValue());
         JS_SetInterruptCallback(rt, XPCShellInterruptCallback);
 
         dom::AutoJSAPI jsapi;
         jsapi.Init();
         cx = jsapi.cx();
 
         argc--;
         argv++;
@@ -1585,17 +1585,17 @@ XRE_XPCShellMain(int argc, char **argv, 
 
     if (!XRE_ShutdownTestShell())
         NS_ERROR("problem shutting down testshell");
 
     // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
     rv = NS_ShutdownXPCOM( nullptr );
     MOZ_ASSERT(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
 
-    sScriptedInterruptCallback.destroyIfConstructed();
+    sScriptedInterruptCallback.reset();
 
 #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
     // test of late call and release (see above)
     JSContext* bogusCX;
     bogus->Peek(&bogusCX);
     bogus = nullptr;
 #endif
 
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -41,34 +41,34 @@ bool AutoScriptEvaluate::StartEvaluating
 
     mEvaluated = true;
     if (!JS_GetErrorReporter(mJSContext)) {
         JS_SetErrorReporter(mJSContext, errorReporter);
         mErrorReporterSet = true;
     }
 
     JS_BeginRequest(mJSContext);
-    mAutoCompartment.construct(mJSContext, scope);
+    mAutoCompartment.emplace(mJSContext, scope);
 
     // Saving the exception state keeps us from interfering with another script
     // that may also be running on this context.  This occurred first with the
     // js debugger, as described in
     // http://bugzilla.mozilla.org/show_bug.cgi?id=88130 but presumably could
     // show up in any situation where a script calls into a wrapped js component
     // on the same context, while the context has a nonzero exception state.
-    mState.construct(mJSContext);
+    mState.emplace(mJSContext);
 
     return true;
 }
 
 AutoScriptEvaluate::~AutoScriptEvaluate()
 {
     if (!mJSContext || !mEvaluated)
         return;
-    mState.ref().restore();
+    mState->restore();
 
     JS_EndRequest(mJSContext);
 
     if (mErrorReporterSet)
         JS_SetErrorReporter(mJSContext, nullptr);
 }
 
 // It turns out that some errors may be not worth reporting. So, this
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -361,17 +361,17 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
                                                           parent, parent.address());
         if (NS_FAILED(rv))
             return rv;
         rv = NS_OK;
 
         MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(parent),
                    "Xray wrapper being used to parent XPCWrappedNative?");
 
-        ac.construct(static_cast<JSContext*>(cx), parent);
+        ac.emplace(static_cast<JSContext*>(cx), parent);
 
         if (parent != plannedParent) {
             XPCWrappedNativeScope* betterScope = ObjectScope(parent);
             if (betterScope != Scope)
                 return GetNewOrUsed(helper, betterScope, Interface, resultWrapper);
 
             newParentVal = OBJECT_TO_JSVAL(parent);
         }
@@ -392,17 +392,17 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
             if (wrapper->FindTearOff(Interface, false, &rv)) {
                 MOZ_ASSERT(NS_FAILED(rv), "returning NS_OK on failure");
                 return rv;
             }
             wrapper.forget(resultWrapper);
             return NS_OK;
         }
     } else {
-        ac.construct(static_cast<JSContext*>(cx), parent);
+        ac.emplace(static_cast<JSContext*>(cx), parent);
     }
 
     AutoMarkingWrappedNativeProtoPtr proto(cx);
 
     // If there is ClassInfo (and we are not building a wrapper for the
     // nsIClassInfo interface) then we use a wrapper that needs a prototype.
 
     // Note that the security check happens inside FindTearOff - after the
--- a/js/xpconnect/src/nsCxPusher.cpp
+++ b/js/xpconnect/src/nsCxPusher.cpp
@@ -34,31 +34,31 @@ AutoCxPusher::AutoCxPusher(JSContext* cx
 #ifdef DEBUG
   mPushedContext = cx;
   mCompartmentDepthOnEntry = cx ? js::GetEnterCompartmentDepth(cx) : 0;
 #endif
 
   // Enter a request and a compartment for the duration that the cx is on the
   // stack if non-null.
   if (cx) {
-    mAutoRequest.construct(cx);
+    mAutoRequest.emplace(cx);
 
     // DOM JSContexts don't store their default compartment object on the cx.
     JSObject *compartmentObject = mScx ? mScx->GetWindowProxy()
                                        : js::DefaultObjectForContextOrNull(cx);
     if (compartmentObject)
-      mAutoCompartment.construct(cx, compartmentObject);
+      mAutoCompartment.emplace(cx, compartmentObject);
   }
 }
 
 AutoCxPusher::~AutoCxPusher()
 {
   // Leave the compartment and request before popping.
-  mAutoCompartment.destroyIfConstructed();
-  mAutoRequest.destroyIfConstructed();
+  mAutoCompartment.reset();
+  mAutoRequest.reset();
 
   // When we push a context, we may save the frame chain and pretend like we
   // haven't entered any compartment. This gets restored on Pop(), but we can
   // run into trouble if a Push/Pop are interleaved with a
   // JSAutoEnterCompartment. Make sure the compartment depth right before we
   // pop is the same as it was right after we pushed.
   MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
                                 js::GetEnterCompartmentDepth(mPushedContext));
@@ -98,68 +98,68 @@ AutoJSContext::Init(bool aSafe MOZ_GUARD
 
   nsXPConnect *xpc = nsXPConnect::XPConnect();
   if (!aSafe) {
     mCx = xpc->GetCurrentJSContext();
   }
 
   if (!mCx) {
     mCx = xpc->GetSafeJSContext();
-    mPusher.construct(mCx);
+    mPusher.emplace(mCx);
   }
 }
 
 AutoJSContext::operator JSContext*() const
 {
   return mCx;
 }
 
 ThreadsafeAutoJSContext::ThreadsafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
 {
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
   if (NS_IsMainThread()) {
     mCx = nullptr;
-    mAutoJSContext.construct();
+    mAutoJSContext.emplace();
   } else {
     mCx = mozilla::dom::workers::GetCurrentThreadJSContext();
-    mRequest.construct(mCx);
+    mRequest.emplace(mCx);
   }
 }
 
 ThreadsafeAutoJSContext::operator JSContext*() const
 {
   if (mCx) {
     return mCx;
   } else {
-    return mAutoJSContext.ref();
+    return *mAutoJSContext;
   }
 }
 
 AutoSafeJSContext::AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
   : AutoJSContext(true MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
   , mAc(mCx, XPCJSRuntime::Get()->GetJSContextStack()->GetSafeJSContextGlobal())
 {
 }
 
 ThreadsafeAutoSafeJSContext::ThreadsafeAutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
 {
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
   if (NS_IsMainThread()) {
     mCx = nullptr;
-    mAutoSafeJSContext.construct();
+    mAutoSafeJSContext.emplace();
   } else {
     mCx = mozilla::dom::workers::GetCurrentThreadJSContext();
-    mRequest.construct(mCx);
+    mRequest.emplace(mCx);
   }
 }
 
 ThreadsafeAutoSafeJSContext::operator JSContext*() const
 {
   if (mCx) {
     return mCx;
   } else {
-    return mAutoSafeJSContext.ref();
+    return *mAutoSafeJSContext;
   }
 }
 
 } // namespace mozilla
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -391,48 +391,47 @@ class AsyncFreeSnowWhite;
 
 template <class StringType>
 class ShortLivedStringBuffer
 {
 public:
     StringType* Create()
     {
         for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
-            if (mStrings[i].empty()) {
-                mStrings[i].construct();
-                return mStrings[i].addr();
+            if (!mStrings[i]) {
+                mStrings[i].emplace();
+                return mStrings[i].ptr();
             }
         }
 
         // All our internal string wrappers are used, allocate a new string.
         return new StringType();
     }
 
     void Destroy(StringType *string)
     {
         for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
-            if (!mStrings[i].empty() &&
-                mStrings[i].addr() == string) {
+            if (mStrings[i] && mStrings[i].ptr() == string) {
                 // One of our internal strings is no longer in use, mark
                 // it as such and free its data.
-                mStrings[i].destroy();
+                mStrings[i].reset();
                 return;
             }
         }
 
         // We're done with a string that's not one of our internal
         // strings, delete it.
         delete string;
     }
 
     ~ShortLivedStringBuffer()
     {
 #ifdef DEBUG
         for (uint32_t i = 0; i < ArrayLength(mStrings); ++i) {
-            MOZ_ASSERT(mStrings[i].empty(), "Short lived string still in use");
+            MOZ_ASSERT(!mStrings[i], "Short lived string still in use");
         }
 #endif
     }
 
 private:
     mozilla::Maybe<StringType> mStrings[2];
 };
 
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -2277,17 +2277,17 @@ HasNativeProperty(JSContext *cx, HandleO
     NS_ENSURE_TRUE(holder, false);
     *hasProp = false;
     Rooted<JSPropertyDescriptor> desc(cx);
     const Wrapper *handler = Wrapper::wrapperHandler(wrapper);
 
     // Try resolveOwnProperty.
     Maybe<ResolvingId> resolvingId;
     if (traits == &XPCWrappedNativeXrayTraits::singleton)
-        resolvingId.construct(cx, wrapper, id);
+        resolvingId.emplace(cx, wrapper, id);
     if (!traits->resolveOwnProperty(cx, *handler, wrapper, holder, id, &desc))
         return false;
     if (desc.object()) {
         *hasProp = true;
         return true;
     }
 
     // Try the holder.