Bug 1149377 - Backout bug 1143011 and bug 1145811 for win32 PGO bustage. a=bustage
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 31 Mar 2015 11:01:00 -0400
changeset 266793 759eb70deb31209180006608b09cbacac98b95f4
parent 266792 1caf521d5c88f7df8bea5e8269b9dded54ac1449
child 266794 1b042c16d6f13df1125452617933a9ba5f2aa635
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbustage
bugs1149377, 1143011, 1145811
milestone39.0a2
Bug 1149377 - Backout bug 1143011 and bug 1145811 for win32 PGO bustage. a=bustage CLOSED TREE
js/src/asmjs/AsmJSValidate.cpp
js/src/irregexp/NativeRegExpMacroAssembler.cpp
js/src/irregexp/NativeRegExpMacroAssembler.h
js/src/jit/BacktrackingAllocator.cpp
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineDebugModeOSR.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineIC.h
js/src/jit/CodeGenerator.cpp
js/src/jit/CodeGenerator.h
js/src/jit/IonCaches.cpp
js/src/jit/IonCaches.h
js/src/jit/JitFrames.cpp
js/src/jit/LIR.h
js/src/jit/LinearScan.cpp
js/src/jit/LiveRangeAllocator.cpp
js/src/jit/MacroAssembler.cpp
js/src/jit/MacroAssembler.h
js/src/jit/RegisterAllocator.cpp
js/src/jit/RegisterAllocator.h
js/src/jit/RegisterSets.h
js/src/jit/Registers.h
js/src/jit/Safepoints.cpp
js/src/jit/Safepoints.h
js/src/jit/StupidAllocator.cpp
js/src/jit/arm/Architecture-arm.cpp
js/src/jit/arm/Architecture-arm.h
js/src/jit/arm/BaselineIC-arm.cpp
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/Trampoline-arm.cpp
js/src/jit/mips/Architecture-mips.h
js/src/jit/mips/MacroAssembler-mips.cpp
js/src/jit/none/Architecture-none.h
js/src/jit/none/Trampoline-none.cpp
js/src/jit/shared/Assembler-x86-shared.h
js/src/jit/shared/CodeGenerator-shared-inl.h
js/src/jit/shared/CodeGenerator-shared.cpp
js/src/jit/shared/CodeGenerator-shared.h
js/src/jit/shared/MacroAssembler-x86-shared.cpp
js/src/jit/shared/MacroAssembler-x86-shared.h
js/src/jit/x64/Architecture-x64.h
js/src/jit/x64/Assembler-x64.cpp
js/src/jit/x64/Trampoline-x64.cpp
js/src/jit/x86/Architecture-x86.h
js/src/jit/x86/Assembler-x86.cpp
js/src/jit/x86/Trampoline-x86.cpp
js/src/jsapi-tests/moz.build
js/src/jsapi-tests/testJitRegisterSet.cpp
js/src/vm/UnboxedObject.cpp
mfbt/Attributes.h
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -8224,39 +8224,44 @@ StackDecrementForCall(MacroAssembler& ma
                       unsigned extraBytes = 0)
 {
     return StackDecrementForCall(masm, alignment, StackArgBytes(argTypes) + extraBytes);
 }
 
 #if defined(JS_CODEGEN_ARM)
 // The ARM system ABI also includes d15 & s31 in the non volatile float registers.
 // Also exclude lr (a.k.a. r14) as we preserve it manually)
-static const LiveRegisterSet NonVolatileRegs =
-    LiveRegisterSet(GeneralRegisterSet(Registers::NonVolatileMask&
-                                       ~(uint32_t(1) << Registers::lr)),
-                    FloatRegisterSet(FloatRegisters::NonVolatileMask
-                                     | (1ULL << FloatRegisters::d15)
-                                     | (1ULL << FloatRegisters::s31)));
+static const RegisterSet NonVolatileRegs =
+    RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask&
+                                   ~(uint32_t(1) << Registers::lr)),
+                FloatRegisterSet(FloatRegisters::NonVolatileMask
+                                 | (1ULL << FloatRegisters::d15)
+                                 | (1ULL << FloatRegisters::s31)));
 #else
-static const LiveRegisterSet NonVolatileRegs =
-    LiveRegisterSet(GeneralRegisterSet(Registers::NonVolatileMask),
-                    FloatRegisterSet(FloatRegisters::NonVolatileMask));
+static const RegisterSet NonVolatileRegs =
+    RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask),
+                FloatRegisterSet(FloatRegisters::NonVolatileMask));
 #endif
+static const FloatRegisterSet NonVolatileSimdRegs = SupportsSimd ? NonVolatileRegs.fpus()
+                                                                 : FloatRegisterSet();
 
 #if defined(JS_CODEGEN_MIPS)
 // Mips is using one more double slot due to stack alignment for double values.
 // Look at MacroAssembler::PushRegsInMask(RegisterSet set)
 static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t) +
                                              NonVolatileRegs.fpus().getPushSizeInBytes() +
                                              sizeof(double);
 #elif defined(JS_CODEGEN_NONE)
 static const unsigned FramePushedAfterSave = 0;
 #else
-static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t)
-                                           + NonVolatileRegs.fpus().getPushSizeInBytes();
+static const unsigned FramePushedAfterSave =
+   SupportsSimd ? NonVolatileRegs.gprs().size() * sizeof(intptr_t) +
+                  NonVolatileRegs.fpus().size() * Simd128DataSize
+                : NonVolatileRegs.gprs().size() * sizeof(intptr_t) +
+                  NonVolatileRegs.fpus().getPushSizeInBytes();
 #endif
 static const unsigned FramePushedForEntrySP = FramePushedAfterSave + sizeof(void*);
 
 static bool
 GenerateEntry(ModuleCompiler& m, unsigned exportIndex)
 {
     MacroAssembler& masm = m.masm();
 
@@ -8271,17 +8276,17 @@ GenerateEntry(ModuleCompiler& m, unsigne
     masm.push(ra);
 #elif defined(JS_CODEGEN_X86)
     static const unsigned EntryFrameSize = sizeof(void*);
 #endif
 
     // Save all caller non-volatile registers before we clobber them here and in
     // the asm.js callee (which does not preserve non-volatile registers).
     masm.setFramePushed(0);
-    masm.PushRegsInMask(NonVolatileRegs);
+    masm.PushRegsInMask(NonVolatileRegs, NonVolatileSimdRegs);
     MOZ_ASSERT(masm.framePushed() == FramePushedAfterSave);
 
     // ARM and MIPS have a globally-pinned GlobalReg (x64 uses RIP-relative
     // addressing, x86 uses immediates in effective addresses). For the
     // AsmJSGlobalRegBias addition, see Assembler-(mips,arm).h.
 #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
     masm.movePtr(IntArgReg1, GlobalReg);
     masm.addPtr(Imm32(AsmJSGlobalRegBias), GlobalReg);
@@ -8418,17 +8423,17 @@ GenerateEntry(ModuleCompiler& m, unsigne
         break;
       case RetType::Float32x4:
         // We don't have control on argv alignment, do an unaligned access.
         masm.storeUnalignedFloat32x4(ReturnFloat32x4Reg, Address(argv, 0));
         break;
     }
 
     // Restore clobbered non-volatile registers of the caller.
-    masm.PopRegsInMask(NonVolatileRegs);
+    masm.PopRegsInMask(NonVolatileRegs, NonVolatileSimdRegs);
     MOZ_ASSERT(masm.framePushed() == 0);
 
     masm.move32(Imm32(true), ReturnReg);
     masm.ret();
 
     return m.finishGeneratingEntry(exportIndex, &begin) && !masm.oom();
 }
 
@@ -9021,20 +9026,20 @@ GenerateOnOutOfBoundsLabelExit(ModuleCom
     // OnOutOfBounds always throws.
     masm.assertStackAlignment(ABIStackAlignment);
     masm.call(AsmJSImmPtr(AsmJSImm_OnOutOfBounds));
     masm.jump(throwLabel);
 
     return m.finishGeneratingInlineStub(&m.onOutOfBoundsLabel()) && !masm.oom();
 }
 
-static const LiveRegisterSet AllRegsExceptSP(
-    GeneralRegisterSet(Registers::AllMask&
-                       ~(uint32_t(1) << Registers::StackPointer)),
-    FloatRegisterSet(FloatRegisters::AllMask));
+static const RegisterSet AllRegsExceptSP =
+    RegisterSet(GeneralRegisterSet(Registers::AllMask&
+                                   ~(uint32_t(1) << Registers::StackPointer)),
+                FloatRegisterSet(FloatRegisters::AllDoubleMask));
 
 // The async interrupt-callback exit is called from arbitrarily-interrupted asm.js
 // code. That means we must first save *all* registers and restore *all*
 // registers (except the stack pointer) when we resume. The address to resume to
 // (assuming that js::HandleExecutionInterrupt doesn't indicate that the
 // execution should be aborted) is stored in AsmJSActivation::resumePC_.
 // Unfortunately, loading this requires a scratch register which we don't have
 // after restoring all registers. To hack around this, push the resumePC on the
@@ -9048,17 +9053,17 @@ GenerateAsyncInterruptExit(ModuleCompile
 
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
     // Be very careful here not to perturb the machine state before saving it
     // to the stack. In particular, add/sub instructions may set conditions in
     // the flags register.
     masm.push(Imm32(0));            // space for resumePC
     masm.pushFlags();               // after this we are safe to use sub
     masm.setFramePushed(0);         // set to zero so we can use masm.framePushed() below
-    masm.PushRegsInMask(AllRegsExceptSP); // save all GP/FP registers (except SP)
+    masm.PushRegsInMask(AllRegsExceptSP, AllRegsExceptSP.fpus()); // save all GP/FP registers (except SP)
 
     Register scratch = ABIArgGenerator::NonArgReturnReg0;
 
     // Store resumePC into the reserved space.
     masm.loadAsmJSActivation(scratch);
     masm.loadPtr(Address(scratch, AsmJSActivation::offsetOfResumePC()), scratch);
     masm.storePtr(scratch, Address(StackPointer, masm.framePushed() + sizeof(void*)));
 
@@ -9073,17 +9078,17 @@ GenerateAsyncInterruptExit(ModuleCompile
     masm.call(AsmJSImmPtr(AsmJSImm_HandleExecutionInterrupt));
 
     masm.branchIfFalseBool(ReturnReg, throwLabel);
 
     // Restore the StackPointer to it's position before the call.
     masm.mov(ABIArgGenerator::NonVolatileReg, StackPointer);
 
     // Restore the machine state to before the interrupt.
-    masm.PopRegsInMask(AllRegsExceptSP); // restore all GP/FP registers (except SP)
+    masm.PopRegsInMask(AllRegsExceptSP, AllRegsExceptSP.fpus()); // restore all GP/FP registers (except SP)
     masm.popFlags();              // after this, nothing that sets conditions
     masm.ret();                   // pop resumePC into PC
 #elif defined(JS_CODEGEN_MIPS)
     // Reserve space to store resumePC.
     masm.subPtr(Imm32(sizeof(intptr_t)), StackPointer);
     // set to zero so we can use masm.framePushed() below.
     masm.setFramePushed(0);
     // When this platform supports SIMD extensions, we'll need to push high lanes
@@ -9118,53 +9123,43 @@ GenerateAsyncInterruptExit(ModuleCompile
 
     // Pop resumePC into PC. Clobber HeapReg to make the jump and restore it
     // during jump delay slot.
     masm.pop(HeapReg);
     masm.as_jr(HeapReg);
     masm.loadAsmJSHeapRegisterFromGlobalData();
 #elif defined(JS_CODEGEN_ARM)
     masm.setFramePushed(0);         // set to zero so we can use masm.framePushed() below
-
-    // Save all GPR, except the stack pointer.
-    masm.PushRegsInMask(LiveRegisterSet(
-                            GeneralRegisterSet(Registers::AllMask & ~(1<<Registers::sp)),
-                            FloatRegisterSet(uint32_t(0))));
+    masm.PushRegsInMask(RegisterSet(GeneralRegisterSet(Registers::AllMask & ~(1<<Registers::sp)), FloatRegisterSet(uint32_t(0))));   // save all GP registers,excep sp
 
     // Save both the APSR and FPSCR in non-volatile registers.
     masm.as_mrs(r4);
     masm.as_vmrs(r5);
     // Save the stack pointer in a non-volatile register.
     masm.mov(sp,r6);
     // Align the stack.
     masm.ma_and(Imm32(~7), sp, sp);
 
     // Store resumePC into the return PC stack slot.
     masm.loadAsmJSActivation(IntArgReg0);
     masm.loadPtr(Address(IntArgReg0, AsmJSActivation::offsetOfResumePC()), IntArgReg1);
     masm.storePtr(IntArgReg1, Address(r6, 14 * sizeof(uint32_t*)));
 
     // When this platform supports SIMD extensions, we'll need to push and pop
     // high lanes of SIMD registers as well.
-
-    // Save all FP registers
     JS_STATIC_ASSERT(!SupportsSimd);
-    masm.PushRegsInMask(LiveRegisterSet(GeneralRegisterSet(0),
-                                        FloatRegisterSet(FloatRegisters::AllDoubleMask)));
+    masm.PushRegsInMask(RegisterSet(GeneralRegisterSet(0), FloatRegisterSet(FloatRegisters::AllDoubleMask)));   // save all FP registers
 
     masm.assertStackAlignment(ABIStackAlignment);
     masm.call(AsmJSImm_HandleExecutionInterrupt);
 
     masm.branchIfFalseBool(ReturnReg, throwLabel);
 
     // Restore the machine state to before the interrupt. this will set the pc!
-
-    // Restore all FP registers
-    masm.PopRegsInMask(LiveRegisterSet(GeneralRegisterSet(0),
-                                       FloatRegisterSet(FloatRegisters::AllDoubleMask)));
+    masm.PopRegsInMask(RegisterSet(GeneralRegisterSet(0), FloatRegisterSet(FloatRegisters::AllDoubleMask)));   // restore all FP registers
     masm.mov(r6,sp);
     masm.as_vmsr(r5);
     masm.as_msr(r4);
     // Restore all GP registers
     masm.startDataTransferM(IsLoad, sp, IA, WriteBack);
     masm.transferReg(r0);
     masm.transferReg(r1);
     masm.transferReg(r2);
@@ -9227,17 +9222,17 @@ GenerateThrowStub(ModuleCompiler& m, Lab
     // frame.
     Register scratch = ABIArgGenerator::NonArgReturnReg0;
     masm.loadAsmJSActivation(scratch);
     masm.storePtr(ImmWord(0), Address(scratch, AsmJSActivation::offsetOfFP()));
 
     masm.setFramePushed(FramePushedForEntrySP);
     masm.loadPtr(Address(scratch, AsmJSActivation::offsetOfEntrySP()), StackPointer);
     masm.Pop(scratch);
-    masm.PopRegsInMask(NonVolatileRegs);
+    masm.PopRegsInMask(NonVolatileRegs, NonVolatileSimdRegs);
     MOZ_ASSERT(masm.framePushed() == 0);
 
     masm.mov(ImmWord(0), ReturnReg);
     masm.ret();
 
     return m.finishGeneratingInlineStub(throwLabel) && !masm.oom();
 }
 
--- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp
+++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp
@@ -63,17 +63,17 @@ using namespace js::jit;
  */
 
 NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(LifoAlloc* alloc, RegExpShared* shared,
                                                        JSRuntime* rt, Mode mode, int registers_to_save)
   : RegExpMacroAssembler(*alloc, shared, registers_to_save),
     runtime(rt), mode_(mode)
 {
     // Find physical registers for each compiler register.
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs(GeneralRegisterSet::All());
 
     input_end_pointer = regs.takeAny();
     current_character = regs.takeAny();
     current_position = regs.takeAny();
     backtrack_stack_pointer = regs.takeAny();
     temp0 = regs.takeAny();
     temp1 = regs.takeAny();
     temp2 = regs.takeAny();
@@ -377,17 +377,17 @@ NativeRegExpMacroAssembler::GenerateCode
         // StackPointer to use for accessing FrameData.
         masm.bind(&stack_overflow_label_);
 
         Label grow_failed;
 
         masm.movePtr(ImmPtr(runtime), temp1);
 
         // Save registers before calling C function
-        LiveGeneralRegisterSet volatileRegs(GeneralRegisterSet::Volatile());
+        GeneralRegisterSet volatileRegs = GeneralRegisterSet::Volatile();
 #if defined(JS_CODEGEN_ARM)
         volatileRegs.add(Register::FromCode(Registers::lr));
 #elif defined(JS_CODEGEN_MIPS)
         volatileRegs.add(Register::FromCode(Registers::ra));
 #endif
         volatileRegs.takeUnchecked(temp0);
         volatileRegs.takeUnchecked(temp1);
         masm.PushRegsInMask(volatileRegs);
@@ -779,17 +779,17 @@ NativeRegExpMacroAssembler::CheckNotBack
         masm.addPtr(Imm32(sizeof(uintptr_t)), StackPointer);
 
         // Compute new value of character position after the matched part.
         masm.subPtr(input_end_pointer, current_position);
     } else {
         MOZ_ASSERT(mode_ == CHAR16);
 
         // Note: temp1 needs to be saved/restored if it is volatile, as it is used after the call.
-        LiveGeneralRegisterSet volatileRegs(GeneralRegisterSet::Volatile());
+        GeneralRegisterSet volatileRegs = GeneralRegisterSet::Volatile();
         volatileRegs.takeUnchecked(temp0);
         volatileRegs.takeUnchecked(temp2);
         masm.PushRegsInMask(volatileRegs);
 
         // Set byte_offset1.
         // Start of capture, where current_character already holds string-end negative offset.
         masm.addPtr(input_end_pointer, current_character);
 
--- a/js/src/irregexp/NativeRegExpMacroAssembler.h
+++ b/js/src/irregexp/NativeRegExpMacroAssembler.h
@@ -176,19 +176,17 @@ class MOZ_STACK_CLASS NativeRegExpMacroA
     jit::Label entry_label_;
     jit::Label start_label_;
     jit::Label backtrack_label_;
     jit::Label success_label_;
     jit::Label exit_label_;
     jit::Label stack_overflow_label_;
     jit::Label exit_with_exception_label_;
 
-    // Set of registers which are used by the code generator, and as such which
-    // are saved.
-    jit::LiveGeneralRegisterSet savedNonVolatileRegisters;
+    jit::GeneralRegisterSet savedNonVolatileRegisters;
 
     struct LabelPatch {
         // Once it is bound via BindBacktrack, |label| becomes null and
         // |labelOffset| is set.
         jit::Label* label;
         size_t labelOffset;
 
         jit::CodeOffsetLabel patchOffset;
--- a/js/src/jit/BacktrackingAllocator.cpp
+++ b/js/src/jit/BacktrackingAllocator.cpp
@@ -10,23 +10,23 @@
 using namespace js;
 using namespace js::jit;
 
 using mozilla::DebugOnly;
 
 bool
 BacktrackingAllocator::init()
 {
-    LiveRegisterSet remainingRegisters(allRegisters_.asLiveSet());
-    while (!remainingRegisters.emptyGeneral()) {
-        AnyRegister reg = AnyRegister(remainingRegisters.takeAnyGeneral());
+    RegisterSet remainingRegisters(allRegisters_);
+    while (!remainingRegisters.empty(/* float = */ false)) {
+        AnyRegister reg = AnyRegister(remainingRegisters.takeUnaliasedGeneral());
         registers[reg.code()].allocatable = true;
     }
-    while (!remainingRegisters.emptyFloat()) {
-        AnyRegister reg = AnyRegister(remainingRegisters.takeAnyFloat());
+    while (!remainingRegisters.empty(/* float = */ true)) {
+        AnyRegister reg = AnyRegister(remainingRegisters.takeUnaliasedFloat());
         registers[reg.code()].allocatable = true;
     }
 
     LifoAlloc* lifoAlloc = mir->alloc().lifoAlloc();
     for (size_t i = 0; i < AnyRegister::Total; i++) {
         registers[i].reg = AnyRegister::FromCode(i);
         registers[i].allocations.setAllocator(lifoAlloc);
 
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -462,17 +462,17 @@ BaselineCompiler::emitEpilogue()
 // This calls:
 //    void PostWriteBarrier(JSRuntime* rt, JSObject* obj);
 bool
 BaselineCompiler::emitOutOfLinePostBarrierSlot()
 {
     masm.bind(&postBarrierSlot_);
 
     Register objReg = R2.scratchReg();
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs(GeneralRegisterSet::All());
     regs.take(R0);
     regs.take(objReg);
     regs.take(BaselineFrameReg);
     Register scratch = regs.takeAny();
 #if defined(JS_CODEGEN_ARM)
     // On ARM, save the link register before calling.  It contains the return
     // address.  The |masm.ret()| later will pop this into |pc| to return.
     masm.push(lr);
@@ -794,19 +794,19 @@ BaselineCompiler::emitDebugTrap()
     return appendICEntry(ICEntry::Kind_DebugTrap, masm.currentOffset());
 }
 
 #ifdef JS_TRACE_LOGGING
 bool
 BaselineCompiler::emitTraceLoggerEnter()
 {
     TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    Register loggerReg = regs.takeAnyGeneral();
-    Register scriptReg = regs.takeAnyGeneral();
+    RegisterSet regs = RegisterSet::Volatile();
+    Register loggerReg = regs.takeGeneral();
+    Register scriptReg = regs.takeGeneral();
 
     Label noTraceLogger;
     traceLoggerEnterToggleOffset_ = masm.toggledJump(&noTraceLogger);
 
     masm.Push(loggerReg);
     masm.Push(scriptReg);
 
     masm.movePtr(ImmPtr(logger), loggerReg);
@@ -828,18 +828,17 @@ BaselineCompiler::emitTraceLoggerEnter()
 
     return true;
 }
 
 bool
 BaselineCompiler::emitTraceLoggerExit()
 {
     TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    Register loggerReg = regs.takeAnyGeneral();
+    Register loggerReg = RegisterSet::Volatile().takeGeneral();
 
     Label noTraceLogger;
     traceLoggerExitToggleOffset_ = masm.toggledJump(&noTraceLogger);
 
     masm.Push(loggerReg);
     masm.movePtr(ImmPtr(logger), loggerReg);
 
     masm.tracelogStopId(loggerReg, TraceLogger_Baseline, /* force = */ true);
@@ -3584,17 +3583,17 @@ static const VMFunction GeneratorThrowIn
 bool
 BaselineCompiler::emit_JSOP_RESUME()
 {
     GeneratorObject::ResumeKind resumeKind = GeneratorObject::getResumeKind(pc);
 
     frame.syncStack(0);
     masm.checkStackAlignment();
 
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs(GeneralRegisterSet::All());
     regs.take(BaselineFrameReg);
 
     // Load generator object.
     Register genObj = regs.takeAny();
     masm.unboxObject(frame.addressOfStackValue(frame.peek(-2)), genObj);
 
     // Load callee.
     Register callee = regs.takeAny();
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -1067,17 +1067,17 @@ EmitBaselineDebugModeOSRHandlerTail(Macr
 
     // Call a stub to free the allocated info.
     masm.setupUnalignedABICall(1, temp);
     masm.loadBaselineFramePtr(BaselineFrameReg, temp);
     masm.passABIArg(temp);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, FinishBaselineDebugModeOSR));
 
     // Restore saved values.
-    AllocatableGeneralRegisterSet jumpRegs(GeneralRegisterSet::All());
+    GeneralRegisterSet jumpRegs(GeneralRegisterSet::All());
     if (returnFromCallVM) {
         jumpRegs.take(ReturnReg);
     } else {
         jumpRegs.take(R0);
         jumpRegs.take(R1);
     }
     jumpRegs.take(BaselineFrameReg);
     Register target = jumpRegs.takeAny();
@@ -1094,17 +1094,17 @@ EmitBaselineDebugModeOSRHandlerTail(Macr
     masm.jump(target);
 }
 
 JitCode*
 JitRuntime::generateBaselineDebugModeOSRHandler(JSContext* cx, uint32_t* noFrameRegPopOffsetOut)
 {
     MacroAssembler masm(cx);
 
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs(GeneralRegisterSet::All());
     regs.take(BaselineFrameReg);
     regs.take(ReturnReg);
     Register temp = regs.takeAny();
     Register syncedStackStart = regs.takeAny();
 
     // Pop the frame reg.
     masm.pop(BaselineFrameReg);
 
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -731,27 +731,27 @@ void
 ICStubCompiler::leaveStubFrame(MacroAssembler& masm, bool calledIntoIon)
 {
     MOZ_ASSERT(entersStubFrame_);
     EmitLeaveStubFrame(masm, calledIntoIon);
 }
 
 inline bool
 ICStubCompiler::emitPostWriteBarrierSlot(MacroAssembler& masm, Register obj, ValueOperand val,
-                                         Register scratch, LiveGeneralRegisterSet saveRegs)
+                                         Register scratch, GeneralRegisterSet saveRegs)
 {
     Label skipBarrier;
     masm.branchPtrInNurseryRange(Assembler::Equal, obj, scratch, &skipBarrier);
     masm.branchValueIsNurseryObject(Assembler::NotEqual, val, scratch, &skipBarrier);
 
     // void PostWriteBarrier(JSRuntime* rt, JSObject* obj);
 #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
     saveRegs.add(BaselineTailCallReg);
 #endif
-    saveRegs.set() = GeneralRegisterSet::Intersect(saveRegs.set(), GeneralRegisterSet::Volatile());
+    saveRegs = GeneralRegisterSet::Intersect(saveRegs, GeneralRegisterSet::Volatile());
     masm.PushRegsInMask(saveRegs);
     masm.setupUnalignedABICall(2, scratch);
     masm.movePtr(ImmPtr(cx->runtime()), scratch);
     masm.passABIArg(scratch);
     masm.passABIArg(obj);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, PostWriteBarrier));
     masm.PopRegsInMask(saveRegs);
 
@@ -995,17 +995,17 @@ ICWarmUpCounter_Fallback::Compiler::gene
 
         leaveStubFrame(masm);
 
         // If no JitCode was found, then skip just exit the IC.
         masm.branchPtr(Assembler::Equal, R0.scratchReg(), ImmPtr(nullptr), &noCompiledCode);
     }
 
     // Get a scratch register.
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
     Register osrDataReg = R0.scratchReg();
     regs.take(osrDataReg);
     regs.takeUnchecked(OsrFrameReg);
 
     Register scratchReg = regs.takeAny();
 
     // At this point, stack looks like:
     //  +-> [...Calling-Frame...]
@@ -1988,17 +1988,17 @@ ICCompare_String::Compiler::generateStub
     masm.branchTestString(Assembler::NotEqual, R0, &failure);
     masm.branchTestString(Assembler::NotEqual, R1, &failure);
 
     MOZ_ASSERT(IsEqualityOp(op));
 
     Register left = masm.extractString(R0, ExtractTemp0);
     Register right = masm.extractString(R1, ExtractTemp1);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     masm.compareStrings(op, left, right, scratchReg, &failure);
     masm.tagValue(JSVAL_TYPE_BOOLEAN, scratchReg, R0);
     EmitReturnFromIC(masm);
 
     masm.bind(&failure);
     EmitStubGuardFailure(masm);
@@ -3186,17 +3186,17 @@ GetDOMProxyProto(JSObject* obj)
 // Callers are expected to have already guarded on the shape of the
 // object, which guarantees the object is a DOM proxy.
 static void
 CheckDOMProxyExpandoDoesNotShadow(JSContext* cx, MacroAssembler& masm, Register object,
                                   const Address& checkExpandoShapeAddr,
                                   Address* expandoAndGenerationAddr,
                                   Address* generationAddr,
                                   Register scratch,
-                                  AllocatableGeneralRegisterSet& domProxyRegSet,
+                                  GeneralRegisterSet& domProxyRegSet,
                                   Label* checkFailed)
 {
     // Guard that the object does not have expando properties, or has an expando
     // which is known to not have the desired property.
 
     // For the remaining code, we need to reserve some registers to load a value.
     // This is ugly, but unavoidable.
     ValueOperand tempVal = domProxyRegSet.takeAnyValue();
@@ -4121,17 +4121,17 @@ DoAtomizeString(JSContext* cx, HandleStr
 }
 
 typedef bool (*DoAtomizeStringFn)(JSContext*, HandleString, MutableHandleValue);
 static const VMFunction DoAtomizeStringInfo = FunctionInfo<DoAtomizeStringFn>(DoAtomizeString);
 
 bool
 ICGetElemNativeCompiler::emitCallNative(MacroAssembler& masm, Register objReg)
 {
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs = availableGeneralRegs(0);
     regs.takeUnchecked(objReg);
     regs.takeUnchecked(BaselineTailCallReg);
 
     enterStubFrame(masm, regs.getAny());
 
     // Push object.
     masm.push(objReg);
 
@@ -4148,17 +4148,17 @@ ICGetElemNativeCompiler::emitCallNative(
     leaveStubFrame(masm);
 
     return true;
 }
 
 bool
 ICGetElemNativeCompiler::emitCallScripted(MacroAssembler& masm, Register objReg)
 {
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs = availableGeneralRegs(0);
     regs.takeUnchecked(objReg);
     regs.takeUnchecked(BaselineTailCallReg);
 
     // Enter stub frame.
     enterStubFrame(masm, regs.getAny());
 
     // Align the stack such that the JitFrameLayout is aligned on
     // JitStackAlignment.
@@ -4222,17 +4222,17 @@ ICGetElemNativeCompiler::generateStubCod
 {
     Label failure;
     Label failurePopR1;
     bool popR1 = false;
 
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
     masm.branchTestString(Assembler::NotEqual, R1, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     // Unbox object.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
 
     // Check object shape.
     masm.loadPtr(Address(objReg, JSObject::offsetOfShape()), scratchReg);
     Address shapeAddr(BaselineStubReg, ICGetElemNativeStub::offsetOfShape());
@@ -4339,17 +4339,17 @@ ICGetElemNativeCompiler::generateStubCod
         // Check if __noSuchMethod__ needs to be called.
 #if JS_HAS_NO_SUCH_METHOD
         if (isCallElem_) {
             Label afterNoSuchMethod;
             Label skipNoSuchMethod;
 
             masm.branchTestUndefined(Assembler::NotEqual, valAddr, &skipNoSuchMethod);
 
-            AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+            GeneralRegisterSet regs = availableGeneralRegs(0);
             regs.take(R1);
             regs.take(R0);
             regs.takeUnchecked(objReg);
             if (popR1)
                 masm.pop(R1.scratchReg());
 
             // Box and push obj and key onto baseline frame stack for decompiler.
             masm.tagValue(JSVAL_TYPE_OBJECT, objReg, R0);
@@ -4442,17 +4442,17 @@ ICGetElemNativeCompiler::generateStubCod
 
 bool
 ICGetElem_String::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
     masm.branchTestString(Assembler::NotEqual, R0, &failure);
     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     // Unbox string in R0.
     Register str = masm.extractString(R0, ExtractTemp0);
 
     // Check for non-linear strings.
     masm.branchIfRope(str, &failure);
 
@@ -4490,17 +4490,17 @@ ICGetElem_String::Compiler::generateStub
 
 bool
 ICGetElem_Dense::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     // Unbox R0 and shape guard.
     Register obj = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICGetElem_Dense::offsetOfShape()), scratchReg);
     masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
 
     // Load obj->elements.
@@ -4524,17 +4524,17 @@ ICGetElem_Dense::Compiler::generateStubC
 #endif
     if (isCallElem_) {
         Label afterNoSuchMethod;
         Label skipNoSuchMethod;
         regs = availableGeneralRegs(0);
         regs.takeUnchecked(obj);
         regs.takeUnchecked(key);
         regs.takeUnchecked(BaselineTailCallReg);
-        ValueOperand val = regs.takeAnyValue();
+        ValueOperand val = regs.takeValueOperand();
 
         masm.loadValue(element, val);
         masm.branchTestUndefined(Assembler::NotEqual, val, &skipNoSuchMethod);
 
         // Box and push obj and key onto baseline frame stack for decompiler.
         EmitRestoreTailCallReg(masm);
         masm.tagValue(JSVAL_TYPE_OBJECT, obj, val);
         masm.pushValue(val);
@@ -4638,17 +4638,17 @@ ICGetElem_TypedArray::Compiler::generate
 {
     Label failure;
 
     if (layout_ != Layout_TypedArray)
         CheckForNeuteredTypedObject(cx, masm, &failure);
 
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     // Unbox R0 and shape guard.
     Register obj = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICGetElem_TypedArray::offsetOfShape()), scratchReg);
     masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
 
     // Ensure the index is an integer.
@@ -4718,17 +4718,17 @@ ICGetElem_Arguments::Compiler::generateS
                           Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags()),
                           Imm32(BaselineFrame::HAS_ARGS_OBJ),
                           &failure);
 
         // Ensure that index is an integer.
         masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
         Register idx = masm.extractInt32(R1, ExtractTemp1);
 
-        AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+        GeneralRegisterSet regs(availableGeneralRegs(2));
         Register scratch = regs.takeAny();
 
         // Load num actual arguments
         Address actualArgs(BaselineFrameReg, BaselineFrame::offsetOfNumActualArgs());
         masm.loadPtr(actualArgs, scratch);
 
         // Ensure idx < argc
         masm.branch32(Assembler::AboveOrEqual, idx, scratch, &failure);
@@ -4748,17 +4748,17 @@ ICGetElem_Arguments::Compiler::generateS
     }
 
     MOZ_ASSERT(which_ == ICGetElem_Arguments::Strict ||
                which_ == ICGetElem_Arguments::Normal);
 
     bool isStrict = which_ == ICGetElem_Arguments::Strict;
     const Class* clasp = isStrict ? &StrictArgumentsObject::class_ : &NormalArgumentsObject::class_;
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     // Guard on input being an arguments object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
     Register objReg = masm.extractObject(R0, ExtractTemp0);
     masm.branchTestObjClass(Assembler::NotEqual, objReg, scratchReg, clasp, &failure);
 
     // Guard on index being int32
@@ -4822,17 +4822,17 @@ ICGetElem_Arguments::Compiler::generateS
 
         masm.branchTestUndefined(Assembler::NotEqual, tempVal, &skipNoSuchMethod);
 
         // Call __noSuchMethod__ checker.  Object pointer is in objReg.
         regs = availableGeneralRegs(0);
         regs.takeUnchecked(objReg);
         regs.takeUnchecked(idxReg);
         regs.takeUnchecked(BaselineTailCallReg);
-        ValueOperand val = regs.takeAnyValue();
+        ValueOperand val = regs.takeValueOperand();
 
         // Box and push obj and key onto baseline frame stack for decompiler.
         EmitRestoreTailCallReg(masm);
         masm.tagValue(JSVAL_TYPE_OBJECT, objReg, val);
         masm.pushValue(val);
         masm.tagValue(JSVAL_TYPE_INT32, idxReg, val);
         masm.pushValue(val);
         EmitRepushTailCallReg(masm);
@@ -5256,17 +5256,17 @@ ICSetElem_Dense::Compiler::generateStubC
     // R0 = object
     // R1 = key
     // Stack = { ... rhs-value, <return-addr>? }
     Label failure;
     Label failureUnstow;
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     // Unbox R0 and guard on its shape.
     Register obj = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICSetElem_Dense::offsetOfShape()), scratchReg);
     masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
 
     // Stow both R0 and R1 (object and key)
@@ -5351,17 +5351,17 @@ ICSetElem_Dense::Compiler::generateStubC
     // for post-write barrier later.
     ValueOperand tmpVal = regs.takeAnyValue();
     masm.loadValue(valueAddr, tmpVal);
     EmitPreBarrier(masm, element, MIRType_Value);
     masm.storeValue(tmpVal, element);
     regs.add(key);
     if (cx->runtime()->gc.nursery.exists()) {
         Register r = regs.takeAny();
-        LiveGeneralRegisterSet saveRegs;
+        GeneralRegisterSet saveRegs;
         emitPostWriteBarrierSlot(masm, obj, tmpVal, r, saveRegs);
         regs.add(r);
     }
     EmitReturnFromIC(masm);
 
 
     // Failure case - fail but first unstow R0 and R1
     masm.bind(&failureUnstow);
@@ -5422,17 +5422,17 @@ ICSetElemDenseAddCompiler::generateStubC
     // R0 = object
     // R1 = key
     // Stack = { ... rhs-value, <return-addr>? }
     Label failure;
     Label failureUnstow;
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     // Unbox R0 and guard on its shape.
     Register obj = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICSetElem_DenseAddImpl<0>::offsetOfShape(0)),
                  scratchReg);
     masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
 
@@ -5536,17 +5536,17 @@ ICSetElemDenseAddCompiler::generateStubC
     // Write the value.  No need for pre-barrier since we're not overwriting an old value.
     ValueOperand tmpVal = regs.takeAnyValue();
     BaseIndex element(scratchReg, key, TimesEight);
     masm.loadValue(valueAddr, tmpVal);
     masm.storeValue(tmpVal, element);
     regs.add(key);
     if (cx->runtime()->gc.nursery.exists()) {
         Register r = regs.takeAny();
-        LiveGeneralRegisterSet saveRegs;
+        GeneralRegisterSet saveRegs;
         emitPostWriteBarrierSlot(masm, obj, tmpVal, r, saveRegs);
         regs.add(r);
     }
     EmitReturnFromIC(masm);
 
     // Failure case - fail but first unstow R0 and R1
     masm.bind(&failureUnstow);
     EmitUnstowICValues(masm, 2);
@@ -5632,17 +5632,17 @@ ICSetElem_TypedArray::Compiler::generate
 {
     Label failure;
 
     if (layout_ != Layout_TypedArray)
         CheckForNeuteredTypedObject(cx, masm, &failure);
 
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratchReg = regs.takeAny();
 
     // Unbox R0 and shape guard.
     Register obj = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICSetElem_TypedArray::offsetOfShape()), scratchReg);
     masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
 
     // Ensure the index is an integer.
@@ -6151,17 +6151,17 @@ ICGetName_Global::Compiler::generateStub
     return true;
 }
 
 template <size_t NumHops>
 bool
 ICGetName_Scope<NumHops>::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     Register obj = R0.scratchReg();
     Register walker = regs.takeAny();
     Register scratch = regs.takeAny();
 
     // Use a local to silence Clang tautological-compare warning if NumHops is 0.
     size_t numHops = NumHops;
 
     for (size_t index = 0; index < NumHops + 1; index++) {
@@ -7160,17 +7160,17 @@ ICGetProp_Primitive::Compiler::generateS
         break;
       case JSVAL_TYPE_BOOLEAN:
         masm.branchTestBoolean(Assembler::NotEqual, R0, &failure);
         break;
       default:
         MOZ_CRASH("unexpected type");
     }
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     Register holderReg = regs.takeAny();
     Register scratchReg = regs.takeAny();
 
     // Verify the shape of the prototype.
     masm.movePtr(ImmGCPtr(prototype_.get()), holderReg);
 
     Address shapeAddr(BaselineStubReg, ICGetProp_Primitive::offsetOfProtoShape());
     masm.loadPtr(Address(holderReg, JSObject::offsetOfShape()), scratchReg);
@@ -7251,17 +7251,17 @@ GuardReceiverObject(MacroAssembler& masm
         }
     }
 }
 
 bool
 ICGetPropNativeCompiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
     Register objReg = InvalidReg;
 
     if (inputDefinitelyObject_) {
         objReg = R0.scratchReg();
     } else {
         regs.take(R0);
         // Guard input is an object and unbox.
         masm.branchTestObject(Assembler::NotEqual, R0, &failure);
@@ -7319,17 +7319,17 @@ ICGetPropNativeCompiler::generateStubCod
         masm.branchTestUndefined(Assembler::NotEqual, R0, &skipNoSuchMethod);
 
         masm.pop(objReg);
 
         // Call __noSuchMethod__ checker.  Object pointer is in objReg.
         regs = availableGeneralRegs(0);
         regs.takeUnchecked(objReg);
         regs.takeUnchecked(BaselineTailCallReg);
-        ValueOperand val = regs.takeAnyValue();
+        ValueOperand val = regs.takeValueOperand();
 
         // Box and push obj onto baseline frame stack for decompiler.
         EmitRestoreTailCallReg(masm);
         masm.tagValue(JSVAL_TYPE_OBJECT, objReg, val);
         masm.pushValue(val);
         EmitRepushTailCallReg(masm);
 
         enterStubFrame(masm, regs.getAnyExcluding(BaselineTailCallReg));
@@ -7396,17 +7396,17 @@ ICGetPropNativeDoesNotExistCompiler::get
     return stub;
 }
 
 bool
 ICGetPropNativeDoesNotExistCompiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     Register scratch = regs.takeAny();
 
 #ifdef DEBUG
     // Ensure that protoChainDepth_ matches the protoChainDepth stored on the stub.
     {
         Label ok;
         masm.load16ZeroExtend(Address(BaselineStubReg, ICStub::offsetOfExtra()), scratch);
         masm.branch32(Assembler::Equal, scratch, Imm32(protoChainDepth_), &ok);
@@ -7446,17 +7446,17 @@ ICGetPropNativeDoesNotExistCompiler::gen
     return true;
 }
 
 bool
 ICGetProp_CallScripted::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
     Label failureLeaveStubFrame;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
     // Unbox and shape guard.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
     GuardReceiverObject(masm, ReceiverGuard::StackGuard(receiver_), objReg, scratch,
@@ -7535,17 +7535,17 @@ ICGetProp_CallScripted::Compiler::genera
     return true;
 }
 
 bool
 ICGetProp_CallNative::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
     Register objReg = InvalidReg;
 
     MOZ_ASSERT(!(inputDefinitelyObject_ && outerClass_));
     if (inputDefinitelyObject_) {
         objReg = R0.scratchReg();
     } else {
         regs.take(R0);
         // Guard input is an object and unbox.
@@ -7608,17 +7608,17 @@ ICGetProp_CallNative::Compiler::generate
 }
 
 bool
 ICGetPropCallDOMProxyNativeCompiler::generateStubCode(MacroAssembler& masm,
                                                       Address* expandoAndGenerationAddr,
                                                       Address* generationAddr)
 {
     Label failure;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
     // Unbox.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
 
@@ -7626,17 +7626,17 @@ ICGetPropCallDOMProxyNativeCompiler::gen
     static const size_t receiverShapeOffset =
         ICGetProp_CallDOMProxyNative::offsetOfReceiverGuard() +
         ReceiverGuard::offsetOfShape();
     masm.loadPtr(Address(BaselineStubReg, receiverShapeOffset), scratch);
     masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
 
     // Guard that our expando object hasn't started shadowing this property.
     {
-        AllocatableGeneralRegisterSet domProxyRegSet(GeneralRegisterSet::All());
+        GeneralRegisterSet domProxyRegSet(GeneralRegisterSet::All());
         domProxyRegSet.take(BaselineStubReg);
         domProxyRegSet.take(objReg);
         domProxyRegSet.take(scratch);
         Address expandoShapeAddr(BaselineStubReg, ICGetProp_CallDOMProxyNative::offsetOfExpandoShape());
         CheckDOMProxyExpandoDoesNotShadow(
                 cx, masm, objReg,
                 expandoShapeAddr, expandoAndGenerationAddr, generationAddr,
                 scratch,
@@ -7749,17 +7749,17 @@ typedef bool (*ProxyGetFn)(JSContext* cx
                            MutableHandleValue vp);
 static const VMFunction ProxyGetInfo = FunctionInfo<ProxyGetFn>(ProxyGet);
 
 bool
 ICGetProp_DOMProxyShadowed::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     // Need to reserve a scratch register, but the scratch register should not be
     // BaselineTailCallReg, because it's used for |enterStubFrame| which needs a
     // non-BaselineTailCallReg scratch reg.
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
@@ -7901,17 +7901,17 @@ DoGetPropGeneric(JSContext* cx, Baseline
 }
 
 typedef bool (*DoGetPropGenericFn)(JSContext*, BaselineFrame*, ICGetProp_Generic*, MutableHandleValue, MutableHandleValue);
 static const VMFunction DoGetPropGenericInfo = FunctionInfo<DoGetPropGenericFn>(DoGetPropGeneric);
 
 bool
 ICGetProp_Generic::Compiler::generateStubCode(MacroAssembler& masm)
 {
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
 
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Sync for the decompiler.
     EmitStowICValues(masm, 1);
 
     enterStubFrame(masm, scratch);
 
@@ -7930,17 +7930,17 @@ ICGetProp_Generic::Compiler::generateStu
     return true;
 }
 
 bool
 ICGetProp_Unboxed::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
 
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Object and group guard.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
     Register object = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICGetProp_Unboxed::offsetOfGroup()), scratch);
     masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfGroup()), scratch,
@@ -7965,17 +7965,17 @@ ICGetProp_Unboxed::Compiler::generateStu
 
 bool
 ICGetProp_TypedObject::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
 
     CheckForNeuteredTypedObject(cx, masm, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
 
     Register scratch1 = regs.takeAnyExcluding(BaselineTailCallReg);
     Register scratch2 = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Object and shape guard.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
     Register object = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICGetProp_TypedObject::offsetOfShape()), scratch1);
@@ -8475,17 +8475,17 @@ ICSetProp_Fallback::Compiler::postGenera
 bool
 ICSetProp_Native::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratch = regs.takeAny();
 
     // Unbox and shape guard.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICSetProp_Native::offsetOfShape()), scratch);
     masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
 
     // Guard that the object group matches.
@@ -8520,17 +8520,17 @@ ICSetProp_Native::Compiler::generateStub
     // Perform the store.
     masm.load32(Address(BaselineStubReg, ICSetProp_Native::offsetOfOffset()), scratch);
     EmitPreBarrier(masm, BaseIndex(holderReg, scratch, TimesOne), MIRType_Value);
     masm.storeValue(R1, BaseIndex(holderReg, scratch, TimesOne));
     if (holderReg != objReg)
         regs.add(holderReg);
     if (cx->runtime()->gc.nursery.exists()) {
         Register scr = regs.takeAny();
-        LiveGeneralRegisterSet saveRegs;
+        GeneralRegisterSet saveRegs;
         saveRegs.add(R1);
         emitPostWriteBarrierSlot(masm, objReg, R1, scr, saveRegs);
         regs.add(scr);
     }
 
     // The RHS has to be in R0.
     masm.moveValue(R1, R0);
     EmitReturnFromIC(masm);
@@ -8571,17 +8571,17 @@ bool
 ICSetPropNativeAddCompiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
     Label failureUnstow;
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratch = regs.takeAny();
 
     // Unbox and guard against old shape.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICSetProp_NativeAddImpl<0>::offsetOfShape(0)), scratch);
     masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
 
     // Guard that the object group matches.
@@ -8664,17 +8664,17 @@ ICSetPropNativeAddCompiler::generateStub
     masm.load32(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfOffset()), scratch);
     masm.storeValue(R1, BaseIndex(holderReg, scratch, TimesOne));
 
     if (holderReg != objReg)
         regs.add(holderReg);
 
     if (cx->runtime()->gc.nursery.exists()) {
         Register scr = regs.takeAny();
-        LiveGeneralRegisterSet saveRegs;
+        GeneralRegisterSet saveRegs;
         saveRegs.add(R1);
         emitPostWriteBarrierSlot(masm, objReg, R1, scr, saveRegs);
     }
 
     // The RHS has to be in R0.
     masm.moveValue(R1, R0);
     EmitReturnFromIC(masm);
 
@@ -8690,17 +8690,17 @@ ICSetPropNativeAddCompiler::generateStub
 bool
 ICSetProp_Unboxed::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratch = regs.takeAny();
 
     // Unbox and group guard.
     Register object = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICSetProp_Unboxed::offsetOfGroup()), scratch);
     masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfGroup()), scratch,
                    &failure);
 
@@ -8719,17 +8719,17 @@ ICSetProp_Unboxed::Compiler::generateStu
 
         // Unstow R0 and R1 (object and key)
         EmitUnstowICValues(masm, 2);
         masm.pop(BaselineStubReg);
         masm.pop(object);
 
         // Trigger post barriers here on the values being written. Fields which
         // objects can be written to also need update stubs.
-        LiveGeneralRegisterSet saveRegs;
+        GeneralRegisterSet saveRegs;
         saveRegs.add(R0);
         saveRegs.add(R1);
         saveRegs.addUnchecked(object);
         saveRegs.add(BaselineStubReg);
         emitPostWriteBarrierSlot(masm, object, R1, scratch, saveRegs);
     }
 
     // Compute the address being written to.
@@ -8761,17 +8761,17 @@ ICSetProp_TypedObject::Compiler::generat
 {
     Label failure;
 
     CheckForNeuteredTypedObject(cx, masm, &failure);
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
+    GeneralRegisterSet regs(availableGeneralRegs(2));
     Register scratch = regs.takeAny();
 
     // Unbox and shape guard.
     Register object = masm.extractObject(R0, ExtractTemp0);
     masm.loadPtr(Address(BaselineStubReg, ICSetProp_TypedObject::offsetOfShape()), scratch);
     masm.branchTestObjShape(Assembler::NotEqual, object, scratch, &failure);
 
     // Guard that the object group matches.
@@ -8794,17 +8794,17 @@ ICSetProp_TypedObject::Compiler::generat
 
         // Unstow R0 and R1 (object and key)
         EmitUnstowICValues(masm, 2);
         masm.pop(BaselineStubReg);
         masm.pop(object);
 
         // Trigger post barriers here on the values being written. Descriptors
         // which can write objects also need update stubs.
-        LiveGeneralRegisterSet saveRegs;
+        GeneralRegisterSet saveRegs;
         saveRegs.add(R0);
         saveRegs.add(R1);
         saveRegs.addUnchecked(object);
         saveRegs.add(BaselineStubReg);
         emitPostWriteBarrierSlot(masm, object, R1, scratch, saveRegs);
     }
 
     // Save the rhs on the stack so we can get a second scratch register.
@@ -8886,17 +8886,17 @@ ICSetProp_CallScripted::Compiler::genera
     Label failureLeaveStubFrame;
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
     // Stow R0 and R1 to free up registers.
     EmitStowICValues(masm, 2);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Unbox and shape guard.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
     GuardReceiverObject(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
                         ICSetProp_CallScripted::offsetOfGuard(), &failureUnstow);
 
     Register holderReg = regs.takeAny();
@@ -9005,17 +9005,17 @@ ICSetProp_CallNative::Compiler::generate
     Label failureUnstow;
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
     // Stow R0 and R1 to free up registers.
     EmitStowICValues(masm, 2);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Unbox and shape guard.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
     GuardReceiverObject(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
                         ICSetProp_CallNative::offsetOfGuard(), &failureUnstow);
 
     Register holderReg = regs.takeAny();
@@ -9713,17 +9713,17 @@ DoSpreadCallFallback(JSContext* cx, Base
         return false;
 
     if (!handled)
         stub->noteUnoptimizableCall();
     return true;
 }
 
 void
-ICCallStubCompiler::pushCallArguments(MacroAssembler& masm, AllocatableGeneralRegisterSet regs,
+ICCallStubCompiler::pushCallArguments(MacroAssembler& masm, GeneralRegisterSet regs,
                                       Register argcReg, bool isJitCall)
 {
     MOZ_ASSERT(!regs.has(argcReg));
 
     // Push the callee and |this| too.
     Register count = regs.takeAny();
     masm.mov(argcReg, count);
     masm.add32(Imm32(2), count);
@@ -9766,18 +9766,17 @@ ICCallStubCompiler::guardSpreadCall(Macr
     // blow the stack limit).
     static_assert(ICCall_Scripted::MAX_ARGS_SPREAD_LENGTH <= ARGS_LENGTH_MAX,
                   "maximum arguments length for optimized stub should be <= ARGS_LENGTH_MAX");
     masm.branch32(Assembler::Above, argcReg, Imm32(ICCall_Scripted::MAX_ARGS_SPREAD_LENGTH),
                   failure);
 }
 
 void
-ICCallStubCompiler::pushSpreadCallArguments(MacroAssembler& masm,
-                                            AllocatableGeneralRegisterSet regs,
+ICCallStubCompiler::pushSpreadCallArguments(MacroAssembler& masm, GeneralRegisterSet regs,
                                             Register argcReg, bool isJitCall)
 {
     // Push arguments
     Register startReg = regs.takeAny();
     Register endReg = regs.takeAny();
     masm.unboxObject(Address(BaselineStackReg, STUB_FRAME_SIZE), startReg);
     masm.loadPtr(Address(startReg, NativeObject::offsetOfElements()), startReg);
     masm.mov(argcReg, endReg);
@@ -9804,19 +9803,18 @@ ICCallStubCompiler::pushSpreadCallArgume
     regs.add(endReg);
 
     // Push the callee and |this|.
     masm.pushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE + 1 * sizeof(Value)));
     masm.pushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE + 2 * sizeof(Value)));
 }
 
 Register
-ICCallStubCompiler::guardFunApply(MacroAssembler& masm, AllocatableGeneralRegisterSet regs,
-                                  Register argcReg, bool checkNative, FunApplyThing applyThing,
-                                  Label* failure)
+ICCallStubCompiler::guardFunApply(MacroAssembler& masm, GeneralRegisterSet regs, Register argcReg,
+                                  bool checkNative, FunApplyThing applyThing, Label* failure)
 {
     // Ensure argc == 2
     masm.branch32(Assembler::NotEqual, argcReg, Imm32(2), failure);
 
     // Stack looks like:
     //      [..., CalleeV, ThisV, Arg0V, Arg1V <MaybeReturnReg>]
 
     Address secondArgSlot(BaselineStackReg, ICStackValueOffset);
@@ -9827,17 +9825,17 @@ ICCallStubCompiler::guardFunApply(MacroA
         // Ensure that this frame doesn't have an arguments object.
         masm.branchTest32(Assembler::NonZero,
                           Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags()),
                           Imm32(BaselineFrame::HAS_ARGS_OBJ),
                           failure);
     } else {
         MOZ_ASSERT(applyThing == FunApply_Array);
 
-        AllocatableGeneralRegisterSet regsx = regs;
+        GeneralRegisterSet regsx = regs;
 
         // Ensure that the second arg is an array.
         ValueOperand secondArgVal = regsx.takeAnyValue();
         masm.loadValue(secondArgSlot, secondArgVal);
 
         masm.branchTestObject(Assembler::NotEqual, secondArgVal, failure);
         Register secondArgObj = masm.extractObject(secondArgVal, ExtractTemp1);
 
@@ -9919,17 +9917,17 @@ ICCallStubCompiler::guardFunApply(MacroA
         masm.loadPtr(Address(target, JSFunction::offsetOfNativeOrScript()), temp);
         masm.loadBaselineOrIonRaw(temp, temp, failure);
         regs.add(temp);
     }
     return target;
 }
 
 void
-ICCallStubCompiler::pushCallerArguments(MacroAssembler& masm, AllocatableGeneralRegisterSet regs)
+ICCallStubCompiler::pushCallerArguments(MacroAssembler& masm, GeneralRegisterSet regs)
 {
     // Initialize copyReg to point to start caller arguments vector.
     // Initialize argcReg to poitn to the end of it.
     Register startReg = regs.takeAny();
     Register endReg = regs.takeAny();
     masm.loadPtr(Address(BaselineFrameReg, 0), startReg);
     masm.loadPtr(Address(startReg, BaselineFrame::offsetOfNumActualArgs()), endReg);
     masm.addPtr(Imm32(BaselineFrame::offsetOfArg(0)), startReg);
@@ -9945,17 +9943,17 @@ ICCallStubCompiler::pushCallerArguments(
     masm.subPtr(Imm32(sizeof(Value)), endReg);
     masm.pushValue(Address(endReg, 0));
     masm.jump(&copyStart);
     masm.bind(&copyDone);
 }
 
 void
 ICCallStubCompiler::pushArrayArguments(MacroAssembler& masm, Address arrayVal,
-                                       AllocatableGeneralRegisterSet regs)
+                                       GeneralRegisterSet regs)
 {
     // Load start and end address of values to copy.
     // guardFunApply has already gauranteed that the array is packed and contains
     // no holes.
     Register startReg = regs.takeAny();
     Register endReg = regs.takeAny();
     masm.extractObject(arrayVal, startReg);
     masm.loadPtr(Address(startReg, NativeObject::offsetOfElements()), startReg);
@@ -9991,17 +9989,17 @@ ICCall_Fallback::Compiler::generateStubC
 
     // Push a stub frame so that we can perform a non-tail call.
     enterStubFrame(masm, R1.scratchReg());
 
     // Values are on the stack left-to-right. Calling convention wants them
     // right-to-left so duplicate them on the stack in reverse order.
     // |this| and callee are pushed last.
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
 
     if (MOZ_UNLIKELY(isSpread_)) {
         // Use BaselineFrameReg instead of BaselineStackReg, because
         // BaselineFrameReg and BaselineStackReg hold the same value just after
         // calling enterStubFrame.
         masm.pushValue(Address(BaselineFrameReg, 0 * sizeof(Value) + STUB_FRAME_SIZE)); // array
         masm.pushValue(Address(BaselineFrameReg, 1 * sizeof(Value) + STUB_FRAME_SIZE)); // this
         masm.pushValue(Address(BaselineFrameReg, 2 * sizeof(Value) + STUB_FRAME_SIZE)); // callee
@@ -10097,17 +10095,17 @@ ICCall_Fallback::Compiler::postGenerateS
 
 typedef bool (*CreateThisFn)(JSContext* cx, HandleObject callee, MutableHandleValue rval);
 static const VMFunction CreateThisInfoBaseline = FunctionInfo<CreateThisFn>(CreateThis);
 
 bool
 ICCallScriptedCompiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
     bool canUseTailCallReg = regs.has(BaselineTailCallReg);
 
     Register argcReg = R0.scratchReg();
     MOZ_ASSERT(argcReg != ArgumentsRectifierReg);
 
     regs.take(argcReg);
     regs.take(ArgumentsRectifierReg);
     regs.takeUnchecked(BaselineTailCallReg);
@@ -10362,17 +10360,17 @@ ICCallScriptedCompiler::generateStubCode
 
 typedef bool (*CopyArrayFn)(JSContext*, HandleArrayObject, MutableHandleValue);
 static const VMFunction CopyArrayInfo = FunctionInfo<CopyArrayFn>(CopyArray);
 
 bool
 ICCall_StringSplit::Compiler::generateStubCode(MacroAssembler& masm)
 {
     // Stack Layout: [ ..., CalleeVal, ThisVal, Arg0Val, +ICStackValueOffset+ ]
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs = availableGeneralRegs(0);
     Label failureRestoreArgc;
 #ifdef DEBUG
     Label oneArg;
     Register argcReg = R0.scratchReg();
     masm.branch32(Assembler::Equal, argcReg, Imm32(1), &oneArg);
     masm.assumeUnreachable("Expected argc == 1");
     masm.bind(&oneArg);
 #endif
@@ -10456,17 +10454,17 @@ ICCall_StringSplit::Compiler::generateSt
 
 bool
 ICCall_IsSuspendedStarGenerator::Compiler::generateStubCode(MacroAssembler& masm)
 {
     // The IsSuspendedStarGenerator intrinsic is only called in self-hosted
     // code, so it's safe to assume we have a single argument and the callee
     // is our intrinsic.
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs = availableGeneralRegs(0);
 
     // Load the argument.
     Address argAddr(BaselineStackReg, ICStackValueOffset);
     ValueOperand argVal = regs.takeAnyValue();
     masm.loadValue(argAddr, argVal);
 
     // Check if it's an object.
     Label returnFalse;
@@ -10495,17 +10493,17 @@ ICCall_IsSuspendedStarGenerator::Compile
     EmitReturnFromIC(masm);
     return true;
 }
 
 bool
 ICCall_Native::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
 
     Register argcReg = R0.scratchReg();
     regs.take(argcReg);
     regs.takeUnchecked(BaselineTailCallReg);
 
     if (isSpread_)
         guardSpreadCall(masm, argcReg, &failure);
 
@@ -10599,17 +10597,17 @@ ICCall_Native::Compiler::generateStubCod
     EmitStubGuardFailure(masm);
     return true;
 }
 
 bool
 ICCall_ClassHook::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
 
     Register argcReg = R0.scratchReg();
     regs.take(argcReg);
     regs.takeUnchecked(BaselineTailCallReg);
 
     // Load the callee in R1.
     BaseValueIndex calleeSlot(BaselineStackReg, argcReg, ICStackValueOffset + sizeof(Value));
     masm.loadValue(calleeSlot, R1);
@@ -10686,17 +10684,17 @@ ICCall_ClassHook::Compiler::generateStub
     EmitStubGuardFailure(masm);
     return true;
 }
 
 bool
 ICCall_ScriptedApplyArray::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
 
     Register argcReg = R0.scratchReg();
     regs.take(argcReg);
     regs.takeUnchecked(BaselineTailCallReg);
     regs.takeUnchecked(ArgumentsRectifierReg);
 
     //
     // Validate inputs
@@ -10788,17 +10786,17 @@ ICCall_ScriptedApplyArray::Compiler::gen
     EmitStubGuardFailure(masm);
     return true;
 }
 
 bool
 ICCall_ScriptedApplyArguments::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
 
     Register argcReg = R0.scratchReg();
     regs.take(argcReg);
     regs.takeUnchecked(BaselineTailCallReg);
     regs.takeUnchecked(ArgumentsRectifierReg);
 
     //
     // Validate inputs
@@ -10884,17 +10882,17 @@ ICCall_ScriptedApplyArguments::Compiler:
     EmitStubGuardFailure(masm);
     return true;
 }
 
 bool
 ICCall_ScriptedFunCall::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+    GeneralRegisterSet regs(availableGeneralRegs(0));
     bool canUseTailCallReg = regs.has(BaselineTailCallReg);
 
     Register argcReg = R0.scratchReg();
     MOZ_ASSERT(argcReg != ArgumentsRectifierReg);
 
     regs.take(argcReg);
     regs.take(ArgumentsRectifierReg);
     regs.takeUnchecked(BaselineTailCallReg);
@@ -11218,17 +11216,17 @@ ICIteratorMore_Fallback::Compiler::gener
 
 bool
 ICIteratorMore_Native::Compiler::generateStubCode(MacroAssembler& masm)
 {
     Label failure;
 
     Register obj = masm.extractObject(R0, ExtractTemp0);
 
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     Register nativeIterator = regs.takeAny();
     Register scratch = regs.takeAny();
 
     masm.branchTestObjClass(Assembler::NotEqual, obj, scratch,
                             &PropertyIteratorObject::class_, &failure);
     masm.loadObjPrivate(obj, JSObject::ITER_CLASS_NFIXED_SLOTS, nativeIterator);
 
     masm.branchTest32(Assembler::NonZero, Address(nativeIterator, offsetof(NativeIterator, flags)),
@@ -11392,17 +11390,17 @@ ICInstanceOf_Function::Compiler::generat
 
     // Ensure RHS is an object.
     masm.branchTestObject(Assembler::NotEqual, R1, &failure);
     Register rhsObj = masm.extractObject(R1, ExtractTemp0);
 
     // Allow using R1's type register as scratch. We have to restore it when
     // we want to jump to the next stub.
     Label failureRestoreR1;
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
+    GeneralRegisterSet regs(availableGeneralRegs(1));
     regs.takeUnchecked(rhsObj);
 
     Register scratch1 = regs.takeAny();
     Register scratch2 = regs.takeAny();
 
     // Shape guard.
     masm.loadPtr(Address(BaselineStubReg, ICInstanceOf_Function::offsetOfShape()), scratch1);
     masm.branchTestObjShape(Assembler::NotEqual, rhsObj, scratch1, &failureRestoreR1);
@@ -11586,17 +11584,17 @@ static const VMFunction ThrowInfoBaselin
 bool
 ICRetSub_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
 {
     // If R0 is BooleanValue(true), rethrow R1.
     Label rethrow;
     masm.branchTestBooleanTruthy(true, R0, &rethrow);
     {
         // Call a stub to get the native code address for the pc offset in R1.
-        AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
+        GeneralRegisterSet regs(availableGeneralRegs(0));
         regs.take(R1);
         regs.takeUnchecked(BaselineTailCallReg);
 
         Register frame = regs.takeAny();
         masm.movePtr(BaselineFrameReg, frame);
 
         enterStubFrame(masm, regs.getAny());
 
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -1122,18 +1122,18 @@ class ICStubCompiler
     void enterStubFrame(MacroAssembler& masm, Register scratch);
     void leaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false);
 
     // Some stubs need to emit SPS profiler updates.  This emits the guarding
     // jitcode for those stubs.  If profiling is not enabled, jumps to the
     // given label.
     void guardProfilingEnabled(MacroAssembler& masm, Register scratch, Label* skip);
 
-    inline AllocatableGeneralRegisterSet availableGeneralRegs(size_t numInputs) const {
-        AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    inline GeneralRegisterSet availableGeneralRegs(size_t numInputs) const {
+        GeneralRegisterSet regs(GeneralRegisterSet::All());
         MOZ_ASSERT(!regs.has(BaselineStackReg));
 #if defined(JS_CODEGEN_ARM)
         MOZ_ASSERT(!regs.has(BaselineTailCallReg));
         regs.take(BaselineSecondScratchReg);
 #elif defined(JS_CODEGEN_MIPS)
         MOZ_ASSERT(!regs.has(BaselineTailCallReg));
         MOZ_ASSERT(!regs.has(BaselineSecondScratchReg));
 #endif
@@ -1157,17 +1157,17 @@ class ICStubCompiler
           default:
             MOZ_CRASH("Invalid numInputs");
         }
 
         return regs;
     }
 
     inline bool emitPostWriteBarrierSlot(MacroAssembler& masm, Register obj, ValueOperand val,
-                                         Register scratch, LiveGeneralRegisterSet saveRegs);
+                                         Register scratch, GeneralRegisterSet saveRegs);
 
   public:
     virtual ICStub* getStub(ICStubSpace* space) = 0;
 
     static ICStubSpace* StubSpaceForKind(ICStub::Kind kind, JSScript* script) {
         if (ICStub::CanMakeCalls(kind))
             return script->baselineScript()->fallbackStubSpace();
         return script->zone()->jitZone()->optimizedStubSpace();
@@ -5259,27 +5259,25 @@ class ICCallStubCompiler : public ICStub
       : ICStubCompiler(cx, kind)
     { }
 
     enum FunApplyThing {
         FunApply_MagicArgs,
         FunApply_Array
     };
 
-    void pushCallArguments(MacroAssembler& masm, AllocatableGeneralRegisterSet regs,
-                           Register argcReg, bool isJitCall);
-    void pushSpreadCallArguments(MacroAssembler& masm, AllocatableGeneralRegisterSet regs,
-                                 Register argcReg, bool isJitCall);
+    void pushCallArguments(MacroAssembler& masm, GeneralRegisterSet regs, Register argcReg,
+                           bool isJitCall);
+    void pushSpreadCallArguments(MacroAssembler& masm, GeneralRegisterSet regs, Register argcReg,
+                                 bool isJitCall);
     void guardSpreadCall(MacroAssembler& masm, Register argcReg, Label* failure);
-    Register guardFunApply(MacroAssembler& masm, AllocatableGeneralRegisterSet regs,
-                           Register argcReg, bool checkNative, FunApplyThing applyThing,
-                           Label* failure);
-    void pushCallerArguments(MacroAssembler& masm, AllocatableGeneralRegisterSet regs);
-    void pushArrayArguments(MacroAssembler& masm, Address arrayVal,
-                            AllocatableGeneralRegisterSet regs);
+    Register guardFunApply(MacroAssembler& masm, GeneralRegisterSet regs, Register argcReg,
+                           bool checkNative, FunApplyThing applyThing, Label* failure);
+    void pushCallerArguments(MacroAssembler& masm, GeneralRegisterSet regs);
+    void pushArrayArguments(MacroAssembler& masm, Address arrayVal, GeneralRegisterSet regs);
 };
 
 class ICCall_Fallback : public ICMonitoredFallbackStub
 {
     friend class ICStubSpace;
   public:
     static const unsigned CONSTRUCTING_FLAG = 0x1;
     static const unsigned UNOPTIMIZABLE_CALL_FLAG = 0x2;
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1133,17 +1133,17 @@ PrepareAndExecuteRegExp(JSContext* cx, M
     if (mode == RegExpShared::Normal) {
         masm.computeEffectiveAddress(Address(StackPointer, matchPairsStartOffset), temp2);
         masm.storePtr(temp2, matchesPointerAddress);
     }
     masm.storePtr(ImmWord(0), startIndexAddress);
     masm.store32(Imm32(0), matchResultAddress);
 
     // Save any volatile inputs.
-    LiveGeneralRegisterSet volatileRegs;
+    GeneralRegisterSet volatileRegs;
     if (input.volatile_())
         volatileRegs.add(input);
     if (regexp.volatile_())
         volatileRegs.add(regexp);
 
     // Execute the RegExp.
     masm.computeEffectiveAddress(Address(StackPointer, inputOutputDataStartOffset), temp2);
     masm.PushRegsInMask(volatileRegs);
@@ -1308,26 +1308,26 @@ CreateDependentString(MacroAssembler& ma
 JitCode*
 JitCompartment::generateRegExpExecStub(JSContext* cx)
 {
     Register regexp = CallTempReg0;
     Register input = CallTempReg1;
     ValueOperand result = JSReturnOperand;
 
     // We are free to clobber all registers, as LRegExpExec is a call instruction.
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs = GeneralRegisterSet::All();
     regs.take(input);
     regs.take(regexp);
 
     // temp5 is used in single byte instructions when creating dependent
     // strings, and has restrictions on which register it can be on some
     // platforms.
     Register temp5;
     {
-        AllocatableGeneralRegisterSet oregs = regs;
+        GeneralRegisterSet oregs = regs;
         do {
             temp5 = oregs.takeAny();
         } while (!MacroAssembler::canUseInSingleByteInstruction(temp5));
         regs.take(temp5);
     }
 
     Register temp1 = regs.takeAny();
     Register temp2 = regs.takeAny();
@@ -1476,17 +1476,17 @@ static const VMFunction RegExpExecRawInf
 
 void
 CodeGenerator::visitOutOfLineRegExpExec(OutOfLineRegExpExec* ool)
 {
     LRegExpExec* lir = ool->lir();
     Register input = ToRegister(lir->string());
     Register regexp = ToRegister(lir->regexp());
 
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs = GeneralRegisterSet::All();
     regs.take(input);
     regs.take(regexp);
     Register temp = regs.takeAny();
 
     masm.computeEffectiveAddress(Address(StackPointer, sizeof(irregexp::InputOutputData)), temp);
 
     pushArg(temp);
     pushArg(input);
@@ -1525,17 +1525,17 @@ JitCompartment::generateRegExpTestStub(J
 {
     Register regexp = CallTempReg2;
     Register input = CallTempReg3;
     Register result = ReturnReg;
 
     MOZ_ASSERT(regexp != result && input != result);
 
     // We are free to clobber all registers, as LRegExpTest is a call instruction.
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs = GeneralRegisterSet::All();
     regs.take(input);
     regs.take(regexp);
     Register temp1 = regs.takeAny();
     Register temp2 = regs.takeAny();
     Register temp3 = regs.takeAny();
 
     MacroAssembler masm(cx);
 
@@ -2651,17 +2651,17 @@ class OutOfLineCallPostWriteBarrier : pu
 
 void
 CodeGenerator::visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier* ool)
 {
     saveLiveVolatile(ool->lir());
 
     const LAllocation* obj = ool->object();
 
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::Volatile());
+    GeneralRegisterSet regs = GeneralRegisterSet::Volatile();
 
     Register objreg;
     bool isGlobal = false;
     if (obj->isConstant()) {
         JSObject* object = &obj->toConstant()->toObject();
         isGlobal = object->is<GlobalObject>();
         objreg = regs.takeAny();
         masm.movePtr(ImmGCPtr(object), objreg);
@@ -3763,17 +3763,17 @@ CodeGenerator::branchIfInvalidated(Regis
 }
 
 void
 CodeGenerator::emitAssertObjectOrStringResult(Register input, MIRType type, TemporaryTypeSet* typeset)
 {
     MOZ_ASSERT(type == MIRType_Object || type == MIRType_ObjectOrNull ||
                type == MIRType_String || type == MIRType_Symbol);
 
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs(GeneralRegisterSet::All());
     regs.take(input);
 
     Register temp = regs.takeAny();
     masm.push(temp);
 
     // Don't check if the script has been invalidated. In that case invalid
     // types are expected (until we reach the OsiPoint and bailout).
     Label done;
@@ -3830,17 +3830,17 @@ CodeGenerator::emitAssertObjectOrStringR
 
     masm.bind(&done);
     masm.pop(temp);
 }
 
 void
 CodeGenerator::emitAssertResultV(const ValueOperand input, TemporaryTypeSet* typeset)
 {
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs(GeneralRegisterSet::All());
     regs.take(input);
 
     Register temp1 = regs.takeAny();
     Register temp2 = regs.takeAny();
     masm.push(temp1);
     masm.push(temp2);
 
     // Don't check if the script has been invalidated. In that case invalid
@@ -6089,36 +6089,36 @@ JitCompartment::generateStringConcatStub
 JitCode*
 JitRuntime::generateMallocStub(JSContext* cx)
 {
     const Register regReturn = CallTempReg0;
     const Register regNBytes = CallTempReg0;
 
     MacroAssembler masm(cx);
 
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
+    RegisterSet regs = RegisterSet::Volatile();
 #ifdef JS_USE_LINK_REGISTER
     masm.pushReturnAddress();
 #endif
     regs.takeUnchecked(regNBytes);
-    LiveRegisterSet save(regs.asLiveSet());
-    masm.PushRegsInMask(save);
-
-    const Register regTemp = regs.takeAnyGeneral();
+    masm.PushRegsInMask(regs);
+
+    const Register regTemp = regs.takeGeneral();
     const Register regRuntime = regTemp;
+    regs.add(regTemp);
     MOZ_ASSERT(regTemp != regNBytes);
 
     masm.setupUnalignedABICall(2, regTemp);
     masm.movePtr(ImmPtr(cx->runtime()), regRuntime);
     masm.passABIArg(regRuntime);
     masm.passABIArg(regNBytes);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, MallocWrapper));
     masm.storeCallResult(regReturn);
 
-    masm.PopRegsInMask(save);
+    masm.PopRegsInMask(regs);
     masm.ret();
 
     Linker linker(masm);
     AutoFlushICache afc("MallocStub");
     JitCode* code = linker.newCode<NoGC>(cx, OTHER_CODE);
 
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(code, "MallocStub");
@@ -6131,29 +6131,29 @@ JitCode*
 JitRuntime::generateFreeStub(JSContext* cx)
 {
     const Register regSlots = CallTempReg0;
 
     MacroAssembler masm(cx);
 #ifdef JS_USE_LINK_REGISTER
     masm.pushReturnAddress();
 #endif
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
+    RegisterSet regs = RegisterSet::Volatile();
     regs.takeUnchecked(regSlots);
-    LiveRegisterSet save(regs.asLiveSet());
-    masm.PushRegsInMask(save);
-
-    const Register regTemp = regs.takeAnyGeneral();
+    masm.PushRegsInMask(regs);
+
+    const Register regTemp = regs.takeGeneral();
+    regs.add(regTemp);
     MOZ_ASSERT(regTemp != regSlots);
 
     masm.setupUnalignedABICall(1, regTemp);
     masm.passABIArg(regSlots);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, js_free));
 
-    masm.PopRegsInMask(save);
+    masm.PopRegsInMask(regs);
 
     masm.ret();
 
     Linker linker(masm);
     AutoFlushICache afc("FreeStub");
     JitCode* code = linker.newCode<NoGC>(cx, OTHER_CODE);
 
 #ifdef JS_ION_PERF
@@ -6167,17 +6167,17 @@ JitRuntime::generateFreeStub(JSContext* 
 JitCode*
 JitRuntime::generateLazyLinkStub(JSContext* cx)
 {
     MacroAssembler masm(cx);
 #ifdef JS_USE_LINK_REGISTER
     masm.pushReturnAddress();
 #endif
 
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::Volatile());
+    GeneralRegisterSet regs = GeneralRegisterSet::Volatile();
     Register temp0 = regs.takeAny();
 
     // The caller did not push an exit frame on the stack, it pushed a
     // JitFrameLayout.  We modify the descriptor to be a valid exit frame and
     // restore it once the lazy link is complete.
     Address descriptor(StackPointer, CommonFrameLayout::offsetOfDescriptor());
     size_t convertToExitFrame = JitFrameLayout::Size() - ExitFrameLayout::Size();
     masm.addPtr(Imm32(convertToExitFrame << FRAMESIZE_SHIFT), descriptor);
@@ -6815,17 +6815,17 @@ CodeGenerator::emitArrayPopShift(LInstru
     masm.branchTest32(Assembler::NonZero, elementFlags, bit, ool->entry());
 
     // Now adjust length and initializedLength.
     masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfLength()));
     masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
 
     if (mir->mode() == MArrayPopShift::Shift) {
         // Don't save the temp registers.
-        LiveRegisterSet temps;
+        RegisterSet temps;
         temps.add(elementsTemp);
         temps.add(lengthTemp);
 
         saveVolatile(temps);
         masm.setupUnalignedABICall(1, lengthTemp);
         masm.passABIArg(obj);
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, js::ArrayShiftMoveElements));
         restoreVolatile(temps);
@@ -7894,17 +7894,17 @@ CodeGenerator::visitStoreFixedSlotT(LSto
                                     : TypedOrValueRegister(valueType, ToAnyRegister(value));
         masm.storeConstantOrRegister(nvalue, address);
     }
 }
 
 void
 CodeGenerator::visitGetNameCache(LGetNameCache* ins)
 {
-    LiveRegisterSet liveRegs = ins->safepoint()->liveRegs();
+    RegisterSet liveRegs = ins->safepoint()->liveRegs();
     Register scopeChain = ToRegister(ins->scopeObj());
     TypedOrValueRegister output(GetValueOutput(ins));
     bool isTypeOf = ins->mir()->accessKind() != MGetNameCache::NAME;
 
     NameIC cache(liveRegs, isTypeOf, scopeChain, ins->mir()->name(), output);
     cache.setProfilerLeavePC(ins->mir()->profilerLeavePc());
     addCache(ins, allocateCache(cache));
 }
@@ -7924,27 +7924,27 @@ CodeGenerator::visitNameIC(OutOfLineUpda
     callVM(NameIC::UpdateInfo, lir);
     StoreValueTo(ic->outputReg()).generate(this);
     restoreLiveIgnore(lir, StoreValueTo(ic->outputReg()).clobbered());
 
     masm.jump(ool->rejoin());
 }
 
 void
-CodeGenerator::addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg,
+CodeGenerator::addGetPropertyCache(LInstruction* ins, RegisterSet liveRegs, Register objReg,
                                    PropertyName* name, TypedOrValueRegister output,
                                    bool monitoredResult, jsbytecode* profilerLeavePc)
 {
     GetPropertyIC cache(liveRegs, objReg, name, output, monitoredResult);
     cache.setProfilerLeavePC(profilerLeavePc);
     addCache(ins, allocateCache(cache));
 }
 
 void
-CodeGenerator::addSetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg,
+CodeGenerator::addSetPropertyCache(LInstruction* ins, RegisterSet liveRegs, Register objReg,
                                    PropertyName* name, ConstantOrRegister value, bool strict,
                                    bool needsTypeBarrier, jsbytecode* profilerLeavePc)
 {
     SetPropertyIC cache(liveRegs, objReg, name, value, strict, needsTypeBarrier);
     cache.setProfilerLeavePC(profilerLeavePc);
     addCache(ins, allocateCache(cache));
 }
 
@@ -7959,30 +7959,30 @@ CodeGenerator::addSetElementCache(LInstr
                        guardHoles);
     cache.setProfilerLeavePC(profilerLeavePc);
     addCache(ins, allocateCache(cache));
 }
 
 void
 CodeGenerator::visitGetPropertyCacheV(LGetPropertyCacheV* ins)
 {
-    LiveRegisterSet liveRegs = ins->safepoint()->liveRegs();
+    RegisterSet liveRegs = ins->safepoint()->liveRegs();
     Register objReg = ToRegister(ins->getOperand(0));
     PropertyName* name = ins->mir()->name();
     bool monitoredResult = ins->mir()->monitoredResult();
     TypedOrValueRegister output = TypedOrValueRegister(GetValueOutput(ins));
 
     addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult,
                         ins->mir()->profilerLeavePc());
 }
 
 void
 CodeGenerator::visitGetPropertyCacheT(LGetPropertyCacheT* ins)
 {
-    LiveRegisterSet liveRegs = ins->safepoint()->liveRegs();
+    RegisterSet liveRegs = ins->safepoint()->liveRegs();
     Register objReg = ToRegister(ins->getOperand(0));
     PropertyName* name = ins->mir()->name();
     bool monitoredResult = ins->mir()->monitoredResult();
     TypedOrValueRegister output(ins->mir()->type(), ToAnyRegister(ins->getDef(0)));
 
     addGetPropertyCache(ins, liveRegs, objReg, name, output, monitoredResult,
                         ins->mir()->profilerLeavePc());
 }
@@ -8015,17 +8015,17 @@ CodeGenerator::visitGetPropertyIC(OutOfL
     masm.jump(ool->rejoin());
 }
 
 void
 CodeGenerator::addGetElementCache(LInstruction* ins, Register obj, ConstantOrRegister index,
                                   TypedOrValueRegister output, bool monitoredResult,
                                   bool allowDoubleResult, jsbytecode* profilerLeavePc)
 {
-    LiveRegisterSet liveRegs = ins->safepoint()->liveRegs();
+    RegisterSet liveRegs = ins->safepoint()->liveRegs();
     GetElementIC cache(liveRegs, obj, index, output, monitoredResult, allowDoubleResult);
     cache.setProfilerLeavePC(profilerLeavePc);
     addCache(ins, allocateCache(cache));
 }
 
 void
 CodeGenerator::visitGetElementCacheV(LGetElementCacheV* ins)
 {
@@ -8214,29 +8214,29 @@ CodeGenerator::visitCallDeleteElement(LC
         callVM(DeleteElementStrictInfo, lir);
     else
         callVM(DeleteElementNonStrictInfo, lir);
 }
 
 void
 CodeGenerator::visitSetPropertyCacheV(LSetPropertyCacheV* ins)
 {
-    LiveRegisterSet liveRegs = ins->safepoint()->liveRegs();
+    RegisterSet liveRegs = ins->safepoint()->liveRegs();
     Register objReg = ToRegister(ins->getOperand(0));
     ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LSetPropertyCacheV::Value));
 
     addSetPropertyCache(ins, liveRegs, objReg, ins->mir()->name(), value,
                         ins->mir()->strict(), ins->mir()->needsTypeBarrier(),
                         ins->mir()->profilerLeavePc());
 }
 
 void
 CodeGenerator::visitSetPropertyCacheT(LSetPropertyCacheT* ins)
 {
-    LiveRegisterSet liveRegs = ins->safepoint()->liveRegs();
+    RegisterSet liveRegs = ins->safepoint()->liveRegs();
     Register objReg = ToRegister(ins->getOperand(0));
     ConstantOrRegister value;
 
     if (ins->getOperand(1)->isConstant())
         value = ConstantOrRegister(*ins->getOperand(1)->toConstant());
     else
         value = TypedOrValueRegister(ins->valueType(), ToAnyRegister(ins->getOperand(1)));
 
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -368,23 +368,23 @@ class CodeGenerator : public CodeGenerat
 
     IonScriptCounts* extractScriptCounts() {
         IonScriptCounts* counts = scriptCounts_;
         scriptCounts_ = nullptr;  // prevent delete in dtor
         return counts;
     }
 
   private:
-    void addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg,
+    void addGetPropertyCache(LInstruction* ins, RegisterSet liveRegs, Register objReg,
                              PropertyName* name, TypedOrValueRegister output,
                              bool monitoredResult, jsbytecode* profilerLeavePc);
     void addGetElementCache(LInstruction* ins, Register obj, ConstantOrRegister index,
                             TypedOrValueRegister output, bool monitoredResult,
                             bool allowDoubleResult, jsbytecode* profilerLeavePc);
-    void addSetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg,
+    void addSetPropertyCache(LInstruction* ins, RegisterSet liveRegs, Register objReg,
                              PropertyName* name, ConstantOrRegister value, bool strict,
                              bool needsTypeBarrier, jsbytecode* profilerLeavePc);
     void addSetElementCache(LInstruction* ins, Register obj, Register unboxIndex, Register temp,
                             FloatRegister tempDouble, FloatRegister tempFloat32,
                             ValueOperand index, ConstantOrRegister value,
                             bool strict, bool guardHoles, jsbytecode* profilerLeavePc);
 
     bool generateBranchV(const ValueOperand& value, Label* ifTrue, Label* ifFalse, FloatRegister fr);
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -765,19 +765,19 @@ CheckDOMProxyExpandoDoesNotShadow(JSCont
 {
     MOZ_ASSERT(IsCacheableDOMProxy(obj));
 
     // Guard that the object does not have expando properties, or has an expando
     // which is known to not have the desired property.
 
     // For the remaining code, we need to reserve some registers to load a value.
     // This is ugly, but unvaoidable.
-    AllocatableRegisterSet domProxyRegSet(RegisterSet::All());
+    RegisterSet domProxyRegSet(RegisterSet::All());
     domProxyRegSet.take(AnyRegister(object));
-    ValueOperand tempVal = domProxyRegSet.takeAnyValue();
+    ValueOperand tempVal = domProxyRegSet.takeValueOperand();
     masm.pushValue(tempVal);
 
     Label failDOMProxyCheck;
     Label domProxyOk;
 
     Value expandoVal = GetProxyExtra(obj, GetDOMProxyExpandoSlot());
 
     masm.loadPtr(Address(object, ProxyObject::offsetOfValues()), tempVal.scratchReg());
@@ -964,39 +964,39 @@ GenerateReadUnboxed(JSContext* cx, IonSc
 
     attacher.jumpRejoin(masm);
 }
 
 static bool
 EmitGetterCall(JSContext* cx, MacroAssembler& masm,
                IonCache::StubAttacher& attacher, JSObject* obj,
                JSObject* holder, HandleShape shape,
-               LiveRegisterSet liveRegs, Register object,
+               RegisterSet liveRegs, Register object,
                TypedOrValueRegister output,
                void* returnAddr)
 {
     MOZ_ASSERT(output.hasValue());
     MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
 
     // Remaining registers should basically be free, but we need to use |object| still
     // so leave it alone.
-    AllocatableRegisterSet regSet(RegisterSet::All());
+    RegisterSet regSet(RegisterSet::All());
     regSet.take(AnyRegister(object));
 
     // This is a slower stub path, and we're going to be doing a call anyway.  Don't need
     // to try so hard to not use the stack.  Scratch regs are just taken from the register
     // set not including the input, current value saved on the stack, and restored when
     // we're done with it.
-    Register scratchReg = regSet.takeAnyGeneral();
+    Register scratchReg = regSet.takeGeneral();
 
     // Shape has a JSNative, PropertyOp or scripted getter function.
     if (IsCacheableGetPropCallNative(obj, holder, shape)) {
-        Register argJSContextReg = regSet.takeAnyGeneral();
-        Register argUintNReg     = regSet.takeAnyGeneral();
-        Register argVpReg        = regSet.takeAnyGeneral();
+        Register argJSContextReg = regSet.takeGeneral();
+        Register argUintNReg     = regSet.takeGeneral();
+        Register argVpReg        = regSet.takeGeneral();
 
         JSFunction* target = &shape->getterValue().toObject().as<JSFunction>();
         MOZ_ASSERT(target);
         MOZ_ASSERT(target->isNative());
 
         // Native functions have the signature:
         //  bool (*)(JSContext*, unsigned, Value* vp)
         // Where vp[0] is space for an outparam, vp[1] is |this|, and vp[2] onward
@@ -1033,21 +1033,21 @@ EmitGetterCall(JSContext* cx, MacroAssem
 
         // Load the outparam vp[0] into output register(s).
         Address outparam(StackPointer, IonOOLNativeExitFrameLayout::offsetOfResult());
         masm.loadTypedOrValue(outparam, output);
 
         // masm.leaveExitFrame & pop locals
         masm.adjustStack(IonOOLNativeExitFrameLayout::Size(0));
     } else if (IsCacheableGetPropCallPropertyOp(obj, holder, shape)) {
-        Register argJSContextReg = regSet.takeAnyGeneral();
-        Register argUintNReg     = regSet.takeAnyGeneral();
-        Register argVpReg        = regSet.takeAnyGeneral();
+        Register argJSContextReg = regSet.takeGeneral();
+        Register argUintNReg     = regSet.takeGeneral();
+        Register argVpReg        = regSet.takeGeneral();
         Register argObjReg       = argUintNReg;
-        Register argIdReg        = regSet.takeAnyGeneral();
+        Register argIdReg        = regSet.takeGeneral();
 
         GetterOp target = shape->getterOp();
         MOZ_ASSERT(target);
 
         // Push stubCode for marking.
         attacher.pushStubCodePointer(masm);
 
         // JSGetterOp: bool fn(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
@@ -1135,17 +1135,17 @@ EmitGetterCall(JSContext* cx, MacroAssem
 
     masm.icRestoreLive(liveRegs, aic);
     return true;
 }
 
 static bool
 GenerateCallGetter(JSContext* cx, IonScript* ion, MacroAssembler& masm,
                    IonCache::StubAttacher& attacher, JSObject* obj, PropertyName* name,
-                   JSObject* holder, HandleShape shape, LiveRegisterSet& liveRegs, Register object,
+                   JSObject* holder, HandleShape shape, RegisterSet& liveRegs, Register object,
                    TypedOrValueRegister output, void* returnAddr, Label* failures = nullptr)
 {
     MOZ_ASSERT(output.hasValue());
 
     // Use the passed in label if there was one. Otherwise, we'll have to make our own.
     Label stubFailure;
     failures = failures ? failures : &stubFailure;
 
@@ -1527,35 +1527,35 @@ PushObjectOpResult(MacroAssembler& masm)
 {
     static_assert(sizeof(ObjectOpResult) == sizeof(uintptr_t),
                   "ObjectOpResult size must match size reserved by masm.Push() here");
     masm.Push(ImmWord(ObjectOpResult::Uninitialized));
 }
 
 static bool
 EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
-                 PropertyName* name, LiveRegisterSet liveRegs, Register object,
+                 PropertyName* name, RegisterSet liveRegs, Register object,
                  TypedOrValueRegister output, jsbytecode* pc, void* returnAddr)
 {
     MOZ_ASSERT(output.hasValue());
     MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
 
     // Remaining registers should be free, but we need to use |object| still
     // so leave it alone.
-    AllocatableRegisterSet regSet(RegisterSet::All());
+    RegisterSet regSet(RegisterSet::All());
     regSet.take(AnyRegister(object));
 
     // Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
     //            MutableHandleValue vp)
-    Register argJSContextReg = regSet.takeAnyGeneral();
-    Register argProxyReg     = regSet.takeAnyGeneral();
-    Register argIdReg        = regSet.takeAnyGeneral();
-    Register argVpReg        = regSet.takeAnyGeneral();
-
-    Register scratch         = regSet.takeAnyGeneral();
+    Register argJSContextReg = regSet.takeGeneral();
+    Register argProxyReg     = regSet.takeGeneral();
+    Register argIdReg        = regSet.takeGeneral();
+    Register argVpReg        = regSet.takeGeneral();
+
+    Register scratch         = regSet.takeGeneral();
 
     void* getFunction = JSOp(*pc) == JSOP_CALLPROP                      ?
                             JS_FUNC_TO_DATA_PTR(void*, Proxy::callProp) :
                             JS_FUNC_TO_DATA_PTR(void*, Proxy::get);
 
     // Push stubCode for marking.
     attacher.pushStubCodePointer(masm);
 
@@ -2229,40 +2229,40 @@ ProxySetProperty(JSContext* cx, HandleOb
     RootedValue receiver(cx, ObjectValue(*proxy));
     ObjectOpResult result;
     return Proxy::set(cx, proxy, id, v, receiver, result)
            && result.checkStrictErrorOrWarning(cx, proxy, id, strict);
 }
 
 static bool
 EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
-                 HandleId propId, LiveRegisterSet liveRegs, Register object,
+                 HandleId propId, RegisterSet liveRegs, Register object,
                  ConstantOrRegister value, void* returnAddr, bool strict)
 {
     MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
 
     // Remaining registers should be free, but we still need to use |object| so
     // leave it alone.
     //
     // WARNING: We do not take() the register used by |value|, if any, so
     // regSet is going to re-allocate it. Hence the emitted code must not touch
     // any of the registers allocated from regSet until after the last use of
     // |value|. (We can't afford to take it, either, because x86.)
-    AllocatableRegisterSet regSet(RegisterSet::All());
+    RegisterSet regSet(RegisterSet::All());
     regSet.take(AnyRegister(object));
 
     // ProxySetProperty(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
     //                  bool strict);
-    Register argJSContextReg = regSet.takeAnyGeneral();
-    Register argProxyReg     = regSet.takeAnyGeneral();
-    Register argIdReg        = regSet.takeAnyGeneral();
-    Register argValueReg     = regSet.takeAnyGeneral();
-    Register argStrictReg    = regSet.takeAnyGeneral();
-
-    Register scratch         = regSet.takeAnyGeneral();
+    Register argJSContextReg = regSet.takeGeneral();
+    Register argProxyReg     = regSet.takeGeneral();
+    Register argIdReg        = regSet.takeGeneral();
+    Register argValueReg     = regSet.takeGeneral();
+    Register argStrictReg    = regSet.takeGeneral();
+
+    Register scratch         = regSet.takeGeneral();
 
     // Push stubCode for marking.
     attacher.pushStubCodePointer(masm);
 
     // Push args on stack so we can take pointers to make handles.
     // Push value before touching any other registers (see WARNING above).
     masm.Push(value);
     masm.movePtr(StackPointer, argValueReg);
@@ -2312,22 +2312,22 @@ SetPropertyIC::attachGenericProxy(JSCont
     MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
     RepatchStubAppender attacher(*this);
 
     Label failures;
     {
         Label proxyFailures;
         Label proxySuccess;
 
-        AllocatableRegisterSet regSet(RegisterSet::All());
+        RegisterSet regSet(RegisterSet::All());
         regSet.take(AnyRegister(object()));
         if (!value().constant())
             regSet.takeUnchecked(value().reg());
 
-        Register scratch = regSet.takeAnyGeneral();
+        Register scratch = regSet.takeGeneral();
         masm.push(scratch);
 
         masm.branchTestObjectIsProxy(false, object(), scratch, &proxyFailures);
 
         // Remove the DOM proxies. They'll take care of themselves so this stub doesn't
         // catch too much. The failure case is actually Equal. Fall through to the failure code.
         masm.branchTestProxyHandlerFamily(Assembler::NotEqual, object(), scratch,
                                           GetDOMProxyHandlerFamily(), &proxySuccess);
@@ -2394,27 +2394,27 @@ SetPropertyIC::attachDOMProxyShadowed(JS
 
     return linkAndAttachStub(cx, masm, attacher, ion, "DOM proxy shadowed set");
 }
 
 static bool
 GenerateCallSetter(JSContext* cx, IonScript* ion, MacroAssembler& masm,
                    IonCache::StubAttacher& attacher, HandleObject obj,
                    HandleObject holder, HandleShape shape, bool strict, Register object,
-                   ConstantOrRegister value, Label* failure, LiveRegisterSet liveRegs,
+                   ConstantOrRegister value, Label* failure, RegisterSet liveRegs,
                    void* returnAddr)
 {
     // Generate prototype guards if needed.
     // Take a scratch register for use, save on stack.
     {
-        AllocatableRegisterSet regSet(RegisterSet::All());
+        RegisterSet regSet(RegisterSet::All());
         regSet.take(AnyRegister(object));
         if (!value.constant())
             regSet.takeUnchecked(value.reg());
-        Register scratchReg = regSet.takeAnyGeneral();
+        Register scratchReg = regSet.takeGeneral();
         masm.push(scratchReg);
 
         Label protoFailure;
         Label protoSuccess;
 
         // Generate prototype/shape guards.
         if (obj != holder)
             GeneratePrototypeGuards(cx, ion, masm, obj, holder, object, scratchReg, &protoFailure);
@@ -2436,41 +2436,41 @@ GenerateCallSetter(JSContext* cx, IonScr
     }
 
     // Good to go for invoking setter.
 
     MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
 
     // Remaining registers should basically be free, but we need to use |object| still
     // so leave it alone.  And of course we need our value, if it's not a constant.
-    AllocatableRegisterSet regSet(RegisterSet::All());
+    RegisterSet regSet(RegisterSet::All());
     regSet.take(AnyRegister(object));
     if (!value.constant())
         regSet.takeUnchecked(value.reg());
 
     // This is a slower stub path, and we're going to be doing a call anyway.  Don't need
     // to try so hard to not use the stack.  Scratch regs are just taken from the register
     // set not including the input, current value saved on the stack, and restored when
     // we're done with it.
     //
     // Be very careful not to use any of these before value is pushed, since they
     // might shadow.
-    Register scratchReg = regSet.takeAnyGeneral();
+    Register scratchReg = regSet.takeGeneral();
 
     if (IsCacheableSetPropCallNative(obj, holder, shape)) {
-        Register argJSContextReg = regSet.takeAnyGeneral();
-        Register argVpReg        = regSet.takeAnyGeneral();
+        Register argJSContextReg = regSet.takeGeneral();
+        Register argVpReg        = regSet.takeGeneral();
 
         MOZ_ASSERT(shape->hasSetterValue() && shape->setterObject() &&
                    shape->setterObject()->is<JSFunction>());
         JSFunction* target = &shape->setterObject()->as<JSFunction>();
 
         MOZ_ASSERT(target->isNative());
 
-        Register argUintNReg = regSet.takeAnyGeneral();
+        Register argUintNReg = regSet.takeGeneral();
 
         // Set up the call:
         //  bool (*)(JSContext*, unsigned, Value* vp)
         // vp[0] is callee/outparam
         // vp[1] is |this|
         // vp[2] is the value
 
         // Build vp and move the base into argVpReg.
@@ -2503,18 +2503,17 @@ GenerateCallSetter(JSContext* cx, IonScr
 
         // masm.leaveExitFrame & pop locals.
         masm.adjustStack(IonOOLNativeExitFrameLayout::Size(1));
     } else if (IsCacheableSetPropCallPropertyOp(obj, holder, shape)) {
         // We can't take all our registers up front, because on x86 we need 2
         // for the value, one for scratch, 5 for the arguments, which makes 8,
         // but we only have 7 to work with.  So only grab the ones we need
         // before we push value and release its reg back into the set.
-        Register argResultReg = regSet.takeAnyGeneral();
-
+        Register argResultReg = regSet.takeGeneral();
 
         SetterOp target = shape->setterOp();
         MOZ_ASSERT(target);
 
         // JSSetterOp: bool fn(JSContext* cx, HandleObject obj,
         //                     HandleId id, HandleValue value, ObjectOpResult& result);
 
         // First, allocate an ObjectOpResult on the stack. We push this before
@@ -2530,21 +2529,21 @@ GenerateCallSetter(JSContext* cx, IonScr
             masm.Push(value.value());
         } else {
             masm.Push(value.reg());
             regSet.add(value.reg());
         }
 
         // OK, now we can grab our remaining registers and grab the pointer to
         // what we just pushed into one of them.
-        Register argJSContextReg = regSet.takeAnyGeneral();
-        Register argValueReg     = regSet.takeAnyGeneral();
+        Register argJSContextReg = regSet.takeGeneral();
+        Register argValueReg     = regSet.takeGeneral();
         // We can just reuse the "object" register for argObjReg
         Register argObjReg       = object;
-        Register argIdReg        = regSet.takeAnyGeneral();
+        Register argIdReg        = regSet.takeGeneral();
         masm.movePtr(StackPointer, argValueReg);
 
         // push canonical jsid from shape instead of propertyname.
         masm.Push(shape->propid(), argIdReg);
         masm.movePtr(StackPointer, argIdReg);
 
         masm.Push(object);
         masm.movePtr(StackPointer, argObjReg);
@@ -3389,17 +3388,17 @@ GetElementIC::attachGetProp(JSContext* c
                       Imm32(JSString::ATOM_BIT), &failures);
 
     // Check the length.
     masm.branch32(Assembler::NotEqual, Address(scratch, JSString::offsetOfLength()),
                   Imm32(name->length()), &failures);
 
     // We have a non-atomized string with the same length. For now call a helper
     // function to do the comparison.
-    LiveRegisterSet volatileRegs(RegisterSet::Volatile());
+    RegisterSet volatileRegs = RegisterSet::Volatile();
     masm.PushRegsInMask(volatileRegs);
 
     Register objReg = object();
     MOZ_ASSERT(objReg != scratch);
 
     if (!volatileRegs.has(objReg))
         masm.push(objReg);
 
@@ -3409,17 +3408,17 @@ GetElementIC::attachGetProp(JSContext* c
     masm.unboxString(val, scratch);
     masm.passABIArg(scratch);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, EqualStringsHelper));
     masm.mov(ReturnReg, scratch);
 
     if (!volatileRegs.has(objReg))
         masm.pop(objReg);
 
-    LiveRegisterSet ignore;
+    RegisterSet ignore = RegisterSet();
     ignore.add(scratch);
     masm.PopRegsInMaskIgnore(volatileRegs, ignore);
 
     masm.branchIfFalseBool(scratch, &failures);
     masm.bind(&equal);
 
     RepatchStubAppender attacher(*this);
     if (canCache == GetPropertyIC::CanAttachReadSlot) {
@@ -3739,31 +3738,30 @@ GenerateGetTypedArrayElement(JSContext* 
 
             str = masm.extractString(val, indexReg);
         } else {
             MOZ_ASSERT(!index.reg().typedReg().isFloat());
             str = index.reg().typedReg().gpr();
         }
 
         // Part 2: Call to translate the str into index
-        AllocatableRegisterSet regs(RegisterSet::Volatile());
-        LiveRegisterSet save(regs.asLiveSet());
-        masm.PushRegsInMask(save);
+        RegisterSet regs = RegisterSet::Volatile();
+        masm.PushRegsInMask(regs);
         regs.takeUnchecked(str);
 
-        Register temp = regs.takeAnyGeneral();
+        Register temp = regs.takeGeneral();
 
         masm.setupUnalignedABICall(1, temp);
         masm.passABIArg(str);
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, GetIndexFromString));
         masm.mov(ReturnReg, indexReg);
 
-        LiveRegisterSet ignore;
+        RegisterSet ignore = RegisterSet();
         ignore.add(indexReg);
-        masm.PopRegsInMaskIgnore(save, ignore);
+        masm.PopRegsInMaskIgnore(RegisterSet::Volatile(), ignore);
 
         masm.branch32(Assembler::Equal, indexReg, Imm32(UINT32_MAX), &failures);
 
     } else {
         MOZ_ASSERT(idval.isInt32());
 
         if (index.reg().hasValue()) {
             ValueOperand val = index.reg().valueReg();
--- a/js/src/jit/IonCaches.h
+++ b/js/src/jit/IonCaches.h
@@ -539,17 +539,17 @@ struct CacheLocation {
     { }
 };
 
 class GetPropertyIC : public RepatchIonCache
 {
   protected:
     // Registers live after the cache, excluding output registers. The initial
     // value of these registers must be preserved by the cache.
-    LiveRegisterSet liveRegs_;
+    RegisterSet liveRegs_;
 
     Register object_;
     PropertyName* name_;
     TypedOrValueRegister output_;
 
     // Only valid if idempotent
     size_t locationsIndex_;
     size_t numLocations_;
@@ -557,17 +557,17 @@ class GetPropertyIC : public RepatchIonC
     bool monitoredResult_ : 1;
     bool hasTypedArrayLengthStub_ : 1;
     bool hasSharedTypedArrayLengthStub_ : 1;
     bool hasStrictArgumentsLengthStub_ : 1;
     bool hasNormalArgumentsLengthStub_ : 1;
     bool hasGenericProxyStub_ : 1;
 
   public:
-    GetPropertyIC(LiveRegisterSet liveRegs,
+    GetPropertyIC(RegisterSet liveRegs,
                   Register object, PropertyName* name,
                   TypedOrValueRegister output,
                   bool monitoredResult)
       : liveRegs_(liveRegs),
         object_(object),
         name_(name),
         output_(output),
         locationsIndex_(0),
@@ -684,28 +684,28 @@ class GetPropertyIC : public RepatchIonC
                        HandleObject obj, MutableHandleValue vp);
 };
 
 class SetPropertyIC : public RepatchIonCache
 {
   protected:
     // Registers live after the cache, excluding output registers. The initial
     // value of these registers must be preserved by the cache.
-    LiveRegisterSet liveRegs_;
+    RegisterSet liveRegs_;
 
     Register object_;
     PropertyName* name_;
     ConstantOrRegister value_;
     bool strict_;
     bool needsTypeBarrier_;
 
     bool hasGenericProxyStub_;
 
   public:
-    SetPropertyIC(LiveRegisterSet liveRegs, Register object, PropertyName* name,
+    SetPropertyIC(RegisterSet liveRegs, Register object, PropertyName* name,
                   ConstantOrRegister value, bool strict, bool needsTypeBarrier)
       : liveRegs_(liveRegs),
         object_(object),
         name_(name),
         value_(value),
         strict_(strict),
         needsTypeBarrier_(needsTypeBarrier),
         hasGenericProxyStub_(false)
@@ -769,34 +769,34 @@ class SetPropertyIC : public RepatchIonC
 
     static bool update(JSContext* cx, HandleScript outerScript, size_t cacheIndex,
                        HandleObject obj, HandleValue value);
 };
 
 class GetElementIC : public RepatchIonCache
 {
   protected:
-    LiveRegisterSet liveRegs_;
+    RegisterSet liveRegs_;
 
     Register object_;
     ConstantOrRegister index_;
     TypedOrValueRegister output_;
 
     bool monitoredResult_ : 1;
     bool allowDoubleResult_ : 1;
     bool hasDenseStub_ : 1;
     bool hasStrictArgumentsStub_ : 1;
     bool hasNormalArgumentsStub_ : 1;
 
     size_t failedUpdates_;
 
     static const size_t MAX_FAILED_UPDATES;
 
   public:
-    GetElementIC(LiveRegisterSet liveRegs, Register object, ConstantOrRegister index,
+    GetElementIC(RegisterSet liveRegs, Register object, ConstantOrRegister index,
                  TypedOrValueRegister output, bool monitoredResult, bool allowDoubleResult)
       : liveRegs_(liveRegs),
         object_(object),
         index_(index),
         output_(output),
         monitoredResult_(monitoredResult),
         allowDoubleResult_(allowDoubleResult),
         hasDenseStub_(false),
@@ -1003,25 +1003,25 @@ class BindNameIC : public RepatchIonCach
     update(JSContext* cx, HandleScript outerScript, size_t cacheIndex, HandleObject scopeChain);
 };
 
 class NameIC : public RepatchIonCache
 {
   protected:
     // Registers live after the cache, excluding output registers. The initial
     // value of these registers must be preserved by the cache.
-    LiveRegisterSet liveRegs_;
+    RegisterSet liveRegs_;
 
     bool typeOf_;
     Register scopeChain_;
     PropertyName* name_;
     TypedOrValueRegister output_;
 
   public:
-    NameIC(LiveRegisterSet liveRegs, bool typeOf,
+    NameIC(RegisterSet liveRegs, bool typeOf,
            Register scopeChain, PropertyName* name,
            TypedOrValueRegister output)
       : liveRegs_(liveRegs),
         typeOf_(typeOf),
         scopeChain_(scopeChain),
         name_(name),
         output_(output)
     {
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -348,17 +348,17 @@ JitFrameIterator::machineState() const
 
     MachineState machine;
     for (GeneralRegisterBackwardIterator iter(reader.allGprSpills()); iter.more(); iter++)
         machine.setRegisterLocation(*iter, --spill);
 
     uint8_t* spillAlign = alignDoubleSpillWithOffset(reinterpret_cast<uint8_t*>(spill), 0);
 
     char* floatSpill = reinterpret_cast<char*>(spillAlign);
-    FloatRegisterSet fregs = reader.allFloatSpills().set();
+    FloatRegisterSet fregs = reader.allFloatSpills();
     fregs = fregs.reduceSetForPush();
     for (FloatRegisterBackwardIterator iter(fregs); iter.more(); iter++) {
         floatSpill -= (*iter).size();
         for (uint32_t a = 0; a < (*iter).numAlignedAliased(); a++) {
             // Only say that registers that actually start here start here.
             // e.g. d0 should not start at s1, only at s0.
             FloatRegister ftmp;
             (*iter).alignedAliased(a, &ftmp);
@@ -1067,18 +1067,18 @@ MarkIonJSFrame(JSTracer* trc, const JitF
     }
 
     while (safepoint.getValueSlot(&entry)) {
         Value* v = (Value*)layout->slotRef(entry);
         gc::MarkValueRoot(trc, v, "ion-gc-slot");
     }
 
     uintptr_t* spill = frame.spillBase();
-    LiveGeneralRegisterSet gcRegs = safepoint.gcSpills();
-    LiveGeneralRegisterSet valueRegs = safepoint.valueSpills();
+    GeneralRegisterSet gcRegs = safepoint.gcSpills();
+    GeneralRegisterSet valueRegs = safepoint.valueSpills();
     for (GeneralRegisterBackwardIterator iter(safepoint.allGprSpills()); iter.more(); iter++) {
         --spill;
         if (gcRegs.has(*iter))
             gc::MarkGCThingRoot(trc, reinterpret_cast<void**>(spill), "ion-gc-spill");
         else if (valueRegs.has(*iter))
             gc::MarkValueRoot(trc, reinterpret_cast<Value*>(spill), "ion-value-spill");
     }
 
@@ -1154,17 +1154,17 @@ UpdateIonJSFrameForMinorGC(JSTracer* trc
         ionScript = frame.ionScriptFromCalleeToken();
     }
 
     Nursery& nursery = trc->runtime()->gc.nursery;
 
     const SafepointIndex* si = ionScript->getSafepointIndex(frame.returnAddressToFp());
     SafepointReader safepoint(ionScript, si);
 
-    LiveGeneralRegisterSet slotsRegs = safepoint.slotsOrElementsSpills();
+    GeneralRegisterSet slotsRegs = safepoint.slotsOrElementsSpills();
     uintptr_t* spill = frame.spillBase();
     for (GeneralRegisterBackwardIterator iter(safepoint.allGprSpills()); iter.more(); iter++) {
         --spill;
         if (slotsRegs.has(*iter))
             nursery.forwardBufferPointer(reinterpret_cast<HeapSlot**>(spill));
     }
 
     // Skip to the right place in the safepoint
--- a/js/src/jit/LIR.h
+++ b/js/src/jit/LIR.h
@@ -1318,25 +1318,25 @@ class LSafepoint : public TempObject
     // use-at-start, any registers for temps, and any registers live after the
     // call except outputs of the instruction.
     //
     // For call instructions, the live regs are empty. Call instructions may
     // have register inputs or temporaries, which will *not* be in the live
     // registers: if passed to the call, the values passed will be marked via
     // MarkJitExitFrame, and no registers can be live after the instruction
     // except its outputs.
-    LiveRegisterSet liveRegs_;
+    RegisterSet liveRegs_;
 
     // The subset of liveRegs which contains gcthing pointers.
-    LiveGeneralRegisterSet gcRegs_;
+    GeneralRegisterSet gcRegs_;
 
 #ifdef CHECK_OSIPOINT_REGISTERS
     // Clobbered regs of the current instruction. This set is never written to
     // the safepoint; it's only used by assertions during compilation.
-    LiveRegisterSet clobberedRegs_;
+    RegisterSet clobberedRegs_;
 #endif
 
     // Offset to a position in the safepoint stream, or
     // INVALID_SAFEPOINT_OFFSET.
     uint32_t safepointOffset_;
 
     // Assembler buffer displacement to OSI point's call location.
     uint32_t osiCallPointOffset_;
@@ -1347,21 +1347,21 @@ class LSafepoint : public TempObject
     // List of slots which have Values.
     SlotList valueSlots_;
 
 #ifdef JS_NUNBOX32
     // List of registers (in liveRegs) and slots which contain pieces of Values.
     NunboxList nunboxParts_;
 #elif JS_PUNBOX64
     // The subset of liveRegs which have Values.
-    LiveGeneralRegisterSet valueRegs_;
+    GeneralRegisterSet valueRegs_;
 #endif
 
     // The subset of liveRegs which contains pointers to slots/elements.
-    LiveGeneralRegisterSet slotsOrElementsRegs_;
+    GeneralRegisterSet slotsOrElementsRegs_;
 
     // List of slots which have slots/elements pointers.
     SlotList slotsOrElementsSlots_;
 
   public:
     void assertInvariants() {
         // Every register in valueRegs and gcRegs should also be in liveRegs.
 #ifndef JS_NUNBOX32
@@ -1381,49 +1381,49 @@ class LSafepoint : public TempObject
       , slotsOrElementsSlots_(alloc)
     {
       assertInvariants();
     }
     void addLiveRegister(AnyRegister reg) {
         liveRegs_.addUnchecked(reg);
         assertInvariants();
     }
-    const LiveRegisterSet& liveRegs() const {
+    const RegisterSet& liveRegs() const {
         return liveRegs_;
     }
 #ifdef CHECK_OSIPOINT_REGISTERS
     void addClobberedRegister(AnyRegister reg) {
         clobberedRegs_.addUnchecked(reg);
         assertInvariants();
     }
-    const LiveRegisterSet& clobberedRegs() const {
+    const RegisterSet& clobberedRegs() const {
         return clobberedRegs_;
     }
 #endif
     void addGcRegister(Register reg) {
         gcRegs_.addUnchecked(reg);
         assertInvariants();
     }
-    LiveGeneralRegisterSet gcRegs() const {
+    GeneralRegisterSet gcRegs() const {
         return gcRegs_;
     }
     bool addGcSlot(bool stack, uint32_t slot) {
         bool result = gcSlots_.append(SlotEntry(stack, slot));
         if (result)
             assertInvariants();
         return result;
     }
     SlotList& gcSlots() {
         return gcSlots_;
     }
 
     SlotList& slotsOrElementsSlots() {
         return slotsOrElementsSlots_;
     }
-    LiveGeneralRegisterSet slotsOrElementsRegs() const {
+    GeneralRegisterSet slotsOrElementsRegs() const {
         return slotsOrElementsRegs_;
     }
     void addSlotsOrElementsRegister(Register reg) {
         slotsOrElementsRegs_.addUnchecked(reg);
         assertInvariants();
     }
     bool addSlotsOrElementsSlot(bool stack, uint32_t slot) {
         bool result = slotsOrElementsSlots_.append(SlotEntry(stack, slot));
@@ -1562,17 +1562,17 @@ class LSafepoint : public TempObject
     }
 
 #elif JS_PUNBOX64
 
     void addValueRegister(Register reg) {
         valueRegs_.add(reg);
         assertInvariants();
     }
-    LiveGeneralRegisterSet valueRegs() const {
+    GeneralRegisterSet valueRegs() const {
         return valueRegs_;
     }
 
     bool addBoxedValue(LAllocation alloc) {
         if (alloc.isRegister()) {
             Register reg = alloc.toRegister().gpr();
             if (!valueRegs().has(reg))
                 addValueRegister(reg);
--- a/js/src/jit/LinearScan.cpp
+++ b/js/src/jit/LinearScan.cpp
@@ -990,27 +990,21 @@ LinearScanAllocator::finishInterval(Live
 AnyRegister::Code
 LinearScanAllocator::findBestFreeRegister(CodePosition* freeUntil)
 {
     JitSpew(JitSpew_RegAlloc, "  Computing freeUntilPos");
 
     // Compute free-until positions for all registers
     CodePosition freeUntilPos[AnyRegister::Total];
     bool needFloat = vregs[current->vreg()].isFloatReg();
-    if (needFloat) {
-        // we may need to look at all of the float32 and float64 registers.
-        for (LiveRegisterSet regs(allRegisters_.asLiveSet()); !regs.emptyFloat(); ) {
-            AnyRegister reg(regs.takeAnyFloat());
-            freeUntilPos[reg.code()] = CodePosition::MAX;
-        }
-    } else {
-        for (LiveRegisterSet regs(allRegisters_.asLiveSet()); !regs.emptyGeneral(); ) {
-            AnyRegister reg(regs.takeAnyGeneral());
-            freeUntilPos[reg.code()] = CodePosition::MAX;
-        }
+    for (RegisterSet regs(allRegisters_); !regs.empty(needFloat); ) {
+        // If the requested register is a FP, we may need to look at
+        // all of the float32 and float64 registers.
+        AnyRegister reg = regs.takeUnaliasedAny(needFloat);
+        freeUntilPos[reg.code()] = CodePosition::MAX;
     }
     for (IntervalIterator i(active.begin()); i != active.end(); i++) {
         LAllocation* alloc = i->getAllocation();
         if (alloc->isRegister(needFloat)) {
             AnyRegister reg = alloc->toRegister();
             for (size_t a = 0; a < reg.numAliased(); a++) {
                 JitSpew(JitSpew_RegAlloc, "   Register %s not free", reg.aliased(a).name());
                 freeUntilPos[reg.aliased(a).code()] = CodePosition::MIN;
@@ -1126,26 +1120,19 @@ LinearScanAllocator::findBestFreeRegiste
 AnyRegister::Code
 LinearScanAllocator::findBestBlockedRegister(CodePosition* nextUsed)
 {
     JitSpew(JitSpew_RegAlloc, "  Computing nextUsePos");
 
     // Compute next-used positions for all registers
     CodePosition nextUsePos[AnyRegister::Total];
     bool needFloat = vregs[current->vreg()].isFloatReg();
-    if (needFloat) {
-        for (LiveRegisterSet regs(allRegisters_.asLiveSet()); !regs.emptyFloat(); ) {
-            AnyRegister reg(regs.takeAnyFloat());
-            nextUsePos[reg.code()] = CodePosition::MAX;
-        }
-    } else {
-        for (LiveRegisterSet regs(allRegisters_.asLiveSet()); !regs.emptyGeneral(); ) {
-            AnyRegister reg(regs.takeAnyGeneral());
-            nextUsePos[reg.code()] = CodePosition::MAX;
-        }
+    for (RegisterSet regs(allRegisters_); !regs.empty(needFloat); ) {
+        AnyRegister reg = regs.takeUnaliasedAny(needFloat);
+        nextUsePos[reg.code()] = CodePosition::MAX;
     }
     for (IntervalIterator i(active.begin()); i != active.end(); i++) {
         LAllocation* alloc = i->getAllocation();
         if (alloc->isRegister(needFloat)) {
             AnyRegister fullreg = alloc->toRegister();
             for (size_t a = 0; a < fullreg.numAliased(); a++) {
                 AnyRegister reg = fullreg.aliased(a);
                 if (i->start() == current->start()) {
--- a/js/src/jit/LiveRangeAllocator.cpp
+++ b/js/src/jit/LiveRangeAllocator.cpp
@@ -640,20 +640,28 @@ LiveRangeAllocator<VREG, forLSRA>::build
             }
         }
 
         // Shorten the front end of live intervals for live variables to their
         // point of definition, if found.
         for (LInstructionReverseIterator ins = block->rbegin(); ins != block->rend(); ins++) {
             // Calls may clobber registers, so force a spill and reload around the callsite.
             if (ins->isCall()) {
-                for (AnyRegisterIterator iter(allRegisters_.asLiveSet()); iter.more(); iter++) {
+                for (AnyRegisterIterator iter(allRegisters_); iter.more(); iter++) {
                     if (forLSRA) {
-                        if (!addFixedRangeAtHead(*iter, inputOf(*ins), outputOf(*ins)))
-                            return false;
+                        AnyRegister reg(*iter);
+                        // AnyRegisterIterator only iterates every allocatable
+                        // register once, and skip all aliased registers. Thus,
+                        // we have to record that each typed-variant/alias of
+                        // the same register has to be spilled if it got
+                        // allocated.
+                        for (size_t i = 0; i < reg.numAliased(); i++) {
+                            if (!addFixedRangeAtHead(reg.aliased(i), inputOf(*ins), outputOf(*ins)))
+                                return false;
+                        }
                     } else {
                         bool found = false;
 
                         for (size_t i = 0; i < ins->numDefs(); i++) {
                             if (ins->getDef(i)->isFixed() &&
                                 ins->getDef(i)->output()->aliases(LAllocation(*iter))) {
                                 found = true;
                                 break;
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1441,17 +1441,17 @@ MacroAssembler::initGCThing(Register obj
     } else {
         MOZ_CRASH("Unknown object");
     }
 
 #ifdef JS_GC_TRACE
     RegisterSet regs = RegisterSet::Volatile();
     PushRegsInMask(regs);
     regs.takeUnchecked(obj);
-    Register temp = regs.takeAnyGeneral();
+    Register temp = regs.takeGeneral();
 
     setupUnalignedABICall(2, temp);
     passABIArg(obj);
     movePtr(ImmGCPtr(templateObj->type()), temp);
     passABIArg(temp);
     callWithABI(JS_FUNC_TO_DATA_PTR(void*, js::gc::TraceCreateObject));
 
     PopRegsInMask(RegisterSet::Volatile());
@@ -1590,17 +1590,17 @@ MacroAssembler::generateBailoutTail(Regi
         passABIArg(ReturnReg);
         callWithABI(JS_FUNC_TO_DATA_PTR(void*, BailoutReportOverRecursed));
         jump(exceptionLabel());
     }
 
     bind(&baseline);
     {
         // Prepare a register set for use in this case.
-        AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+        GeneralRegisterSet regs(GeneralRegisterSet::All());
         MOZ_ASSERT(!regs.has(BaselineStackReg));
         regs.take(bailoutInfo);
 
         // Reset SP to the point where clobbering starts.
         loadPtr(Address(bailoutInfo, offsetof(BaselineBailoutInfo, incomingStack)),
                 BaselineStackReg);
 
         Register copyCur = regs.takeAny();
@@ -1652,17 +1652,17 @@ MacroAssembler::generateBailoutTail(Regi
 
             // Call a stub to free allocated memory and create arguments objects.
             setupUnalignedABICall(1, temp);
             passABIArg(bailoutInfo);
             callWithABI(JS_FUNC_TO_DATA_PTR(void*, FinishBailoutToBaseline));
             branchTest32(Zero, ReturnReg, ReturnReg, exceptionLabel());
 
             // Restore values where they need to be and resume execution.
-            AllocatableGeneralRegisterSet enterMonRegs(GeneralRegisterSet::All());
+            GeneralRegisterSet enterMonRegs(GeneralRegisterSet::All());
             enterMonRegs.take(R0);
             enterMonRegs.take(BaselineStubReg);
             enterMonRegs.take(BaselineFrameReg);
             enterMonRegs.takeUnchecked(BaselineTailCallReg);
 
             pop(BaselineStubReg);
             pop(BaselineTailCallReg);
             pop(BaselineFrameReg);
@@ -1690,17 +1690,17 @@ MacroAssembler::generateBailoutTail(Regi
 
             // Call a stub to free allocated memory and create arguments objects.
             setupUnalignedABICall(1, temp);
             passABIArg(bailoutInfo);
             callWithABI(JS_FUNC_TO_DATA_PTR(void*, FinishBailoutToBaseline));
             branchTest32(Zero, ReturnReg, ReturnReg, exceptionLabel());
 
             // Restore values where they need to be and resume execution.
-            AllocatableGeneralRegisterSet enterRegs(GeneralRegisterSet::All());
+            GeneralRegisterSet enterRegs(GeneralRegisterSet::All());
             enterRegs.take(R0);
             enterRegs.take(R1);
             enterRegs.take(BaselineFrameReg);
             Register jitcodeReg = enterRegs.takeAny();
 
             pop(jitcodeReg);
             pop(BaselineFrameReg);
             popValue(R1);
@@ -1754,27 +1754,26 @@ AssumeUnreachable_(const char* output) {
 }
 #endif
 
 void
 MacroAssembler::assumeUnreachable(const char* output)
 {
 #ifdef DEBUG
     if (!IsCompilingAsmJS()) {
-        AllocatableRegisterSet regs(RegisterSet::Volatile());
-        LiveRegisterSet save(regs.asLiveSet());
-        PushRegsInMask(save);
-        Register temp = regs.takeAnyGeneral();
+        RegisterSet regs = RegisterSet::Volatile();
+        PushRegsInMask(regs);
+        Register temp = regs.takeGeneral();
 
         setupUnalignedABICall(1, temp);
         movePtr(ImmPtr(output), temp);
         passABIArg(temp);
         callWithABI(JS_FUNC_TO_DATA_PTR(void*, AssumeUnreachable_));
 
-        PopRegsInMask(save);
+        PopRegsInMask(RegisterSet::Volatile());
     }
 #endif
 
     breakpoint();
 }
 
 template<typename T>
 void
@@ -1796,160 +1795,158 @@ Printf0_(const char* output) {
     // output. stderr is less likely to interfere with the program's normal
     // output, and it's always unbuffered.
     fprintf(stderr, "%s", output);
 }
 
 void
 MacroAssembler::printf(const char* output)
 {
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    LiveRegisterSet save(regs.asLiveSet());
-    PushRegsInMask(save);
+    RegisterSet regs = RegisterSet::Volatile();
+    PushRegsInMask(regs);
 
-    Register temp = regs.takeAnyGeneral();
+    Register temp = regs.takeGeneral();
 
     setupUnalignedABICall(1, temp);
     movePtr(ImmPtr(output), temp);
     passABIArg(temp);
     callWithABI(JS_FUNC_TO_DATA_PTR(void*, Printf0_));
 
-    PopRegsInMask(save);
+    PopRegsInMask(RegisterSet::Volatile());
 }
 
 static void
 Printf1_(const char* output, uintptr_t value) {
     char* line = JS_sprintf_append(nullptr, output, value);
     fprintf(stderr, "%s", line);
     js_free(line);
 }
 
 void
 MacroAssembler::printf(const char* output, Register value)
 {
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    LiveRegisterSet save(regs.asLiveSet());
-    PushRegsInMask(save);
+    RegisterSet regs = RegisterSet::Volatile();
+    PushRegsInMask(regs);
 
     regs.takeUnchecked(value);
 
-    Register temp = regs.takeAnyGeneral();
+    Register temp = regs.takeGeneral();
 
     setupUnalignedABICall(2, temp);
     movePtr(ImmPtr(output), temp);
     passABIArg(temp);
     passABIArg(value);
     callWithABI(JS_FUNC_TO_DATA_PTR(void*, Printf1_));
 
-    PopRegsInMask(save);
+    PopRegsInMask(RegisterSet::Volatile());
 }
 
 #ifdef JS_TRACE_LOGGING
 void
 MacroAssembler::tracelogStartId(Register logger, uint32_t textId, bool force)
 {
     if (!force && !TraceLogTextIdEnabled(textId))
         return;
 
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    LiveRegisterSet save(regs.asLiveSet());
-    PushRegsInMask(save);
+    PushRegsInMask(RegisterSet::Volatile());
+
+    RegisterSet regs = RegisterSet::Volatile();
     regs.takeUnchecked(logger);
 
-    Register temp = regs.takeAnyGeneral();
+    Register temp = regs.takeGeneral();
 
     setupUnalignedABICall(2, temp);
     passABIArg(logger);
     move32(Imm32(textId), temp);
     passABIArg(temp);
     callWithABI(JS_FUNC_TO_DATA_PTR(void*, TraceLogStartEventPrivate));
 
-    PopRegsInMask(save);
+    PopRegsInMask(RegisterSet::Volatile());
 }
 
 void
 MacroAssembler::tracelogStartId(Register logger, Register textId)
 {
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    LiveRegisterSet save(regs.asLiveSet());
-    PushRegsInMask(save);
+    PushRegsInMask(RegisterSet::Volatile());
+
+    RegisterSet regs = RegisterSet::Volatile();
     regs.takeUnchecked(logger);
     regs.takeUnchecked(textId);
 
-    Register temp = regs.takeAnyGeneral();
+    Register temp = regs.takeGeneral();
 
     setupUnalignedABICall(2, temp);
     passABIArg(logger);
     passABIArg(textId);
     callWithABI(JS_FUNC_TO_DATA_PTR(void*, TraceLogStartEventPrivate));
 
-    PopRegsInMask(save);
+    PopRegsInMask(RegisterSet::Volatile());
 }
 
 void
 MacroAssembler::tracelogStartEvent(Register logger, Register event)
 {
     void (&TraceLogFunc)(TraceLoggerThread*, const TraceLoggerEvent&) = TraceLogStartEvent;
 
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    LiveRegisterSet save(regs.asLiveSet());
-    PushRegsInMask(save);
+    PushRegsInMask(RegisterSet::Volatile());
+
+    RegisterSet regs = RegisterSet::Volatile();
     regs.takeUnchecked(logger);
     regs.takeUnchecked(event);
 
-    Register temp = regs.takeAnyGeneral();
+    Register temp = regs.takeGeneral();
 
     setupUnalignedABICall(2, temp);
     passABIArg(logger);
     passABIArg(event);
     callWithABI(JS_FUNC_TO_DATA_PTR(void*, TraceLogFunc));
 
-    PopRegsInMask(save);
+    PopRegsInMask(RegisterSet::Volatile());
 }
 
 void
 MacroAssembler::tracelogStopId(Register logger, uint32_t textId, bool force)
 {
     if (!force && !TraceLogTextIdEnabled(textId))
         return;
 
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    LiveRegisterSet save(regs.asLiveSet());
-    PushRegsInMask(save);
+    PushRegsInMask(RegisterSet::Volatile());
+
+    RegisterSet regs = RegisterSet::Volatile();
     regs.takeUnchecked(logger);
 
-    Register temp = regs.takeAnyGeneral();
+    Register temp = regs.takeGeneral();
 
     setupUnalignedABICall(2, temp);
     passABIArg(logger);
     move32(Imm32(textId), temp);
     passABIArg(temp);
 
     callWithABI(JS_FUNC_TO_DATA_PTR(void*, TraceLogStopEventPrivate));
 
-    PopRegsInMask(save);
+    PopRegsInMask(RegisterSet::Volatile());
 }
 
 void
 MacroAssembler::tracelogStopId(Register logger, Register textId)
 {
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    LiveRegisterSet save(regs.asLiveSet());
-    PushRegsInMask(save);
+    PushRegsInMask(RegisterSet::Volatile());
+    RegisterSet regs = RegisterSet::Volatile();
     regs.takeUnchecked(logger);
+
     regs.takeUnchecked(textId);
 
-    Register temp = regs.takeAnyGeneral();
+    Register temp = regs.takeGeneral();
 
     setupUnalignedABICall(2, temp);
     passABIArg(logger);
     passABIArg(textId);
     callWithABI(JS_FUNC_TO_DATA_PTR(void*, TraceLogStopEventPrivate));
 
-    PopRegsInMask(save);
+    PopRegsInMask(RegisterSet::Volatile());
 }
 #endif
 
 void
 MacroAssembler::convertInt32ValueToDouble(const Address& address, Register scratch, Label* done)
 {
     branchTestInt32(Assembler::NotEqual, address, done);
     unboxInt32(address, scratch);
@@ -2527,31 +2524,49 @@ MacroAssembler::alignJitStackBasedOnNArg
         andPtr(Imm32(~(JitStackAlignment - 1)), StackPointer);
     }
 }
 
 // ===============================================================
 // Stack manipulation functions.
 
 void
-MacroAssembler::PushRegsInMask(LiveGeneralRegisterSet set)
+MacroAssembler::PushRegsInMask(RegisterSet set)
 {
-    PushRegsInMask(LiveRegisterSet(set.set(), FloatRegisterSet()));
+    PushRegsInMask(set, FloatRegisterSet());
+}
+
+void
+MacroAssembler::PushRegsInMask(GeneralRegisterSet set)
+{
+    PushRegsInMask(RegisterSet(set, FloatRegisterSet()));
 }
 
 void
-MacroAssembler::PopRegsInMask(LiveRegisterSet set)
+MacroAssembler::PopRegsInMask(RegisterSet set)
 {
-    PopRegsInMaskIgnore(set, LiveRegisterSet());
+    PopRegsInMaskIgnore(set, RegisterSet());
 }
 
 void
-MacroAssembler::PopRegsInMask(LiveGeneralRegisterSet set)
+MacroAssembler::PopRegsInMask(RegisterSet set, FloatRegisterSet simdSet)
+{
+    PopRegsInMaskIgnore(set, RegisterSet(), simdSet);
+}
+
+void
+MacroAssembler::PopRegsInMask(GeneralRegisterSet set)
 {
-    PopRegsInMask(LiveRegisterSet(set.set(), FloatRegisterSet()));
+    PopRegsInMask(RegisterSet(set, FloatRegisterSet()));
+}
+
+void
+MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
+{
+    PopRegsInMaskIgnore(set, ignore, FloatRegisterSet());
 }
 
 void
 MacroAssembler::Push(jsid id, Register scratchReg)
 {
     if (JSID_IS_GCTHING(id)) {
         // If we're pushing a gcthing, then we can't just push the tagged jsid
         // value since the GC won't have any idea that the push instruction
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -291,22 +291,26 @@ class MacroAssembler : public MacroAssem
     size_t instructionsSize() const {
         return size();
     }
 
   public:
     // ===============================================================
     // Stack manipulation functions.
 
-    void PushRegsInMask(LiveRegisterSet set) PER_ARCH;
-    void PushRegsInMask(LiveGeneralRegisterSet set);
+    void PushRegsInMask(RegisterSet set, FloatRegisterSet simdSet) PER_ARCH;
+    void PushRegsInMask(RegisterSet set);
+    void PushRegsInMask(GeneralRegisterSet set);
 
-    void PopRegsInMask(LiveRegisterSet set);
-    void PopRegsInMask(LiveGeneralRegisterSet set);
-    void PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) PER_ARCH;
+    void PopRegsInMask(RegisterSet set);
+    void PopRegsInMask(RegisterSet set, FloatRegisterSet simdSet);
+    void PopRegsInMask(GeneralRegisterSet set);
+    void PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore,
+                             FloatRegisterSet simdSet) PER_ARCH;
+    void PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore);
 
     void Push(const Operand op) PER_ARCH ONLY_X86_X64;
     void Push(Register reg) PER_ARCH;
     void Push(const Imm32 imm) PER_ARCH;
     void Push(const ImmWord imm) PER_ARCH;
     void Push(const ImmPtr imm) PER_ARCH;
     void Push(const ImmGCPtr ptr) PER_ARCH;
     void Push(FloatRegister reg) PER_ARCH;
@@ -1222,28 +1226,28 @@ class MacroAssembler : public MacroAssem
         uint32_t initialStack;
 #endif
         uint32_t alignmentPadding;
     };
 
     void alignFrameForICArguments(AfterICSaveLive& aic);
     void restoreFrameAlignmentForICArguments(AfterICSaveLive& aic);
 
-    AfterICSaveLive icSaveLive(LiveRegisterSet& liveRegs) {
+    AfterICSaveLive icSaveLive(RegisterSet& liveRegs) {
         PushRegsInMask(liveRegs);
         AfterICSaveLive aic(framePushed());
         alignFrameForICArguments(aic);
         return aic;
     }
 
     bool icBuildOOLFakeExitFrame(void* fakeReturnAddr, AfterICSaveLive& aic) {
         return buildOOLFakeExitFrame(fakeReturnAddr);
     }
 
-    void icRestoreLive(LiveRegisterSet& liveRegs, AfterICSaveLive& aic) {
+    void icRestoreLive(RegisterSet& liveRegs, AfterICSaveLive& aic) {
         restoreFrameAlignmentForICArguments(aic);
         MOZ_ASSERT(framePushed() == aic.initialStack);
         PopRegsInMask(liveRegs);
     }
 
     // Align the stack pointer based on the number of arguments which are pushed
     // on the stack, such that the JitFrameLayout would be correctly aligned on
     // the JitStackAlignment.
--- a/js/src/jit/RegisterAllocator.cpp
+++ b/js/src/jit/RegisterAllocator.cpp
@@ -139,18 +139,18 @@ AllocationIntegrityState::check(bool pop
                     if (ins->getTemp(i)->isBogusTemp())
                         continue;
                     uint32_t vreg = info.temps[i].virtualRegister();
                     LAllocation* alloc = ins->getTemp(i)->output();
                     if (!checkSafepointAllocation(ins, vreg, *alloc, populateSafepoints))
                         return false;
                 }
                 MOZ_ASSERT_IF(ins->isCall() && !populateSafepoints,
-                              safepoint->liveRegs().emptyFloat() &&
-                              safepoint->liveRegs().emptyGeneral());
+                              safepoint->liveRegs().empty(true) &&
+                              safepoint->liveRegs().empty(false));
             }
 
             size_t inputIndex = 0;
             for (LInstruction::InputIterator alloc(*ins); alloc.more(); alloc.next()) {
                 LAllocation oldInput = info.inputs[inputIndex++];
                 if (!oldInput.isUse())
                     continue;
 
--- a/js/src/jit/RegisterAllocator.h
+++ b/js/src/jit/RegisterAllocator.h
@@ -256,17 +256,17 @@ class RegisterAllocator
 
   protected:
     // Context
     MIRGenerator* mir;
     LIRGenerator* lir;
     LIRGraph& graph;
 
     // Pool of all registers that should be considered allocateable
-    AllocatableRegisterSet allRegisters_;
+    RegisterSet allRegisters_;
 
     // Computed data
     InstructionDataMap insData;
 
     RegisterAllocator(MIRGenerator* mir, LIRGenerator* lir, LIRGraph& graph)
       : mir(mir),
         lir(lir),
         graph(graph),
--- a/js/src/jit/RegisterSets.h
+++ b/js/src/jit/RegisterSets.h
@@ -318,22 +318,19 @@ struct Int32Key {
     inline bool isConstant() const {
         return !isRegister_;
     }
 };
 
 template <typename T>
 class TypedRegisterSet
 {
-  public:
-    typedef T RegType;
     typedef typename T::SetType SetType;
+    SetType bits_;
 
-  private:
-    SetType bits_;
 
   public:
     explicit MOZ_CONSTEXPR TypedRegisterSet(SetType bits)
       : bits_(bits)
     { }
 
     MOZ_CONSTEXPR TypedRegisterSet() : bits_(0)
     { }
@@ -365,61 +362,184 @@ class TypedRegisterSet
         return TypedRegisterSet(~in.bits_ & allocatableVolatile);
     }
     static inline TypedRegisterSet Volatile() {
         return TypedRegisterSet(T::Codes::AllocatableMask & T::Codes::VolatileMask);
     }
     static inline TypedRegisterSet NonVolatile() {
         return TypedRegisterSet(T::Codes::AllocatableMask & T::Codes::NonVolatileMask);
     }
+    bool has(T reg) const {
+        // When checking to see if a set has a register, we only want that exact
+        // register, not worrying about aliasing.
+        return !!(bits_ & (SetType(1) << reg.code()));
+    }
+    void addUnchecked(T reg) {
+        bits_ |= (SetType(1) << reg.code());
+    }
+    void addAllAliasedUnchecked(T reg) {
+        for (uint32_t a = 0; a < reg.numAliased(); a++) {
+            T tmp;
+            reg.aliased(a, &tmp);
+            bits_ |= (SetType(1) << tmp.code());
+        }
+    }
 
+    void add(T reg) {
+        // Make sure we don't add two overlapping registers.
+#ifdef DEBUG
+        for (uint32_t a = 0; a < reg.numAliased(); a++) {
+            T tmp;
+            reg.aliased(a, &tmp);
+            MOZ_ASSERT(!has(tmp));
+        }
+#endif
+        addUnchecked(reg);
+    }
+
+    void add(ValueOperand value) {
+#if defined(JS_NUNBOX32)
+        add(value.payloadReg());
+        add(value.typeReg());
+#elif defined(JS_PUNBOX64)
+        add(value.valueReg());
+#else
+#error "Bad architecture"
+#endif
+    }
+    // Determine if some register are still allocated.  This function should
+    // be used with the set of allocatable registers used for the initialization
+    // of the current set.
+    bool someAllocated(const TypedRegisterSet& allocatable) const {
+        return allocatable.bits_ & ~bits_;
+    }
     bool empty() const {
         return !bits_;
     }
-
-    bool hasRegisterIndex(T reg) const {
-        return !!(bits_ & (SetType(1) << reg.code()));
-    }
-    bool hasAllocatable(T reg) const {
-        return !(~bits_ & reg.alignedOrDominatedAliasedSet());
+    void take(T reg) {
+        MOZ_ASSERT(has(reg));
+        takeUnchecked(reg);
     }
-
-    void addRegisterIndex(T reg) {
-        bits_ |= (SetType(1) << reg.code());
-    }
-    void addAllocatable(T reg) {
-        bits_ |= reg.alignedOrDominatedAliasedSet();
-    }
-
-
-    void takeRegisterIndex(T reg) {
+    void takeUnchecked(T reg) {
         bits_ &= ~(SetType(1) << reg.code());
     }
-    void takeAllocatable(T reg) {
-        bits_ &= ~reg.alignedOrDominatedAliasedSet();
+    void takeAllAliasedUnchecked(T reg) {
+        for (uint32_t a = 0; a < reg.numAliased(); a++) {
+            T tmp;
+            reg.aliased(a, &tmp);
+            takeUnchecked(tmp);
+        }
+    }
+    void take(ValueOperand value) {
+#if defined(JS_NUNBOX32)
+        take(value.payloadReg());
+        take(value.typeReg());
+#elif defined(JS_PUNBOX64)
+        take(value.valueReg());
+#else
+#error "Bad architecture"
+#endif
     }
-
+    void takeUnchecked(ValueOperand value) {
+#if defined(JS_NUNBOX32)
+        takeUnchecked(value.payloadReg());
+        takeUnchecked(value.typeReg());
+#elif defined(JS_PUNBOX64)
+        takeUnchecked(value.valueReg());
+#else
+#error "Bad architecture"
+#endif
+    }
+    ValueOperand takeValueOperand() {
+#if defined(JS_NUNBOX32)
+        return ValueOperand(takeAny(), takeAny());
+#elif defined(JS_PUNBOX64)
+        return ValueOperand(takeAny());
+#else
+#error "Bad architecture"
+#endif
+    }
     T getAny() const {
         // The choice of first or last here is mostly arbitrary, as they are
         // about the same speed on popular architectures. We choose first, as
         // it has the advantage of using the "lower" registers more often. These
         // registers are sometimes more efficient (e.g. optimized encodings for
         // EAX on x86).
         return getFirst();
     }
+    T getAnyExcluding(T preclude) {
+        MOZ_ASSERT(!empty());
+        if (!has(preclude))
+            return getAny();
+
+        take(preclude);
+        MOZ_ASSERT(!empty());
+        T result = getAny();
+        add(preclude);
+        return result;
+    }
     T getFirst() const {
         MOZ_ASSERT(!empty());
         return T::FromCode(T::FirstBit(bits_));
     }
     T getLast() const {
         MOZ_ASSERT(!empty());
         int ireg = T::LastBit(bits_);
         return T::FromCode(ireg);
     }
-
+    T takeAny() {
+        MOZ_ASSERT(!empty());
+        T reg = getAny();
+        takeAllAliasedUnchecked(reg);
+        return reg;
+    }
+    T takeUnaliasedAny() {
+        // This variant is used by LinearScan for iterating over all registers.
+        MOZ_ASSERT(!empty());
+        T reg = getAny();
+        takeUnchecked(reg);
+        return reg;
+    }
+    T takeAnyExcluding(T preclude) {
+        T reg = getAnyExcluding(preclude);
+        takeAllAliasedUnchecked(reg);
+        return reg;
+    }
+    ValueOperand takeAnyValue() {
+#if defined(JS_NUNBOX32)
+        T type = takeAny();
+        T payload = takeAny();
+        return ValueOperand(type, payload);
+#elif defined(JS_PUNBOX64)
+        T reg = takeAny();
+        return ValueOperand(reg);
+#else
+#error "Bad architecture"
+#endif
+    }
+    T takeFirst() {
+        // This function is used to implement a forward register set iterator.
+        MOZ_ASSERT(!empty());
+        T reg = getFirst();
+        // The iterator is used by PushRegsInMask which might be called with
+        // AllAlllocatableRegister mask.  To avoid saving more than needed we
+        // should take aliased registers too.
+        takeAllAliasedUnchecked(reg);
+        return reg;
+    }
+    T takeLast() {
+        // This function is used to implement a backward register set iterator.
+        MOZ_ASSERT(!empty());
+        T reg = getLast();
+        takeAllAliasedUnchecked(reg);
+        return reg;
+    }
+    void clear() {
+        bits_ = 0;
+    }
     SetType bits() const {
         return bits_;
     }
     uint32_t size() const {
         return T::SetSize(bits_);
     }
     bool operator ==(const TypedRegisterSet<T>& other) const {
         return other.bits_ == bits_;
@@ -467,632 +587,163 @@ class RegisterSet {
     }
     static inline RegisterSet VolatileNot(const RegisterSet& in) {
         return RegisterSet(GeneralRegisterSet::VolatileNot(in.gpr_),
                            FloatRegisterSet::VolatileNot(in.fpu_));
     }
     static inline RegisterSet Volatile() {
         return RegisterSet(GeneralRegisterSet::Volatile(), FloatRegisterSet::Volatile());
     }
-
-    bool empty() const {
-        return fpu_.empty() && gpr_.empty();
-    }
-    bool emptyGeneral() const {
-        return gpr_.empty();
-    }
-    bool emptyFloat() const {
-        return fpu_.empty();
-    }
-    MOZ_CONSTEXPR GeneralRegisterSet gprs() const {
-        return gpr_;
-    }
-    GeneralRegisterSet& gprs() {
-        return gpr_;
-    }
-    MOZ_CONSTEXPR FloatRegisterSet fpus() const {
-        return fpu_;
-    }
-    FloatRegisterSet& fpus() {
-        return fpu_;
-    }
-    bool operator ==(const RegisterSet& other) const {
-        return other.gpr_ == gpr_ && other.fpu_ == fpu_;
-    }
-
-};
-
-// There are 2 use cases for register sets:
-//
-//   1. To serve as a pool of allocatable register. This is useful for working
-//      on the code produced by some stub where free registers are available, or
-//      when we can release some registers.
-//
-//   2. To serve as a list of typed registers. This is useful for working with
-//      live registers and to manipulate them with the proper instructions. This
-//      is used by the register allocator to fill the Safepoints.
-//
-// These 2 uses cases can be used on top of 3 different backend representation
-// of register sets, which are either GeneralRegisterSet, FloatRegisterSet, or
-// RegisterSet (for both). These classes are used to store the bit sets to
-// represent each register.
-//
-// Each use case defines an Accessor class, such as AllocatableSetAccessor or
-// LiveSetAccessor, which is parameterized with the type of the register
-// set. These accessors are in charge of manipulating the register set in a
-// consistent way.
-//
-// The RegSetCommonInterface class is used to wrap the accessors with convenient
-// shortcuts which are based on the accessors.
-//
-// Then, to avoid to many levels of complexity while using these interfaces,
-// shortcut templates are created to make it easy to distinguish between a
-// register set used for allocating registers, or a register set used for making
-// a collection of allocated (live) registers.
-//
-// This separation exists to prevent mixing LiveSet and AllocatableSet
-// manipulations of the same register set, and ensure safety while avoiding
-// false positive.
-
-template <typename RegisterSet>
-class AllocatableSet;
-
-template <typename RegisterSet>
-class LiveSet;
-
-// Base accessors classes have the minimal set of raw methods to manipulate the register set
-// given as parameter in a consistent manner.  These methods are:
-//
-//    - has: Returns if all the bits needed to take a register are present.
-//
-//    - takeUnchecked: Subtracts the bits used to represent the register in the
-//      register set.
-//
-//    - addUnchecked: Adds the bits used to represent the register in the
-//      register set.
-
-// The AllocatableSet accessors are used to make a pool of unused
-// registers. Taking or adding registers should consider the aliasing rules of
-// the architecture.  For example, on ARM, the following piece of code should
-// work fine, knowing that the double register |d0| is composed of float
-// registers |s0| and |s1|:
-//
-//     AllocatableFloatRegisterSet regs;
-//     regs.add(s0);
-//     regs.add(s1);
-//     // d0 is now available.
-//     regs.take(d0);
-//
-// These accessors are useful for allocating registers within the functions used
-// to generate stubs, trampolines, and inline caches (BaselineIC, IonCache).
-template <typename Set>
-class AllocatableSetAccessors
-{
-  public:
-    typedef Set RegSet;
-    typedef typename RegSet::RegType RegType;
-    typedef typename RegSet::SetType SetType;
-
-  protected:
-    RegSet set_;
-
-  public:
-    AllocatableSetAccessors() : set_() {}
-    explicit MOZ_CONSTEXPR AllocatableSetAccessors(SetType set) : set_(set) {}
-    explicit MOZ_CONSTEXPR AllocatableSetAccessors(RegSet set) : set_(set) {}
-
-    bool has(RegType reg) const {
-        return set_.hasAllocatable(reg);
-    }
-
-    void addUnchecked(RegType reg) {
-        set_.addAllocatable(reg);
-    }
-
-    void takeUnchecked(RegType reg) {
-        set_.takeAllocatable(reg);
-    }
-};
-
-// Specialization of the AllocatableSet accessors for the RegisterSet aggregate.
-template <>
-class AllocatableSetAccessors<RegisterSet>
-{
-  public:
-    typedef RegisterSet RegSet;
-    typedef AnyRegister RegType;
-    typedef char SetType;
-
-  protected:
-    RegisterSet set_;
-
-  public:
-    AllocatableSetAccessors() : set_() {}
-    explicit MOZ_CONSTEXPR AllocatableSetAccessors(SetType) = delete;
-    explicit MOZ_CONSTEXPR AllocatableSetAccessors(RegisterSet set) : set_(set) {}
-
     bool has(Register reg) const {
-        return set_.gprs().hasAllocatable(reg);
+        return gpr_.has(reg);
     }
     bool has(FloatRegister reg) const {
-        return set_.fpus().hasAllocatable(reg);
-    }
-
-    void addUnchecked(Register reg) {
-        set_.gprs().addAllocatable(reg);
-    }
-    void addUnchecked(FloatRegister reg) {
-        set_.fpus().addAllocatable(reg);
-    }
-
-    void takeUnchecked(Register reg) {
-        set_.gprs().takeAllocatable(reg);
-    }
-    void takeUnchecked(FloatRegister reg) {
-        set_.fpus().takeAllocatable(reg);
-    }
-};
-
-
-// The LiveSet accessors are used to collect a list of allocated
-// registers. Taking or adding a register should *not* consider the aliases, as
-// we care about interpreting the registers with the correct type.  For example,
-// on x64, where one float registers can be interpreted as an Int32x4, a Double,
-// or a Float, adding xmm0 as an Int32x4, does not make the register available
-// as a Double.
-//
-//     LiveFloatRegisterSet regs;
-//     regs.add(xmm0.asInt32x4());
-//     regs.take(xmm0); // Assert!
-//
-// These accessors are useful for recording the result of a register allocator,
-// such as what the Backtracking allocator do on the Safepoints.
-template <typename Set>
-class LiveSetAccessors
-{
-  public:
-    typedef Set RegSet;
-    typedef typename RegSet::RegType RegType;
-    typedef typename RegSet::SetType SetType;
-
-  protected:
-    RegSet set_;
-
-  public:
-    LiveSetAccessors() : set_() {}
-    explicit MOZ_CONSTEXPR LiveSetAccessors(SetType set) : set_(set) {}
-    explicit MOZ_CONSTEXPR LiveSetAccessors(RegSet set) : set_(set) {}
-
-    bool has(RegType reg) const {
-        return set_.hasRegisterIndex(reg);
-    }
-
-    void addUnchecked(RegType reg) {
-        set_.addRegisterIndex(reg);
-    }
-
-    void takeUnchecked(RegType reg) {
-        set_.takeRegisterIndex(reg);
-    }
-};
-
-// Specialization of the LiveSet accessors for the RegisterSet aggregate.
-template <>
-class LiveSetAccessors<RegisterSet>
-{
-  public:
-    typedef RegisterSet RegSet;
-    typedef AnyRegister RegType;
-    typedef char SetType;
-
-  protected:
-    RegisterSet set_;
-
-  public:
-    LiveSetAccessors() : set_() {}
-    explicit MOZ_CONSTEXPR LiveSetAccessors(SetType) = delete;
-    explicit MOZ_CONSTEXPR LiveSetAccessors(RegisterSet set) : set_(set) {}
-
-    bool has(Register reg) const {
-        return set_.gprs().hasRegisterIndex(reg);
-    }
-    bool has(FloatRegister reg) const {
-        return set_.fpus().hasRegisterIndex(reg);
-    }
-
-    void addUnchecked(Register reg) {
-        set_.gprs().addRegisterIndex(reg);
-    }
-    void addUnchecked(FloatRegister reg) {
-        set_.fpus().addRegisterIndex(reg);
-    }
-
-    void takeUnchecked(Register reg) {
-        set_.gprs().takeRegisterIndex(reg);
-    }
-    void takeUnchecked(FloatRegister reg) {
-        set_.fpus().takeRegisterIndex(reg);
+        return fpu_.has(reg);
     }
-};
-
-#define DEFINE_ACCESSOR_CONSTRUCTORS_(REGSET)                         \
-    typedef typename Parent::RegSet  RegSet;                          \
-    typedef typename Parent::RegType RegType;                         \
-    typedef typename Parent::SetType SetType;                         \
-                                                                      \
-    MOZ_CONSTEXPR_TMPL REGSET() : Parent() {}                         \
-    explicit MOZ_CONSTEXPR_TMPL REGSET(SetType set) : Parent(set) {}  \
-    explicit MOZ_CONSTEXPR_TMPL REGSET(RegSet set) : Parent(set) {}
-
-// This class adds checked accessors on top of the unchecked variants defined by
-// AllocatableSet and LiveSet accessors. Also it defines interface which are
-// specialized to the register set implementation, such as |getAny| and
-// |takeAny| variants.
-template <class Accessors, typename Set>
-class SpecializedRegSet : public Accessors
-{
-    typedef Accessors Parent;
-
-  public:
-    DEFINE_ACCESSOR_CONSTRUCTORS_(SpecializedRegSet)
-
-    SetType bits() const {
-        return this->Parent::set_.bits();
-    }
-
-    using Parent::has;
-
-    using Parent::addUnchecked;
-    void add(RegType reg) {
-        MOZ_ASSERT(!has(reg));
-        addUnchecked(reg);
-    }
-
-    using Parent::takeUnchecked;
-    void take(RegType reg) {
-        MOZ_ASSERT(has(reg));
-        takeUnchecked(reg);
-    }
-
-    RegType getAny() const {
-        return this->Parent::set_.getAny();
-    }
-    RegType getFirst() const {
-        return this->Parent::set_.getFirst();
-    }
-    RegType getLast() const {
-        return this->Parent::set_.getLast();
-    }
-
-    RegType getAnyExcluding(RegType preclude) {
-        if (!has(preclude))
-            return getAny();
-
-        take(preclude);
-        RegType result = getAny();
-        add(preclude);
-        return result;
-    }
-
-    RegType takeAny() {
-        RegType reg = getAny();
-        take(reg);
-        return reg;
-    }
-    RegType takeFirst() {
-        RegType reg = getFirst();
-        take(reg);
-        return reg;
-    }
-    RegType takeLast() {
-        RegType reg = getLast();
-        take(reg);
-        return reg;
-    }
-
-    ValueOperand takeAnyValue() {
-#if defined(JS_NUNBOX32)
-        return ValueOperand(takeAny(), takeAny());
-#elif defined(JS_PUNBOX64)
-        return ValueOperand(takeAny());
-#else
-#error "Bad architecture"
-#endif
-    }
-
-    RegType takeAnyExcluding(RegType preclude) {
-        RegType reg = getAnyExcluding(preclude);
-        take(reg);
-        return reg;
-    }
-};
-
-// Specialization of the accessors for the RegisterSet aggregate.
-template <class Accessors>
-class SpecializedRegSet<Accessors, RegisterSet> : public Accessors
-{
-    typedef Accessors Parent;
-
-  public:
-    DEFINE_ACCESSOR_CONSTRUCTORS_(SpecializedRegSet)
-
-    GeneralRegisterSet gprs() const {
-        return this->Parent::set_.gprs();
-    }
-    GeneralRegisterSet& gprs() {
-        return this->Parent::set_.gprs();
-    }
-    FloatRegisterSet fpus() const {
-        return this->Parent::set_.fpus();
-    }
-    FloatRegisterSet& fpus() {
-        return this->Parent::set_.fpus();
-    }
-
-    bool emptyGeneral() const {
-        return this->Parent::set_.emptyGeneral();
-    }
-    bool emptyFloat() const {
-        return this->Parent::set_.emptyFloat();
-    }
-
-
-    using Parent::has;
     bool has(AnyRegister reg) const {
         return reg.isFloat() ? has(reg.fpu()) : has(reg.gpr());
     }
-
-
-    using Parent::addUnchecked;
-    void addUnchecked(AnyRegister reg) {
-        if (reg.isFloat())
-            addUnchecked(reg.fpu());
-        else
-            addUnchecked(reg.gpr());
-    }
-
     void add(Register reg) {
-        MOZ_ASSERT(!has(reg));
-        addUnchecked(reg);
+        gpr_.add(reg);
     }
     void add(FloatRegister reg) {
-        MOZ_ASSERT(!has(reg));
-        addUnchecked(reg);
-    }
-    void add(AnyRegister reg) {
-        if (reg.isFloat())
-            add(reg.fpu());
-        else
-            add(reg.gpr());
-    }
-
-    using Parent::takeUnchecked;
-    void takeUnchecked(AnyRegister reg) {
-        if (reg.isFloat())
-            takeUnchecked(reg.fpu());
-        else
-            takeUnchecked(reg.gpr());
-    }
-
-    void take(Register reg) {
-        MOZ_ASSERT(has(reg));
-        takeUnchecked(reg);
-    }
-    void take(FloatRegister reg) {
-        MOZ_ASSERT(has(reg));
-        takeUnchecked(reg);
-    }
-    void take(AnyRegister reg) {
-        if (reg.isFloat())
-            take(reg.fpu());
-        else
-            take(reg.gpr());
-    }
-
-    Register getAnyGeneral() const {
-        return this->Parent::set_.gprs().getAny();
-    }
-    FloatRegister getAnyFloat() const {
-        return this->Parent::set_.fpus().getAny();
+        fpu_.add(reg);
     }
-
-    Register takeAnyGeneral() {
-        Register reg = getAnyGeneral();
-        take(reg);
-        return reg;
-    }
-    FloatRegister takeAnyFloat() {
-        FloatRegister reg = getAnyFloat();
-        take(reg);
-        return reg;
-    }
-    ValueOperand takeAnyValue() {
-#if defined(JS_NUNBOX32)
-        return ValueOperand(takeAnyGeneral(), takeAnyGeneral());
-#elif defined(JS_PUNBOX64)
-        return ValueOperand(takeAnyGeneral());
-#else
-#error "Bad architecture"
-#endif
+    void add(AnyRegister any) {
+        if (any.isFloat())
+            add(any.fpu());
+        else
+            add(any.gpr());
     }
-};
-
-
-// Interface which is common to all register set implementations. It overloads
-// |add|, |take| and |takeUnchecked| methods for types such as |ValueOperand|
-// and |TypedOrValueRegister|.
-template <class Accessors, typename Set>
-class CommonRegSet : public SpecializedRegSet<Accessors, Set>
-{
-    typedef SpecializedRegSet<Accessors, Set> Parent;
-
-  public:
-    DEFINE_ACCESSOR_CONSTRUCTORS_(CommonRegSet)
-
-    RegSet set() const {
-        return this->Parent::set_;
-    }
-    RegSet& set() {
-        return this->Parent::set_;
-    }
-
-    bool empty() const {
-        return this->Parent::set_.empty();
-    }
-
-    using Parent::add;
     void add(ValueOperand value) {
 #if defined(JS_NUNBOX32)
         add(value.payloadReg());
         add(value.typeReg());
 #elif defined(JS_PUNBOX64)
         add(value.valueReg());
 #else
 #error "Bad architecture"
 #endif
     }
     void add(TypedOrValueRegister reg) {
         if (reg.hasValue())
             add(reg.valueReg());
         else if (reg.hasTyped())
             add(reg.typedReg());
     }
+    void addUnchecked(Register reg) {
+        gpr_.addUnchecked(reg);
+    }
+    void addUnchecked(FloatRegister reg) {
+        fpu_.addUnchecked(reg);
+    }
+    void addUnchecked(AnyRegister any) {
+        if (any.isFloat())
+            addUnchecked(any.fpu());
+        else
+            addUnchecked(any.gpr());
+    }
+    void addAllAliasedUnchecked(const AnyRegister& reg) {
+        if (reg.isFloat())
+            fpu_.addAllAliasedUnchecked(reg.fpu());
+        else
+            gpr_.addAllAliasedUnchecked(reg.gpr());
+    }
 
-    using Parent::take;
-    void take(ValueOperand value) {
+
+    bool empty(bool floats) const {
+        return floats ? fpu_.empty() : gpr_.empty();
+    }
+    FloatRegister takeFloat() {
+        return fpu_.takeAny();
+    }
+    FloatRegister takeUnaliasedFloat() {
+        return fpu_.takeUnaliasedAny();
+    }
+    Register takeGeneral() {
+        return gpr_.takeAny();
+    }
+    Register takeUnaliasedGeneral() {
+        return gpr_.takeUnaliasedAny();
+    }
+    ValueOperand takeValueOperand() {
 #if defined(JS_NUNBOX32)
-        take(value.payloadReg());
-        take(value.typeReg());
+        return ValueOperand(takeGeneral(), takeGeneral());
 #elif defined(JS_PUNBOX64)
-        take(value.valueReg());
+        return ValueOperand(takeGeneral());
 #else
 #error "Bad architecture"
 #endif
     }
-    void take(TypedOrValueRegister reg) {
-        if (reg.hasValue())
-            take(reg.valueReg());
-        else if (reg.hasTyped())
-            take(reg.typedReg());
+    void take(AnyRegister reg) {
+        if (reg.isFloat())
+            fpu_.take(reg.fpu());
+        else
+            gpr_.take(reg.gpr());
+    }
+    void takeAllAliasedUnchecked(AnyRegister reg) {
+        if (reg.isFloat())
+            fpu_.takeAllAliasedUnchecked(reg.fpu());
+        else
+            gpr_.takeAllAliasedUnchecked(reg.gpr());
+    }
+    // This function is used by LinearScan to find a free register.
+    AnyRegister takeUnaliasedAny(bool isFloat) {
+        if (isFloat)
+            return AnyRegister(takeUnaliasedFloat());
+        return AnyRegister(takeUnaliasedGeneral());
+    }
+    void clear() {
+        gpr_.clear();
+        fpu_.clear();
+    }
+    MOZ_CONSTEXPR GeneralRegisterSet gprs() const {
+        return gpr_;
+    }
+    MOZ_CONSTEXPR FloatRegisterSet fpus() const {
+        return fpu_;
+    }
+    bool operator ==(const RegisterSet& other) const {
+        return other.gpr_ == gpr_ && other.fpu_ == fpu_;
     }
 
-    using Parent::takeUnchecked;
+    void takeUnchecked(Register reg) {
+        gpr_.takeUnchecked(reg);
+    }
+    void takeUnchecked(FloatRegister reg) {
+        fpu_.takeUnchecked(reg);
+    }
+    void takeUnchecked(AnyRegister reg) {
+        if (reg.isFloat())
+            fpu_.takeUnchecked(reg.fpu());
+        else
+            gpr_.takeUnchecked(reg.gpr());
+    }
     void takeUnchecked(ValueOperand value) {
-#if defined(JS_NUNBOX32)
-        takeUnchecked(value.payloadReg());
-        takeUnchecked(value.typeReg());
-#elif defined(JS_PUNBOX64)
-        takeUnchecked(value.valueReg());
-#else
-#error "Bad architecture"
-#endif
+        gpr_.takeUnchecked(value);
     }
     void takeUnchecked(TypedOrValueRegister reg) {
         if (reg.hasValue())
             takeUnchecked(reg.valueReg());
         else if (reg.hasTyped())
             takeUnchecked(reg.typedReg());
     }
 };
 
-
-// These classes do not provide any additional members, they only use their
-// constructors to forward to the common interface for all register sets.  The
-// only benefit of these classes is to provide user friendly names.
-template <typename Set>
-class LiveSet : public CommonRegSet<LiveSetAccessors<Set>, Set>
-{
-    typedef CommonRegSet<LiveSetAccessors<Set>, Set> Parent;
-
-  public:
-    DEFINE_ACCESSOR_CONSTRUCTORS_(LiveSet)
-};
-
-template <typename Set>
-class AllocatableSet : public CommonRegSet<AllocatableSetAccessors<Set>, Set>
-{
-    typedef CommonRegSet<AllocatableSetAccessors<Set>, Set> Parent;
-
-  public:
-    DEFINE_ACCESSOR_CONSTRUCTORS_(AllocatableSet)
-
-    LiveSet<Set> asLiveSet() const {
-        return LiveSet<Set>(this->set());
-    }
-};
-
-#define DEFINE_ACCESSOR_CONSTRUCTORS_FOR_REGISTERSET_(REGSET)               \
-    typedef Parent::RegSet  RegSet;                                         \
-    typedef Parent::RegType RegType;                                        \
-    typedef Parent::SetType SetType;                                        \
-                                                                            \
-    MOZ_CONSTEXPR_TMPL REGSET() : Parent() {}                               \
-    explicit MOZ_CONSTEXPR_TMPL REGSET(SetType) = delete;                   \
-    explicit MOZ_CONSTEXPR_TMPL REGSET(RegSet set) : Parent(set) {}         \
-    MOZ_CONSTEXPR_TMPL REGSET(GeneralRegisterSet gpr, FloatRegisterSet fpu) \
-      : Parent(RegisterSet(gpr, fpu))                                       \
-    {}                                                                      \
-    REGSET(REGSET<GeneralRegisterSet> gpr, REGSET<FloatRegisterSet> fpu)    \
-      : Parent(RegisterSet(gpr.set(), fpu.set()))                           \
-    {}
-
-template <>
-class LiveSet<RegisterSet>
-  : public CommonRegSet<LiveSetAccessors<RegisterSet>, RegisterSet>
-{
-    // Note: We have to provide a qualified name for LiveSetAccessors, as it is
-    // interpreted as being the specialized class name inherited from the parent
-    // class specialization.
-    typedef CommonRegSet<jit::LiveSetAccessors<RegisterSet>, RegisterSet> Parent;
-
-  public:
-    DEFINE_ACCESSOR_CONSTRUCTORS_FOR_REGISTERSET_(LiveSet)
-};
-
-template <>
-class AllocatableSet<RegisterSet>
-  : public CommonRegSet<AllocatableSetAccessors<RegisterSet>, RegisterSet>
-{
-    // Note: We have to provide a qualified name for AllocatableSetAccessors, as
-    // it is interpreted as being the specialized class name inherited from the
-    // parent class specialization.
-    typedef CommonRegSet<jit::AllocatableSetAccessors<RegisterSet>, RegisterSet> Parent;
-
-  public:
-    DEFINE_ACCESSOR_CONSTRUCTORS_FOR_REGISTERSET_(AllocatableSet)
-
-    LiveSet<RegisterSet> asLiveSet() const {
-        return LiveSet<RegisterSet>(this->set());
-    }
-};
-
-#undef DEFINE_ACCESSOR_CONSTRUCTORS_FOR_REGISTERSET_
-#undef DEFINE_ACCESSOR_CONSTRUCTORS_
-
-typedef AllocatableSet<GeneralRegisterSet> AllocatableGeneralRegisterSet;
-typedef AllocatableSet<FloatRegisterSet> AllocatableFloatRegisterSet;
-typedef AllocatableSet<RegisterSet> AllocatableRegisterSet;
-
-typedef LiveSet<GeneralRegisterSet> LiveGeneralRegisterSet;
-typedef LiveSet<FloatRegisterSet> LiveFloatRegisterSet;
-typedef LiveSet<RegisterSet> LiveRegisterSet;
-
 // iterates in whatever order happens to be convenient.
 // Use TypedRegisterBackwardIterator or TypedRegisterForwardIterator if a
 // specific order is required.
 template <typename T>
 class TypedRegisterIterator
 {
-    LiveSet<TypedRegisterSet<T>> regset_;
+    TypedRegisterSet<T> regset_;
 
   public:
     explicit TypedRegisterIterator(TypedRegisterSet<T> regset) : regset_(regset)
     { }
-    explicit TypedRegisterIterator(LiveSet<TypedRegisterSet<T>> regset) : regset_(regset)
-    { }
     TypedRegisterIterator(const TypedRegisterIterator& other) : regset_(other.regset_)
     { }
 
     bool more() const {
         return !regset_.empty();
     }
     TypedRegisterIterator<T> operator ++(int) {
         TypedRegisterIterator<T> old(*this);
@@ -1107,23 +758,21 @@ class TypedRegisterIterator
         return regset_.getAny();
     }
 };
 
 // iterates backwards, that is, rn to r0
 template <typename T>
 class TypedRegisterBackwardIterator
 {
-    LiveSet<TypedRegisterSet<T>> regset_;
+    TypedRegisterSet<T> regset_;
 
   public:
     explicit TypedRegisterBackwardIterator(TypedRegisterSet<T> regset) : regset_(regset)
     { }
-    explicit TypedRegisterBackwardIterator(LiveSet<TypedRegisterSet<T>> regset) : regset_(regset)
-    { }
     TypedRegisterBackwardIterator(const TypedRegisterBackwardIterator& other)
       : regset_(other.regset_)
     { }
 
     bool more() const {
         return !regset_.empty();
     }
     TypedRegisterBackwardIterator<T> operator ++(int) {
@@ -1139,23 +788,21 @@ class TypedRegisterBackwardIterator
         return regset_.getLast();
     }
 };
 
 // iterates forwards, that is r0 to rn
 template <typename T>
 class TypedRegisterForwardIterator
 {
-    LiveSet<TypedRegisterSet<T>> regset_;
+    TypedRegisterSet<T> regset_;
 
   public:
     explicit TypedRegisterForwardIterator(TypedRegisterSet<T> regset) : regset_(regset)
     { }
-    explicit TypedRegisterForwardIterator(LiveSet<TypedRegisterSet<T>> regset) : regset_(regset)
-    { }
     TypedRegisterForwardIterator(const TypedRegisterForwardIterator& other) : regset_(other.regset_)
     { }
 
     bool more() const {
         return !regset_.empty();
     }
     TypedRegisterForwardIterator<T> operator ++(int) {
         TypedRegisterForwardIterator<T> old(*this);
@@ -1188,19 +835,16 @@ class AnyRegisterIterator
       : geniter_(GeneralRegisterSet::All()), floatiter_(FloatRegisterSet::All())
     { }
     AnyRegisterIterator(GeneralRegisterSet genset, FloatRegisterSet floatset)
       : geniter_(genset), floatiter_(floatset)
     { }
     explicit AnyRegisterIterator(const RegisterSet& set)
       : geniter_(set.gpr_), floatiter_(set.fpu_)
     { }
-    explicit AnyRegisterIterator(const LiveSet<RegisterSet>& set)
-      : geniter_(set.gprs()), floatiter_(set.fpus())
-    { }
     AnyRegisterIterator(const AnyRegisterIterator& other)
       : geniter_(other.geniter_), floatiter_(other.floatiter_)
     { }
     bool more() const {
         return geniter_.more() || floatiter_.more();
     }
     AnyRegisterIterator operator ++(int) {
         AnyRegisterIterator old(*this);
@@ -1243,20 +887,20 @@ class ABIArg
 
     bool argInRegister() const { return kind() != Stack; }
     AnyRegister reg() const { return kind_ == GPR ? AnyRegister(gpr()) : AnyRegister(fpu()); }
 };
 
 // Get the set of registers which should be saved by a block of code which
 // clobbers all registers besides |unused|, but does not clobber floating point
 // registers.
-inline LiveGeneralRegisterSet
-SavedNonVolatileRegisters(AllocatableGeneralRegisterSet unused)
+inline GeneralRegisterSet
+SavedNonVolatileRegisters(GeneralRegisterSet unused)
 {
-    LiveGeneralRegisterSet result;
+    GeneralRegisterSet result;
 
     for (GeneralRegisterIterator iter(GeneralRegisterSet::NonVolatile()); iter.more(); iter++) {
         Register reg = *iter;
         if (!unused.has(reg))
             result.add(reg);
     }
 
     // ARM and MIPS require an additional register to be saved, if calls can be made.
--- a/js/src/jit/Registers.h
+++ b/js/src/jit/Registers.h
@@ -68,21 +68,16 @@ struct Register {
 
     // N.B. FloatRegister is an explicit outparam here because msvc-2010
     // miscompiled it on win64 when the value was simply returned.  This
     // now has an explicit outparam for compatability.
     void aliased(uint32_t aliasIdx, Register* ret) const {
         MOZ_ASSERT(aliasIdx == 0);
         *ret = *this;
     }
-
-    SetType alignedOrDominatedAliasedSet() const {
-        return SetType(1) << code_;
-    }
-
     static uint32_t SetSize(SetType x) {
         return Codes::SetSize(x);
     }
     static uint32_t FirstBit(SetType x) {
         return Codes::FirstBit(x);
     }
     static uint32_t LastBit(SetType x) {
         return Codes::LastBit(x);
--- a/js/src/jit/Safepoints.cpp
+++ b/js/src/jit/Safepoints.cpp
@@ -83,21 +83,21 @@ ReadFloatRegisterMask(CompactBufferReade
     uint64_t ret = stream.readUnsigned();
     ret |= uint64_t(stream.readUnsigned()) << 32;
     return ret;
 }
 
 void
 SafepointWriter::writeGcRegs(LSafepoint* safepoint)
 {
-    LiveGeneralRegisterSet gc(safepoint->gcRegs());
-    LiveGeneralRegisterSet spilledGpr(safepoint->liveRegs().gprs());
-    LiveFloatRegisterSet spilledFloat(safepoint->liveRegs().fpus());
-    LiveGeneralRegisterSet slots(safepoint->slotsOrElementsRegs());
-    LiveGeneralRegisterSet valueRegs;
+    GeneralRegisterSet gc = safepoint->gcRegs();
+    GeneralRegisterSet spilledGpr = safepoint->liveRegs().gprs();
+    FloatRegisterSet spilledFloat = safepoint->liveRegs().fpus();
+    GeneralRegisterSet slots = safepoint->slotsOrElementsRegs();
+    GeneralRegisterSet valueRegs;
 
     WriteRegisterMask(stream_, spilledGpr.bits());
     if (!spilledGpr.empty()) {
         WriteRegisterMask(stream_, gc.bits());
         WriteRegisterMask(stream_, slots.bits());
 
 #ifdef JS_PUNBOX64
         valueRegs = safepoint->valueRegs();
--- a/js/src/jit/Safepoints.h
+++ b/js/src/jit/Safepoints.h
@@ -87,30 +87,30 @@ class SafepointReader
   public:
     SafepointReader(IonScript* script, const SafepointIndex* si);
 
     static CodeLocationLabel InvalidationPatchPoint(IonScript* script, const SafepointIndex* si);
 
     uint32_t osiCallPointOffset() const {
         return osiCallPointOffset_;
     }
-    LiveGeneralRegisterSet gcSpills() const {
-        return LiveGeneralRegisterSet(gcSpills_);
+    GeneralRegisterSet gcSpills() const {
+        return gcSpills_;
     }
-    LiveGeneralRegisterSet slotsOrElementsSpills() const {
-        return LiveGeneralRegisterSet(slotsOrElementsSpills_);
+    GeneralRegisterSet slotsOrElementsSpills() const {
+        return slotsOrElementsSpills_;
     }
-    LiveGeneralRegisterSet valueSpills() const {
-        return LiveGeneralRegisterSet(valueSpills_);
+    GeneralRegisterSet valueSpills() const {
+        return valueSpills_;
     }
-    LiveGeneralRegisterSet allGprSpills() const {
-        return LiveGeneralRegisterSet(allGprSpills_);
+    GeneralRegisterSet allGprSpills() const {
+        return allGprSpills_;
     }
-    LiveFloatRegisterSet allFloatSpills() const {
-        return LiveFloatRegisterSet(allFloatSpills_);
+    FloatRegisterSet allFloatSpills() const {
+        return allFloatSpills_;
     }
     uint32_t osiReturnPointOffset() const;
 
     // Returns true if a slot was read, false if there are no more slots.
     bool getGcSlot(SafepointSlotEntry* entry);
 
     // Returns true if a slot was read, false if there are no more value slots.
     bool getValueSlot(SafepointSlotEntry* entry);
--- a/js/src/jit/StupidAllocator.cpp
+++ b/js/src/jit/StupidAllocator.cpp
@@ -71,22 +71,22 @@ StupidAllocator::init()
 
             virtualRegisters[vreg] = def;
         }
     }
 
     // Assign physical registers to the tracked allocation.
     {
         registerCount = 0;
-        LiveRegisterSet remainingRegisters(allRegisters_.asLiveSet());
-        while (!remainingRegisters.emptyGeneral())
-            registers[registerCount++].reg = AnyRegister(remainingRegisters.takeAnyGeneral());
+        RegisterSet remainingRegisters(allRegisters_);
+        while (!remainingRegisters.empty(/* float = */ false))
+            registers[registerCount++].reg = AnyRegister(remainingRegisters.takeUnaliasedGeneral());
 
-        while (!remainingRegisters.emptyFloat())
-            registers[registerCount++].reg = AnyRegister(remainingRegisters.takeAnyFloat());
+        while (!remainingRegisters.empty(/* float = */ true))
+            registers[registerCount++].reg = AnyRegister(remainingRegisters.takeUnaliasedFloat());
 
         MOZ_ASSERT(registerCount <= MAX_REGISTERS);
     }
 
     return true;
 }
 
 bool
--- a/js/src/jit/arm/Architecture-arm.cpp
+++ b/js/src/jit/arm/Architecture-arm.cpp
@@ -342,31 +342,31 @@ FloatRegisters::FromName(const char* nam
     }
 
     return Invalid;
 }
 
 FloatRegisterSet
 VFPRegister::ReduceSetForPush(const FloatRegisterSet& s)
 {
-    LiveFloatRegisterSet mod;
-    for (FloatRegisterIterator iter(s); iter.more(); iter++) {
+    FloatRegisterSet mod;
+    for (TypedRegisterIterator<FloatRegister> iter(s); iter.more(); iter++) {
         if ((*iter).isSingle()) {
             // Add in just this float.
             mod.addUnchecked(*iter);
         } else if ((*iter).id() < 16) {
             // A double with an overlay, add in both floats.
             mod.addUnchecked((*iter).singleOverlay(0));
             mod.addUnchecked((*iter).singleOverlay(1));
         } else {
             // Add in the lone double in the range 16-31.
             mod.addUnchecked(*iter);
         }
     }
-    return mod.set();
+    return mod;
 }
 
 uint32_t
 VFPRegister::GetPushSizeInBytes(const FloatRegisterSet& s)
 {
     FloatRegisterSet ss = s.reduceSetForPush();
     uint64_t bits = ss.bits();
     uint32_t ret = mozilla::CountPopulation32(bits&0xffffffff) * sizeof(float);
--- a/js/src/jit/arm/Architecture-arm.h
+++ b/js/src/jit/arm/Architecture-arm.h
@@ -511,47 +511,17 @@ class VFPRegister
             MOZ_ASSERT(code_ < NumAliasedDoubles);
             *ret = singleOverlay(aliasIdx - 1);
             return;
         }
         MOZ_ASSERT((code_ & 1) == 0);
         *ret = doubleOverlay(aliasIdx - 1);
         return;
     }
-
     typedef FloatRegisters::SetType SetType;
-
-    // This function is used to ensure that Register set can take all Single
-    // registers, even if we are taking a mix of either double or single
-    // registers.
-    //
-    //   s0.alignedOrDominatedAliasedSet() == s0 | d0.
-    //   s1.alignedOrDominatedAliasedSet() == s1.
-    //   d0.alignedOrDominatedAliasedSet() == s0 | s1 | d0.
-    //
-    // This way the Allocator register set does not have to do any arithmetics
-    // to know if a register is available or not, as we have the following
-    // relations:
-    //
-    //   d0.alignedOrDominatedAliasedSet() ==
-    //       s0.alignedOrDominatedAliasedSet() | s1.alignedOrDominatedAliasedSet()
-    //
-    //   s0.alignedOrDominatedAliasedSet() & s1.alignedOrDominatedAliasedSet() == 0
-    //
-    SetType alignedOrDominatedAliasedSet() const {
-        if (isSingle()) {
-            if (code_ % 2 != 0)
-                return SetType(1) << code_;
-            return (SetType(1) << code_) | (SetType(1) << (32 + code_ / 2));
-        }
-
-        MOZ_ASSERT(isDouble());
-        return (SetType(0b11) << (code_ * 2)) | (SetType(1) << (32 + code_));
-    }
-
     static uint32_t SetSize(SetType x) {
         static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
         return mozilla::CountPopulation32(x);
     }
     static Code FromName(const char* name) {
         return FloatRegisters::FromName(name);
     }
     static TypedRegisterSet<VFPRegister> ReduceSetForPush(const TypedRegisterSet<VFPRegister>& s);
--- a/js/src/jit/arm/BaselineIC-arm.cpp
+++ b/js/src/jit/arm/BaselineIC-arm.cpp
@@ -81,18 +81,18 @@ ICBinaryArith_Int32::Compiler::generateS
     Label failure;
     masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
 
     // Add R0 and R1. Don't need to explicitly unbox, just use R2's payloadReg.
     Register scratchReg = R2.payloadReg();
 
     // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
-    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
-    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs.set());
+    GeneralRegisterSet savedRegs = availableGeneralRegs(2);
+    savedRegs = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs);
     ValueOperand savedValue = savedRegs.takeAnyValue();
 
     Label maybeNegZero, revertRegister;
     switch(op_) {
       case JSOP_ADD:
         masm.ma_add(R0.payloadReg(), R1.payloadReg(), scratchReg, SetCond);
 
         // Just jump to failure on overflow. R0 and R1 are preserved, so we can
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -5127,18 +5127,19 @@ MacroAssemblerARMCompat::asMasm() const
 {
     return *static_cast<const MacroAssembler*>(this);
 }
 
 // ===============================================================
 // Stack manipulation functions.
 
 void
-MacroAssembler::PushRegsInMask(LiveRegisterSet set)
-{
+MacroAssembler::PushRegsInMask(RegisterSet set, FloatRegisterSet simdSet)
+{
+    MOZ_ASSERT(!SupportsSimd() && simdSet.size() == 0);
     int32_t diffF = set.fpus().getPushSizeInBytes();
     int32_t diffG = set.gprs().size() * sizeof(intptr_t);
 
     if (set.gprs().size() > 1) {
         adjustFrame(diffG);
         startDataTransferM(IsStore, StackPointer, DB, WriteBack);
         for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
             diffG -= sizeof(intptr_t);
@@ -5155,41 +5156,42 @@ MacroAssembler::PushRegsInMask(LiveRegis
     MOZ_ASSERT(diffG == 0);
 
     adjustFrame(diffF);
     diffF += transferMultipleByRuns(set.fpus(), IsStore, StackPointer, DB);
     MOZ_ASSERT(diffF == 0);
 }
 
 void
-MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
-{
+MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore, FloatRegisterSet simdSet)
+{
+    MOZ_ASSERT(!SupportsSimd() && simdSet.size() == 0);
     int32_t diffG = set.gprs().size() * sizeof(intptr_t);
     int32_t diffF = set.fpus().getPushSizeInBytes();
     const int32_t reservedG = diffG;
     const int32_t reservedF = diffF;
 
     // ARM can load multiple registers at once, but only if we want back all
     // the registers we previously saved to the stack.
-    if (ignore.emptyFloat()) {
+    if (ignore.empty(true)) {
         diffF -= transferMultipleByRuns(set.fpus(), IsLoad, StackPointer, IA);
         adjustFrame(-reservedF);
     } else {
-        LiveFloatRegisterSet fpset(set.fpus().reduceSetForPush());
-        LiveFloatRegisterSet fpignore(ignore.fpus().reduceSetForPush());
+        TypedRegisterSet<VFPRegister> fpset = set.fpus().reduceSetForPush();
+        TypedRegisterSet<VFPRegister> fpignore = ignore.fpus().reduceSetForPush();
         for (FloatRegisterBackwardIterator iter(fpset); iter.more(); iter++) {
             diffF -= (*iter).size();
             if (!fpignore.has(*iter))
                 loadDouble(Address(StackPointer, diffF), *iter);
         }
         freeStack(reservedF);
     }
     MOZ_ASSERT(diffF == 0);
 
-    if (set.gprs().size() > 1 && ignore.emptyGeneral()) {
+    if (set.gprs().size() > 1 && ignore.empty(false)) {
         startDataTransferM(IsLoad, StackPointer, IA, WriteBack);
         for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
             diffG -= sizeof(intptr_t);
             transferReg(*iter);
         }
         finishDataTransfer();
         adjustFrame(-reservedG);
     } else {
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -200,17 +200,17 @@ JitRuntime::generateEnterJIT(JSContext* 
     masm.transferReg(r8);  // [sp',4] = descriptor, argc*8+20
     masm.transferReg(r9);  // [sp',8]  = callee token
     masm.transferReg(r10); // [sp',12]  = actual arguments
     masm.finishDataTransfer();
 
     Label returnLabel;
     if (type == EnterJitBaseline) {
         // Handle OSR.
-        AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+        GeneralRegisterSet regs(GeneralRegisterSet::All());
         regs.take(JSReturnOperand);
         regs.takeUnchecked(OsrFrameReg);
         regs.take(r11);
         regs.take(ReturnReg);
 
         const Address slot_numStackValues(r11, offsetof(EnterJITStack, numStackValues));
 
         Label notOsr;
@@ -720,17 +720,17 @@ JitRuntime::generateVMWrapper(JSContext*
     MOZ_ASSERT(functionWrappers_);
     MOZ_ASSERT(functionWrappers_->initialized());
     VMWrapperMap::AddPtr p = functionWrappers_->lookupForAdd(&f);
     if (p)
         return p->value();
 
     // Generate a separated code for the wrapper.
     MacroAssembler masm(cx);
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet(Register::Codes::WrapperMask));
+    GeneralRegisterSet regs = GeneralRegisterSet(Register::Codes::WrapperMask);
 
     // Wrapper register set is a superset of Volatile register set.
     JS_STATIC_ASSERT((Register::Codes::VolatileMask & ~Register::Codes::WrapperMask) == 0);
 
     // The context is the first argument; r0 is the first argument register.
     Register cxreg = r0;
     regs.take(cxreg);
 
@@ -899,23 +899,23 @@ JitRuntime::generateVMWrapper(JSContext*
     return wrapper;
 }
 
 JitCode*
 JitRuntime::generatePreBarrier(JSContext* cx, MIRType type)
 {
     MacroAssembler masm(cx);
 
-    LiveRegisterSet save;
+    RegisterSet save;
     if (cx->runtime()->jitSupportsFloatingPoint) {
-        save.set() = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
-                                 FloatRegisterSet(FloatRegisters::VolatileDoubleMask));
+        save = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
+                           FloatRegisterSet(FloatRegisters::VolatileDoubleMask));
     } else {
-        save.set() = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
-                                 FloatRegisterSet());
+        save = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
+                           FloatRegisterSet());
     }
     save.add(lr);
     masm.PushRegsInMask(save);
 
     MOZ_ASSERT(PreBarrierReg == r1);
     masm.movePtr(ImmPtr(cx->runtime()), r0);
 
     masm.setupUnalignedABICall(2, r2);
--- a/js/src/jit/mips/Architecture-mips.h
+++ b/js/src/jit/mips/Architecture-mips.h
@@ -485,25 +485,16 @@ class FloatRegister
         if (aliasIdx == 0) {
             *ret = *this;
             return;
         }
         MOZ_ASSERT(aliasIdx == 1);
         *ret = singleOverlay(aliasIdx - 1);
     }
     typedef FloatRegisters::SetType SetType;
-
-    SetType alignedOrDominatedAliasedSet() const {
-        if (isSingle())
-            return SetType(1) << code_;
-
-        MOZ_ASSERT(isDouble());
-        return SetType(0b11) << code_;
-    }
-
     static uint32_t SetSize(SetType x) {
         static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
         return mozilla::CountPopulation32(x);
     }
     static Code FromName(const char* name) {
         return FloatRegisters::FromName(name);
     }
     static TypedRegisterSet<FloatRegister> ReduceSetForPush(const TypedRegisterSet<FloatRegister>& s);
--- a/js/src/jit/mips/MacroAssembler-mips.cpp
+++ b/js/src/jit/mips/MacroAssembler-mips.cpp
@@ -3663,18 +3663,19 @@ MacroAssemblerMIPSCompat::asMasm() const
 {
     return *static_cast<const MacroAssembler*>(this);
 }
 
 // ===============================================================
 // Stack manipulation functions.
 
 void
-MacroAssembler::PushRegsInMask(LiveRegisterSet set)
-{
+MacroAssembler::PushRegsInMask(RegisterSet set, FloatRegisterSet simdSet)
+{
+    MOZ_ASSERT(!SupportsSimd() && simdSet.size() == 0);
     int32_t diffF = set.fpus().getPushSizeInBytes();
     int32_t diffG = set.gprs().size() * sizeof(intptr_t);
 
     reserveStack(diffG);
     for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
         diffG -= sizeof(intptr_t);
         storePtr(*iter, Address(StackPointer, diffG));
     }
@@ -3690,18 +3691,19 @@ MacroAssembler::PushRegsInMask(LiveRegis
         if ((*iter).code() % 2 == 0)
             as_sd(*iter, SecondScratchReg, -diffF);
         diffF -= sizeof(double);
     }
     MOZ_ASSERT(diffF == 0);
 }
 
 void
-MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
-{
+MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore, FloatRegisterSet simdSet)
+{
+    MOZ_ASSERT(!SupportsSimd() && simdSet.size() == 0);
     int32_t diffG = set.gprs().size() * sizeof(intptr_t);
     int32_t diffF = set.fpus().getPushSizeInBytes();
     const int32_t reservedG = diffG;
     const int32_t reservedF = diffF;
 
     // Read the buffer form the first aligned location.
     ma_addu(SecondScratchReg, sp, Imm32(reservedF + sizeof(double)));
     ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1)));
--- a/js/src/jit/none/Architecture-none.h
+++ b/js/src/jit/none/Architecture-none.h
@@ -118,17 +118,16 @@ struct FloatRegister
     bool operator == (FloatRegister) const { MOZ_CRASH(); }
     bool aliases(FloatRegister) const { MOZ_CRASH(); }
     uint32_t numAliased() const { MOZ_CRASH(); }
     void aliased(uint32_t, FloatRegister*) { MOZ_CRASH(); }
     bool equiv(FloatRegister) const { MOZ_CRASH(); }
     uint32_t size() const { MOZ_CRASH(); }
     uint32_t numAlignedAliased() const { MOZ_CRASH(); }
     void alignedAliased(uint32_t, FloatRegister*) { MOZ_CRASH(); }
-    SetType alignedOrDominatedAliasedSet() const { MOZ_CRASH(); }
     template <typename T> static T ReduceSetForPush(T) { MOZ_CRASH(); }
     uint32_t getRegisterDumpOffsetInBytes() { MOZ_CRASH(); }
     static uint32_t SetSize(SetType x) { MOZ_CRASH(); }
     static Code FromName(const char* name) { MOZ_CRASH(); }
 
     // This is used in static initializers, so produce a bogus value instead of crashing.
     static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>&) { return 0; }
 };
--- a/js/src/jit/none/Trampoline-none.cpp
+++ b/js/src/jit/none/Trampoline-none.cpp
@@ -54,18 +54,22 @@ bool ICCompare_Int32::Compiler::generate
 bool ICCompare_Double::Compiler::generateStubCode(MacroAssembler&) { MOZ_CRASH(); }
 bool ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler&) { MOZ_CRASH(); }
 bool ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler&) { MOZ_CRASH(); }
 JitCode* JitRuntime::generateProfilerExitFrameTailStub(JSContext*) { MOZ_CRASH(); }
 
 // ===============================================================
 // Stack manipulation functions.
 
-void MacroAssembler::PushRegsInMask(LiveRegisterSet) { MOZ_CRASH(); }
-void MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet, LiveRegisterSet) { MOZ_CRASH(); }
+void MacroAssembler::PushRegsInMask(RegisterSet set, FloatRegisterSet simdSet) { MOZ_CRASH(); }
+void MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore,
+                                         FloatRegisterSet simdSet)
+{
+    MOZ_CRASH();
+}
 
 void MacroAssembler::Push(Register reg) { MOZ_CRASH(); }
 void MacroAssembler::Push(const Imm32 imm) { MOZ_CRASH(); }
 void MacroAssembler::Push(const ImmWord imm) { MOZ_CRASH(); }
 void MacroAssembler::Push(const ImmPtr imm) { MOZ_CRASH(); }
 void MacroAssembler::Push(const ImmGCPtr ptr) { MOZ_CRASH(); }
 void MacroAssembler::Push(FloatRegister reg) { MOZ_CRASH(); }
 
--- a/js/src/jit/shared/Assembler-x86-shared.h
+++ b/js/src/jit/shared/Assembler-x86-shared.h
@@ -1048,18 +1048,18 @@ class AssemblerX86Shared : public Assemb
     }
     void cmpw(Register rhs, Register lhs) {
         masm.cmpw_rr(rhs.code(), lhs.code());
     }
     void setCC(Condition cond, Register r) {
         masm.setCC_r(static_cast<X86Encoding::Condition>(cond), r.code());
     }
     void testb(Register rhs, Register lhs) {
-        MOZ_ASSERT(AllocatableGeneralRegisterSet(Registers::SingleByteRegs).has(rhs));
-        MOZ_ASSERT(AllocatableGeneralRegisterSet(Registers::SingleByteRegs).has(lhs));
+        MOZ_ASSERT(GeneralRegisterSet(Registers::SingleByteRegs).has(rhs));
+        MOZ_ASSERT(GeneralRegisterSet(Registers::SingleByteRegs).has(lhs));
         masm.testb_rr(rhs.code(), lhs.code());
     }
     void testw(Register rhs, Register lhs) {
         masm.testw_rr(lhs.code(), rhs.code());
     }
     void testl(Register rhs, Register lhs) {
         masm.testl_rr(lhs.code(), rhs.code());
     }
--- a/js/src/jit/shared/CodeGenerator-shared-inl.h
+++ b/js/src/jit/shared/CodeGenerator-shared-inl.h
@@ -154,40 +154,38 @@ void
 CodeGeneratorShared::restoreLive(LInstruction* ins)
 {
     MOZ_ASSERT(!ins->isCall());
     LSafepoint* safepoint = ins->safepoint();
     masm.PopRegsInMask(safepoint->liveRegs());
 }
 
 void
-CodeGeneratorShared::restoreLiveIgnore(LInstruction* ins, LiveRegisterSet ignore)
+CodeGeneratorShared::restoreLiveIgnore(LInstruction* ins, RegisterSet ignore)
 {
     MOZ_ASSERT(!ins->isCall());
     LSafepoint* safepoint = ins->safepoint();
     masm.PopRegsInMaskIgnore(safepoint->liveRegs(), ignore);
 }
 
 void
 CodeGeneratorShared::saveLiveVolatile(LInstruction* ins)
 {
     MOZ_ASSERT(!ins->isCall());
     LSafepoint* safepoint = ins->safepoint();
-    LiveRegisterSet regs;
-    regs.set() = RegisterSet::Intersect(safepoint->liveRegs().set(), RegisterSet::Volatile());
+    RegisterSet regs = RegisterSet::Intersect(safepoint->liveRegs(), RegisterSet::Volatile());
     masm.PushRegsInMask(regs);
 }
 
 void
 CodeGeneratorShared::restoreLiveVolatile(LInstruction* ins)
 {
     MOZ_ASSERT(!ins->isCall());
     LSafepoint* safepoint = ins->safepoint();
-    LiveRegisterSet regs;
-    regs.set() = RegisterSet::Intersect(safepoint->liveRegs().set(), RegisterSet::Volatile());
+    RegisterSet regs = RegisterSet::Intersect(safepoint->liveRegs(), RegisterSet::Volatile());
     masm.PopRegsInMask(regs);
 }
 
 void
 CodeGeneratorShared::verifyHeapAccessDisassembly(uint32_t begin, uint32_t end, bool isLoad,
                                                  Scalar::Type type, unsigned numElems,
                                                  const Operand& mem, LAllocation alloc)
 {
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -1043,17 +1043,17 @@ CodeGeneratorShared::markOsiPoint(LOsiPo
     masm.propagateOOM(osiIndices_.append(OsiIndex(offset, so)));
 
     return offset;
 }
 
 #ifdef CHECK_OSIPOINT_REGISTERS
 template <class Op>
 static void
-HandleRegisterDump(Op op, MacroAssembler& masm, LiveRegisterSet liveRegs, Register activation,
+HandleRegisterDump(Op op, MacroAssembler& masm, RegisterSet liveRegs, Register activation,
                    Register scratch)
 {
     const size_t baseOffset = JitActivation::offsetOfRegs();
 
     // Handle live GPRs.
     for (GeneralRegisterIterator iter(liveRegs.gprs()); iter.more(); iter++) {
         Register reg = *iter;
         Address dump(activation, baseOffset + RegisterDump::offsetOfRegister(reg));
@@ -1102,24 +1102,24 @@ class StoreOp
             masm.storeUnalignedFloat32x4(reg, dump);
 #endif
         else
             MOZ_CRASH("Unexpected register type.");
     }
 };
 
 static void
-StoreAllLiveRegs(MacroAssembler& masm, LiveRegisterSet liveRegs)
+StoreAllLiveRegs(MacroAssembler& masm, RegisterSet liveRegs)
 {
     // Store a copy of all live registers before performing the call.
     // When we reach the OsiPoint, we can use this to check nothing
     // modified them in the meantime.
 
     // Load pointer to the JitActivation in a scratch register.
-    AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
+    GeneralRegisterSet allRegs(GeneralRegisterSet::All());
     Register scratch = allRegs.takeAny();
     masm.push(scratch);
     masm.loadJitActivation(scratch);
 
     Address checkRegs(scratch, JitActivation::offsetOfCheckRegs());
     masm.add32(Imm32(1), checkRegs);
 
     StoreOp op(masm);
@@ -1159,17 +1159,17 @@ class VerifyOp
 
 void
 CodeGeneratorShared::verifyOsiPointRegs(LSafepoint* safepoint)
 {
     // Ensure the live registers stored by callVM did not change between
     // the call and this OsiPoint. Try-catch relies on this invariant.
 
     // Load pointer to the JitActivation in a scratch register.
-    AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
+    GeneralRegisterSet allRegs(GeneralRegisterSet::All());
     Register scratch = allRegs.takeAny();
     masm.push(scratch);
     masm.loadJitActivation(scratch);
 
     // If we should not check registers (because the instruction did not call
     // into the VM, or a GC happened), we're done.
     Label failure, done;
     Address checkRegs(scratch, JitActivation::offsetOfCheckRegs());
@@ -1186,19 +1186,18 @@ CodeGeneratorShared::verifyOsiPointRegs(
     // return from this script to the caller.
     masm.store32(Imm32(0), checkRegs);
 
     // Ignore clobbered registers. Some instructions (like LValueToInt32) modify
     // temps after calling into the VM. This is fine because no other
     // instructions (including this OsiPoint) will depend on them. Also
     // backtracking can also use the same register for an input and an output.
     // These are marked as clobbered and shouldn't get checked.
-    LiveRegisterSet liveRegs;
-    liveRegs.set() = RegisterSet::Intersect(safepoint->liveRegs().set(),
-                                            RegisterSet::Not(safepoint->clobberedRegs().set()));
+    RegisterSet liveRegs = safepoint->liveRegs();
+    liveRegs = RegisterSet::Intersect(liveRegs, RegisterSet::Not(safepoint->clobberedRegs()));
 
     VerifyOp op(masm, &failure);
     HandleRegisterDump<VerifyOp>(op, masm, liveRegs, scratch, allRegs.getAny());
 
     masm.jump(&done);
 
     // Do not profile the callWithABI that occurs below.  This is to avoid a
     // rare corner case that occurs when profiling interacts with itself:
@@ -1226,31 +1225,31 @@ CodeGeneratorShared::verifyOsiPointRegs(
 }
 
 bool
 CodeGeneratorShared::shouldVerifyOsiPointRegs(LSafepoint* safepoint)
 {
     if (!checkOsiPointRegisters)
         return false;
 
-    if (safepoint->liveRegs().emptyGeneral() && safepoint->liveRegs().emptyFloat())
+    if (safepoint->liveRegs().empty(true) && safepoint->liveRegs().empty(false))
         return false; // No registers to check.
 
     return true;
 }
 
 void
 CodeGeneratorShared::resetOsiPointRegs(LSafepoint* safepoint)
 {
     if (!shouldVerifyOsiPointRegs(safepoint))
         return;
 
     // Set checkRegs to 0. If we perform a VM call, the instruction
     // will set it to 1.
-    AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
+    GeneralRegisterSet allRegs(GeneralRegisterSet::All());
     Register scratch = allRegs.takeAny();
     masm.push(scratch);
     masm.loadJitActivation(scratch);
     Address checkRegs(scratch, JitActivation::offsetOfCheckRegs());
     masm.store32(Imm32(0), checkRegs);
     masm.pop(scratch);
 }
 #endif
@@ -1641,19 +1640,19 @@ CodeGeneratorShared::computeDivisionCons
 void
 CodeGeneratorShared::emitTracelogScript(bool isStart)
 {
     if (!TraceLogTextIdEnabled(TraceLogger_Scripts))
         return;
 
     Label done;
 
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    Register logger = regs.takeAnyGeneral();
-    Register script = regs.takeAnyGeneral();
+    RegisterSet regs = RegisterSet::Volatile();
+    Register logger = regs.takeGeneral();
+    Register script = regs.takeGeneral();
 
     masm.Push(logger);
 
     CodeOffsetLabel patchLogger = masm.movWithPatch(ImmPtr(nullptr), logger);
     masm.propagateOOM(patchableTraceLoggers_.append(patchLogger));
 
     Address enabledAddress(logger, TraceLoggerThread::offsetOfEnabled());
     masm.branch32(Assembler::Equal, enabledAddress, Imm32(0), &done);
@@ -1677,18 +1676,18 @@ CodeGeneratorShared::emitTracelogScript(
 
 void
 CodeGeneratorShared::emitTracelogTree(bool isStart, uint32_t textId)
 {
     if (!TraceLogTextIdEnabled(textId))
         return;
 
     Label done;
-    AllocatableRegisterSet regs(RegisterSet::Volatile());
-    Register logger = regs.takeAnyGeneral();
+    RegisterSet regs = RegisterSet::Volatile();
+    Register logger = regs.takeGeneral();
 
     masm.Push(logger);
 
     CodeOffsetLabel patchLocation = masm.movWithPatch(ImmPtr(nullptr), logger);
     masm.propagateOOM(patchableTraceLoggers_.append(patchLocation));
 
     Address enabledAddress(logger, TraceLoggerThread::offsetOfEnabled());
     masm.branch32(Assembler::Equal, enabledAddress, Imm32(0), &done);
--- a/js/src/jit/shared/CodeGenerator-shared.h
+++ b/js/src/jit/shared/CodeGenerator-shared.h
@@ -402,55 +402,55 @@ class CodeGeneratorShared : public LElem
     // after storing the function call's return value to an output register.
     // (The only registers that don't need to be saved/restored are 1) the
     // temporary register used to store the return value of the function call,
     // if there is one [otherwise that stored value would be overwritten]; and
     // 2) temporary registers whose values aren't needed in the rest of the LIR
     // instruction [this is purely an optimization].  All other volatiles must
     // be saved and restored in case future LIR instructions need those values.)
     void saveVolatile(Register output) {
-        LiveRegisterSet regs(RegisterSet::Volatile());
+        RegisterSet regs = RegisterSet::Volatile();
         regs.takeUnchecked(output);
         masm.PushRegsInMask(regs);
     }
     void restoreVolatile(Register output) {
-        LiveRegisterSet regs(RegisterSet::Volatile());
+        RegisterSet regs = RegisterSet::Volatile();
         regs.takeUnchecked(output);
         masm.PopRegsInMask(regs);
     }
     void saveVolatile(FloatRegister output) {
-        LiveRegisterSet regs(RegisterSet::Volatile());
+        RegisterSet regs = RegisterSet::Volatile();
         regs.takeUnchecked(output);
         masm.PushRegsInMask(regs);
     }
     void restoreVolatile(FloatRegister output) {
-        LiveRegisterSet regs(RegisterSet::Volatile());
+        RegisterSet regs = RegisterSet::Volatile();
         regs.takeUnchecked(output);
         masm.PopRegsInMask(regs);
     }
-    void saveVolatile(LiveRegisterSet temps) {
-        masm.PushRegsInMask(LiveRegisterSet(RegisterSet::VolatileNot(temps.set())));
+    void saveVolatile(RegisterSet temps) {
+        masm.PushRegsInMask(RegisterSet::VolatileNot(temps));
     }
-    void restoreVolatile(LiveRegisterSet temps) {
-        masm.PopRegsInMask(LiveRegisterSet(RegisterSet::VolatileNot(temps.set())));
+    void restoreVolatile(RegisterSet temps) {
+        masm.PopRegsInMask(RegisterSet::VolatileNot(temps));
     }
     void saveVolatile() {
-        masm.PushRegsInMask(LiveRegisterSet(RegisterSet::Volatile()));
+        masm.PushRegsInMask(RegisterSet::Volatile());
     }
     void restoreVolatile() {
-        masm.PopRegsInMask(LiveRegisterSet(RegisterSet::Volatile()));
+        masm.PopRegsInMask(RegisterSet::Volatile());
     }
 
     // These functions have to be called before and after any callVM and before
     // any modifications of the stack.  Modification of the stack made after
     // these calls should update the framePushed variable, needed by the exit
     // frame produced by callVM.
     inline void saveLive(LInstruction* ins);
     inline void restoreLive(LInstruction* ins);
-    inline void restoreLiveIgnore(LInstruction* ins, LiveRegisterSet reg);
+    inline void restoreLiveIgnore(LInstruction* ins, RegisterSet reg);
 
     // Save/restore all registers that are both live and volatile.
     inline void saveLiveVolatile(LInstruction* ins);
     inline void restoreLiveVolatile(LInstruction* ins);
 
     template <typename T>
     void pushArg(const T& t) {
         masm.Push(t);
@@ -678,36 +678,36 @@ ArgList()
 }
 
 // Store wrappers, to generate the right move of data after the VM call.
 
 struct StoreNothing
 {
     inline void generate(CodeGeneratorShared* codegen) const {
     }
-    inline LiveRegisterSet clobbered() const {
-        return LiveRegisterSet(); // No register gets clobbered
+    inline RegisterSet clobbered() const {
+        return RegisterSet(); // No register gets clobbered
     }
 };
 
 class StoreRegisterTo
 {
   private:
     Register out_;
 
   public:
     explicit StoreRegisterTo(Register out)
       : out_(out)
     { }
 
     inline void generate(CodeGeneratorShared* codegen) const {
         codegen->storeResultTo(out_);
     }
-    inline LiveRegisterSet clobbered() const {
-        LiveRegisterSet set;
+    inline RegisterSet clobbered() const {
+        RegisterSet set = RegisterSet();
         set.add(out_);
         return set;
     }
 };
 
 class StoreFloatRegisterTo
 {
   private:
@@ -716,18 +716,18 @@ class StoreFloatRegisterTo
   public:
     explicit StoreFloatRegisterTo(FloatRegister out)
       : out_(out)
     { }
 
     inline void generate(CodeGeneratorShared* codegen) const {
         codegen->storeFloatResultTo(out_);
     }
-    inline LiveRegisterSet clobbered() const {
-        LiveRegisterSet set;
+    inline RegisterSet clobbered() const {
+        RegisterSet set = RegisterSet();
         set.add(out_);
         return set;
     }
 };
 
 template <typename Output>
 class StoreValueTo_
 {
@@ -737,18 +737,18 @@ class StoreValueTo_
   public:
     explicit StoreValueTo_(const Output& out)
       : out_(out)
     { }
 
     inline void generate(CodeGeneratorShared* codegen) const {
         codegen->storeResultValueTo(out_);
     }
-    inline LiveRegisterSet clobbered() const {
-        LiveRegisterSet set;
+    inline RegisterSet clobbered() const {
+        RegisterSet set = RegisterSet();
         set.add(out_);
         return set;
     }
 };
 
 template <typename Output>
 StoreValueTo_<Output> StoreValueTo(const Output& out)
 {
--- a/js/src/jit/shared/MacroAssembler-x86-shared.cpp
+++ b/js/src/jit/shared/MacroAssembler-x86-shared.cpp
@@ -174,95 +174,116 @@ MacroAssemblerX86Shared::asMasm() const
 {
     return *static_cast<const MacroAssembler*>(this);
 }
 
 // ===============================================================
 // Stack manipulation functions.
 
 void
-MacroAssembler::PushRegsInMask(LiveRegisterSet set)
+MacroAssembler::PushRegsInMask(RegisterSet set, FloatRegisterSet simdSet)
 {
-    FloatRegisterSet fpuSet(set.fpus().reduceSetForPush());
-    unsigned numFpu = fpuSet.size();
-    int32_t diffF = fpuSet.getPushSizeInBytes();
+    FloatRegisterSet doubleSet(FloatRegisterSet::Subtract(set.fpus(), simdSet));
+    MOZ_ASSERT_IF(simdSet.empty(), doubleSet == set.fpus());
+    doubleSet = doubleSet.reduceSetForPush();
+    unsigned numSimd = simdSet.size();
+    unsigned numDouble = doubleSet.size();
+    int32_t diffF = doubleSet.getPushSizeInBytes() + numSimd * Simd128DataSize;
     int32_t diffG = set.gprs().size() * sizeof(intptr_t);
 
     // On x86, always use push to push the integer registers, as it's fast
     // on modern hardware and it's a small instruction.
     for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
         diffG -= sizeof(intptr_t);
         Push(*iter);
     }
     MOZ_ASSERT(diffG == 0);
 
     reserveStack(diffF);
-    for (FloatRegisterBackwardIterator iter(fpuSet); iter.more(); iter++) {
+    for (FloatRegisterBackwardIterator iter(doubleSet); iter.more(); iter++) {
         FloatRegister reg = *iter;
         diffF -= reg.size();
-        numFpu -= 1;
+        numDouble -= 1;
         Address spillAddress(StackPointer, diffF);
         if (reg.isDouble())
             storeDouble(reg, spillAddress);
         else if (reg.isSingle())
             storeFloat32(reg, spillAddress);
         else if (reg.isInt32x4())
             storeUnalignedInt32x4(reg, spillAddress);
         else if (reg.isFloat32x4())
             storeUnalignedFloat32x4(reg, spillAddress);
         else
             MOZ_CRASH("Unknown register type.");
     }
-    MOZ_ASSERT(numFpu == 0);
+    MOZ_ASSERT(numDouble == 0);
+    for (FloatRegisterBackwardIterator iter(simdSet); iter.more(); iter++) {
+        diffF -= Simd128DataSize;
+        numSimd -= 1;
+        // XXX how to choose the right move type?
+        storeUnalignedInt32x4(*iter, Address(StackPointer, diffF));
+    }
+    MOZ_ASSERT(numSimd == 0);
     // x64 padding to keep the stack aligned on uintptr_t. Keep in sync with
     // GetPushBytesInSize.
     diffF -= diffF % sizeof(uintptr_t);
     MOZ_ASSERT(diffF == 0);
 }
 
 void
-MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
+MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore, FloatRegisterSet simdSet)
 {
-    FloatRegisterSet fpuSet(set.fpus().reduceSetForPush());
-    unsigned numFpu = fpuSet.size();
+    FloatRegisterSet doubleSet(FloatRegisterSet::Subtract(set.fpus(), simdSet));
+    MOZ_ASSERT_IF(simdSet.empty(), doubleSet == set.fpus());
+    doubleSet = doubleSet.reduceSetForPush();
+    unsigned numSimd = simdSet.size();
+    unsigned numDouble = doubleSet.size();
     int32_t diffG = set.gprs().size() * sizeof(intptr_t);
-    int32_t diffF = fpuSet.getPushSizeInBytes();
+    int32_t diffF = doubleSet.getPushSizeInBytes() + numSimd * Simd128DataSize;
     const int32_t reservedG = diffG;
     const int32_t reservedF = diffF;
 
-    for (FloatRegisterBackwardIterator iter(fpuSet); iter.more(); iter++) {
+    for (FloatRegisterBackwardIterator iter(simdSet); iter.more(); iter++) {
+        diffF -= Simd128DataSize;
+        numSimd -= 1;
+        if (!ignore.has(*iter))
+            // XXX how to choose the right move type?
+            loadUnalignedInt32x4(Address(StackPointer, diffF), *iter);
+    }
+    MOZ_ASSERT(numSimd == 0);
+    for (FloatRegisterBackwardIterator iter(doubleSet); iter.more(); iter++) {
         FloatRegister reg = *iter;
         diffF -= reg.size();
-        numFpu -= 1;
+        numDouble -= 1;
         if (ignore.has(reg))
             continue;
 
         Address spillAddress(StackPointer, diffF);
         if (reg.isDouble())
             loadDouble(spillAddress, reg);
         else if (reg.isSingle())
             loadFloat32(spillAddress, reg);
         else if (reg.isInt32x4())
             loadUnalignedInt32x4(spillAddress, reg);
         else if (reg.isFloat32x4())
             loadUnalignedFloat32x4(spillAddress, reg);
         else
             MOZ_CRASH("Unknown register type.");
     }
     freeStack(reservedF);
-    MOZ_ASSERT(numFpu == 0);
+    MOZ_ASSERT(numDouble == 0);
     // x64 padding to keep the stack aligned on uintptr_t. Keep in sync with
     // GetPushBytesInSize.
     diffF -= diffF % sizeof(uintptr_t);
     MOZ_ASSERT(diffF == 0);
 
     // On x86, use pop to pop the integer registers, if we're not going to
     // ignore any slots, as it's fast on modern hardware and it's a small
     // instruction.
-    if (ignore.emptyGeneral()) {
+    if (ignore.empty(false)) {
         for (GeneralRegisterForwardIterator iter(set.gprs()); iter.more(); iter++) {
             diffG -= sizeof(intptr_t);
             Pop(*iter);
         }
     } else {
         for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
             diffG -= sizeof(intptr_t);
             if (!ignore.has(*iter))
--- a/js/src/jit/shared/MacroAssembler-x86-shared.h
+++ b/js/src/jit/shared/MacroAssembler-x86-shared.h
@@ -12,26 +12,26 @@
 
 #if defined(JS_CODEGEN_X86)
 # include "jit/x86/Assembler-x86.h"
 #elif defined(JS_CODEGEN_X64)
 # include "jit/x64/Assembler-x64.h"
 #endif
 
 #ifdef DEBUG
-  #define CHECK_BYTEREG(reg)                                               \
-      JS_BEGIN_MACRO                                                       \
-        AllocatableGeneralRegisterSet byteRegs(Registers::SingleByteRegs); \
-        MOZ_ASSERT(byteRegs.has(reg));                                     \
+  #define CHECK_BYTEREG(reg)                                    \
+      JS_BEGIN_MACRO                                            \
+        GeneralRegisterSet byteRegs(Registers::SingleByteRegs); \
+        MOZ_ASSERT(byteRegs.has(reg));                          \
       JS_END_MACRO
-  #define CHECK_BYTEREGS(r1, r2)                                           \
-      JS_BEGIN_MACRO                                                       \
-        AllocatableGeneralRegisterSet byteRegs(Registers::SingleByteRegs); \
-        MOZ_ASSERT(byteRegs.has(r1));                                      \
-        MOZ_ASSERT(byteRegs.has(r2));                                      \
+  #define CHECK_BYTEREGS(r1, r2)                                \
+      JS_BEGIN_MACRO                                            \
+        GeneralRegisterSet byteRegs(Registers::SingleByteRegs); \
+        MOZ_ASSERT(byteRegs.has(r1));                           \
+        MOZ_ASSERT(byteRegs.has(r2));                           \
       JS_END_MACRO
 #else
   #define CHECK_BYTEREG(reg) (void)0
   #define CHECK_BYTEREGS(r1, r2) (void)0
 #endif
 
 namespace js {
 namespace jit {
@@ -723,17 +723,17 @@ class MacroAssemblerX86Shared : public A
         Register original_;
         Register substitute_;
 
       public:
         template <typename T>
         AutoEnsureByteRegister(MacroAssemblerX86Shared* masm, T address, Register reg)
           : masm(masm), original_(reg)
         {
-            AllocatableGeneralRegisterSet singleByteRegs(Registers::SingleByteRegs);
+            GeneralRegisterSet singleByteRegs(Registers::SingleByteRegs);
             if (singleByteRegs.has(reg)) {
                 substitute_ = reg;
             } else {
                 MOZ_ASSERT(address.base != StackPointer);
                 do {
                     substitute_ = singleByteRegs.takeAny();
                 } while (Operand(address).containsReg(substitute_));
 
@@ -1392,17 +1392,17 @@ class MacroAssemblerX86Shared : public A
     void convertBoolToInt32(Register source, Register dest) {
         // Note that C++ bool is only 1 byte, so zero extend it to clear the
         // higher-order bits.
         movzbl(source, dest);
     }
 
     void emitSet(Assembler::Condition cond, Register dest,
                  Assembler::NaNCond ifNaN = Assembler::NaN_HandledByCond) {
-        if (AllocatableGeneralRegisterSet(Registers::SingleByteRegs).has(dest)) {
+        if (GeneralRegisterSet(Registers::SingleByteRegs).has(dest)) {
             // If the register we're defining is a single byte register,
             // take advantage of the setCC instruction
             setCC(cond, dest);
             movzbl(dest, dest);
 
             if (ifNaN != Assembler::NaN_HandledByCond) {
                 Label noNaN;
                 j(Assembler::NoParity, &noNaN);
--- a/js/src/jit/x64/Architecture-x64.h
+++ b/js/src/jit/x64/Architecture-x64.h
@@ -330,20 +330,16 @@ struct FloatRegister {
     void aliased(uint32_t aliasIdx, FloatRegister* ret) const {
         MOZ_ASSERT(aliasIdx < Codes::NumTypes);
         *ret = FloatRegister(reg_, Codes::ContentType((aliasIdx + type_) % Codes::NumTypes));
     }
     void alignedAliased(uint32_t aliasIdx, FloatRegister* ret) const {
         aliased(aliasIdx, ret);
     }
 
-    SetType alignedOrDominatedAliasedSet() const {
-        return Codes::Spread << reg_;
-    }
-
     static TypedRegisterSet<FloatRegister> ReduceSetForPush(const TypedRegisterSet<FloatRegister>& s);
     static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>& s);
     uint32_t getRegisterDumpOffsetInBytes();
 };
 
 // Arm/D32 has double registers that can NOT be treated as float32
 // and this requires some dances in lowering.
 inline bool
--- a/js/src/jit/x64/Assembler-x64.cpp
+++ b/js/src/jit/x64/Assembler-x64.cpp
@@ -302,32 +302,22 @@ Assembler::TraceJumpRelocations(JSTracer
         MarkJitCodeUnbarriered(trc, &child, "rel32");
         MOZ_ASSERT(child == CodeFromJump(code, code->raw() + iter.offset()));
     }
 }
 
 FloatRegisterSet
 FloatRegister::ReduceSetForPush(const FloatRegisterSet& s)
 {
-    SetType bits = s.bits();
-
-    // Ignore all SIMD register, if not supported.
-    if (!JitSupportsSimd())
-        bits &= Codes::AllPhysMask * Codes::SpreadScalar;
+    if (JitSupportsSimd())
+        return s;
 
-    // Exclude registers which are already pushed with a larger type. High bits
-    // are associated with larger register types. Thus we keep the set of
-    // registers which are not included in larger type.
-    bits &= ~(bits >> (1 * Codes::TotalPhys));
-    bits &= ~(bits >> (2 * Codes::TotalPhys));
-    bits &= ~(bits >> (3 * Codes::TotalPhys));
-
-    return FloatRegisterSet(bits);
+    // Ignore all SIMD register.
+    return FloatRegisterSet(s.bits() & (Codes::AllPhysMask * Codes::SpreadScalar));
 }
-
 uint32_t
 FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s)
 {
     SetType all = s.bits();
     SetType float32x4Set =
         (all >> (uint32_t(Codes::Float32x4) * Codes::TotalPhys)) & Codes::AllPhysMask;
     SetType int32x4Set =
         (all >> (uint32_t(Codes::Int32x4) * Codes::TotalPhys)) & Codes::AllPhysMask;
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -14,19 +14,19 @@
 #include "jit/VMFunctions.h"
 #include "jit/x64/BaselineHelpers-x64.h"
 
 using namespace js;
 using namespace js::jit;
 
 // All registers to save and restore. This includes the stack pointer, since we
 // use the ability to reference register values on the stack by index.
-static const LiveRegisterSet AllRegs =
-    LiveRegisterSet(GeneralRegisterSet(Registers::AllMask),
-                         FloatRegisterSet(FloatRegisters::AllMask));
+static const RegisterSet AllRegs =
+  RegisterSet(GeneralRegisterSet(Registers::AllMask),
+              FloatRegisterSet(FloatRegisters::AllMask));
 
 // Generates a trampoline for calling Jit compiled code from a C++ function.
 // The trampoline use the EnterJitCode signature, with the standard x64 fastcall
 // calling convention.
 JitCode*
 JitRuntime::generateEnterJIT(JSContext* cx, EnterJitType type)
 {
     MacroAssembler masm(cx);
@@ -145,17 +145,17 @@ JitRuntime::generateEnterJIT(JSContext* 
 
     // Create a frame descriptor.
     masm.makeFrameDescriptor(r14, JitFrame_Entry);
     masm.push(r14);
 
     CodeLabel returnLabel;
     if (type == EnterJitBaseline) {
         // Handle OSR.
-        AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+        GeneralRegisterSet regs(GeneralRegisterSet::All());
         regs.takeUnchecked(OsrFrameReg);
         regs.take(rbp);
         regs.take(reg_code);
 
         // Ensure that |scratch| does not end up being JSReturnOperand.
         // Do takeUnchecked because on Win64/x64, reg_code (IntArgReg0) and JSReturnOperand are
         // the same (rcx).  See bug 849398.
         regs.takeUnchecked(JSReturnOperand);
@@ -511,21 +511,22 @@ PushBailoutFrame(MacroAssembler& masm, R
     if (JitSupportsSimd()) {
         masm.PushRegsInMask(AllRegs);
     } else {
         // When SIMD isn't supported, PushRegsInMask reduces the set of float
         // registers to be double-sized, while the RegisterDump expects each of
         // the float registers to have the maximal possible size
         // (Simd128DataSize). To work around this, we just spill the double
         // registers by hand here, using the register dump offset directly.
-        for (GeneralRegisterBackwardIterator iter(AllRegs.gprs()); iter.more(); iter++)
+        RegisterSet set = AllRegs;
+        for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++)
             masm.Push(*iter);
 
         masm.reserveStack(sizeof(RegisterDump::FPUArray));
-        for (FloatRegisterBackwardIterator iter(AllRegs.fpus()); iter.more(); iter++) {
+        for (FloatRegisterBackwardIterator iter(set.fpus()); iter.more(); iter++) {
             FloatRegister reg = *iter;
             Address spillAddress(StackPointer, reg.getRegisterDumpOffsetInBytes());
             masm.storeDouble(reg, spillAddress);
         }
     }
 
     // Get the stack pointer into a register, pre-alignment.
     masm.movq(rsp, spArg);
@@ -596,17 +597,17 @@ JitRuntime::generateVMWrapper(JSContext*
     if (p)
         return p->value();
 
     // Generate a separated code for the wrapper.
     MacroAssembler masm;
 
     // Avoid conflicts with argument registers while discarding the result after
     // the function call.
-    AllocatableGeneralRegisterSet regs(Register::Codes::WrapperMask);
+    GeneralRegisterSet regs = GeneralRegisterSet(Register::Codes::WrapperMask);
 
     // Wrapper register set is a superset of Volatile register set.
     JS_STATIC_ASSERT((Register::Codes::VolatileMask & ~Register::Codes::WrapperMask) == 0);
 
     // The context is the first argument.
     Register cxreg = IntArgReg0;
     regs.take(cxreg);
 
@@ -771,19 +772,18 @@ JitRuntime::generateVMWrapper(JSContext*
     return wrapper;
 }
 
 JitCode*
 JitRuntime::generatePreBarrier(JSContext* cx, MIRType type)
 {
     MacroAssembler masm;
 
-    LiveRegisterSet regs =
-        LiveRegisterSet(GeneralRegisterSet(Registers::VolatileMask),
-                             FloatRegisterSet(FloatRegisters::VolatileMask));
+    RegisterSet regs = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
+                                   FloatRegisterSet(FloatRegisters::VolatileMask));
     masm.PushRegsInMask(regs);
 
     MOZ_ASSERT(PreBarrierReg == rdx);
     masm.mov(ImmPtr(cx->runtime()), rcx);
 
     masm.setupUnalignedABICall(2, rax);
     masm.passABIArg(rcx);
     masm.passABIArg(rdx);
--- a/js/src/jit/x86/Architecture-x86.h
+++ b/js/src/jit/x86/Architecture-x86.h
@@ -303,20 +303,16 @@ struct FloatRegister {
     void aliased(uint32_t aliasIdx, FloatRegister* ret) const {
         MOZ_ASSERT(aliasIdx < Codes::NumTypes);
         *ret = FloatRegister(reg_, Codes::ContentType((aliasIdx + type_) % Codes::NumTypes));
     }
     void alignedAliased(uint32_t aliasIdx, FloatRegister* ret) const {
         aliased(aliasIdx, ret);
     }
 
-    SetType alignedOrDominatedAliasedSet() const {
-        return Codes::Spread << reg_;
-    }
-
     static TypedRegisterSet<FloatRegister> ReduceSetForPush(const TypedRegisterSet<FloatRegister>& s);
     static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>& s);
     uint32_t getRegisterDumpOffsetInBytes();
 };
 
 // Arm/D32 has double registers that can NOT be treated as float32
 // and this requires some dances in lowering.
 inline bool
--- a/js/src/jit/x86/Assembler-x86.cpp
+++ b/js/src/jit/x86/Assembler-x86.cpp
@@ -100,32 +100,22 @@ Assembler::TraceJumpRelocations(JSTracer
         MarkJitCodeUnbarriered(trc, &child, "rel32");
         MOZ_ASSERT(child == CodeFromJump(code->raw() + iter.offset()));
     }
 }
 
 FloatRegisterSet
 FloatRegister::ReduceSetForPush(const FloatRegisterSet& s)
 {
-    SetType bits = s.bits();
-
-    // Ignore all SIMD register, if not supported.
-    if (!JitSupportsSimd())
-        bits &= Codes::AllPhysMask * Codes::SpreadScalar;
+    if (JitSupportsSimd())
+        return s;
 
-    // Exclude registers which are already pushed with a larger type. High bits
-    // are associated with larger register types. Thus we keep the set of
-    // registers which are not included in larger type.
-    bits &= ~(bits >> (1 * Codes::TotalPhys));
-    bits &= ~(bits >> (2 * Codes::TotalPhys));
-    bits &= ~(bits >> (3 * Codes::TotalPhys));
-
-    return FloatRegisterSet(bits);
+    // Ignore all SIMD register.
+    return FloatRegisterSet(s.bits() & (Codes::AllPhysMask * Codes::SpreadScalar));
 }
-
 uint32_t
 FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s)
 {
     SetType all = s.bits();
     SetType float32x4Set =
         (all >> (uint32_t(Codes::Float32x4) * Codes::TotalPhys)) & Codes::AllPhysMask;
     SetType int32x4Set =
         (all >> (uint32_t(Codes::Int32x4) * Codes::TotalPhys)) & Codes::AllPhysMask;
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -20,19 +20,19 @@
 
 #include "jsscriptinlines.h"
 
 using namespace js;
 using namespace js::jit;
 
 // All registers to save and restore. This includes the stack pointer, since we
 // use the ability to reference register values on the stack by index.
-static const LiveRegisterSet AllRegs =
-  LiveRegisterSet(GeneralRegisterSet(Registers::AllMask),
-                       FloatRegisterSet(FloatRegisters::AllMask));
+static const RegisterSet AllRegs =
+  RegisterSet(GeneralRegisterSet(Registers::AllMask),
+              FloatRegisterSet(FloatRegisters::AllMask));
 
 enum EnterJitEbpArgumentOffset {
     ARG_JITCODE         = 2 * sizeof(void*),
     ARG_ARGC            = 3 * sizeof(void*),
     ARG_ARGV            = 4 * sizeof(void*),
     ARG_STACKFRAME      = 5 * sizeof(void*),
     ARG_CALLEETOKEN     = 6 * sizeof(void*),
     ARG_SCOPECHAIN      = 7 * sizeof(void*),
@@ -137,17 +137,17 @@ JitRuntime::generateEnterJIT(JSContext* 
     // Create a frame descriptor.
     masm.subl(esp, esi);
     masm.makeFrameDescriptor(esi, JitFrame_Entry);
     masm.push(esi);
 
     CodeLabel returnLabel;
     if (type == EnterJitBaseline) {
         // Handle OSR.
-        AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+        GeneralRegisterSet regs(GeneralRegisterSet::All());
         regs.take(JSReturnOperand);
         regs.takeUnchecked(OsrFrameReg);
         regs.take(ebp);
         regs.take(ReturnReg);
 
         Register scratch = regs.takeAny();
 
         Label notOsr;
@@ -505,21 +505,22 @@ PushBailoutFrame(MacroAssembler& masm, u
     if (JitSupportsSimd()) {
         masm.PushRegsInMask(AllRegs);
     } else {
         // When SIMD isn't supported, PushRegsInMask reduces the set of float
         // registers to be double-sized, while the RegisterDump expects each of
         // the float registers to have the maximal possible size
         // (Simd128DataSize). To work around this, we just spill the double
         // registers by hand here, using the register dump offset directly.
-        for (GeneralRegisterBackwardIterator iter(AllRegs.gprs()); iter.more(); iter++)
+        RegisterSet set = AllRegs;
+        for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++)
             masm.Push(*iter);
 
         masm.reserveStack(sizeof(RegisterDump::FPUArray));
-        for (FloatRegisterBackwardIterator iter(AllRegs.fpus()); iter.more(); iter++) {
+        for (FloatRegisterBackwardIterator iter(set.fpus()); iter.more(); iter++) {
             FloatRegister reg = *iter;
             Address spillAddress(StackPointer, reg.getRegisterDumpOffsetInBytes());
             masm.storeDouble(reg, spillAddress);
         }
     }
 
     // Push the bailout table number.
     masm.push(Imm32(frameClass));
@@ -622,17 +623,17 @@ JitRuntime::generateVMWrapper(JSContext*
     if (p)
         return p->value();
 
     // Generate a separated code for the wrapper.
     MacroAssembler masm;
 
     // Avoid conflicts with argument registers while discarding the result after
     // the function call.
-    AllocatableGeneralRegisterSet regs(Register::Codes::WrapperMask);
+    GeneralRegisterSet regs = GeneralRegisterSet(Register::Codes::WrapperMask);
 
     // Wrapper register set is a superset of Volatile register set.
     JS_STATIC_ASSERT((Register::Codes::VolatileMask & ~Register::Codes::WrapperMask) == 0);
 
     // The context is the first argument.
     Register cxreg = regs.takeAny();
 
     // Stack is:
@@ -792,23 +793,23 @@ JitRuntime::generateVMWrapper(JSContext*
     return wrapper;
 }
 
 JitCode*
 JitRuntime::generatePreBarrier(JSContext* cx, MIRType type)
 {
     MacroAssembler masm;
 
-    LiveRegisterSet save;
+    RegisterSet save;
     if (cx->runtime()->jitSupportsFloatingPoint) {
-        save.set() = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
-                                 FloatRegisterSet(FloatRegisters::VolatileMask));
+        save = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
+                           FloatRegisterSet(FloatRegisters::VolatileMask));
     } else {
-        save.set() = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
-                                 FloatRegisterSet());
+        save = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
+                           FloatRegisterSet());
     }
     masm.PushRegsInMask(save);
 
     MOZ_ASSERT(PreBarrierReg == edx);
     masm.movl(ImmPtr(cx->runtime()), ecx);
 
     masm.setupUnalignedABICall(2, eax);
     masm.passABIArg(ecx);
--- a/js/src/jsapi-tests/moz.build
+++ b/js/src/jsapi-tests/moz.build
@@ -90,17 +90,16 @@ UNIFIED_SOURCES += [
 if CONFIG['ENABLE_ION']:
     UNIFIED_SOURCES += [
         'testJitDCEinGVN.cpp',
         'testJitFoldsTo.cpp',
         'testJitGVN.cpp',
         'testJitMoveEmitterCycles-mips.cpp',
         'testJitMoveEmitterCycles.cpp',
         'testJitRangeAnalysis.cpp',
-        'testJitRegisterSet.cpp',
         'testJitRValueAlloc.cpp',
     ]
 
 DEFINES['EXPORT_JS_API'] = True
 # Building against js_static requires that we declare mfbt sybols "exported"
 # on its behalf.
 DEFINES['IMPL_MFBT'] = True
 
deleted file mode 100644
--- a/js/src/jsapi-tests/testJitRegisterSet.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- */
-/* 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 "jit/RegisterSets.h"
-
-#include "jsapi-tests/tests.h"
-
-using namespace js;
-using namespace js::jit;
-
-static bool
-CoPrime(size_t a, size_t b)
-{
-    if (b <= 1)
-        return a == 1 || b == 1;
-    return CoPrime(b, a % b);
-}
-
-// This macros are use to iterave over all registers in a large number of
-// non-looping sequences, which does not rely on the getFirst / getLast
-// functions.
-#define BEGIN_INDEX_WALK(RegTotal)                          \
-    static const size_t Total = RegTotal;                   \
-    for (size_t walk = 1; walk < RegTotal; walk += 2) {     \
-        if (!CoPrime(RegTotal, walk))                       \
-            continue;                                       \
-        for (size_t start = 0; start < RegTotal; start++) { \
-            size_t index = start;
-
-#define END_INDEX_WALK                                      \
-        }                                                   \
-    }
-
-#define FOR_ALL_REGISTERS(Register, reg)            \
-    do {                                            \
-        Register reg = Register::FromCode(index);
-
-#define END_FOR_ALL_REGISTERS                    \
-        index = (index + walk) % Total;          \
-    } while(index != start)
-
-BEGIN_TEST(testJitRegisterSet_GPR)
-{
-    BEGIN_INDEX_WALK(Registers::Total)
-
-    LiveGeneralRegisterSet liveRegs;
-    AllocatableGeneralRegisterSet pool(GeneralRegisterSet::All());
-    CHECK(liveRegs.empty());
-    CHECK(pool.set() == GeneralRegisterSet::All());
-
-    FOR_ALL_REGISTERS(Register, reg) {
-
-        CHECK(!pool.has(reg) || !liveRegs.has(reg));
-        if (pool.has(reg)) {
-            CHECK(!liveRegs.has(reg));
-            pool.take(reg);
-            liveRegs.add(reg);
-            CHECK(liveRegs.has(reg));
-            CHECK(!pool.has(reg));
-        }
-        CHECK(!pool.has(reg) || !liveRegs.has(reg));
-
-    } END_FOR_ALL_REGISTERS;
-
-    CHECK(pool.empty());
-
-    FOR_ALL_REGISTERS(Register, reg) {
-
-        CHECK(!pool.has(reg) || !liveRegs.has(reg));
-        if (liveRegs.has(reg)) {
-            CHECK(!pool.has(reg));
-            liveRegs.take(reg);
-            pool.add(reg);
-            CHECK(pool.has(reg));
-            CHECK(!liveRegs.has(reg));
-        }
-        CHECK(!pool.has(reg) || !liveRegs.has(reg));
-
-    } END_FOR_ALL_REGISTERS;
-
-    CHECK(liveRegs.empty());
-    CHECK(pool.set() == GeneralRegisterSet::All());
-
-    END_INDEX_WALK
-    return true;
-}
-END_TEST(testJitRegisterSet_GPR)
-
-BEGIN_TEST(testJitRegisterSet_FPU)
-{
-    BEGIN_INDEX_WALK(FloatRegisters::Total)
-
-    LiveFloatRegisterSet liveRegs;
-    AllocatableFloatRegisterSet pool(FloatRegisterSet::All());
-    CHECK(liveRegs.empty());
-    CHECK(pool.set() == FloatRegisterSet::All());
-
-    FOR_ALL_REGISTERS(FloatRegister, reg) {
-
-        CHECK(!pool.has(reg) || !liveRegs.has(reg));
-        if (pool.has(reg)) {
-            CHECK(!liveRegs.has(reg));
-            pool.take(reg);
-            liveRegs.add(reg);
-            CHECK(liveRegs.has(reg));
-            CHECK(!pool.has(reg));
-        }
-        CHECK(!pool.has(reg) || !liveRegs.has(reg));
-
-    } END_FOR_ALL_REGISTERS;
-
-    CHECK(pool.empty());
-
-    FOR_ALL_REGISTERS(FloatRegister, reg) {
-
-        CHECK(!pool.has(reg) || !liveRegs.has(reg));
-        if (liveRegs.has(reg)) {
-            CHECK(!pool.has(reg));
-            liveRegs.take(reg);
-            pool.add(reg);
-            CHECK(pool.has(reg));
-            CHECK(!liveRegs.has(reg));
-        }
-        CHECK(!pool.has(reg) || !liveRegs.has(reg));
-
-    } END_FOR_ALL_REGISTERS;
-
-    CHECK(liveRegs.empty());
-    CHECK(pool.set() == FloatRegisterSet::All());
-
-    END_INDEX_WALK
-    return true;
-}
-END_TEST(testJitRegisterSet_FPU)
--- a/js/src/vm/UnboxedObject.cpp
+++ b/js/src/vm/UnboxedObject.cpp
@@ -95,22 +95,22 @@ UnboxedLayout::makeConstructorCode(JSCon
 #else
     propertiesReg = IntArgReg0;
     newKindReg = IntArgReg1;
 #endif
 
     MOZ_ASSERT(propertiesReg.volatile_());
     MOZ_ASSERT(newKindReg.volatile_());
 
-    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    GeneralRegisterSet regs(GeneralRegisterSet::All());
     regs.take(propertiesReg);
     regs.take(newKindReg);
     Register object = regs.takeAny(), scratch1 = regs.takeAny(), scratch2 = regs.takeAny();
 
-    LiveGeneralRegisterSet savedNonVolatileRegisters = SavedNonVolatileRegisters(regs);
+    GeneralRegisterSet savedNonVolatileRegisters = SavedNonVolatileRegisters(regs);
     for (GeneralRegisterForwardIterator iter(savedNonVolatileRegisters); iter.more(); ++iter)
         masm.Push(*iter);
 
     Label failure, tenuredObject, allocated;
     masm.branch32(Assembler::NotEqual, newKindReg, Imm32(GenericObject), &tenuredObject);
     masm.branchTest32(Assembler::NonZero, AbsoluteAddress(group->addressOfFlags()),
                       Imm32(OBJECT_FLAG_PRE_TENURE), &tenuredObject);
 
--- a/mfbt/Attributes.h
+++ b/mfbt/Attributes.h
@@ -79,21 +79,18 @@
 #  if __has_attribute(noinline)
 #    define MOZ_HAVE_NEVER_INLINE        __attribute__((noinline))
 #  endif
 #  if __has_attribute(noreturn)
 #    define MOZ_HAVE_NORETURN            __attribute__((noreturn))
 #  endif
 #elif defined(__GNUC__)
 #  if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
-#    define MOZ_HAVE_CXX11_CONSTEXPR
-#    if MOZ_GCC_VERSION_AT_LEAST(4, 8, 0)
-#      define MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
-#    endif
-#    define MOZ_HAVE_EXPLICIT_CONVERSION
+#      define MOZ_HAVE_CXX11_CONSTEXPR
+#      define MOZ_HAVE_EXPLICIT_CONVERSION
 #  endif
 #  define MOZ_HAVE_NEVER_INLINE          __attribute__((noinline))
 #  define MOZ_HAVE_NORETURN              __attribute__((noreturn))
 #endif
 
 /*
  * When built with clang analyzer (a.k.a scan-build), define MOZ_HAVE_NORETURN
  * to mark some false positives
@@ -112,25 +109,19 @@
  * value may be computed at compile time.  It should be prefered to just
  * marking variables as MOZ_CONSTEXPR because if the compiler does not support
  * constexpr it will fall back to making the variable const, and some compilers
  * do not accept variables being marked both const and constexpr.
  */
 #ifdef MOZ_HAVE_CXX11_CONSTEXPR
 #  define MOZ_CONSTEXPR         constexpr
 #  define MOZ_CONSTEXPR_VAR     constexpr
-#  ifdef MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES
-#    define MOZ_CONSTEXPR_TMPL  constexpr
-#  else
-#    define MOZ_CONSTEXPR_TMPL
-#  endif
 #else
 #  define MOZ_CONSTEXPR         /* no support */
 #  define MOZ_CONSTEXPR_VAR     const
-#  define MOZ_CONSTEXPR_TMPL
 #endif
 
 /*
  * MOZ_EXPLICIT_CONVERSION is a specifier on a type conversion
  * overloaded operator that declares that a C++11 compiler should restrict
  * this operator to allow only explicit type conversions, disallowing
  * implicit conversions.
  *