Back out 5 changesets (bug 774364, bug 1195578) for SM(p) OOMs
authorPhil Ringnalda <philringnalda@gmail.com>
Thu, 10 Sep 2015 13:48:35 -0700
changeset 296180 91f4cc676c0a748d513a26b8689553dbf2033653
parent 296179 f11cf71a5ccad575161d0208044aef25199c7823
child 296181 ba1fb46745fba671a113888120d88ed9bd6e7ab7
push id962
push userjlund@mozilla.com
push dateFri, 04 Dec 2015 23:28:54 +0000
treeherdermozilla-release@23a2d286e80f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs774364, 1195578
milestone43.0a1
backs out1739b4d8202c6a1f17338112a413a999f9b82eff
4ed0c752ce47dab0affd2b3da58d008a9283e7b9
174b80f07d0cc911824b2a8c4dca744130423ab2
2a20dd7465827a0e64abb9b72628c3e5786ed5fc
a36d8aa117c42ec45cc361a3d550a7a0e0afa4a2
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Back out 5 changesets (bug 774364, bug 1195578) for SM(p) OOMs Backed out changeset 1739b4d8202c (bug 774364) Backed out changeset 4ed0c752ce47 (bug 774364) Backed out changeset 174b80f07d0c (bug 774364) Backed out changeset 2a20dd746582 (bug 774364) Backed out changeset a36d8aa117c4 (bug 1195578)
js/src/builtin/TestingFunctions.cpp
js/src/frontend/Parser.cpp
js/src/frontend/TokenStream.h
js/src/jit-test/tests/basic/math-random.js
js/src/jit-test/tests/parser/arrow-with-block.js
js/src/jit/CodeGenerator.cpp
js/src/jit/CodeGenerator.h
js/src/jit/Registers.h
js/src/jit/arm/CodeGenerator-arm.cpp
js/src/jit/arm/CodeGenerator-arm.h
js/src/jit/arm/LIR-arm.h
js/src/jit/arm/Lowering-arm.cpp
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/arm64/CodeGenerator-arm64.cpp
js/src/jit/arm64/CodeGenerator-arm64.h
js/src/jit/arm64/LIR-arm64.h
js/src/jit/arm64/Lowering-arm64.cpp
js/src/jit/arm64/MacroAssembler-arm64.h
js/src/jit/mips32/CodeGenerator-mips32.cpp
js/src/jit/mips32/CodeGenerator-mips32.h
js/src/jit/mips32/LIR-mips32.h
js/src/jit/mips32/Lowering-mips32.cpp
js/src/jit/mips32/MacroAssembler-mips32.cpp
js/src/jit/mips32/MacroAssembler-mips32.h
js/src/jit/none/CodeGenerator-none.h
js/src/jit/none/LIR-none.h
js/src/jit/none/Lowering-none.h
js/src/jit/shared/Assembler-shared.h
js/src/jit/shared/LIR-shared.h
js/src/jit/x64/BaseAssembler-x64.h
js/src/jit/x64/CodeGenerator-x64.cpp
js/src/jit/x64/CodeGenerator-x64.h
js/src/jit/x64/LIR-x64.h
js/src/jit/x64/Lowering-x64.cpp
js/src/jit/x64/MacroAssembler-x64.h
js/src/jit/x86-shared/Assembler-x86-shared.h
js/src/jit/x86-shared/BaseAssembler-x86-shared.h
js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
js/src/jit/x86-shared/CodeGenerator-x86-shared.h
js/src/jit/x86-shared/Encoding-x86-shared.h
js/src/jit/x86/Assembler-x86.h
js/src/jit/x86/BaseAssembler-x86.h
js/src/jit/x86/CodeGenerator-x86.cpp
js/src/jit/x86/CodeGenerator-x86.h
js/src/jit/x86/LIR-x86.h
js/src/jit/x86/Lowering-x86.cpp
js/src/jit/x86/MacroAssembler-x86.cpp
js/src/jit/x86/MacroAssembler-x86.h
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2756,33 +2756,16 @@ GetLcovInfo(JSContext* cx, unsigned argc
 
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
-#ifdef DEBUG
-static bool
-SetRNGState(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    if (!args.requireAtLeast(cx, "SetRNGState", 1))
-        return false;
-
-    double seed;
-    if (!ToNumber(cx, args[0], &seed))
-        return false;
-
-    cx->compartment()->rngState = static_cast<uint64_t>(seed) & RNG_MASK;
-    return true;
-}
-#endif
-
 static const JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'compartment' [, 'shrinking'])",
 "  Run the garbage collector. When obj is given, GC only its compartment.\n"
 "  If 'compartment' is given, GC any compartments that were scheduled for\n"
 "  GC via schedulegc.\n"
 "  If 'shrinking' is passed as the optional second argument, perform a\n"
 "  shrinking GC rather than a normal GC."),
@@ -3220,22 +3203,16 @@ gc::ZealModeHelpText),
 "  On non-ARM, no-op. On ARM, set the hardware capabilities. The list of \n"
 "  flags is available by calling this function with \"help\" as the flag's name"),
 
     JS_FN_HELP("getLcovInfo", GetLcovInfo, 1, 0,
 "getLcovInfo(global)",
 "  Generate LCOV tracefile for the given compartment.  If no global are provided then\n"
 "  the current global is used as the default one.\n"),
 
-#ifdef DEBUG
-    JS_FN_HELP("setRNGState", SetRNGState, 1, 0,
-"setRNGState(seed)",
-"  Set this compartment's RNG state.\n"),
-#endif
-
     JS_FS_HELP_END
 };
 
 static const JSPropertySpec TestingProperties[] = {
     JS_PSG("timesAccessed", TimesAccessed, 0),
     JS_PS_END
 };
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -7070,71 +7070,31 @@ Parser<ParseHandler>::assignExpr(InHandl
         // A line terminator between ArrowParameters and the => should trigger a SyntaxError.
         tokenStream.ungetToken();
         TokenKind next;
         if (!tokenStream.peekTokenSameLine(&next) || next != TOK_ARROW) {
             report(ParseError, false, null(), JSMSG_UNEXPECTED_TOKEN,
                    "expression", TokenKindToDesc(TOK_ARROW));
             return null();
         }
-        tokenStream.consumeKnownToken(TOK_ARROW);
-
-        bool isBlock = false;
-        if (!tokenStream.peekToken(&next, TokenStream::Operand))
-            return null();
-        if (next == TOK_LC)
-            isBlock = true;
 
         tokenStream.seek(start);
         if (!abortIfSyntaxParser())
             return null();
 
         TokenKind ignored;
         if (!tokenStream.peekToken(&ignored, TokenStream::Operand))
             return null();
 
         if (pc->sc->isFunctionBox() && pc->sc->asFunctionBox()->isDerivedClassConstructor()) {
             report(ParseError, false, null(), JSMSG_DISABLED_DERIVED_CLASS, "arrow functions");
             return null();
         }
 
-        Node arrowFunc = functionDef(inHandling, yieldHandling, nullptr, Arrow, NotGenerator);
-        if (!arrowFunc)
-            return null();
-
-        if (isBlock) {
-            // This arrow function could be a non-trailing member of a comma
-            // expression or a semicolon terminating a full expression.  If so,
-            // the next token is that comma/semicolon, gotten with None:
-            //
-            //   a => {}, b; // as if (a => {}), b;
-            //   a => {};
-            //
-            // But if this arrow function ends a statement, ASI permits the
-            // next token to start an expression statement.  In that case the
-            // next token must be gotten as Operand:
-            //
-            //   a => {} // complete expression statement
-            //   /x/g;   // regular expression as a statement, *not* division
-            //
-            // Getting the second case right requires the first token-peek
-            // after the arrow function use Operand, and that peek must occur
-            // before Parser::expr() looks for a comma.  Do so here, then
-            // immediately add the modifier exception needed for the first
-            // case.
-            //
-            // Note that the second case occurs *only* if the arrow function
-            // has block body.  An arrow function not ending in such, ends in
-            // another AssignmentExpression that we can inductively assume was
-            // peeked consistently.
-            if (!tokenStream.peekToken(&ignored, TokenStream::Operand))
-                return null();
-            tokenStream.addModifierException(TokenStream::NoneIsOperand);
-        }
-        return arrowFunc;
+        return functionDef(inHandling, yieldHandling, nullptr, Arrow, NotGenerator);
       }
 
       default:
         MOZ_ASSERT(!tokenStream.isCurrentTokenAssignment());
         tokenStream.ungetToken();
         return lhs;
     }
 
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -116,38 +116,24 @@ struct Token
         //   var s = `Hello ${entity}!`;
         //                          ^ TemplateTail context
         TemplateTail,
     };
     enum ModifierException
     {
         NoException,
 
-        // Used in following 2 cases:
-        // a) After |yield| we look for a token on the same line that starts an
+        // After |yield| we look for a token on the same line that starts an
         // expression (Operand): |yield <expr>|.  If no token is found, the
         // |yield| stands alone, and the next token on a subsequent line must
         // be: a comma continuing a comma expression, a semicolon terminating
         // the statement that ended with |yield|, or the start of another
         // statement (possibly an expression statement).  The comma/semicolon
         // cases are gotten as operators (None), contrasting with Operand
         // earlier.
-        // b) After an arrow function with a block body in an expression
-        // statement, the next token must be: a colon in a conditional
-        // expression, a comma continuing a comma expression, a semicolon
-        // terminating the statement, or the token on a subsequent line that is
-        // the start of another statement (possibly an expression statement).
-        // Colon is gotten as operator (None), and it should only be gotten in
-        // conditional expression and missing it results in SyntaxError.
-        // Comma/semicolon cases are also gotten as operators (None), and 4th
-        // case is gotten after them.  If no comma/semicolon found but EOL,
-        // the next token should be gotten as operand in 4th case (especially if
-        // '/' is the first character).  So we should peek the token as
-        // operand before try getting colon/comma/semicolon.
-        // See also the comment in Parser::assignExpr().
         NoneIsOperand,
 
         // If a semicolon is inserted automatically, the next token is already
         // gotten with None, but we expect Operand.
         OperandIsNone,
 
         // If name of method definition is `get` or `set`, the next token is
         // already gotten with KeywordIsName, but we expect None.
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/math-random.js
+++ /dev/null
@@ -1,44 +0,0 @@
-function test() {
-  // With this seed, state won't be reset in 10000 iteration.  The result is
-  // deterministic and it can be used to check the correctness of
-  // implementation.
-  setRNGState(0x12341234);
-
-  function f() {
-    let x = [];
-    for (let i = 0; i < 10000; i++)  {
-      x.push(Math.random());
-    }
-    return x;
-  }
-  let x = f();
-  assertEq(x[0], 0.3562073961260165);
-  assertEq(x[10], 0.9777930699941514);
-  assertEq(x[100], 0.9146259915430884);
-  assertEq(x[1000], 0.315983055288946);
-  assertEq(x[2000], 0.7132284805929497);
-  assertEq(x[3000], 0.9621073641614717);
-  assertEq(x[4000], 0.3928228025111996);
-  assertEq(x[5000], 0.555710685962832);
-  assertEq(x[6000], 0.5207553912782503);
-  assertEq(x[7000], 0.08268413491723015);
-  assertEq(x[8000], 0.031796243723989925);
-  assertEq(x[9000], 0.900683320457098);
-  assertEq(x[9999], 0.7750389203054577);
-
-  // With this seed, state will be reset before calculating high bits.
-  // The result is nondeterministic, but it should be in [0, 1) range.
-  setRNGState(0);
-  x = f();
-  assertEq(x[0] >= 0 && x[0] < 1, true);
-
-  // With this seed, high bits will be 0 and state will be reset before
-  // calculating low bits.  The result is also nondeterministic, but it should
-  // be in [0, 1 / (1 << 26)) range.
-  setRNGState(0x615c0e462aa9);
-  x = f();
-  assertEq(x[0] >= 0 && x[0] < 1 / (1 << 26), true);
-}
-
-if (typeof setRNGState == "function")
-  test();
deleted file mode 100644
--- a/js/src/jit-test/tests/parser/arrow-with-block.js
+++ /dev/null
@@ -1,92 +0,0 @@
-load(libdir + "asserts.js");
-
-let x = 10;
-let g = 4;
-
-assertEq(eval(`
-a => {}
-/x/g;
-`).toString(), "/x/g");
-assertEq(eval(`
-a => {}
-/x/;
-`).toString(), "/x/");
-assertThrowsInstanceOf(() => eval(`
-a => {} /x/g;
-`), SyntaxError);
-
-assertEq(eval(`
-a => {},
-/x/;
-`).toString(), "/x/");
-assertEq(eval(`
-a => {}
-,
-/x/;
-`).toString(), "/x/");
-
-assertEq(eval(`
-false ?
-a => {} :
-/x/;
-`).toString(), "/x/");
-assertEq(eval(`
-false ?
-a => {}
-:
-/x/;
-`).toString(), "/x/");
-
-assertEq(eval(`
-a => {};
-/x/;
-`).toString(), "/x/");
-assertEq(eval(`
-a => {}
-;
-/x/;
-`).toString(), "/x/");
-
-assertEq(eval(`
-a => 200
-/x/g;
-`) instanceof Function, true);
-assertEq(eval(`
-a => 200
-/x/g;
-`)(), 5);
-assertEq(eval(`
-a => 200 /x/g;
-`)(), 5);
-
-assertEq(eval(`
-a => 1,
-/x/;
-`).toString(), "/x/");
-assertEq(eval(`
-a => 1
-,
-/x/;
-`).toString(), "/x/");
-
-assertEq(eval(`
-false ?
-a => 1 :
-/x/;
-`).toString(), "/x/");
-assertEq(eval(`
-false ?
-a => 1
-:
-/x/;
-`).toString(), "/x/");
-
-assertEq(eval(`
-a => 1;
-/x/;
-`).toString(), "/x/");
-assertEq(eval(`
-a => 1
-;
-/x/;
-`).toString(), "/x/");
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -10327,133 +10327,10 @@ CodeGenerator::visitNewTarget(LNewTarget
     masm.bind(&actualArgsSufficient);
 
     BaseValueIndex newTarget(masm.getStackPointer(), argvLen, frameSize() + JitFrameLayout::offsetOfActualArgs());
     masm.loadValue(newTarget, output);
 
     masm.bind(&done);
 }
 
-// Out-of-line math_random_no_outparam call for LRandom.
-class OutOfLineRandom : public OutOfLineCodeBase<CodeGenerator>
-{
-    LRandom* lir_;
-
-  public:
-    explicit OutOfLineRandom(LRandom* lir)
-      : lir_(lir)
-    { }
-
-    void accept(CodeGenerator* codegen) {
-        codegen->visitOutOfLineRandom(this);
-    }
-
-    LRandom* lir() const {
-        return lir_;
-    }
-};
-
-static const uint64_t RNG_HIGH_MASK = (0xFFFFFFFFFFFFFFFFULL >>
-                                       (RNG_STATE_WIDTH - RNG_HIGH_BITS)) << RNG_LOW_BITS;
-static const double RNG_DSCALE_INV = 1 / RNG_DSCALE;
-
-void
-CodeGenerator::visitRandom(LRandom* ins)
-{
-    FloatRegister output = ToFloatRegister(ins->output());
-    Register JSCompartmentReg = ToRegister(ins->temp1());
-#ifdef JS_PUNBOX64
-    Register64 rngStateReg = Register64(ToRegister(ins->tempMaybeEAX()));
-    Register64 highReg = Register64(ToRegister(ins->tempMaybeEDX()));
-#else
-    Register64 rngStateReg = Register64(ToRegister(ins->temp2()), ToRegister(ins->temp3()));
-    Register64 highReg = Register64(ToRegister(ins->tempMaybeEAX()), ToRegister(ins->tempMaybeEDX()));
-#endif
-    // tempReg is used only on x86.
-    Register tempReg = ToRegister(ins->tempMaybeEAX());
-
-    // rngState = cx->compartment()->rngState;
-    masm.loadJSContext(JSCompartmentReg);
-    masm.loadPtr(Address(JSCompartmentReg, JSContext::offsetOfCompartment()), JSCompartmentReg);
-    masm.load64(Address(JSCompartmentReg, JSCompartment::offsetOfRngState()), rngStateReg);
-
-    // if rngState == 0, escape from inlined code and call
-    // math_random_no_outparam.
-    OutOfLineRandom* ool = new(alloc()) OutOfLineRandom(ins);
-    addOutOfLineCode(ool, ins->mir());
-    masm.branchTest64(Assembler::Zero, rngStateReg, rngStateReg, tempReg, ool->entry());
-
-    // rngState = rngState * RNG_MULTIPLIER;
-    masm.mul64(Imm64(RNG_MULTIPLIER), rngStateReg);
-
-    // rngState += RNG_ADDEND;
-    masm.add64(Imm32(RNG_ADDEND), rngStateReg);
-
-    // rngState &= RNG_MASK;
-    masm.and64(Imm64(RNG_MASK), rngStateReg);
-
-    // if rngState == 0, escape from inlined code and call
-    // math_random_no_outparam.
-    masm.branchTest64(Assembler::Zero, rngStateReg, rngStateReg, tempReg, ool->entry());
-
-    // high = (rngState >> (RNG_STATE_WIDTH - RNG_HIGH_BITS)) << RNG_LOW_BITS;
-    masm.move64(rngStateReg, highReg);
-    masm.lshift64(Imm32(RNG_LOW_BITS - (RNG_STATE_WIDTH - RNG_HIGH_BITS)), highReg);
-    masm.and64(Imm64(RNG_HIGH_MASK), highReg);
-#ifdef JS_CODEGEN_X86
-    // eax and edx are overwritten by mul64 on x86.
-    masm.push64(highReg);
-#endif
-
-    // rngState = rngState * RNG_MULTIPLIER;
-    masm.mul64(Imm64(RNG_MULTIPLIER), rngStateReg);
-
-    // rngState += RNG_ADDEND;
-    masm.add64(Imm32(RNG_ADDEND), rngStateReg);
-
-    // rngState &= RNG_MASK;
-    masm.and64(Imm64(RNG_MASK), rngStateReg);
-
-    // cx->compartment()->rngState = rngState;
-    masm.store64(rngStateReg, Address(JSCompartmentReg, JSCompartment::offsetOfRngState()));
-
-    // low = rngState >> (RNG_STATE_WIDTH - RNG_LOW_BITS);
-    const Register64& lowReg = rngStateReg;
-    masm.rshift64(Imm32(RNG_STATE_WIDTH - RNG_LOW_BITS), lowReg);
-
-    // output = double(high | low);
-#ifdef JS_CODEGEN_X86
-    masm.pop64(highReg);
-#endif
-    masm.or64(highReg, lowReg);
-    masm.convertUInt64ToDouble(lowReg, tempReg, output);
-
-    // output = output * RNG_DSCALE_INV;
-    masm.mulDoublePtr(ImmPtr(&RNG_DSCALE_INV), tempReg, output);
-
-    masm.bind(ool->rejoin());
-}
-
-void
-CodeGenerator::visitOutOfLineRandom(OutOfLineRandom* ool)
-{
-    LRandom* ins = ool->lir();
-    Register temp1 = ToRegister(ins->tempMaybeEAX());
-    Register temp2 = ToRegister(ins->tempMaybeEDX());
-    MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg);
-
-    LiveRegisterSet regs;
-    setReturnDoubleRegs(&regs);
-    saveVolatile(regs);
-
-    masm.loadJSContext(temp1);
-
-    masm.setupUnalignedABICall(temp2);
-    masm.passABIArg(temp1);
-    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE);
-
-    restoreVolatile(regs);
-
-    masm.jump(ool->rejoin());
-}
-
 } // namespace jit
 } // namespace js
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -40,17 +40,16 @@ class OutOfLineUnboxFloatingPoint;
 class OutOfLineStoreElementHole;
 class OutOfLineTypeOfV;
 class OutOfLineUpdateCache;
 class OutOfLineCallPostWriteBarrier;
 class OutOfLineIsCallable;
 class OutOfLineRegExpExec;
 class OutOfLineRegExpTest;
 class OutOfLineLambdaArrow;
-class OutOfLineRandom;
 
 class CodeGenerator : public CodeGeneratorSpecific
 {
     void generateArgumentsChecks(bool bailout = true);
     bool generateBody();
 
   public:
     CodeGenerator(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm = nullptr);
@@ -379,19 +378,16 @@ class CodeGenerator : public CodeGenerat
     void visitAssertResultT(LAssertResultT* ins);
     void emitAssertResultV(const ValueOperand output, const TemporaryTypeSet* typeset);
     void emitAssertObjectOrStringResult(Register input, MIRType type, const TemporaryTypeSet* typeset);
 
     void visitInterruptCheck(LInterruptCheck* lir);
     void visitAsmJSInterruptCheck(LAsmJSInterruptCheck* lir);
     void visitRecompileCheck(LRecompileCheck* ins);
 
-    void visitRandom(LRandom* ins);
-    void visitOutOfLineRandom(OutOfLineRandom* ool);
-
     IonScriptCounts* extractScriptCounts() {
         IonScriptCounts* counts = scriptCounts_;
         scriptCounts_ = nullptr;  // prevent delete in dtor
         return counts;
     }
 
   private:
     void addGetPropertyCache(LInstruction* ins, LiveRegisterSet liveRegs, Register objReg,
--- a/js/src/jit/Registers.h
+++ b/js/src/jit/Registers.h
@@ -88,36 +88,16 @@ struct Register {
     static uint32_t FirstBit(SetType x) {
         return Codes::FirstBit(x);
     }
     static uint32_t LastBit(SetType x) {
         return Codes::LastBit(x);
     }
 };
 
-struct Register64
-{
-#ifdef JS_PUNBOX64
-    Register reg;
-#else
-    Register high;
-    Register low;
-#endif
-
-#ifdef JS_PUNBOX64
-    explicit MOZ_CONSTEXPR Register64(Register r)
-      : reg(r)
-    {}
-#else
-    MOZ_CONSTEXPR Register64(Register h, Register l)
-      : high(h), low(l)
-    {}
-#endif
-};
-
 class RegisterDump
 {
   public:
     typedef mozilla::Array<Registers::RegisterContent, Registers::Total> GPRArray;
     typedef mozilla::Array<FloatRegisters::RegisterContent, FloatRegisters::TotalPhys> FPUArray;
 
   protected: // Silence Clang warning.
     GPRArray regs_;
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/arm/CodeGenerator-arm.h"
 
 #include "mozilla/MathAlgorithms.h"
 
 #include "jscntxt.h"
 #include "jscompartment.h"
+#include "jsmath.h"
 #include "jsnum.h"
 
 #include "jit/CodeGenerator.h"
 #include "jit/JitCompartment.h"
 #include "jit/JitFrames.h"
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
 #include "js/Conversions.h"
@@ -2319,17 +2320,21 @@ CodeGeneratorARM::memoryBarrier(MemoryBa
 
 void
 CodeGeneratorARM::visitMemoryBarrier(LMemoryBarrier* ins)
 {
     memoryBarrier(ins->type());
 }
 
 void
-CodeGeneratorARM::setReturnDoubleRegs(LiveRegisterSet* regs)
+CodeGeneratorARM::visitRandom(LRandom* ins)
 {
-    MOZ_ASSERT(ReturnFloat32Reg.code_ == FloatRegisters::s0);
-    MOZ_ASSERT(ReturnDoubleReg.code_ == FloatRegisters::s0);
-    FloatRegister s1 = {FloatRegisters::s1, VFPRegister::Single};
-    regs->add(ReturnFloat32Reg);
-    regs->add(s1);
-    regs->add(ReturnDoubleReg);
+    Register temp = ToRegister(ins->temp());
+    Register temp2 = ToRegister(ins->temp2());
+
+    masm.loadJSContext(temp);
+
+    masm.setupUnalignedABICall(temp2);
+    masm.passABIArg(temp);
+    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE);
+
+    MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg);
 }
--- a/js/src/jit/arm/CodeGenerator-arm.h
+++ b/js/src/jit/arm/CodeGenerator-arm.h
@@ -209,17 +209,17 @@ class CodeGeneratorARM : public CodeGene
     void visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr* ins);
     void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins);
     void visitAsmJSPassStackArg(LAsmJSPassStackArg* ins);
 
     void visitMemoryBarrier(LMemoryBarrier* ins);
 
     void generateInvalidateEpilogue();
 
-    void setReturnDoubleRegs(LiveRegisterSet* regs);
+    void visitRandom(LRandom* ins);
 
   protected:
     void visitEffectiveAddress(LEffectiveAddress* ins);
     void visitUDiv(LUDiv* ins);
     void visitUMod(LUMod* ins);
     void visitSoftUDivOrMod(LSoftUDivOrMod* ins);
 
   public:
--- a/js/src/jit/arm/LIR-arm.h
+++ b/js/src/jit/arm/LIR-arm.h
@@ -492,12 +492,29 @@ class LAsmJSAtomicBinopCallout : public 
         return getOperand(1);
     }
 
     const MAsmJSAtomicBinopHeap* mir() const {
         return mir_->toAsmJSAtomicBinopHeap();
     }
 };
 
+// Math.random().
+class LRandom : public LCallInstructionHelper<1, 0, 2>
+{
+  public:
+    LIR_HEADER(Random)
+    LRandom(const LDefinition& temp, const LDefinition& temp2) {
+        setTemp(0, temp);
+        setTemp(1, temp2);
+    }
+    const LDefinition* temp() {
+        return getTemp(0);
+    }
+    const LDefinition* temp2() {
+        return getTemp(1);
+    }
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_arm_LIR_arm_h */
--- a/js/src/jit/arm/Lowering-arm.cpp
+++ b/js/src/jit/arm/Lowering-arm.cpp
@@ -736,15 +736,11 @@ LIRGeneratorARM::visitSubstr(MSubstr* in
                                          tempByteOpRegister());
     define(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGeneratorARM::visitRandom(MRandom* ins)
 {
-    LRandom *lir = new(alloc()) LRandom(temp(),
-                                        temp(),
-                                        temp(),
-                                        temp(),
-                                        temp());
-    defineFixed(lir, ins, LFloatReg(ReturnDoubleReg));
+    LRandom* lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1));
+    defineReturn(lir, ins);
 }
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -85,29 +85,16 @@ void
 MacroAssemblerARM::convertUInt32ToDouble(Register src, FloatRegister dest_)
 {
     // Direct conversions aren't possible.
     VFPRegister dest = VFPRegister(dest_);
     as_vxfer(src, InvalidReg, dest.uintOverlay(), CoreToFloat);
     as_vcvt(dest, dest.uintOverlay());
 }
 
-static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
-
-void
-MacroAssemblerARMCompat::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
-{
-    convertUInt32ToDouble(src.high, dest);
-    movePtr(ImmPtr(&TO_DOUBLE_HIGH_SCALE), ScratchRegister);
-    loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg);
-    mulDouble(ScratchDoubleReg, dest);
-    convertUInt32ToDouble(src.low, ScratchDoubleReg);
-    addDouble(ScratchDoubleReg, dest);
-}
-
 void
 MacroAssemblerARM::convertUInt32ToFloat32(Register src, FloatRegister dest_)
 {
     // Direct conversions aren't possible.
     VFPRegister dest = VFPRegister(dest_);
     as_vxfer(src, InvalidReg, dest.uintOverlay(), CoreToFloat);
     as_vcvt(VFPRegister(dest).singleOverlay(), dest.uintOverlay());
 }
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -982,27 +982,16 @@ class MacroAssemblerARMCompat : public M
     }
     void branchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
         branch32(cond, lhs, imm, label);
     }
     void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
         subPtr(imm, lhs);
         branch32(cond, lhs, Imm32(0), label);
     }
-    void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, Label* label) {
-        if (cond == Assembler::Zero) {
-            MOZ_ASSERT(lhs.low == rhs.low);
-            MOZ_ASSERT(lhs.high == rhs.high);
-            mov(lhs.low, ScratchRegister);
-            or32(lhs.high, ScratchRegister);
-            branchTestPtr(cond, ScratchRegister, ScratchRegister, label);
-        } else {
-            MOZ_CRASH("Unsupported condition");
-        }
-    }
     void moveValue(const Value& val, Register type, Register data);
 
     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Condition cond = Always,
                                  Label* documentation = nullptr);
     CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation) {
         return jumpWithPatch(label, Always, documentation);
     }
     template <typename T>
@@ -1212,73 +1201,53 @@ class MacroAssemblerARMCompat : public M
         j(cond, label);
     }
     void xor32(Imm32 imm, Register dest);
 
     void and32(Register src, Register dest);
     void and32(Imm32 imm, Register dest);
     void and32(Imm32 imm, const Address& dest);
     void and32(const Address& src, Register dest);
-    void and64(Imm64 imm, Register64 dest) {
-        and32(Imm32(imm.value & 0xFFFFFFFFL), dest.low);
-        and32(Imm32((imm.value >> 32) & 0xFFFFFFFFL), dest.high);
-    }
     void or32(Register src, Register dest);
     void or32(Imm32 imm, Register dest);
     void or32(Imm32 imm, const Address& dest);
     void xorPtr(Imm32 imm, Register dest);
     void xorPtr(Register src, Register dest);
     void orPtr(Imm32 imm, Register dest);
     void orPtr(Register src, Register dest);
-    void or64(Register64 src, Register64 dest) {
-        or32(src.low, dest.low);
-        or32(src.high, dest.high);
-    }
     void andPtr(Imm32 imm, Register dest);
     void andPtr(Register src, Register dest);
     void addPtr(Register src, Register dest);
     void addPtr(const Address& src, Register dest);
-    void add64(Imm32 imm, Register64 dest) {
-        ma_add(imm, dest.low, SetCC);
-        ma_adc(Imm32(0), dest.high, LeaveCC);
-    }
     void not32(Register reg);
 
     void move32(Imm32 imm, Register dest);
     void move32(Register src, Register dest);
 
     void movePtr(Register src, Register dest);
     void movePtr(ImmWord imm, Register dest);
     void movePtr(ImmPtr imm, Register dest);
     void movePtr(AsmJSImmPtr imm, Register dest);
     void movePtr(ImmGCPtr imm, Register dest);
-    void move64(Register64 src, Register64 dest) {
-        move32(src.low, dest.low);
-        move32(src.high, dest.high);
-    }
 
     void load8SignExtend(const Address& address, Register dest);
     void load8SignExtend(const BaseIndex& src, Register dest);
 
     void load8ZeroExtend(const Address& address, Register dest);
     void load8ZeroExtend(const BaseIndex& src, Register dest);
 
     void load16SignExtend(const Address& address, Register dest);
     void load16SignExtend(const BaseIndex& src, Register dest);
 
     void load16ZeroExtend(const Address& address, Register dest);
     void load16ZeroExtend(const BaseIndex& src, Register dest);
 
     void load32(const Address& address, Register dest);
     void load32(const BaseIndex& address, Register dest);
     void load32(AbsoluteAddress address, Register dest);
-    void load64(const Address& address, Register64 dest) {
-        load32(address, dest.low);
-        load32(Address(address.base, address.offset + 4), dest.high);
-    }
 
     void loadPtr(const Address& address, Register dest);
     void loadPtr(const BaseIndex& src, Register dest);
     void loadPtr(AbsoluteAddress address, Register dest);
     void loadPtr(AsmJSAbsoluteAddress address, Register dest);
 
     void loadPrivate(const Address& address, Register dest);
 
@@ -1335,21 +1304,16 @@ class MacroAssemblerARMCompat : public M
     void store32(Register src, AbsoluteAddress address);
     void store32(Register src, const Address& address);
     void store32(Register src, const BaseIndex& address);
     void store32(Imm32 src, const Address& address);
     void store32(Imm32 src, const BaseIndex& address);
 
     void store32_NoSecondScratch(Imm32 src, const Address& address);
 
-    void store64(Register64 src, Address address) {
-        store32(src.low, address);
-        store32(src.high, Address(address.base, address.offset + 4));
-    }
-
     template <typename T> void storePtr(ImmWord imm, T address);
     template <typename T> void storePtr(ImmPtr imm, T address);
     template <typename T> void storePtr(ImmGCPtr imm, T address);
     void storePtr(Register src, const Address& address);
     void storePtr(Register src, const BaseIndex& address);
     void storePtr(Register src, AbsoluteAddress dest);
     void storeDouble(FloatRegister src, Address addr) {
         ma_vstr(src, addr);
@@ -1684,49 +1648,16 @@ class MacroAssemblerARMCompat : public M
         addPtr(Imm32(imm.value), dest);
     }
     void addPtr(ImmPtr imm, const Register dest) {
         addPtr(ImmWord(uintptr_t(imm.value)), dest);
     }
     void mulBy3(const Register& src, const Register& dest) {
         as_add(dest, src, lsl(src, 1));
     }
-    void mul64(Imm64 imm, const Register64& dest) {
-        // LOW32  = LOW(LOW(dest) * LOW(imm));
-        // HIGH32 = LOW(HIGH(dest) * LOW(imm)) [multiply imm into upper bits]
-        //        + LOW(LOW(dest) * HIGH(imm)) [multiply dest into upper bits]
-        //        + HIGH(LOW(dest) * LOW(imm)) [carry]
-
-        // HIGH(dest) = LOW(HIGH(dest) * LOW(imm));
-        ma_mov(Imm32(imm.value & 0xFFFFFFFFL), ScratchRegister);
-        as_mul(dest.high, dest.high, ScratchRegister);
-
-        // high:low = LOW(dest) * LOW(imm);
-        as_umull(secondScratchReg_, ScratchRegister, dest.low, ScratchRegister);
-
-        // HIGH(dest) += high;
-        as_add(dest.high, dest.high, O2Reg(secondScratchReg_));
-
-        // HIGH(dest) += LOW(LOW(dest) * HIGH(imm));
-        if (((imm.value >> 32) & 0xFFFFFFFFL) == 5)
-            as_add(secondScratchReg_, dest.low, lsl(dest.low, 2));
-        else
-            MOZ_CRASH("Not supported imm");
-        as_add(dest.high, dest.high, O2Reg(secondScratchReg_));
-
-        // LOW(dest) = low;
-        ma_mov(ScratchRegister, dest.low);
-    }
-
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
-    void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) {
-        movePtr(imm, ScratchRegister);
-        loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg);
-        mulDouble(ScratchDoubleReg, dest);
-    }
 
     void setStackArg(Register reg, uint32_t arg);
 
     void breakpoint();
     // Conditional breakpoint.
     void breakpoint(Condition cc);
 
     // Trigger the simulator's interactive read-eval-print loop.
@@ -1745,29 +1676,19 @@ class MacroAssemblerARMCompat : public M
     void checkStackAlignment();
 
     void rshiftPtr(Imm32 imm, Register dest) {
         ma_lsr(imm, dest, dest);
     }
     void rshiftPtrArithmetic(Imm32 imm, Register dest) {
         ma_asr(imm, dest, dest);
     }
-    void rshift64(Imm32 imm, Register64 dest) {
-        as_mov(dest.low, lsr(dest.low, imm.value));
-        as_orr(dest.low, dest.low, lsl(dest.high, 32 - imm.value));
-        as_mov(dest.high, lsr(dest.high, imm.value));
-    }
     void lshiftPtr(Imm32 imm, Register dest) {
         ma_lsl(imm, dest, dest);
     }
-    void lshift64(Imm32 imm, Register64 dest) {
-        as_mov(dest.high, lsl(dest.high, imm.value));
-        as_orr(dest.high, dest.high, lsr(dest.low, 32 - imm.value));
-        as_mov(dest.low, lsl(dest.low, imm.value));
-    }
 
     // If source is a double, load it into dest. If source is int32, convert it
     // to double. Else, branch to failure.
     void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
 
     void
     emitSet(Assembler::Condition cond, Register dest)
     {
--- a/js/src/jit/arm64/CodeGenerator-arm64.cpp
+++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -603,16 +603,22 @@ CodeGeneratorARM64::visitInterruptCheck(
 }
 
 void
 CodeGeneratorARM64::generateInvalidateEpilogue()
 {
     MOZ_CRASH("generateInvalidateEpilogue");
 }
 
+void
+CodeGeneratorARM64::visitRandom(LRandom* ins)
+{
+    MOZ_CRASH("visitRandom");
+}
+
 template <class U>
 Register
 getBase(U* mir)
 {
     switch (mir->base()) {
       case U::Heap: return HeapReg;
       case U::Global: return GlobalReg;
     }
@@ -721,19 +727,8 @@ CodeGeneratorARM64::visitNegD(LNegD* ins
     MOZ_CRASH("visitNegD");
 }
 
 void
 CodeGeneratorARM64::visitNegF(LNegF* ins)
 {
     MOZ_CRASH("visitNegF");
 }
-
-void
-CodeGeneratorARM64::setReturnDoubleRegs(LiveRegisterSet* regs)
-{
-    MOZ_ASSERT(ReturnFloat32Reg.code_ == FloatRegisters::s0);
-    MOZ_ASSERT(ReturnDoubleReg.code_ == FloatRegisters::d0);
-    FloatRegister s1 = {FloatRegisters::s1, FloatRegisters::Single};
-    regs->add(ReturnFloat32Reg);
-    regs->add(s1);
-    regs->add(ReturnDoubleReg);
-}
--- a/js/src/jit/arm64/CodeGenerator-arm64.h
+++ b/js/src/jit/arm64/CodeGenerator-arm64.h
@@ -215,17 +215,17 @@ class CodeGeneratorARM64 : public CodeGe
     void visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar* ins);
     void visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar* ins);
     void visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr* ins);
     void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins);
     void visitAsmJSPassStackArg(LAsmJSPassStackArg* ins);
 
     void generateInvalidateEpilogue();
 
-    void setReturnDoubleRegs(LiveRegisterSet* regs);
+    void visitRandom(LRandom* ins);
 
   protected:
     void postAsmJSCall(LAsmJSCall* lir) {
         MOZ_CRASH("postAsmJSCall");
     }
 
     void visitEffectiveAddress(LEffectiveAddress* ins);
     void visitUDiv(LUDiv* ins);
--- a/js/src/jit/arm64/LIR-arm64.h
+++ b/js/src/jit/arm64/LIR-arm64.h
@@ -402,12 +402,29 @@ class LAsmJSLoadFuncPtr : public LInstru
     const LAllocation* index() {
         return getOperand(0);
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
 };
 
+// Math.random().
+class LRandom : public LCallInstructionHelper<1, 0, 2>
+{
+  public:
+    LIR_HEADER(Random)
+    LRandom(const LDefinition& temp, const LDefinition& temp2) {
+        setTemp(0, temp);
+        setTemp(1, temp2);
+    }
+    const LDefinition* temp() {
+        return getTemp(0);
+    }
+    const LDefinition* temp2() {
+        return getTemp(1);
+    }
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_arm64_LIR_arm64_h */
--- a/js/src/jit/arm64/Lowering-arm64.cpp
+++ b/js/src/jit/arm64/Lowering-arm64.cpp
@@ -299,13 +299,10 @@ void
 LIRGeneratorARM64::visitSubstr(MSubstr* ins)
 {
     MOZ_CRASH("visitSubstr");
 }
 
 void
 LIRGeneratorARM64::visitRandom(MRandom* ins)
 {
-    LRandom *lir = new(alloc()) LRandom(temp(),
-                                        temp(),
-                                        temp());
-    defineFixed(lir, ins, LFloatReg(ReturnDoubleReg));
+    MOZ_CRASH("visitRandom");
 }
--- a/js/src/jit/arm64/MacroAssembler-arm64.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64.h
@@ -779,19 +779,16 @@ class MacroAssemblerCompat : public vixl
     void movePtr(AsmJSImmPtr imm, Register dest) {
         BufferOffset off = movePatchablePtr(ImmWord(0xffffffffffffffffULL), dest);
         append(AsmJSAbsoluteLink(CodeOffsetLabel(off.getOffset()), imm.kind()));
     }
     void movePtr(ImmGCPtr imm, Register dest) {
         BufferOffset load = movePatchablePtr(ImmPtr(imm.value), dest);
         writeDataRelocation(imm, load);
     }
-    void move64(Register64 src, Register64 dest) {
-        movePtr(src.reg, dest.reg);
-    }
 
     void mov(ImmWord imm, Register dest) {
         movePtr(imm, dest);
     }
     void mov(ImmPtr imm, Register dest) {
         movePtr(imm, dest);
     }
     void mov(AsmJSImmPtr imm, Register dest) {
@@ -990,20 +987,16 @@ class MacroAssemblerCompat : public vixl
         temps.Exclude(ARMRegister(ScratchReg2, 32)); // Disallow ScratchReg2.
         const ARMRegister scratch32 = temps.AcquireW();
 
         MOZ_ASSERT(scratch32.asUnsized() != address.base);
         Mov(scratch32, uint64_t(imm.value));
         Str(scratch32, MemOperand(ARMRegister(address.base, 64), address.offset));
     }
 
-    void store64(Register64 src, Address address) {
-        storePtr(src.reg, address);
-    }
-
     // SIMD.
     void loadInt32x1(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
     void loadInt32x1(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
     void loadInt32x2(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
     void loadInt32x2(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
     void loadInt32x3(const Address& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
     void loadInt32x3(const BaseIndex& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
     void storeInt32x1(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); }
@@ -1075,29 +1068,23 @@ class MacroAssemblerCompat : public vixl
     }
 
     void rshiftPtr(Imm32 imm, Register dest) {
         Lsr(ARMRegister(dest, 64), ARMRegister(dest, 64), imm.value);
     }
     void rshiftPtr(Imm32 imm, Register src, Register dest) {
         Lsr(ARMRegister(dest, 64), ARMRegister(src, 64), imm.value);
     }
-    void rshift64(Imm32 imm, Register64 dest) {
-        rshiftPtr(imm, dest.reg);
-    }
 
     void rshiftPtrArithmetic(Imm32 imm, Register dest) {
         Asr(ARMRegister(dest, 64), ARMRegister(dest, 64), imm.value);
     }
     void lshiftPtr(Imm32 imm, Register dest) {
         Lsl(ARMRegister(dest, 64), ARMRegister(dest, 64), imm.value);
     }
-    void lshift64(Imm32 imm, Register64 dest) {
-        lshiftPtr(imm, dest.reg);
-    }
     void xorPtr(Imm32 imm, Register dest) {
         Eor(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(imm.value));
     }
     void xor32(Imm32 imm, Register dest) {
         Eor(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(imm.value));
     }
 
     void xorPtr(Register src, Register dest) {
@@ -1121,19 +1108,16 @@ class MacroAssemblerCompat : public vixl
     void or32(Imm32 imm, const Address& dest) {
         vixl::UseScratchRegisterScope temps(this);
         const ARMRegister scratch32 = temps.AcquireW();
         MOZ_ASSERT(scratch32.asUnsized() != dest.base);
         load32(dest, scratch32.asUnsized());
         Orr(scratch32, scratch32, Operand(imm.value));
         store32(scratch32.asUnsized(), dest);
     }
-    void or64(Register64 src, Register64 dest) {
-        orPtr(src.reg, dest.reg);
-    }
     void andPtr(Imm32 imm, Register dest) {
         And(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(imm.value));
     }
     void andPtr(Register src, Register dest) {
         And(ARMRegister(dest, 64), ARMRegister(dest, 64), Operand(ARMRegister(src, 64)));
     }
     void and32(Imm32 imm, Register dest) {
         And(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(imm.value));
@@ -1155,22 +1139,16 @@ class MacroAssemblerCompat : public vixl
     }
     void and32(Address src, Register dest) {
         vixl::UseScratchRegisterScope temps(this);
         const ARMRegister scratch32 = temps.AcquireW();
         MOZ_ASSERT(scratch32.asUnsized() != src.base);
         load32(src, scratch32.asUnsized());
         And(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(scratch32));
     }
-    void and64(Imm64 imm, Register64 dest) {
-        vixl::UseScratchRegisterScope temps(this);
-        const Register scratch = temps.AcquireX().asUnsized();
-        mov(ImmWord(imm.value), scratch);
-        andPtr(scratch, dest.reg);
-    }
 
     void testPtr(Register lhs, Register rhs) {
         Tst(ARMRegister(lhs, 64), Operand(ARMRegister(rhs, 64)));
     }
     void test32(Register lhs, Register rhs) {
         Tst(ARMRegister(lhs, 32), Operand(ARMRegister(rhs, 32)));
     }
     void test32(const Address& addr, Imm32 imm) {
@@ -1248,17 +1226,17 @@ class MacroAssemblerCompat : public vixl
         vixl::UseScratchRegisterScope temps(this);
         const Register scratch = temps.AcquireX().asUnsized();
         MOZ_ASSERT(scratch != lhs.base);
         loadPtr(lhs, scratch);
         cmpPtr(scratch, rhs);
     }
 
     void loadDouble(const Address& src, FloatRegister dest) {
-        Ldr(ARMFPRegister(dest, 64), MemOperand(src));
+        Ldr(ARMFPRegister(dest, 64), MemOperand(ARMRegister(src.base,64), src.offset));
     }
     void loadDouble(const BaseIndex& src, FloatRegister dest) {
         ARMRegister base(src.base, 64);
         ARMRegister index(src.index, 64);
 
         if (src.offset == 0) {
             Ldr(ARMFPRegister(dest, 64), MemOperand(base, index, vixl::LSL, unsigned(src.scale)));
             return;
@@ -1392,19 +1370,16 @@ class MacroAssemblerCompat : public vixl
         doBaseIndex(ARMRegister(dest, 32), src, vixl::LDR_w);
     }
     void load32(AbsoluteAddress address, Register dest) {
         vixl::UseScratchRegisterScope temps(this);
         const ARMRegister scratch64 = temps.AcquireX();
         movePtr(ImmWord((uintptr_t)address.addr), scratch64.asUnsized());
         ldr(ARMRegister(dest, 32), MemOperand(scratch64));
     }
-    void load64(const Address& address, Register64 dest) {
-        loadPtr(address, dest.reg);
-    }
 
     void load8SignExtend(const Address& address, Register dest) {
         Ldrsb(ARMRegister(dest, 32), MemOperand(ARMRegister(address.base, 64), address.offset));
     }
     void load8SignExtend(const BaseIndex& src, Register dest) {
         doBaseIndex(ARMRegister(dest, 32), src, vixl::LDRSB_w);
     }
 
@@ -1455,19 +1430,16 @@ class MacroAssemblerCompat : public vixl
         vixl::UseScratchRegisterScope temps(this);
         const ARMRegister scratch32 = temps.AcquireW();
         MOZ_ASSERT(scratch32.asUnsized() != dest.base);
 
         Ldr(scratch32, MemOperand(ARMRegister(dest.base, 64), dest.offset));
         Adds(scratch32, scratch32, Operand(imm.value));
         Str(scratch32, MemOperand(ARMRegister(dest.base, 64), dest.offset));
     }
-    void add64(Imm32 imm, Register64 dest) {
-        Add(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), Operand(imm.value));
-    }
 
     void sub32(Imm32 imm, Register dest) {
         Sub(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(imm.value));
     }
     void sub32(Register src, Register dest) {
         Sub(ARMRegister(dest, 32), ARMRegister(dest, 32), Operand(ARMRegister(src, 32)));
     }
 
@@ -2003,19 +1975,16 @@ class MacroAssemblerCompat : public vixl
         vixl::UseScratchRegisterScope temps(this);
         const ARMRegister scratch64 = temps.AcquireX();
         MOZ_ASSERT(scratch64.asUnsized() != valaddr.base);
         MOZ_ASSERT(scratch64.asUnsized() != value.valueReg());
         loadValue(valaddr, scratch64.asUnsized());
         Cmp(ARMRegister(value.valueReg(), 64), Operand(scratch64));
         B(label, cond);
     }
-    void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, Label* label) {
-        branchTestPtr(cond, lhs.reg, rhs.reg, label);
-    }
 
     void compareDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs) {
         Fcmp(ARMFPRegister(lhs, 64), ARMFPRegister(rhs, 64));
     }
     void branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs, Label* label) {
         compareDouble(cond, lhs, rhs);
         switch (cond) {
           case DoubleNotEqual: {
@@ -3053,37 +3022,16 @@ class MacroAssemblerCompat : public vixl
     }
 
     void mulBy3(Register src, Register dest) {
         ARMRegister xdest(dest, 64);
         ARMRegister xsrc(src, 64);
         Add(xdest, xsrc, Operand(xsrc, vixl::LSL, 1));
     }
 
-    void mul64(Imm64 imm, const Register64& dest) {
-        vixl::UseScratchRegisterScope temps(this);
-        const ARMRegister scratch64 = temps.AcquireX();
-        MOZ_ASSERT(dest.reg != scratch64.asUnsized());
-        mov(ImmWord(imm.value), scratch64.asUnsized());
-        Mul(ARMRegister(dest.reg, 64), ARMRegister(dest.reg, 64), scratch64);
-    }
-
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest) {
-        Ucvtf(ARMFPRegister(dest, 64), ARMRegister(src.reg, 64));
-    }
-    void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) {
-        vixl::UseScratchRegisterScope temps(this);
-        const Register scratch = temps.AcquireX().asUnsized();
-        MOZ_ASSERT(temp != scratch);
-        movePtr(imm, scratch);
-        const ARMFPRegister scratchDouble = temps.AcquireD();
-        Ldr(scratchDouble, MemOperand(Address(scratch, 0)));
-        fmul(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), scratchDouble);
-    }
-
     template <typename T>
     void branchAdd32(Condition cond, T src, Register dest, Label* label) {
         adds32(src, dest);
         branch(cond, label);
     }
 
     template <typename T>
     void branchSub32(Condition cond, T src, Register dest, Label* label) {
--- a/js/src/jit/mips32/CodeGenerator-mips32.cpp
+++ b/js/src/jit/mips32/CodeGenerator-mips32.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/mips32/CodeGenerator-mips32.h"
 
 #include "mozilla/MathAlgorithms.h"
 
 #include "jscntxt.h"
 #include "jscompartment.h"
+#include "jsmath.h"
 #include "jsnum.h"
 
 #include "jit/CodeGenerator.h"
 #include "jit/JitCompartment.h"
 #include "jit/JitFrames.h"
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
 #include "js/Conversions.h"
@@ -2114,15 +2115,21 @@ CodeGeneratorMIPS::visitNegF(LNegF* ins)
 {
     FloatRegister input = ToFloatRegister(ins->input());
     FloatRegister output = ToFloatRegister(ins->output());
 
     masm.as_negs(output, input);
 }
 
 void
-CodeGeneratorMIPS::setReturnDoubleRegs(LiveRegisterSet* regs)
+CodeGeneratorMIPS::visitRandom(LRandom* ins)
 {
-    MOZ_ASSERT(ReturnFloat32Reg.code_ == ReturnDoubleReg.code_);
-    regs->add(ReturnFloat32Reg);
-    regs->add(ReturnDoubleReg.singleOverlay(1));
-    regs->add(ReturnDoubleReg);
+    Register temp = ToRegister(ins->temp());
+    Register temp2 = ToRegister(ins->temp2());
+
+    masm.loadJSContext(temp);
+
+    masm.setupUnalignedABICall(temp2);
+    masm.passABIArg(temp);
+    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE);
+
+    MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg);
 }
--- a/js/src/jit/mips32/CodeGenerator-mips32.h
+++ b/js/src/jit/mips32/CodeGenerator-mips32.h
@@ -236,17 +236,17 @@ class CodeGeneratorMIPS : public CodeGen
     void visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar* ins);
     void visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr* ins);
     void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins);
 
     void visitAsmJSPassStackArg(LAsmJSPassStackArg* ins);
 
     void generateInvalidateEpilogue();
 
-    void setReturnDoubleRegs(LiveRegisterSet* regs);
+    void visitRandom(LRandom* ins);
 
   protected:
     void visitEffectiveAddress(LEffectiveAddress* ins);
     void visitUDivOrMod(LUDivOrMod* ins);
 
   public:
     // Unimplemented SIMD instructions
     void visitSimdSplatX4(LSimdSplatX4* lir) { MOZ_CRASH("NYI"); }
--- a/js/src/jit/mips32/LIR-mips32.h
+++ b/js/src/jit/mips32/LIR-mips32.h
@@ -345,12 +345,29 @@ class LAsmJSLoadFuncPtr : public LInstru
     const MAsmJSLoadFuncPtr* mir() const {
         return mir_->toAsmJSLoadFuncPtr();
     }
     const LAllocation* index() {
         return getOperand(0);
     }
 };
 
+// Math.random().
+class LRandom : public LCallInstructionHelper<1, 0, 2>
+{
+  public:
+    LIR_HEADER(Random)
+    LRandom(const LDefinition& temp, const LDefinition& temp2) {
+        setTemp(0, temp);
+        setTemp(1, temp2);
+    }
+    const LDefinition* temp() {
+        return getTemp(0);
+    }
+    const LDefinition* temp2() {
+        return getTemp(1);
+    }
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips32_LIR_mips32_h */
--- a/js/src/jit/mips32/Lowering-mips32.cpp
+++ b/js/src/jit/mips32/Lowering-mips32.cpp
@@ -570,15 +570,11 @@ void
 LIRGeneratorMIPS::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
 LIRGeneratorMIPS::visitRandom(MRandom* ins)
 {
-    LRandom *lir = new(alloc()) LRandom(temp(),
-                                        temp(),
-                                        temp(),
-                                        temp(),
-                                        temp());
-    defineFixed(lir, ins, LFloatReg(ReturnDoubleReg));
+    LRandom* lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1));
+    defineReturn(lir, ins);
 }
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -74,73 +74,16 @@ MacroAssemblerMIPS::convertUInt32ToDoubl
     as_cvtdw(dest, dest);
 
     // Add unsigned value of INT32_MIN
     ma_lid(SecondScratchDoubleReg, 2147483648.0);
     as_addd(dest, dest, SecondScratchDoubleReg);
 }
 
 void
-MacroAssemblerMIPSCompat::mul64(Imm64 imm, const Register64& dest)
-{
-    // LOW32  = LOW(LOW(dest) * LOW(imm));
-    // HIGH32 = LOW(HIGH(dest) * LOW(imm)) [multiply imm into upper bits]
-    //        + LOW(LOW(dest) * HIGH(imm)) [multiply dest into upper bits]
-    //        + HIGH(LOW(dest) * LOW(imm)) [carry]
-
-    // HIGH(dest) = LOW(HIGH(dest) * LOW(imm));
-    ma_li(ScratchRegister, Imm32(imm.value & LOW_32_MASK));
-    as_multu(dest.high, ScratchRegister);
-    as_mflo(dest.high);
-
-    // mfhi:mflo = LOW(dest) * LOW(imm);
-    as_multu(dest.low, ScratchRegister);
-
-    // HIGH(dest) += mfhi;
-    as_mfhi(ScratchRegister);
-    as_addu(dest.high, dest.high, ScratchRegister);
-
-    if (((imm.value >> 32) & LOW_32_MASK) == 5) {
-        // Optimized case for Math.random().
-
-        // HIGH(dest) += LOW(LOW(dest) * HIGH(imm));
-        as_sll(ScratchRegister, dest.low, 2);
-        as_addu(ScratchRegister, ScratchRegister, dest.low);
-        as_addu(dest.high, dest.high, ScratchRegister);
-
-        // LOW(dest) = mflo;
-        as_mflo(dest.low);
-    } else {
-        // tmp = mflo
-        as_mflo(SecondScratchReg);
-
-        // HIGH(dest) += LOW(LOW(dest) * HIGH(imm));
-        ma_li(ScratchRegister, Imm32((imm.value >> 32) & LOW_32_MASK));
-        as_multu(dest.low, ScratchRegister);
-        as_mflo(ScratchRegister);
-        as_addu(dest.high, dest.high, ScratchRegister);
-
-        // LOW(dest) = tmp;
-        ma_move(dest.low, SecondScratchReg);
-    }
-}
-
-static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
-
-void
-MacroAssemblerMIPSCompat::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
-{
-    convertUInt32ToDouble(src.high, dest);
-    loadConstantDouble(TO_DOUBLE_HIGH_SCALE, ScratchDoubleReg);
-    mulDouble(ScratchDoubleReg, dest);
-    convertUInt32ToDouble(src.low, ScratchDoubleReg);
-    addDouble(ScratchDoubleReg, dest);
-}
-
-void
 MacroAssemblerMIPS::convertUInt32ToFloat32(Register src, FloatRegister dest)
 {
     Label positive, done;
     ma_b(src, src, &positive, NotSigned, ShortJump);
 
     // We cannot do the same as convertUInt32ToDouble because float32 doesn't
     // have enough precision.
     convertUInt32ToDouble(src, dest);
@@ -2720,30 +2663,16 @@ MacroAssemblerMIPSCompat::branchTestDoub
 
 void
 MacroAssemblerMIPSCompat::branchTestBooleanTruthy(bool b, const ValueOperand& operand,
                                                   Label* label)
 {
     ma_b(operand.payloadReg(), operand.payloadReg(), label, b ? NonZero : Zero);
 }
 
-void
-MacroAssemblerMIPSCompat::branchTest64(Condition cond, Register64 lhs, Register64 rhs,
-                                       Register temp, Label* label)
-{
-    if (cond == Assembler::Zero) {
-        MOZ_ASSERT(lhs.low == rhs.low);
-        MOZ_ASSERT(lhs.high == rhs.high);
-        ma_or(ScratchRegister, lhs.low, lhs.high);
-        branchTestPtr(cond, ScratchRegister, ScratchRegister, label);
-    } else {
-        MOZ_CRASH("Unsupported condition");
-    }
-}
-
 Register
 MacroAssemblerMIPSCompat::extractObject(const Address& address, Register scratch)
 {
     ma_lw(scratch, Address(address.base, address.offset + PAYLOAD_OFFSET));
     return scratch;
 }
 
 Register
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -60,20 +60,16 @@ struct ImmType : public ImmTag
 
 static const ValueOperand JSReturnOperand = ValueOperand(JSReturnReg_Type, JSReturnReg_Data);
 static const ValueOperand softfpReturnOperand = ValueOperand(v1, v0);
 
 static Register CallReg = t9;
 static const int defaultShift = 3;
 static_assert(1 << defaultShift == sizeof(JS::Value), "The defaultShift is wrong");
 
-static const uint32_t LOW_32_MASK = (1LL << 32) - 1;
-static const int32_t LOW_32_OFFSET = 0;
-static const int32_t HIGH_32_OFFSET = 4;
-
 class MacroAssemblerMIPS : public Assembler
 {
   public:
     // higher level tag testing code
     Operand ToPayload(Operand base);
     Address ToPayload(Address base) {
         return ToPayload(Operand(base)).toAddress();
     }
@@ -689,18 +685,16 @@ class MacroAssemblerMIPSCompat : public 
         branchTest32(cond, lhs, rhs, label);
     }
     void branchTestPtr(Condition cond, Register lhs, const Imm32 rhs, Label* label) {
         branchTest32(cond, lhs, rhs, label);
     }
     void branchTestPtr(Condition cond, const Address& lhs, Imm32 imm, Label* label) {
         branchTest32(cond, lhs, imm, label);
     }
-    void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp,
-                      Label* label);
     void branchPtr(Condition cond, Register lhs, Register rhs, Label* label) {
         ma_b(lhs, rhs, label, cond);
     }
     void branchPtr(Condition cond, Register lhs, ImmGCPtr ptr, Label* label) {
         ma_li(ScratchRegister, ptr);
         ma_b(lhs, ScratchRegister, label, cond);
     }
     void branchPtr(Condition cond, Register lhs, ImmWord imm, Label* label) {
@@ -1108,21 +1102,16 @@ public:
     template <typename T, typename S>
     void atomicXor32(const T& value, const S& mem) {
         MOZ_CRASH("NYI");
     }
 
     void add32(Register src, Register dest);
     void add32(Imm32 imm, Register dest);
     void add32(Imm32 imm, const Address& dest);
-    void add64(Imm32 imm, Register64 dest) {
-        as_addiu(dest.low, dest.low, imm.value);
-        as_sltiu(ScratchRegister, dest.low, imm.value);
-        as_addu(dest.high, dest.high, ScratchRegister);
-    }
     void sub32(Imm32 imm, Register dest);
     void sub32(Register src, Register dest);
 
     void incrementInt32Value(const Address& addr) {
         add32(Imm32(1), ToPayload(addr));
     }
 
     template <typename T>
@@ -1150,45 +1139,33 @@ public:
             MOZ_CRASH("NYI");
         }
     }
 
     void and32(Register src, Register dest);
     void and32(Imm32 imm, Register dest);
     void and32(Imm32 imm, const Address& dest);
     void and32(const Address& src, Register dest);
-    void and64(Imm64 imm, Register64 dest) {
-        and32(Imm32(imm.value & LOW_32_MASK), dest.low);
-        and32(Imm32((imm.value >> 32) & LOW_32_MASK), dest.high);
-    }
     void or32(Imm32 imm, Register dest);
     void or32(Imm32 imm, const Address& dest);
     void or32(Register src, Register dest);
-    void or64(Register64 src, Register64 dest) {
-        or32(src.low, dest.low);
-        or32(src.high, dest.high);
-    }
     void xor32(Imm32 imm, Register dest);
     void xorPtr(Imm32 imm, Register dest);
     void xorPtr(Register src, Register dest);
     void orPtr(Imm32 imm, Register dest);
     void orPtr(Register src, Register dest);
     void andPtr(Imm32 imm, Register dest);
     void andPtr(Register src, Register dest);
     void addPtr(Register src, Register dest);
     void subPtr(Register src, Register dest);
     void addPtr(const Address& src, Register dest);
     void not32(Register reg);
 
     void move32(Imm32 imm, Register dest);
     void move32(Register src, Register dest);
-    void move64(Register64 src, Register64 dest) {
-        move32(src.low, dest.low);
-        move32(src.high, dest.high);
-    }
 
     void movePtr(Register src, Register dest);
     void movePtr(ImmWord imm, Register dest);
     void movePtr(ImmPtr imm, Register dest);
     void movePtr(AsmJSImmPtr imm, Register dest);
     void movePtr(ImmGCPtr imm, Register dest);
 
     void load8SignExtend(const Address& address, Register dest);
@@ -1201,20 +1178,16 @@ public:
     void load16SignExtend(const BaseIndex& src, Register dest);
 
     void load16ZeroExtend(const Address& address, Register dest);
     void load16ZeroExtend(const BaseIndex& src, Register dest);
 
     void load32(const Address& address, Register dest);
     void load32(const BaseIndex& address, Register dest);
     void load32(AbsoluteAddress address, Register dest);
-    void load64(const Address& address, Register64 dest) {
-        load32(Address(address.base, address.offset + LOW_32_OFFSET), dest.low);
-        load32(Address(address.base, address.offset + HIGH_32_OFFSET), dest.high);
-    }
 
     void loadPtr(const Address& address, Register dest);
     void loadPtr(const BaseIndex& src, Register dest);
     void loadPtr(AbsoluteAddress address, Register dest);
     void loadPtr(AsmJSAbsoluteAddress address, Register dest);
 
     void loadPrivate(const Address& address, Register dest);
 
@@ -1275,21 +1248,16 @@ public:
     void store32(Imm32 src, const BaseIndex& address);
 
     // NOTE: This will use second scratch on MIPS. Only ARM needs the
     // implementation without second scratch.
     void store32_NoSecondScratch(Imm32 src, const Address& address) {
         store32(src, address);
     }
 
-    void store64(Register64 src, Address address) {
-        store32(src.low, Address(address.base, address.offset + LOW_32_OFFSET));
-        store32(src.high, Address(address.base, address.offset + HIGH_32_OFFSET));
-    }
-
     template <typename T> void storePtr(ImmWord imm, T address);
     template <typename T> void storePtr(ImmPtr imm, T address);
     template <typename T> void storePtr(ImmGCPtr imm, T address);
     void storePtr(Register src, const Address& address);
     void storePtr(Register src, const BaseIndex& address);
     void storePtr(Register src, AbsoluteAddress dest);
     void storeDouble(FloatRegister src, Address addr) {
         ma_sd(src, addr);
@@ -1349,25 +1317,16 @@ public:
     void addPtr(ImmPtr imm, const Register dest) {
         addPtr(ImmWord(uintptr_t(imm.value)), dest);
     }
     void mulBy3(const Register& src, const Register& dest) {
         as_addu(dest, src, src);
         as_addu(dest, dest, src);
     }
 
-    void mul64(Imm64 imm, const Register64& dest);
-
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
-    void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) {
-        movePtr(imm, ScratchRegister);
-        loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg);
-        mulDouble(ScratchDoubleReg, dest);
-    }
-
     void breakpoint();
 
     void branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
                       Label* label);
 
     void branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
                      Label* label);
 
@@ -1378,31 +1337,19 @@ public:
     static void calculateAlignedStackPointer(void** stackPointer);
 
     void rshiftPtr(Imm32 imm, Register dest) {
         ma_srl(dest, dest, imm);
     }
     void rshiftPtrArithmetic(Imm32 imm, Register dest) {
         ma_sra(dest, dest, imm);
     }
-    void rshift64(Imm32 imm, Register64 dest) {
-        as_srl(dest.low, dest.low, imm.value);
-        as_sll(ScratchRegister, dest.high, 32 - imm.value);
-        as_or(dest.low, dest.low, ScratchRegister);
-        as_srl(dest.high, dest.high, imm.value);
-    }
     void lshiftPtr(Imm32 imm, Register dest) {
         ma_sll(dest, dest, imm);
     }
-    void lshift64(Imm32 imm, Register64 dest) {
-        as_sll(dest.high, dest.high, imm.value);
-        as_srl(ScratchRegister, dest.low, 32 - imm.value);
-        as_or(dest.high, dest.high, ScratchRegister);
-        as_sll(dest.low, dest.low, imm.value);
-    }
 
     // If source is a double, load it into dest. If source is int32,
     // convert it to double. Else, branch to failure.
     void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
 
     template <typename T1, typename T2>
     void cmpPtrSet(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest)
     {
--- a/js/src/jit/none/CodeGenerator-none.h
+++ b/js/src/jit/none/CodeGenerator-none.h
@@ -46,17 +46,16 @@ class CodeGeneratorNone : public CodeGen
     void testZeroEmitBranch(Assembler::Condition, Register, MBasicBlock*, MBasicBlock*) {
         MOZ_CRASH();
     }
     void emitTableSwitchDispatch(MTableSwitch*, Register, Register) { MOZ_CRASH(); }
     ValueOperand ToValue(LInstruction*, size_t) { MOZ_CRASH(); }
     ValueOperand ToOutValue(LInstruction*) { MOZ_CRASH(); }
     ValueOperand ToTempValue(LInstruction*, size_t) { MOZ_CRASH(); }
     void generateInvalidateEpilogue() { MOZ_CRASH(); }
-    void setReturnDoubleRegs(LiveRegisterSet* regs) { MOZ_CRASH(); }
 };
 
 typedef CodeGeneratorNone CodeGeneratorSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_none_CodeGenerator_none_h */
--- a/js/src/jit/none/LIR-none.h
+++ b/js/src/jit/none/LIR-none.h
@@ -107,13 +107,14 @@ class LModPowTwoI : public LInstructionH
     int32_t shift() { MOZ_CRASH(); }
     LModPowTwoI(const LAllocation& lhs, int32_t shift) { MOZ_CRASH(); }
     MMod* mir() const { MOZ_CRASH(); }
 };
 
 class LGuardShape : public LInstruction {};
 class LGuardObjectGroup : public LInstruction {};
 class LMulI : public LInstruction {};
+class LRandom : public LInstructionHelper<1, 0, 5> {};
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_none_LIR_none_h */
--- a/js/src/jit/none/Lowering-none.h
+++ b/js/src/jit/none/Lowering-none.h
@@ -82,16 +82,17 @@ class LIRGeneratorNone : public LIRGener
 
     LTableSwitch* newLTableSwitch(LAllocation, LDefinition, MTableSwitch*) { MOZ_CRASH(); }
     LTableSwitchV* newLTableSwitchV(MTableSwitch*) { MOZ_CRASH(); }
     void visitSimdSelect(MSimdSelect* ins) { MOZ_CRASH(); }
     void visitSimdSplatX4(MSimdSplatX4* ins) { MOZ_CRASH(); }
     void visitSimdValueX4(MSimdValueX4* lir) { MOZ_CRASH(); }
     void visitSubstr(MSubstr*) { MOZ_CRASH(); }
     void visitSimdBinaryArith(js::jit::MSimdBinaryArith*) { MOZ_CRASH(); }
+    void visitRandom(MRandom* ) { MOZ_CRASH(); }
 
 };
 
 typedef LIRGeneratorNone LIRGeneratorSpecific;
 
 } // namespace jit
 } // namespace js
 
--- a/js/src/jit/shared/Assembler-shared.h
+++ b/js/src/jit/shared/Assembler-shared.h
@@ -120,25 +120,16 @@ struct Imm32
 struct ImmWord
 {
     uintptr_t value;
 
     explicit ImmWord(uintptr_t value) : value(value)
     { }
 };
 
-// Used for 64-bit immediates which do not require relocation.
-struct Imm64
-{
-    uint64_t value;
-
-    explicit Imm64(uint64_t value) : value(value)
-    { }
-};
-
 #ifdef DEBUG
 static inline bool
 IsCompilingAsmJS()
 {
     // asm.js compilation pushes a JitContext with a null JSCompartment.
     JitContext* jctx = MaybeGetJitContext();
     return jctx && jctx->compartment == nullptr;
 }
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -7119,63 +7119,12 @@ class LArrowNewTarget : public LInstruct
 
     LIR_HEADER(ArrowNewTarget)
 
     const LAllocation* callee() {
         return getOperand(0);
     }
 };
 
-// Math.random().
-#ifdef JS_PUNBOX64
-# define LRANDOM_NUM_TEMPS 3
-#else
-# define LRANDOM_NUM_TEMPS 5
-#endif
-
-class LRandom : public LInstructionHelper<1, 0, LRANDOM_NUM_TEMPS>
-{
-  public:
-    LIR_HEADER(Random)
-    LRandom(const LDefinition &tempMaybeEAX, const LDefinition &tempMaybeEDX,
-            const LDefinition &temp1
-#ifndef JS_PUNBOX64
-            , const LDefinition &temp2, const LDefinition &temp3
-#endif
-            )
-    {
-        setTemp(0, tempMaybeEAX);
-        setTemp(1, tempMaybeEDX);
-        setTemp(2, temp1);
-#ifndef JS_PUNBOX64
-        setTemp(3, temp2);
-        setTemp(4, temp3);
-#endif
-    }
-    // On x86, following 2 methods return eax and edx necessary for mull.
-    // On others, following 2 methods return ordinary temporary registers.
-    const LDefinition* tempMaybeEAX() {
-        return getTemp(0);
-    }
-    const LDefinition* tempMaybeEDX() {
-        return getTemp(1);
-    }
-    const LDefinition *temp1() {
-        return getTemp(2);
-    }
-#ifndef JS_PUNBOX64
-    const LDefinition *temp2() {
-        return getTemp(3);
-    }
-    const LDefinition *temp3() {
-        return getTemp(4);
-    }
-#endif
-
-    MRandom* mir() const {
-        return mir_->toRandom();
-    }
-};
-
 } // namespace jit
 } // namespace js
 
 #endif /* jit_shared_LIR_shared_h */
deleted file mode 100644
--- a/js/src/jit/x64/BaseAssembler-x64.h
+++ /dev/null
@@ -1,782 +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/. */
-
-#ifndef jit_x64_BaseAssembler_x64_h
-#define jit_x64_BaseAssembler_x64_h
-
-#include "jit/x86-shared/BaseAssembler-x86-shared.h"
-
-namespace js {
-namespace jit {
-
-namespace X86Encoding {
-
-class BaseAssemblerX64 : public BaseAssembler
-{
-  public:
-
-    // Arithmetic operations:
-
-    void addq_rr(RegisterID src, RegisterID dst)
-    {
-        spew("addq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_ADD_GvEv, src, dst);
-    }
-
-    void addq_mr(int32_t offset, RegisterID base, RegisterID dst)
-    {
-        spew("addq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_ADD_GvEv, offset, base, dst);
-    }
-
-    void addq_mr(const void* addr, RegisterID dst)
-    {
-        spew("addq       %p, %s", addr, GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_ADD_GvEv, addr, dst);
-    }
-
-    void addq_ir(int32_t imm, RegisterID dst)
-    {
-        spew("addq       $%d, %s", imm, GPReg64Name(dst));
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_ADD);
-            m_formatter.immediate8s(imm);
-        } else {
-            if (dst == rax)
-                m_formatter.oneByteOp64(OP_ADD_EAXIv);
-            else
-                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    void addq_im(int32_t imm, int32_t offset, RegisterID base)
-    {
-        spew("addq       $%d, " MEM_ob, imm, ADDR_ob(offset, base));
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, offset, base, GROUP1_OP_ADD);
-            m_formatter.immediate8s(imm);
-        } else {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIz, offset, base, GROUP1_OP_ADD);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    void addq_im(int32_t imm, const void* addr)
-    {
-        spew("addq       $%d, %p", imm, addr);
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, addr, GROUP1_OP_ADD);
-            m_formatter.immediate8s(imm);
-        } else {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIz, addr, GROUP1_OP_ADD);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    void andq_rr(RegisterID src, RegisterID dst)
-    {
-        spew("andq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_AND_GvEv, src, dst);
-    }
-
-    void andq_mr(int32_t offset, RegisterID base, RegisterID dst)
-    {
-        spew("andq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_AND_GvEv, offset, base, dst);
-    }
-
-    void andq_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
-    {
-        spew("andq       " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_AND_GvEv, offset, base, index, scale, dst);
-    }
-
-    void andq_mr(const void* addr, RegisterID dst)
-    {
-        spew("andq       %p, %s", addr, GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_AND_GvEv, addr, dst);
-    }
-
-    void orq_mr(int32_t offset, RegisterID base, RegisterID dst)
-    {
-        spew("orq        " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_OR_GvEv, offset, base, dst);
-    }
-
-    void orq_mr(const void* addr, RegisterID dst)
-    {
-        spew("orq        %p, %s", addr, GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_OR_GvEv, addr, dst);
-    }
-
-    void andq_ir(int32_t imm, RegisterID dst)
-    {
-        spew("andq       $0x%" PRIx64 ", %s", int64_t(imm), GPReg64Name(dst));
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_AND);
-            m_formatter.immediate8s(imm);
-        } else {
-            if (dst == rax)
-                m_formatter.oneByteOp64(OP_AND_EAXIv);
-            else
-                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_AND);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    void negq_r(RegisterID dst)
-    {
-        spew("negq       %s", GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_GROUP3_Ev, dst, GROUP3_OP_NEG);
-    }
-
-    void orq_rr(RegisterID src, RegisterID dst)
-    {
-        spew("orq        %s, %s", GPReg64Name(src), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_OR_GvEv, src, dst);
-    }
-
-    void orq_ir(int32_t imm, RegisterID dst)
-    {
-        spew("orq        $0x%" PRIx64 ", %s", int64_t(imm), GPReg64Name(dst));
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_OR);
-            m_formatter.immediate8s(imm);
-        } else {
-            if (dst == rax)
-                m_formatter.oneByteOp64(OP_OR_EAXIv);
-            else
-                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_OR);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    void notq_r(RegisterID dst)
-    {
-        spew("notq       %s", GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_GROUP3_Ev, dst, GROUP3_OP_NOT);
-    }
-
-    void subq_rr(RegisterID src, RegisterID dst)
-    {
-        spew("subq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_SUB_GvEv, src, dst);
-    }
-
-    void subq_rm(RegisterID src, int32_t offset, RegisterID base)
-    {
-        spew("subq       %s, " MEM_ob, GPReg64Name(src), ADDR_ob(offset, base));
-        m_formatter.oneByteOp64(OP_SUB_EvGv, offset, base, src);
-    }
-
-    void subq_mr(int32_t offset, RegisterID base, RegisterID dst)
-    {
-        spew("subq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_SUB_GvEv, offset, base, dst);
-    }
-
-    void subq_mr(const void* addr, RegisterID dst)
-    {
-        spew("subq       %p, %s", addr, GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_SUB_GvEv, addr, dst);
-    }
-
-    void subq_ir(int32_t imm, RegisterID dst)
-    {
-        spew("subq       $%d, %s", imm, GPReg64Name(dst));
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_SUB);
-            m_formatter.immediate8s(imm);
-        } else {
-            if (dst == rax)
-                m_formatter.oneByteOp64(OP_SUB_EAXIv);
-            else
-                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_SUB);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    void xorq_rr(RegisterID src, RegisterID dst)
-    {
-        spew("xorq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_XOR_GvEv, src, dst);
-    }
-
-    void xorq_ir(int32_t imm, RegisterID dst)
-    {
-        spew("xorq       $0x%" PRIx64 ", %s", int64_t(imm), GPReg64Name(dst));
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_XOR);
-            m_formatter.immediate8s(imm);
-        } else {
-            if (dst == rax)
-                m_formatter.oneByteOp64(OP_XOR_EAXIv);
-            else
-                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_XOR);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    void sarq_CLr(RegisterID dst)
-    {
-        spew("sarq       %%cl, %s", GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_GROUP2_EvCL, dst, GROUP2_OP_SAR);
-    }
-
-    void sarq_ir(int32_t imm, RegisterID dst)
-    {
-        MOZ_ASSERT(imm < 64);
-        spew("sarq       $%d, %s", imm, GPReg64Name(dst));
-        if (imm == 1)
-            m_formatter.oneByteOp64(OP_GROUP2_Ev1, dst, GROUP2_OP_SAR);
-        else {
-            m_formatter.oneByteOp64(OP_GROUP2_EvIb, dst, GROUP2_OP_SAR);
-            m_formatter.immediate8u(imm);
-        }
-    }
-
-    void shlq_ir(int32_t imm, RegisterID dst)
-    {
-        MOZ_ASSERT(imm < 64);
-        spew("shlq       $%d, %s", imm, GPReg64Name(dst));
-        if (imm == 1)
-            m_formatter.oneByteOp64(OP_GROUP2_Ev1, dst, GROUP2_OP_SHL);
-        else {
-            m_formatter.oneByteOp64(OP_GROUP2_EvIb, dst, GROUP2_OP_SHL);
-            m_formatter.immediate8u(imm);
-        }
-    }
-
-    void shrq_ir(int32_t imm, RegisterID dst)
-    {
-        MOZ_ASSERT(imm < 64);
-        spew("shrq       $%d, %s", imm, GPReg64Name(dst));
-        if (imm == 1)
-            m_formatter.oneByteOp64(OP_GROUP2_Ev1, dst, GROUP2_OP_SHR);
-        else {
-            m_formatter.oneByteOp64(OP_GROUP2_EvIb, dst, GROUP2_OP_SHR);
-            m_formatter.immediate8u(imm);
-        }
-    }
-
-    void imulq_rr(RegisterID src, RegisterID dst)
-    {
-        spew("imulq      %s, %s", GPReg64Name(src), GPReg64Name(dst));
-        m_formatter.twoByteOp64(OP2_IMUL_GvEv, src, dst);
-    }
-
-    // Comparisons:
-
-    void cmpq_rr(RegisterID rhs, RegisterID lhs)
-    {
-        spew("cmpq       %s, %s", GPReg64Name(rhs), GPReg64Name(lhs));
-        m_formatter.oneByteOp64(OP_CMP_GvEv, rhs, lhs);
-    }
-
-    void cmpq_rm(RegisterID rhs, int32_t offset, RegisterID base)
-    {
-        spew("cmpq       %s, " MEM_ob, GPReg64Name(rhs), ADDR_ob(offset, base));
-        m_formatter.oneByteOp64(OP_CMP_EvGv, offset, base, rhs);
-    }
-
-    void cmpq_mr(int32_t offset, RegisterID base, RegisterID lhs)
-    {
-        spew("cmpq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(lhs));
-        m_formatter.oneByteOp64(OP_CMP_GvEv, offset, base, lhs);
-    }
-
-    void cmpq_ir(int32_t rhs, RegisterID lhs)
-    {
-        if (rhs == 0) {
-            testq_rr(lhs, lhs);
-            return;
-        }
-
-        spew("cmpq       $0x%" PRIx64 ", %s", int64_t(rhs), GPReg64Name(lhs));
-        if (CAN_SIGN_EXTEND_8_32(rhs)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, lhs, GROUP1_OP_CMP);
-            m_formatter.immediate8s(rhs);
-        } else {
-            if (lhs == rax)
-                m_formatter.oneByteOp64(OP_CMP_EAXIv);
-            else
-                m_formatter.oneByteOp64(OP_GROUP1_EvIz, lhs, GROUP1_OP_CMP);
-            m_formatter.immediate32(rhs);
-        }
-    }
-
-    void cmpq_im(int32_t rhs, int32_t offset, RegisterID base)
-    {
-        spew("cmpq       $0x%" PRIx64 ", " MEM_ob, int64_t(rhs), ADDR_ob(offset, base));
-        if (CAN_SIGN_EXTEND_8_32(rhs)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, offset, base, GROUP1_OP_CMP);
-            m_formatter.immediate8s(rhs);
-        } else {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIz, offset, base, GROUP1_OP_CMP);
-            m_formatter.immediate32(rhs);
-        }
-    }
-
-    void cmpq_im(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
-    {
-        spew("cmpq       $0x%x, " MEM_obs, rhs, ADDR_obs(offset, base, index, scale));
-        if (CAN_SIGN_EXTEND_8_32(rhs)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_CMP);
-            m_formatter.immediate8s(rhs);
-        } else {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_CMP);
-            m_formatter.immediate32(rhs);
-        }
-    }
-    void cmpq_im(int32_t rhs, const void* addr)
-    {
-        spew("cmpq       $0x%" PRIx64 ", %p", int64_t(rhs), addr);
-        if (CAN_SIGN_EXTEND_8_32(rhs)) {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIb, addr, GROUP1_OP_CMP);
-            m_formatter.immediate8s(rhs);
-        } else {
-            m_formatter.oneByteOp64(OP_GROUP1_EvIz, addr, GROUP1_OP_CMP);
-            m_formatter.immediate32(rhs);
-        }
-    }
-    void cmpq_rm(RegisterID rhs, const void* addr)
-    {
-        spew("cmpq       %s, %p", GPReg64Name(rhs), addr);
-        m_formatter.oneByteOp64(OP_CMP_EvGv, addr, rhs);
-    }
-
-    void testq_rr(RegisterID rhs, RegisterID lhs)
-    {
-        spew("testq      %s, %s", GPReg64Name(rhs), GPReg64Name(lhs));
-        m_formatter.oneByteOp64(OP_TEST_EvGv, lhs, rhs);
-    }
-
-    void testq_ir(int32_t rhs, RegisterID lhs)
-    {
-        // If the mask fits in a 32-bit immediate, we can use testl with a
-        // 32-bit subreg.
-        if (CAN_ZERO_EXTEND_32_64(rhs)) {
-            testl_ir(rhs, lhs);
-            return;
-        }
-        spew("testq      $0x%" PRIx64 ", %s", int64_t(rhs), GPReg64Name(lhs));
-        if (lhs == rax)
-            m_formatter.oneByteOp64(OP_TEST_EAXIv);
-        else
-            m_formatter.oneByteOp64(OP_GROUP3_EvIz, lhs, GROUP3_OP_TEST);
-        m_formatter.immediate32(rhs);
-    }
-
-    void testq_i32m(int32_t rhs, int32_t offset, RegisterID base)
-    {
-        spew("testq      $0x%" PRIx64 ", " MEM_ob, int64_t(rhs), ADDR_ob(offset, base));
-        m_formatter.oneByteOp64(OP_GROUP3_EvIz, offset, base, GROUP3_OP_TEST);
-        m_formatter.immediate32(rhs);
-    }
-
-    void testq_i32m(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
-    {
-        spew("testq      $0x%4x, " MEM_obs, rhs, ADDR_obs(offset, base, index, scale));
-        m_formatter.oneByteOp64(OP_GROUP3_EvIz, offset, base, index, scale, GROUP3_OP_TEST);
-        m_formatter.immediate32(rhs);
-    }
-
-    // Various move ops:
-
-    void xchgq_rr(RegisterID src, RegisterID dst)
-    {
-        spew("xchgq      %s, %s", GPReg64Name(src), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_XCHG_GvEv, src, dst);
-    }
-    void xchgq_rm(RegisterID src, int32_t offset, RegisterID base)
-    {
-        spew("xchgq      %s, " MEM_ob, GPReg64Name(src), ADDR_ob(offset, base));
-        m_formatter.oneByteOp64(OP_XCHG_GvEv, offset, base, src);
-    }
-    void xchgq_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
-    {
-        spew("xchgq      %s, " MEM_obs, GPReg64Name(src), ADDR_obs(offset, base, index, scale));
-        m_formatter.oneByteOp64(OP_XCHG_GvEv, offset, base, index, scale, src);
-    }
-
-    void movq_rr(RegisterID src, RegisterID dst)
-    {
-        spew("movq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_MOV_GvEv, src, dst);
-    }
-
-    void movq_rm(RegisterID src, int32_t offset, RegisterID base)
-    {
-        spew("movq       %s, " MEM_ob, GPReg64Name(src), ADDR_ob(offset, base));
-        m_formatter.oneByteOp64(OP_MOV_EvGv, offset, base, src);
-    }
-
-    void movq_rm_disp32(RegisterID src, int32_t offset, RegisterID base)
-    {
-        spew("movq       %s, " MEM_o32b, GPReg64Name(src), ADDR_o32b(offset, base));
-        m_formatter.oneByteOp64_disp32(OP_MOV_EvGv, offset, base, src);
-    }
-
-    void movq_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
-    {
-        spew("movq       %s, " MEM_obs, GPReg64Name(src), ADDR_obs(offset, base, index, scale));
-        m_formatter.oneByteOp64(OP_MOV_EvGv, offset, base, index, scale, src);
-    }
-
-    void movq_rm(RegisterID src, const void* addr)
-    {
-        if (src == rax && !IsAddressImmediate(addr)) {
-            movq_EAXm(addr);
-            return;
-        }
-
-        spew("movq       %s, %p", GPReg64Name(src), addr);
-        m_formatter.oneByteOp64(OP_MOV_EvGv, addr, src);
-    }
-
-    void movq_mEAX(const void* addr)
-    {
-        if (IsAddressImmediate(addr)) {
-            movq_mr(addr, rax);
-            return;
-        }
-
-        spew("movq       %p, %%rax", addr);
-        m_formatter.oneByteOp64(OP_MOV_EAXOv);
-        m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
-    }
-
-    void movq_EAXm(const void* addr)
-    {
-        if (IsAddressImmediate(addr)) {
-            movq_rm(rax, addr);
-            return;
-        }
-
-        spew("movq       %%rax, %p", addr);
-        m_formatter.oneByteOp64(OP_MOV_OvEAX);
-        m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
-    }
-
-    void movq_mr(int32_t offset, RegisterID base, RegisterID dst)
-    {
-        spew("movq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_MOV_GvEv, offset, base, dst);
-    }
-
-    void movq_mr_disp32(int32_t offset, RegisterID base, RegisterID dst)
-    {
-        spew("movq       " MEM_o32b ", %s", ADDR_o32b(offset, base), GPReg64Name(dst));
-        m_formatter.oneByteOp64_disp32(OP_MOV_GvEv, offset, base, dst);
-    }
-
-    void movq_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
-    {
-        spew("movq       " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_MOV_GvEv, offset, base, index, scale, dst);
-    }
-
-    void movq_mr(const void* addr, RegisterID dst)
-    {
-        if (dst == rax && !IsAddressImmediate(addr)) {
-            movq_mEAX(addr);
-            return;
-        }
-
-        spew("movq       %p, %s", addr, GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_MOV_GvEv, addr, dst);
-    }
-
-    void leaq_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
-    {
-        spew("leaq       " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg64Name(dst)),
-        m_formatter.oneByteOp64(OP_LEA, offset, base, index, scale, dst);
-    }
-
-    void movq_i32m(int32_t imm, int32_t offset, RegisterID base)
-    {
-        spew("movq       $%d, " MEM_ob, imm, ADDR_ob(offset, base));
-        m_formatter.oneByteOp64(OP_GROUP11_EvIz, offset, base, GROUP11_MOV);
-        m_formatter.immediate32(imm);
-    }
-
-    void movq_i32m(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
-    {
-        spew("movq       $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
-        m_formatter.oneByteOp64(OP_GROUP11_EvIz, offset, base, index, scale, GROUP11_MOV);
-        m_formatter.immediate32(imm);
-    }
-    void movq_i32m(int32_t imm, const void* addr)
-    {
-        spew("movq       $%d, %p", imm, addr);
-        m_formatter.oneByteOp64(OP_GROUP11_EvIz, addr, GROUP11_MOV);
-        m_formatter.immediate32(imm);
-    }
-
-    // Note that this instruction sign-extends its 32-bit immediate field to 64
-    // bits and loads the 64-bit value into a 64-bit register.
-    //
-    // Note also that this is similar to the movl_i32r instruction, except that
-    // movl_i32r *zero*-extends its 32-bit immediate, and it has smaller code
-    // size, so it's preferred for values which could use either.
-    void movq_i32r(int32_t imm, RegisterID dst)
-    {
-        spew("movq       $%d, %s", imm, GPRegName(dst));
-        m_formatter.oneByteOp64(OP_GROUP11_EvIz, dst, GROUP11_MOV);
-        m_formatter.immediate32(imm);
-    }
-
-    void movq_i64r(int64_t imm, RegisterID dst)
-    {
-        spew("movabsq    $0x%" PRIx64 ", %s", imm, GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_MOV_EAXIv, dst);
-        m_formatter.immediate64(imm);
-    }
-
-    void movslq_rr(RegisterID src, RegisterID dst)
-    {
-        spew("movslq     %s, %s", GPReg32Name(src), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_MOVSXD_GvEv, src, dst);
-    }
-    void movslq_mr(int32_t offset, RegisterID base, RegisterID dst)
-    {
-        spew("movslq     " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_MOVSXD_GvEv, offset, base, dst);
-    }
-    void movslq_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
-    {
-        spew("movslq     " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_MOVSXD_GvEv, offset, base, index, scale, dst);
-    }
-
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    movl_ripr(RegisterID dst)
-    {
-        m_formatter.oneByteRipOp(OP_MOV_GvEv, 0, (RegisterID)dst);
-        JmpSrc label(m_formatter.size());
-        spew("movl       " MEM_o32r ", %s", ADDR_o32r(label.offset()), GPReg32Name(dst));
-        return label;
-    }
-
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    movl_rrip(RegisterID src)
-    {
-        m_formatter.oneByteRipOp(OP_MOV_EvGv, 0, (RegisterID)src);
-        JmpSrc label(m_formatter.size());
-        spew("movl       %s, " MEM_o32r "", GPReg32Name(src), ADDR_o32r(label.offset()));
-        return label;
-    }
-
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    movq_ripr(RegisterID dst)
-    {
-        m_formatter.oneByteRipOp64(OP_MOV_GvEv, 0, dst);
-        JmpSrc label(m_formatter.size());
-        spew("movq       " MEM_o32r ", %s", ADDR_o32r(label.offset()), GPRegName(dst));
-        return label;
-    }
-
-    void leaq_mr(int32_t offset, RegisterID base, RegisterID dst)
-    {
-        spew("leaq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
-        m_formatter.oneByteOp64(OP_LEA, offset, base, dst);
-    }
-
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    leaq_rip(RegisterID dst)
-    {
-        m_formatter.oneByteRipOp64(OP_LEA, 0, dst);
-        JmpSrc label(m_formatter.size());
-        spew("leaq       " MEM_o32r ", %s", ADDR_o32r(label.offset()), GPRegName(dst));
-        return label;
-    }
-
-    // Flow control:
-
-    void jmp_rip(int ripOffset)
-    {
-        // rip-relative addressing.
-        spew("jmp        *%d(%%rip)", ripOffset);
-        m_formatter.oneByteRipOp(OP_GROUP5_Ev, ripOffset, GROUP5_OP_JMPN);
-    }
-
-    void immediate64(int64_t imm)
-    {
-        spew(".quad      %lld", (long long)imm);
-        m_formatter.immediate64(imm);
-    }
-
-    // SSE operations:
-
-    void vcvtsq2sd_rr(RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
-    {
-        twoByteOpInt64Simd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, src1, src0, dst);
-    }
-    void vcvtsq2ss_rr(RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
-    {
-        twoByteOpInt64Simd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, src1, src0, dst);
-    }
-
-    void vcvtsi2sdq_rr(RegisterID src, XMMRegisterID dst)
-    {
-        twoByteOpInt64Simd("vcvtsi2sdq", VEX_SD, OP2_CVTSI2SD_VsdEd, src, invalid_xmm, dst);
-    }
-
-    void vcvttsd2sq_rr(XMMRegisterID src, RegisterID dst)
-    {
-        twoByteOpSimdInt64("vcvttsd2si", VEX_SD, OP2_CVTTSD2SI_GdWsd, src, dst);
-    }
-
-    void vcvttss2sq_rr(XMMRegisterID src, RegisterID dst)
-    {
-        twoByteOpSimdInt64("vcvttss2si", VEX_SS, OP2_CVTTSD2SI_GdWsd, src, dst);
-    }
-
-    void vmovq_rr(XMMRegisterID src, RegisterID dst)
-    {
-        // While this is called "vmovq", it actually uses the vmovd encoding
-        // with a REX prefix modifying it to be 64-bit.
-        twoByteOpSimdInt64("vmovq", VEX_PD, OP2_MOVD_EdVd, (XMMRegisterID)dst, (RegisterID)src);
-    }
-
-    void vmovq_rr(RegisterID src, XMMRegisterID dst)
-    {
-        // While this is called "vmovq", it actually uses the vmovd encoding
-        // with a REX prefix modifying it to be 64-bit.
-        twoByteOpInt64Simd("vmovq", VEX_PD, OP2_MOVD_VdEd, src, invalid_xmm, dst);
-    }
-
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    vmovsd_ripr(XMMRegisterID dst)
-    {
-        return twoByteRipOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, invalid_xmm, dst);
-    }
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    vmovss_ripr(XMMRegisterID dst)
-    {
-        return twoByteRipOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, invalid_xmm, dst);
-    }
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    vmovsd_rrip(XMMRegisterID src)
-    {
-        return twoByteRipOpSimd("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, invalid_xmm, src);
-    }
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    vmovss_rrip(XMMRegisterID src)
-    {
-        return twoByteRipOpSimd("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, invalid_xmm, src);
-    }
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    vmovdqa_rrip(XMMRegisterID src)
-    {
-        return twoByteRipOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, invalid_xmm, src);
-    }
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    vmovaps_rrip(XMMRegisterID src)
-    {
-        return twoByteRipOpSimd("vmovdqa", VEX_PS, OP2_MOVAPS_WsdVsd, invalid_xmm, src);
-    }
-
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    vmovaps_ripr(XMMRegisterID dst)
-    {
-        return twoByteRipOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, invalid_xmm, dst);
-    }
-
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    vmovdqa_ripr(XMMRegisterID dst)
-    {
-        return twoByteRipOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, invalid_xmm, dst);
-    }
-
-  private:
-
-    MOZ_WARN_UNUSED_RESULT JmpSrc
-    twoByteRipOpSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
-                     XMMRegisterID src0, XMMRegisterID dst)
-    {
-        if (useLegacySSEEncoding(src0, dst)) {
-            m_formatter.legacySSEPrefix(ty);
-            m_formatter.twoByteRipOp(opcode, 0, dst);
-            JmpSrc label(m_formatter.size());
-            if (IsXMMReversedOperands(opcode))
-                spew("%-11s%s, " MEM_o32r "", legacySSEOpName(name), XMMRegName(dst), ADDR_o32r(label.offset()));
-            else
-                spew("%-11s" MEM_o32r ", %s", legacySSEOpName(name), ADDR_o32r(label.offset()), XMMRegName(dst));
-            return label;
-        }
-
-        m_formatter.twoByteRipOpVex(ty, opcode, 0, src0, dst);
-        JmpSrc label(m_formatter.size());
-        if (src0 == invalid_xmm) {
-            if (IsXMMReversedOperands(opcode))
-                spew("%-11s%s, " MEM_o32r "", name, XMMRegName(dst), ADDR_o32r(label.offset()));
-            else
-                spew("%-11s" MEM_o32r ", %s", name, ADDR_o32r(label.offset()), XMMRegName(dst));
-        } else {
-            spew("%-11s" MEM_o32r ", %s, %s", name, ADDR_o32r(label.offset()), XMMRegName(src0), XMMRegName(dst));
-        }
-        return label;
-    }
-
-    void twoByteOpInt64Simd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
-                            RegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
-    {
-        if (useLegacySSEEncoding(src0, dst)) {
-            if (IsXMMReversedOperands(opcode))
-                spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(dst), GPRegName(rm));
-            else
-                spew("%-11s%s, %s", legacySSEOpName(name), GPRegName(rm), XMMRegName(dst));
-            m_formatter.legacySSEPrefix(ty);
-            m_formatter.twoByteOp64(opcode, rm, dst);
-            return;
-        }
-
-        if (src0 == invalid_xmm) {
-            if (IsXMMReversedOperands(opcode))
-                spew("%-11s%s, %s", name, XMMRegName(dst), GPRegName(rm));
-            else
-                spew("%-11s%s, %s", name, GPRegName(rm), XMMRegName(dst));
-        } else {
-            spew("%-11s%s, %s, %s", name, GPRegName(rm), XMMRegName(src0), XMMRegName(dst));
-        }
-        m_formatter.twoByteOpVex64(ty, opcode, rm, src0, dst);
-    }
-
-    void twoByteOpSimdInt64(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
-                            XMMRegisterID rm, RegisterID dst)
-    {
-        if (useLegacySSEEncodingForOtherOutput()) {
-            if (IsXMMReversedOperands(opcode))
-                spew("%-11s%s, %s", legacySSEOpName(name), GPRegName(dst), XMMRegName(rm));
-            else if (opcode == OP2_MOVD_EdVd)
-                spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName((XMMRegisterID)dst), GPRegName((RegisterID)rm));
-            else
-                spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), GPRegName(dst));
-            m_formatter.legacySSEPrefix(ty);
-            m_formatter.twoByteOp64(opcode, (RegisterID)rm, dst);
-            return;
-        }
-
-        if (IsXMMReversedOperands(opcode))
-            spew("%-11s%s, %s", name, GPRegName(dst), XMMRegName(rm));
-        else if (opcode == OP2_MOVD_EdVd)
-            spew("%-11s%s, %s", name, XMMRegName((XMMRegisterID)dst), GPRegName((RegisterID)rm));
-        else
-            spew("%-11s%s, %s", name, XMMRegName(rm), GPRegName(dst));
-        m_formatter.twoByteOpVex64(ty, opcode, (RegisterID)rm, invalid_xmm, (XMMRegisterID)dst);
-    }
-};
-
-typedef BaseAssemblerX64 BaseAssemblerSpecific;
-
-} // namespace X86Encoding
-
-} // namespace jit
-} // namespace js
-
-#endif /* jit_x64_BaseAssembler_x64_h */
--- a/js/src/jit/x64/CodeGenerator-x64.cpp
+++ b/js/src/jit/x64/CodeGenerator-x64.cpp
@@ -836,8 +836,134 @@ CodeGeneratorX64::visitTruncateFToInt32(
     FloatRegister input = ToFloatRegister(ins->input());
     Register output = ToRegister(ins->output());
 
     // On x64, branchTruncateFloat32 uses vcvttss2sq. Unlike the x86
     // implementation, this should handle most floats and we can just
     // call a stub if it fails.
     emitTruncateFloat32(input, output, ins->mir());
 }
+
+namespace js {
+namespace jit {
+
+// Out-of-line math_random_no_outparam call for LRandom.
+class OutOfLineRandom : public OutOfLineCodeBase<CodeGeneratorX64>
+{
+    LRandom* lir_;
+
+  public:
+    explicit OutOfLineRandom(LRandom* lir)
+      : lir_(lir)
+    { }
+
+    void accept(CodeGeneratorX64* codegen) {
+        codegen->visitOutOfLineRandom(this);
+    }
+
+    LRandom* lir() const {
+        return lir_;
+    }
+};
+
+} // namespace jit
+} // namespace js
+
+static const double RNG_DSCALE_INV = 1 / RNG_DSCALE;
+
+void
+CodeGeneratorX64::visitRandom(LRandom* ins)
+{
+    FloatRegister output = ToFloatRegister(ins->output());
+
+    Register JSCompartmentReg = ToRegister(ins->temp());
+    Register rngStateReg = ToRegister(ins->temp2());
+    Register highReg = ToRegister(ins->temp3());
+    Register lowReg = ToRegister(ins->temp4());
+    Register rngMaskReg = ToRegister(ins->temp5());
+
+    // rngState = cx->compartment()->rngState
+    masm.loadJSContext(JSCompartmentReg);
+    masm.loadPtr(Address(JSCompartmentReg, JSContext::offsetOfCompartment()), JSCompartmentReg);
+    masm.loadPtr(Address(JSCompartmentReg, JSCompartment::offsetOfRngState()), rngStateReg);
+
+    // if rngState == 0, escape from inlined code and call
+    // math_random_no_outparam.
+    OutOfLineRandom* ool = new(alloc()) OutOfLineRandom(ins);
+    addOutOfLineCode(ool, ins->mir());
+    masm.branchTestPtr(Assembler::Zero, rngStateReg, rngStateReg, ool->entry());
+
+    // nextstate = rngState * RNG_MULTIPLIER;
+    Register& rngMultiplierReg = lowReg;
+    masm.movq(ImmWord(RNG_MULTIPLIER), rngMultiplierReg);
+    masm.imulq(rngMultiplierReg, rngStateReg);
+
+    // nextstate += RNG_ADDEND;
+    masm.addq(Imm32(RNG_ADDEND), rngStateReg);
+
+    // nextstate &= RNG_MASK;
+    masm.movq(ImmWord(RNG_MASK), rngMaskReg);
+    masm.andq(rngMaskReg, rngStateReg);
+
+    // rngState = nextstate
+
+    // if rngState == 0, escape from inlined code and call
+    // math_random_no_outparam.
+    masm.j(Assembler::Zero, ool->entry());
+
+    // high = (nextstate >> (RNG_STATE_WIDTH - RNG_HIGH_BITS)) << RNG_LOW_BITS;
+    masm.movq(rngStateReg, highReg);
+    masm.shrq(Imm32(RNG_STATE_WIDTH - RNG_HIGH_BITS), highReg);
+    masm.shlq(Imm32(RNG_LOW_BITS), highReg);
+
+    // nextstate = rngState * RNG_MULTIPLIER;
+    masm.imulq(rngMultiplierReg, rngStateReg);
+
+    // nextstate += RNG_ADDEND;
+    masm.addq(Imm32(RNG_ADDEND), rngStateReg);
+
+    // nextstate &= RNG_MASK;
+    masm.andq(rngMaskReg, rngStateReg);
+
+    // low = nextstate >> (RNG_STATE_WIDTH - RNG_LOW_BITS);
+    masm.movq(rngStateReg, lowReg);
+    masm.shrq(Imm32(RNG_STATE_WIDTH - RNG_LOW_BITS), lowReg);
+
+    // output = double(high | low);
+    masm.orq(highReg, lowReg);
+    masm.vcvtsi2sdq(lowReg, output);
+
+    // output = output * RNG_DSCALE_INV;
+    Register& rngDscaleInvReg = lowReg;
+    masm.movq(ImmPtr(&RNG_DSCALE_INV), rngDscaleInvReg);
+    masm.vmulsd(Operand(rngDscaleInvReg, 0), output, output);
+
+    // cx->compartment()->rngState = nextstate
+    masm.storePtr(rngStateReg, Address(JSCompartmentReg, JSCompartment::offsetOfRngState()));
+
+    masm.bind(ool->rejoin());
+}
+
+void
+CodeGeneratorX64::visitOutOfLineRandom(OutOfLineRandom* ool)
+{
+    LRandom* ins = ool->lir();
+    Register temp = ToRegister(ins->temp());
+    Register temp2 = ToRegister(ins->temp2());
+    MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg);
+
+    LiveRegisterSet regs;
+    regs.add(ReturnFloat32Reg);
+    regs.add(ReturnDoubleReg);
+    regs.add(ReturnInt32x4Reg);
+    regs.add(ReturnFloat32x4Reg);
+    saveVolatile(regs);
+
+    masm.loadJSContext(temp);
+
+    masm.setupUnalignedABICall(temp2);
+    masm.passABIArg(temp);
+    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE);
+
+    restoreVolatile(regs);
+
+    masm.jump(ool->rejoin());
+}
--- a/js/src/jit/x64/CodeGenerator-x64.h
+++ b/js/src/jit/x64/CodeGenerator-x64.h
@@ -7,16 +7,18 @@
 #ifndef jit_x64_CodeGenerator_x64_h
 #define jit_x64_CodeGenerator_x64_h
 
 #include "jit/x86-shared/CodeGenerator-x86-shared.h"
 
 namespace js {
 namespace jit {
 
+class OutOfLineRandom;
+
 class CodeGeneratorX64 : public CodeGeneratorX86Shared
 {
     CodeGeneratorX64* thisFromCtor() {
         return this;
     }
 
   protected:
     ValueOperand ToValue(LInstruction* ins, size_t pos);
@@ -54,16 +56,18 @@ class CodeGeneratorX64 : public CodeGene
     void visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins);
     void visitAsmJSAtomicBinopHeapForEffect(LAsmJSAtomicBinopHeapForEffect* ins);
     void visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar* ins);
     void visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar* ins);
     void visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr* ins);
     void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins);
     void visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble* lir);
     void visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32* lir);
+    void visitRandom(LRandom* ins);
+    void visitOutOfLineRandom(OutOfLineRandom* ool);
 };
 
 typedef CodeGeneratorX64 CodeGeneratorSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_x64_CodeGenerator_x64_h */
--- a/js/src/jit/x64/LIR-x64.h
+++ b/js/src/jit/x64/LIR-x64.h
@@ -94,12 +94,47 @@ class LAsmJSLoadFuncPtr : public LInstru
     const LAllocation* index() {
         return getOperand(0);
     }
     const LDefinition* temp() {
         return getTemp(0);
     }
 };
 
+// Math.random().
+class LRandom : public LInstructionHelper<1, 0, 5>
+{
+  public:
+    LIR_HEADER(Random)
+    LRandom(const LDefinition &temp, const LDefinition &temp2, const LDefinition &temp3,
+            const LDefinition &temp4, const LDefinition &temp5)
+    {
+        setTemp(0, temp);
+        setTemp(1, temp2);
+        setTemp(2, temp3);
+        setTemp(3, temp4);
+        setTemp(4, temp5);
+    }
+    const LDefinition* temp() {
+        return getTemp(0);
+    }
+    const LDefinition* temp2() {
+        return getTemp(1);
+    }
+    const LDefinition *temp3() {
+        return getTemp(2);
+    }
+    const LDefinition *temp4() {
+        return getTemp(3);
+    }
+    const LDefinition *temp5() {
+        return getTemp(4);
+    }
+
+    MRandom* mir() const {
+        return mir_->toRandom();
+    }
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_x64_LIR_x64_h */
--- a/js/src/jit/x64/Lowering-x64.cpp
+++ b/js/src/jit/x64/Lowering-x64.cpp
@@ -333,11 +333,13 @@ LIRGeneratorX64::visitStoreTypedArrayEle
     MOZ_CRASH("NYI");
 }
 
 void
 LIRGeneratorX64::visitRandom(MRandom* ins)
 {
     LRandom *lir = new(alloc()) LRandom(temp(),
                                         temp(),
+                                        temp(),
+                                        temp(),
                                         temp());
     defineFixed(lir, ins, LFloatReg(ReturnDoubleReg));
 }
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -599,38 +599,31 @@ class MacroAssemblerX64 : public MacroAs
         }
     }
     void addPtr(ImmPtr imm, Register dest) {
         addPtr(ImmWord(uintptr_t(imm.value)), dest);
     }
     void addPtr(const Address& src, Register dest) {
         addq(Operand(src), dest);
     }
-    void add64(Imm32 imm, Register64 dest) {
-        addq(imm, dest.reg);
-    }
     void subPtr(Imm32 imm, Register dest) {
         subq(imm, dest);
     }
     void subPtr(Register src, Register dest) {
         subq(src, dest);
     }
     void subPtr(const Address& addr, Register dest) {
         subq(Operand(addr), dest);
     }
     void subPtr(Register src, const Address& dest) {
         subq(src, Operand(dest));
     }
     void mulBy3(const Register& src, const Register& dest) {
         lea(Operand(src, src, TimesTwo), dest);
     }
-    void mul64(Imm64 imm, const Register64& dest) {
-        movq(ImmWord(uintptr_t(imm.value)), ScratchReg);
-        imulq(ScratchReg, dest.reg);
-    }
 
     void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label* label) {
         if (X86Encoding::IsAddressImmediate(lhs.addr)) {
             branch32(cond, Operand(lhs), rhs, label);
         } else {
             ScratchRegisterScope scratch(asMasm());
             mov(ImmPtr(lhs.addr), scratch);
             branch32(cond, Address(scratch, 0), rhs, label);
@@ -743,20 +736,16 @@ class MacroAssemblerX64 : public MacroAs
         testPtr(Operand(lhs), imm);
         j(cond, label);
     }
     void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
         subPtr(imm, lhs);
         j(cond, label);
     }
 
-    void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, Label* label) {
-        branchTestPtr(cond, lhs.reg, rhs.reg, label);
-    }
-
     void movePtr(Register src, Register dest) {
         movq(src, dest);
     }
     void movePtr(Register src, const Operand& dest) {
         movq(src, dest);
     }
     void movePtr(ImmWord imm, Register dest) {
         mov(imm, dest);
@@ -765,19 +754,16 @@ class MacroAssemblerX64 : public MacroAs
         mov(imm, dest);
     }
     void movePtr(AsmJSImmPtr imm, Register dest) {
         mov(imm, dest);
     }
     void movePtr(ImmGCPtr imm, Register dest) {
         movq(imm, dest);
     }
-    void move64(Register64 src, Register64 dest) {
-        movq(src.reg, dest.reg);
-    }
     void loadPtr(AbsoluteAddress address, Register dest) {
         if (X86Encoding::IsAddressImmediate(address.addr)) {
             movq(Operand(address), dest);
         } else {
             ScratchRegisterScope scratch(asMasm());
             mov(ImmPtr(address.addr), scratch);
             loadPtr(Address(scratch, 0x0), dest);
         }
@@ -799,19 +785,16 @@ class MacroAssemblerX64 : public MacroAs
         if (X86Encoding::IsAddressImmediate(address.addr)) {
             movl(Operand(address), dest);
         } else {
             ScratchRegisterScope scratch(asMasm());
             mov(ImmPtr(address.addr), scratch);
             load32(Address(scratch, 0x0), dest);
         }
     }
-    void load64(const Address& address, Register64 dest) {
-        movq(Operand(address), dest.reg);
-    }
     template <typename T>
     void storePtr(ImmWord imm, T address) {
         if ((intptr_t)imm.value <= INT32_MAX && (intptr_t)imm.value >= INT32_MIN) {
             movq(Imm32((int32_t)imm.value), Operand(address));
         } else {
             ScratchRegisterScope scratch(asMasm());
             mov(imm, scratch);
             movq(scratch, Operand(address));
@@ -849,59 +832,43 @@ class MacroAssemblerX64 : public MacroAs
         if (X86Encoding::IsAddressImmediate(address.addr)) {
             movl(src, Operand(address));
         } else {
             ScratchRegisterScope scratch(asMasm());
             mov(ImmPtr(address.addr), scratch);
             store32(src, Address(scratch, 0x0));
         }
     }
-    void store64(Register64 src, Address address) {
-        movq(src.reg, Operand(address));
-    }
     void rshiftPtr(Imm32 imm, Register dest) {
         shrq(imm, dest);
     }
     void rshiftPtrArithmetic(Imm32 imm, Register dest) {
         sarq(imm, dest);
     }
-    void rshift64(Imm32 imm, Register64 dest) {
-        shrq(imm, dest.reg);
-    }
     void lshiftPtr(Imm32 imm, Register dest) {
         shlq(imm, dest);
     }
-    void lshift64(Imm32 imm, Register64 dest) {
-        shlq(imm, dest.reg);
-    }
     void xorPtr(Imm32 imm, Register dest) {
         xorq(imm, dest);
     }
     void xorPtr(Register src, Register dest) {
         xorq(src, dest);
     }
     void orPtr(Imm32 imm, Register dest) {
         orq(imm, dest);
     }
     void orPtr(Register src, Register dest) {
         orq(src, dest);
     }
-    void or64(Register64 src, Register64 dest) {
-        orq(src.reg, dest.reg);
-    }
     void andPtr(Imm32 imm, Register dest) {
         andq(imm, dest);
     }
     void andPtr(Register src, Register dest) {
         andq(src, dest);
     }
-    void and64(Imm64 imm, Register64 dest) {
-        movq(ImmWord(uintptr_t(imm.value)), ScratchReg);
-        andq(ScratchReg, dest.reg);
-    }
 
     void splitTag(Register src, Register dest) {
         if (src != dest)
             movq(src, dest);
         shrq(Imm32(JSVAL_TAG_SHIFT), dest);
     }
     void splitTag(const ValueOperand& operand, Register dest) {
         splitTag(operand.valueReg(), dest);
@@ -1416,25 +1383,16 @@ class MacroAssemblerX64 : public MacroAs
     void convertUInt32ToDouble(Register src, FloatRegister dest) {
         vcvtsq2sd(src, dest, dest);
     }
 
     void convertUInt32ToFloat32(Register src, FloatRegister dest) {
         vcvtsq2ss(src, dest, dest);
     }
 
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest) {
-        vcvtsi2sdq(src.reg, dest);
-    }
-
-    void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) {
-        movq(imm, ScratchReg);
-        vmulsd(Operand(ScratchReg, 0), dest, dest);
-    }
-
     void inc64(AbsoluteAddress dest) {
         if (X86Encoding::IsAddressImmediate(dest.addr)) {
             addPtr(Imm32(1), Operand(dest));
         } else {
             ScratchRegisterScope scratch(asMasm());
             mov(ImmPtr(dest.addr), scratch);
             addPtr(Imm32(1), Address(scratch, 0));
         }
--- a/js/src/jit/x86-shared/Assembler-x86-shared.h
+++ b/js/src/jit/x86-shared/Assembler-x86-shared.h
@@ -5,24 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_x86_shared_Assembler_x86_shared_h
 #define jit_x86_shared_Assembler_x86_shared_h
 
 #include <cstddef>
 
 #include "jit/shared/Assembler-shared.h"
-
-#if defined(JS_CODEGEN_X86)
-# include "jit/x86/BaseAssembler-x86.h"
-#elif defined(JS_CODEGEN_X64)
-# include "jit/x64/BaseAssembler-x64.h"
-#else
-# error "Unknown architecture!"
-#endif
+#include "jit/x86-shared/BaseAssembler-x86-shared.h"
 
 namespace js {
 namespace jit {
 
 struct ScratchFloat32Scope : public AutoFloatRegisterScope
 {
     explicit ScratchFloat32Scope(MacroAssembler& masm)
       : AutoFloatRegisterScope(masm, ScratchFloat32Reg)
@@ -263,17 +256,17 @@ class AssemblerX86Shared : public Assemb
             dataRelocations_.writeUnsigned(masm.currentOffset());
         }
     }
     void writePrebarrierOffset(CodeOffsetLabel label) {
         preBarriers_.writeUnsigned(label.offset());
     }
 
   protected:
-    X86Encoding::BaseAssemblerSpecific masm;
+    X86Encoding::BaseAssembler masm;
 
     typedef X86Encoding::JmpSrc JmpSrc;
     typedef X86Encoding::JmpDst JmpDst;
 
   public:
     AssemblerX86Shared()
     {
         if (!HasAVX())
--- a/js/src/jit/x86-shared/BaseAssembler-x86-shared.h
+++ b/js/src/jit/x86-shared/BaseAssembler-x86-shared.h
@@ -251,16 +251,30 @@ public:
     void pop_flags()
     {
         spew("popf");
         m_formatter.oneByteOp(OP_POPFLAGS);
     }
 
     // Arithmetic operations:
 
+#ifdef JS_CODEGEN_X86
+    void adcl_im(int32_t imm, const void* addr)
+    {
+        spew("adcl       %d, %p", imm, addr);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_ADC);
+            m_formatter.immediate8s(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_ADC);
+            m_formatter.immediate32(imm);
+        }
+    }
+#endif
+
     void addl_rr(RegisterID src, RegisterID dst)
     {
         spew("addl       %s, %s", GPReg32Name(src), GPReg32Name(dst));
         m_formatter.oneByteOp(OP_ADD_GvEv, src, dst);
     }
 
     void addw_rr(RegisterID src, RegisterID dst)
     {
@@ -340,16 +354,74 @@ public:
             m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_ADD);
             m_formatter.immediate8s(imm);
         } else {
             m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_ADD);
             m_formatter.immediate32(imm);
         }
     }
 
+#ifdef JS_CODEGEN_X64
+    void addq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("addq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_ADD_GvEv, src, dst);
+    }
+
+    void addq_mr(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("addq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_ADD_GvEv, offset, base, dst);
+    }
+
+    void addq_mr(const void* addr, RegisterID dst)
+    {
+        spew("addq       %p, %s", addr, GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_ADD_GvEv, addr, dst);
+    }
+
+    void addq_ir(int32_t imm, RegisterID dst)
+    {
+        spew("addq       $%d, %s", imm, GPReg64Name(dst));
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_ADD);
+            m_formatter.immediate8s(imm);
+        } else {
+            if (dst == rax)
+                m_formatter.oneByteOp64(OP_ADD_EAXIv);
+            else
+                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD);
+            m_formatter.immediate32(imm);
+        }
+    }
+
+    void addq_im(int32_t imm, int32_t offset, RegisterID base)
+    {
+        spew("addq       $%d, " MEM_ob, imm, ADDR_ob(offset, base));
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, offset, base, GROUP1_OP_ADD);
+            m_formatter.immediate8s(imm);
+        } else {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIz, offset, base, GROUP1_OP_ADD);
+            m_formatter.immediate32(imm);
+        }
+    }
+
+    void addq_im(int32_t imm, const void* addr)
+    {
+        spew("addq       $%d, %p", imm, addr);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, addr, GROUP1_OP_ADD);
+            m_formatter.immediate8s(imm);
+        } else {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIz, addr, GROUP1_OP_ADD);
+            m_formatter.immediate32(imm);
+        }
+    }
+#endif
     void addl_im(int32_t imm, const void* addr)
     {
         spew("addl       $%d, %p", imm, addr);
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_ADD);
             m_formatter.immediate8s(imm);
         } else {
             m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_ADD);
@@ -792,16 +864,81 @@ public:
             m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_AND);
             m_formatter.immediate8s(imm);
         } else {
             m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_AND);
             m_formatter.immediate16(imm);
         }
     }
 
+#ifdef JS_CODEGEN_X64
+    void andq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("andq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_AND_GvEv, src, dst);
+    }
+
+    void andq_mr(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("andq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_AND_GvEv, offset, base, dst);
+    }
+
+    void andq_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    {
+        spew("andq       " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_AND_GvEv, offset, base, index, scale, dst);
+    }
+
+    void andq_mr(const void* addr, RegisterID dst)
+    {
+        spew("andq       %p, %s", addr, GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_AND_GvEv, addr, dst);
+    }
+
+    void orq_mr(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("orq        " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_OR_GvEv, offset, base, dst);
+    }
+
+    void orq_mr(const void* addr, RegisterID dst)
+    {
+        spew("orq        %p, %s", addr, GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_OR_GvEv, addr, dst);
+    }
+
+    void andq_ir(int32_t imm, RegisterID dst)
+    {
+        spew("andq       $0x%" PRIx64 ", %s", int64_t(imm), GPReg64Name(dst));
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_AND);
+            m_formatter.immediate8s(imm);
+        } else {
+            if (dst == rax)
+                m_formatter.oneByteOp64(OP_AND_EAXIv);
+            else
+                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_AND);
+            m_formatter.immediate32(imm);
+        }
+    }
+#else
+    void andl_im(int32_t imm, const void* addr)
+    {
+        spew("andl       $0x%x, %p", imm, addr);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_AND);
+            m_formatter.immediate8s(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_AND);
+            m_formatter.immediate32(imm);
+        }
+    }
+#endif
+
     void fld_m(int32_t offset, RegisterID base)
     {
         spew("fld        " MEM_ob, ADDR_ob(offset, base));
         m_formatter.oneByteOp(OP_FPU6, offset, base, FPU6_OP_FLD);
     }
     void fld32_m(int32_t offset, RegisterID base)
     {
         spew("fld        " MEM_ob, ADDR_ob(offset, base));
@@ -968,16 +1105,63 @@ public:
             m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_OR);
             m_formatter.immediate8s(imm);
         } else {
             m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_OR);
             m_formatter.immediate16(imm);
         }
     }
 
+#ifdef JS_CODEGEN_X64
+    void negq_r(RegisterID dst)
+    {
+        spew("negq       %s", GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_GROUP3_Ev, dst, GROUP3_OP_NEG);
+    }
+
+    void orq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("orq        %s, %s", GPReg64Name(src), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_OR_GvEv, src, dst);
+    }
+
+    void orq_ir(int32_t imm, RegisterID dst)
+    {
+        spew("orq        $0x%" PRIx64 ", %s", int64_t(imm), GPReg64Name(dst));
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_OR);
+            m_formatter.immediate8s(imm);
+        } else {
+            if (dst == rax)
+                m_formatter.oneByteOp64(OP_OR_EAXIv);
+            else
+                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_OR);
+            m_formatter.immediate32(imm);
+        }
+    }
+
+    void notq_r(RegisterID dst)
+    {
+        spew("notq       %s", GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_GROUP3_Ev, dst, GROUP3_OP_NOT);
+    }
+#else
+    void orl_im(int32_t imm, const void* addr)
+    {
+        spew("orl        $0x%x, %p", imm, addr);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_OR);
+            m_formatter.immediate8s(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_OR);
+            m_formatter.immediate32(imm);
+        }
+    }
+#endif
+
     void subl_rr(RegisterID src, RegisterID dst)
     {
         spew("subl       %s, %s", GPReg32Name(src), GPReg32Name(dst));
         m_formatter.oneByteOp(OP_SUB_GvEv, src, dst);
     }
 
     void subw_rr(RegisterID src, RegisterID dst)
     {
@@ -1094,16 +1278,69 @@ public:
             m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_SUB);
             m_formatter.immediate8s(imm);
         } else {
             m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_SUB);
             m_formatter.immediate16(imm);
         }
     }
 
+#ifdef JS_CODEGEN_X64
+    void subq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("subq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_SUB_GvEv, src, dst);
+    }
+
+    void subq_rm(RegisterID src, int32_t offset, RegisterID base)
+    {
+        spew("subq       %s, " MEM_ob, GPReg64Name(src), ADDR_ob(offset, base));
+        m_formatter.oneByteOp64(OP_SUB_EvGv, offset, base, src);
+    }
+
+    void subq_mr(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("subq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_SUB_GvEv, offset, base, dst);
+    }
+
+    void subq_mr(const void* addr, RegisterID dst)
+    {
+        spew("subq       %p, %s", addr, GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_SUB_GvEv, addr, dst);
+    }
+
+    void subq_ir(int32_t imm, RegisterID dst)
+    {
+        spew("subq       $%d, %s", imm, GPReg64Name(dst));
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_SUB);
+            m_formatter.immediate8s(imm);
+        } else {
+            if (dst == rax)
+                m_formatter.oneByteOp64(OP_SUB_EAXIv);
+            else
+                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_SUB);
+            m_formatter.immediate32(imm);
+        }
+    }
+#else
+    void subl_im(int32_t imm, const void* addr)
+    {
+        spew("subl       $%d, %p", imm, addr);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_SUB);
+            m_formatter.immediate8s(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_SUB);
+            m_formatter.immediate32(imm);
+        }
+    }
+#endif
+
     void xorl_rr(RegisterID src, RegisterID dst)
     {
         spew("xorl       %s, %s", GPReg32Name(src), GPReg32Name(dst));
         m_formatter.oneByteOp(OP_XOR_GvEv, src, dst);
     }
 
     void xorw_rr(RegisterID src, RegisterID dst)
     {
@@ -1220,16 +1457,39 @@ public:
             if (dst == rax)
                 m_formatter.oneByteOp(OP_XOR_EAXIv);
             else
                 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_XOR);
             m_formatter.immediate16(imm);
         }
     }
 
+#ifdef JS_CODEGEN_X64
+    void xorq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("xorq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_XOR_GvEv, src, dst);
+    }
+
+    void xorq_ir(int32_t imm, RegisterID dst)
+    {
+        spew("xorq       $0x%" PRIx64 ", %s", int64_t(imm), GPReg64Name(dst));
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, dst, GROUP1_OP_XOR);
+            m_formatter.immediate8s(imm);
+        } else {
+            if (dst == rax)
+                m_formatter.oneByteOp64(OP_XOR_EAXIv);
+            else
+                m_formatter.oneByteOp64(OP_GROUP1_EvIz, dst, GROUP1_OP_XOR);
+            m_formatter.immediate32(imm);
+        }
+    }
+#endif
+
     void sarl_ir(int32_t imm, RegisterID dst)
     {
         MOZ_ASSERT(imm < 32);
         spew("sarl       $%d, %s", imm, GPReg32Name(dst));
         if (imm == 1)
             m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_SAR);
         else {
             m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_SAR);
@@ -1274,16 +1534,60 @@ public:
     }
 
     void shll_CLr(RegisterID dst)
     {
         spew("shll       %%cl, %s", GPReg32Name(dst));
         m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_SHL);
     }
 
+#ifdef JS_CODEGEN_X64
+    void sarq_CLr(RegisterID dst)
+    {
+        spew("sarq       %%cl, %s", GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_GROUP2_EvCL, dst, GROUP2_OP_SAR);
+    }
+
+    void sarq_ir(int32_t imm, RegisterID dst)
+    {
+        MOZ_ASSERT(imm < 64);
+        spew("sarq       $%d, %s", imm, GPReg64Name(dst));
+        if (imm == 1)
+            m_formatter.oneByteOp64(OP_GROUP2_Ev1, dst, GROUP2_OP_SAR);
+        else {
+            m_formatter.oneByteOp64(OP_GROUP2_EvIb, dst, GROUP2_OP_SAR);
+            m_formatter.immediate8u(imm);
+        }
+    }
+
+    void shlq_ir(int32_t imm, RegisterID dst)
+    {
+        MOZ_ASSERT(imm < 64);
+        spew("shlq       $%d, %s", imm, GPReg64Name(dst));
+        if (imm == 1)
+            m_formatter.oneByteOp64(OP_GROUP2_Ev1, dst, GROUP2_OP_SHL);
+        else {
+            m_formatter.oneByteOp64(OP_GROUP2_EvIb, dst, GROUP2_OP_SHL);
+            m_formatter.immediate8u(imm);
+        }
+    }
+
+    void shrq_ir(int32_t imm, RegisterID dst)
+    {
+        MOZ_ASSERT(imm < 64);
+        spew("shrq       $%d, %s", imm, GPReg64Name(dst));
+        if (imm == 1)
+            m_formatter.oneByteOp64(OP_GROUP2_Ev1, dst, GROUP2_OP_SHR);
+        else {
+            m_formatter.oneByteOp64(OP_GROUP2_EvIb, dst, GROUP2_OP_SHR);
+            m_formatter.immediate8u(imm);
+        }
+    }
+#endif
+
     void bsr_rr(RegisterID src, RegisterID dst)
     {
         spew("bsr        %s, %s", GPReg32Name(src), GPReg32Name(dst));
         m_formatter.twoByteOp(OP2_BSR_GvEv, src, dst);
     }
 
     void imull_rr(RegisterID src, RegisterID dst)
     {
@@ -1310,16 +1614,24 @@ public:
             m_formatter.oneByteOp(OP_IMUL_GvEvIb, src, dst);
             m_formatter.immediate8s(value);
         } else {
             m_formatter.oneByteOp(OP_IMUL_GvEvIz, src, dst);
             m_formatter.immediate32(value);
         }
     }
 
+#ifdef JS_CODEGEN_X64
+    void imulq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("imulq      %s, %s", GPReg64Name(src), GPReg64Name(dst));
+        m_formatter.twoByteOp64(OP2_IMUL_GvEv, src, dst);
+    }
+#endif
+
     void mull_r(RegisterID multiplier)
     {
         spew("mull       %s", GPReg32Name(multiplier));
         m_formatter.oneByteOp(OP_GROUP3_Ev, multiplier, GROUP3_OP_MUL);
     }
 
     void idivl_r(RegisterID divisor)
     {
@@ -1532,16 +1844,95 @@ public:
 
     void cmpl_i32m(int32_t rhs, const void* addr)
     {
         spew("cmpl       $0x%04x, %p", rhs, addr);
         m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_CMP);
         m_formatter.immediate32(rhs);
     }
 
+#ifdef JS_CODEGEN_X64
+    void cmpq_rr(RegisterID rhs, RegisterID lhs)
+    {
+        spew("cmpq       %s, %s", GPReg64Name(rhs), GPReg64Name(lhs));
+        m_formatter.oneByteOp64(OP_CMP_GvEv, rhs, lhs);
+    }
+
+    void cmpq_rm(RegisterID rhs, int32_t offset, RegisterID base)
+    {
+        spew("cmpq       %s, " MEM_ob, GPReg64Name(rhs), ADDR_ob(offset, base));
+        m_formatter.oneByteOp64(OP_CMP_EvGv, offset, base, rhs);
+    }
+
+    void cmpq_mr(int32_t offset, RegisterID base, RegisterID lhs)
+    {
+        spew("cmpq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(lhs));
+        m_formatter.oneByteOp64(OP_CMP_GvEv, offset, base, lhs);
+    }
+
+    void cmpq_ir(int32_t rhs, RegisterID lhs)
+    {
+        if (rhs == 0) {
+            testq_rr(lhs, lhs);
+            return;
+        }
+
+        spew("cmpq       $0x%" PRIx64 ", %s", int64_t(rhs), GPReg64Name(lhs));
+        if (CAN_SIGN_EXTEND_8_32(rhs)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, lhs, GROUP1_OP_CMP);
+            m_formatter.immediate8s(rhs);
+        } else {
+            if (lhs == rax)
+                m_formatter.oneByteOp64(OP_CMP_EAXIv);
+            else
+                m_formatter.oneByteOp64(OP_GROUP1_EvIz, lhs, GROUP1_OP_CMP);
+            m_formatter.immediate32(rhs);
+        }
+    }
+
+    void cmpq_im(int32_t rhs, int32_t offset, RegisterID base)
+    {
+        spew("cmpq       $0x%" PRIx64 ", " MEM_ob, int64_t(rhs), ADDR_ob(offset, base));
+        if (CAN_SIGN_EXTEND_8_32(rhs)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, offset, base, GROUP1_OP_CMP);
+            m_formatter.immediate8s(rhs);
+        } else {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIz, offset, base, GROUP1_OP_CMP);
+            m_formatter.immediate32(rhs);
+        }
+    }
+
+    void cmpq_im(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
+    {
+        spew("cmpq       $0x%x, " MEM_obs, rhs, ADDR_obs(offset, base, index, scale));
+        if (CAN_SIGN_EXTEND_8_32(rhs)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_CMP);
+            m_formatter.immediate8s(rhs);
+        } else {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_CMP);
+            m_formatter.immediate32(rhs);
+        }
+    }
+    void cmpq_im(int32_t rhs, const void* addr)
+    {
+        spew("cmpq       $0x%" PRIx64 ", %p", int64_t(rhs), addr);
+        if (CAN_SIGN_EXTEND_8_32(rhs)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, addr, GROUP1_OP_CMP);
+            m_formatter.immediate8s(rhs);
+        } else {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIz, addr, GROUP1_OP_CMP);
+            m_formatter.immediate32(rhs);
+        }
+    }
+    void cmpq_rm(RegisterID rhs, const void* addr)
+    {
+        spew("cmpq       %s, %p", GPReg64Name(rhs), addr);
+        m_formatter.oneByteOp64(OP_CMP_EvGv, addr, rhs);
+    }
+#endif
     void cmpl_rm(RegisterID rhs, const void* addr)
     {
         spew("cmpl       %s, %p", GPReg32Name(rhs), addr);
         m_formatter.oneByteOp(OP_CMP_EvGv, addr, rhs);
     }
 
     void cmpl_rm_disp32(RegisterID rhs, const void* addr)
     {
@@ -1653,16 +2044,54 @@ public:
 
     void testl_i32m(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
     {
         spew("testl      $0x%4x, " MEM_obs, rhs, ADDR_obs(offset, base, index, scale));
         m_formatter.oneByteOp(OP_GROUP3_EvIz, offset, base, index, scale, GROUP3_OP_TEST);
         m_formatter.immediate32(rhs);
     }
 
+#ifdef JS_CODEGEN_X64
+    void testq_rr(RegisterID rhs, RegisterID lhs)
+    {
+        spew("testq      %s, %s", GPReg64Name(rhs), GPReg64Name(lhs));
+        m_formatter.oneByteOp64(OP_TEST_EvGv, lhs, rhs);
+    }
+
+    void testq_ir(int32_t rhs, RegisterID lhs)
+    {
+        // If the mask fits in a 32-bit immediate, we can use testl with a
+        // 32-bit subreg.
+        if (CAN_ZERO_EXTEND_32_64(rhs)) {
+            testl_ir(rhs, lhs);
+            return;
+        }
+        spew("testq      $0x%" PRIx64 ", %s", int64_t(rhs), GPReg64Name(lhs));
+        if (lhs == rax)
+            m_formatter.oneByteOp64(OP_TEST_EAXIv);
+        else
+            m_formatter.oneByteOp64(OP_GROUP3_EvIz, lhs, GROUP3_OP_TEST);
+        m_formatter.immediate32(rhs);
+    }
+
+    void testq_i32m(int32_t rhs, int32_t offset, RegisterID base)
+    {
+        spew("testq      $0x%" PRIx64 ", " MEM_ob, int64_t(rhs), ADDR_ob(offset, base));
+        m_formatter.oneByteOp64(OP_GROUP3_EvIz, offset, base, GROUP3_OP_TEST);
+        m_formatter.immediate32(rhs);
+    }
+
+    void testq_i32m(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
+    {
+        spew("testq      $0x%4x, " MEM_obs, rhs, ADDR_obs(offset, base, index, scale));
+        m_formatter.oneByteOp64(OP_GROUP3_EvIz, offset, base, index, scale, GROUP3_OP_TEST);
+        m_formatter.immediate32(rhs);
+    }
+#endif
+
     void testw_rr(RegisterID rhs, RegisterID lhs)
     {
         spew("testw      %s, %s", GPReg16Name(rhs), GPReg16Name(lhs));
         m_formatter.prefix(PRE_OPERAND_SIZE);
         m_formatter.oneByteOp(OP_TEST_EvGv, lhs, rhs);
     }
 
     void testb_ir(int32_t rhs, RegisterID lhs)
@@ -1753,16 +2182,34 @@ public:
         m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, src);
     }
     void xchgl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
     {
         spew("xchgl      %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
         m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, index, scale, src);
     }
 
+#ifdef JS_CODEGEN_X64
+    void xchgq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("xchgq      %s, %s", GPReg64Name(src), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_XCHG_GvEv, src, dst);
+    }
+    void xchgq_rm(RegisterID src, int32_t offset, RegisterID base)
+    {
+        spew("xchgq      %s, " MEM_ob, GPReg64Name(src), ADDR_ob(offset, base));
+        m_formatter.oneByteOp64(OP_XCHG_GvEv, offset, base, src);
+    }
+    void xchgq_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
+    {
+        spew("xchgq      %s, " MEM_obs, GPReg64Name(src), ADDR_obs(offset, base, index, scale));
+        m_formatter.oneByteOp64(OP_XCHG_GvEv, offset, base, index, scale, src);
+    }
+#endif
+
     void movl_rr(RegisterID src, RegisterID dst)
     {
         spew("movl       %s, %s", GPReg32Name(src), GPReg32Name(dst));
         m_formatter.oneByteOp(OP_MOV_GvEv, src, dst);
     }
 
     void movw_rm(RegisterID src, int32_t offset, RegisterID base)
     {
@@ -1960,16 +2407,53 @@ public:
         m_formatter.oneByteOp(OP_MOV_OvEAX);
 #ifdef JS_CODEGEN_X64
         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
 #else
         m_formatter.immediate32(reinterpret_cast<int32_t>(addr));
 #endif
     }
 
+#ifdef JS_CODEGEN_X64
+    void movq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("movq       %s, %s", GPReg64Name(src), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_MOV_GvEv, src, dst);
+    }
+
+    void movq_rm(RegisterID src, int32_t offset, RegisterID base)
+    {
+        spew("movq       %s, " MEM_ob, GPReg64Name(src), ADDR_ob(offset, base));
+        m_formatter.oneByteOp64(OP_MOV_EvGv, offset, base, src);
+    }
+
+    void movq_rm_disp32(RegisterID src, int32_t offset, RegisterID base)
+    {
+        spew("movq       %s, " MEM_o32b, GPReg64Name(src), ADDR_o32b(offset, base));
+        m_formatter.oneByteOp64_disp32(OP_MOV_EvGv, offset, base, src);
+    }
+
+    void movq_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
+    {
+        spew("movq       %s, " MEM_obs, GPReg64Name(src), ADDR_obs(offset, base, index, scale));
+        m_formatter.oneByteOp64(OP_MOV_EvGv, offset, base, index, scale, src);
+    }
+
+    void movq_rm(RegisterID src, const void* addr)
+    {
+        if (src == rax && !IsAddressImmediate(addr)) {
+            movq_EAXm(addr);
+            return;
+        }
+
+        spew("movq       %s, %p", GPReg64Name(src), addr);
+        m_formatter.oneByteOp64(OP_MOV_EvGv, addr, src);
+    }
+#endif
+
     void vmovq_rm(XMMRegisterID src, int32_t offset, RegisterID base)
     {
         // vmovq_rm can be encoded either as a true vmovq or as a vmovd with a
         // REX prefix modifying it to be 64-bit. We choose the vmovq encoding
         // because it's smaller (when it doesn't need a REX prefix for other
         // reasons) and because it works on 32-bit x86 too.
         twoByteOpSimd("vmovq", VEX_PD, OP2_MOVQ_WdVd, offset, base, invalid_xmm, src);
     }
@@ -1984,16 +2468,71 @@ public:
         twoByteOpSimd("vmovq", VEX_PD, OP2_MOVQ_WdVd, offset, base, index, scale, invalid_xmm, src);
     }
 
     void vmovq_rm(XMMRegisterID src, const void* addr)
     {
         twoByteOpSimd("vmovq", VEX_PD, OP2_MOVQ_WdVd, addr, invalid_xmm, src);
     }
 
+#ifdef JS_CODEGEN_X64
+    void movq_mEAX(const void* addr)
+    {
+        if (IsAddressImmediate(addr)) {
+            movq_mr(addr, rax);
+            return;
+        }
+
+        spew("movq       %p, %%rax", addr);
+        m_formatter.oneByteOp64(OP_MOV_EAXOv);
+        m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
+    }
+
+    void movq_EAXm(const void* addr)
+    {
+        if (IsAddressImmediate(addr)) {
+            movq_rm(rax, addr);
+            return;
+        }
+
+        spew("movq       %%rax, %p", addr);
+        m_formatter.oneByteOp64(OP_MOV_OvEAX);
+        m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
+    }
+
+    void movq_mr(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("movq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_MOV_GvEv, offset, base, dst);
+    }
+
+    void movq_mr_disp32(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("movq       " MEM_o32b ", %s", ADDR_o32b(offset, base), GPReg64Name(dst));
+        m_formatter.oneByteOp64_disp32(OP_MOV_GvEv, offset, base, dst);
+    }
+
+    void movq_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    {
+        spew("movq       " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_MOV_GvEv, offset, base, index, scale, dst);
+    }
+
+    void movq_mr(const void* addr, RegisterID dst)
+    {
+        if (dst == rax && !IsAddressImmediate(addr)) {
+            movq_mEAX(addr);
+            return;
+        }
+
+        spew("movq       %p, %s", addr, GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_MOV_GvEv, addr, dst);
+    }
+#endif
+
     void vmovq_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
     {
         // vmovq_mr can be encoded either as a true vmovq or as a vmovd with a
         // REX prefix modifying it to be 64-bit. We choose the vmovq encoding
         // because it's smaller (when it doesn't need a REX prefix for other
         // reasons) and because it works on 32-bit x86 too.
         twoByteOpSimd("vmovq", VEX_SS, OP2_MOVQ_VdWd, offset, base, invalid_xmm, dst);
     }
@@ -2008,16 +2547,105 @@ public:
         twoByteOpSimd("vmovq", VEX_SS, OP2_MOVQ_VdWd, offset, base, index, scale, invalid_xmm, dst);
     }
 
     void vmovq_mr(const void* addr, XMMRegisterID dst)
     {
         twoByteOpSimd("vmovq", VEX_SS, OP2_MOVQ_VdWd, addr, invalid_xmm, dst);
     }
 
+#ifdef JS_CODEGEN_X64
+    void leaq_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    {
+        spew("leaq       " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg64Name(dst)),
+        m_formatter.oneByteOp64(OP_LEA, offset, base, index, scale, dst);
+    }
+
+    void movq_i32m(int32_t imm, int32_t offset, RegisterID base)
+    {
+        spew("movq       $%d, " MEM_ob, imm, ADDR_ob(offset, base));
+        m_formatter.oneByteOp64(OP_GROUP11_EvIz, offset, base, GROUP11_MOV);
+        m_formatter.immediate32(imm);
+    }
+
+    void movq_i32m(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
+    {
+        spew("movq       $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
+        m_formatter.oneByteOp64(OP_GROUP11_EvIz, offset, base, index, scale, GROUP11_MOV);
+        m_formatter.immediate32(imm);
+    }
+    void movq_i32m(int32_t imm, const void* addr)
+    {
+        spew("movq       $%d, %p", imm, addr);
+        m_formatter.oneByteOp64(OP_GROUP11_EvIz, addr, GROUP11_MOV);
+        m_formatter.immediate32(imm);
+    }
+
+    // Note that this instruction sign-extends its 32-bit immediate field to 64
+    // bits and loads the 64-bit value into a 64-bit register.
+    //
+    // Note also that this is similar to the movl_i32r instruction, except that
+    // movl_i32r *zero*-extends its 32-bit immediate, and it has smaller code
+    // size, so it's preferred for values which could use either.
+    void movq_i32r(int32_t imm, RegisterID dst) {
+        spew("movq       $%d, %s", imm, GPRegName(dst));
+        m_formatter.oneByteOp64(OP_GROUP11_EvIz, dst, GROUP11_MOV);
+        m_formatter.immediate32(imm);
+    }
+
+    void movq_i64r(int64_t imm, RegisterID dst)
+    {
+        spew("movabsq    $0x%" PRIx64 ", %s", imm, GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_MOV_EAXIv, dst);
+        m_formatter.immediate64(imm);
+    }
+
+    void movslq_rr(RegisterID src, RegisterID dst)
+    {
+        spew("movslq     %s, %s", GPReg32Name(src), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_MOVSXD_GvEv, src, dst);
+    }
+    void movslq_mr(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("movslq     " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_MOVSXD_GvEv, offset, base, dst);
+    }
+    void movslq_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    {
+        spew("movslq     " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_MOVSXD_GvEv, offset, base, index, scale, dst);
+    }
+
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    movl_ripr(RegisterID dst)
+    {
+        m_formatter.oneByteRipOp(OP_MOV_GvEv, 0, (RegisterID)dst);
+        JmpSrc label(m_formatter.size());
+        spew("movl       " MEM_o32r ", %s", ADDR_o32r(label.offset()), GPReg32Name(dst));
+        return label;
+    }
+
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    movl_rrip(RegisterID src)
+    {
+        m_formatter.oneByteRipOp(OP_MOV_EvGv, 0, (RegisterID)src);
+        JmpSrc label(m_formatter.size());
+        spew("movl       %s, " MEM_o32r "", GPReg32Name(src), ADDR_o32r(label.offset()));
+        return label;
+    }
+
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    movq_ripr(RegisterID dst)
+    {
+        m_formatter.oneByteRipOp64(OP_MOV_GvEv, 0, dst);
+        JmpSrc label(m_formatter.size());
+        spew("movq       " MEM_o32r ", %s", ADDR_o32r(label.offset()), GPRegName(dst));
+        return label;
+    }
+#endif
     void movl_rm(RegisterID src, const void* addr)
     {
         if (src == rax
 #ifdef JS_CODEGEN_X64
             && !IsAddressImmediate(addr)
 #endif
             ) {
             movl_EAXm(addr);
@@ -2197,16 +2825,32 @@ public:
         m_formatter.oneByteOp(OP_LEA, offset, base, index, scale, dst);
     }
 
     void leal_mr(int32_t offset, RegisterID base, RegisterID dst)
     {
         spew("leal       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
         m_formatter.oneByteOp(OP_LEA, offset, base, dst);
     }
+#ifdef JS_CODEGEN_X64
+    void leaq_mr(int32_t offset, RegisterID base, RegisterID dst)
+    {
+        spew("leaq       " MEM_ob ", %s", ADDR_ob(offset, base), GPReg64Name(dst));
+        m_formatter.oneByteOp64(OP_LEA, offset, base, dst);
+    }
+
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    leaq_rip(RegisterID dst)
+    {
+        m_formatter.oneByteRipOp64(OP_LEA, 0, dst);
+        JmpSrc label(m_formatter.size());
+        spew("leaq       " MEM_o32r ", %s", ADDR_o32r(label.offset()), GPRegName(dst));
+        return label;
+    }
+#endif
 
     // Flow control:
 
     MOZ_WARN_UNUSED_RESULT JmpSrc
     call()
     {
         m_formatter.oneByteOp(OP_CALL_rel32);
         JmpSrc r = m_formatter.immediateRel32();
@@ -2275,16 +2919,30 @@ public:
         m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_JMPN);
     }
 
     void jmp_m(int32_t offset, RegisterID base, RegisterID index, int scale) {
         spew("jmp        *" MEM_obs, ADDR_obs(offset, base, index, scale));
         m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, index, scale, GROUP5_OP_JMPN);
     }
 
+#ifdef JS_CODEGEN_X64
+    void jmp_rip(int ripOffset) {
+        // rip-relative addressing.
+        spew("jmp        *%d(%%rip)", ripOffset);
+        m_formatter.oneByteRipOp(OP_GROUP5_Ev, ripOffset, GROUP5_OP_JMPN);
+    }
+
+    void immediate64(int64_t imm)
+    {
+        spew(".quad      %lld", (long long)imm);
+        m_formatter.immediate64(imm);
+    }
+#endif
+
     void jCC_i(Condition cond, JmpDst dst)
     {
         int32_t diff = dst.offset() - m_formatter.size();
         spew("j%s        .Llabel%d", CCName(cond), dst.offset());
 
         // The jump immediate is an offset from the end of the jump instruction.
         // A conditional jump instruction is either 1 byte opcode and 1 byte
         // offset, or 2 bytes opcode and 4 bytes offset.
@@ -2436,16 +3094,27 @@ public:
         twoByteOpSimd("vcvttps2dq", VEX_SS, OP2_CVTTPS2DQ_VdqWps, src, invalid_xmm, dst);
     }
 
     void vcvtdq2ps_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         twoByteOpSimd("vcvtdq2ps", VEX_PS, OP2_CVTDQ2PS_VpsWdq, src, invalid_xmm, dst);
     }
 
+#ifdef JS_CODEGEN_X64
+    void vcvtsq2sd_rr(RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
+    {
+        twoByteOpInt64Simd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, src1, src0, dst);
+    }
+    void vcvtsq2ss_rr(RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
+    {
+        twoByteOpInt64Simd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, src1, src0, dst);
+    }
+#endif
+
     void vcvtsi2sd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
     {
         twoByteOpSimd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, offset, base, src0, dst);
     }
 
     void vcvtsi2sd_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID src0, XMMRegisterID dst)
     {
         twoByteOpSimd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, offset, base, index, scale, src0, dst);
@@ -2456,26 +3125,52 @@ public:
         twoByteOpSimd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, offset, base, src0, dst);
     }
 
     void vcvtsi2ss_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID src0, XMMRegisterID dst)
     {
         twoByteOpSimd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, offset, base, index, scale, src0, dst);
     }
 
+#ifdef JS_CODEGEN_X86
+    void vcvtsi2sd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
+    {
+        twoByteOpSimd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, address, src0, dst);
+    }
+#endif
+
+#ifdef JS_CODEGEN_X64
+    void vcvtsi2sdq_rr(RegisterID src, XMMRegisterID dst)
+    {
+        twoByteOpInt64Simd("vcvtsi2sdq", VEX_SD, OP2_CVTSI2SD_VsdEd, src, invalid_xmm, dst);
+    }
+#endif
+
     void vcvttsd2si_rr(XMMRegisterID src, RegisterID dst)
     {
         twoByteOpSimdInt32("vcvttsd2si", VEX_SD, OP2_CVTTSD2SI_GdWsd, src, dst);
     }
 
     void vcvttss2si_rr(XMMRegisterID src, RegisterID dst)
     {
         twoByteOpSimdInt32("vcvttss2si", VEX_SS, OP2_CVTTSD2SI_GdWsd, src, dst);
     }
 
+#ifdef JS_CODEGEN_X64
+    void vcvttsd2sq_rr(XMMRegisterID src, RegisterID dst)
+    {
+        twoByteOpSimdInt64("vcvttsd2si", VEX_SD, OP2_CVTTSD2SI_GdWsd, src, dst);
+    }
+
+    void vcvttss2sq_rr(XMMRegisterID src, RegisterID dst)
+    {
+        twoByteOpSimdInt64("vcvttss2si", VEX_SS, OP2_CVTTSD2SI_GdWsd, src, dst);
+    }
+#endif
+
     void vunpcklps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
     {
         twoByteOpSimd("vunpcklps", VEX_PS, OP2_UNPCKLPS_VsdWsd, src1, src0, dst);
     }
     void vunpcklps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
     {
         twoByteOpSimd("vunpcklps", VEX_PS, OP2_UNPCKLPS_VsdWsd, offset, base, src0, dst);
     }
@@ -2697,16 +3392,32 @@ public:
         twoByteOpSimd_disp32("vmovd", VEX_PD, OP2_MOVD_EdVd, offset, base, invalid_xmm, src);
     }
 
     void vmovd_rm(XMMRegisterID src, const void* address)
     {
         twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_EdVd, address, invalid_xmm, src);
     }
 
+#ifdef JS_CODEGEN_X64
+    void vmovq_rr(XMMRegisterID src, RegisterID dst)
+    {
+        // While this is called "vmovq", it actually uses the vmovd encoding
+        // with a REX prefix modifying it to be 64-bit.
+        twoByteOpSimdInt64("vmovq", VEX_PD, OP2_MOVD_EdVd, (XMMRegisterID)dst, (RegisterID)src);
+    }
+
+    void vmovq_rr(RegisterID src, XMMRegisterID dst)
+    {
+        // While this is called "vmovq", it actually uses the vmovd encoding
+        // with a REX prefix modifying it to be 64-bit.
+        twoByteOpInt64Simd("vmovq", VEX_PD, OP2_MOVD_VdEd, src, invalid_xmm, dst);
+    }
+#endif
+
     void vmovsd_rm(XMMRegisterID src, int32_t offset, RegisterID base)
     {
         twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, offset, base, invalid_xmm, src);
     }
 
     void vmovsd_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base)
     {
         twoByteOpSimd_disp32("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, offset, base, invalid_xmm, src);
@@ -2821,16 +3532,48 @@ public:
     {
         twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, address, invalid_xmm, src);
     }
 
     void vmovups_rm(XMMRegisterID src, const void* address)
     {
         twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_WpsVps, address, invalid_xmm, src);
     }
+#ifdef JS_CODEGEN_X64
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    vmovsd_ripr(XMMRegisterID dst)
+    {
+        return twoByteRipOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, invalid_xmm, dst);
+    }
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    vmovss_ripr(XMMRegisterID dst)
+    {
+        return twoByteRipOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, invalid_xmm, dst);
+    }
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    vmovsd_rrip(XMMRegisterID src)
+    {
+        return twoByteRipOpSimd("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, invalid_xmm, src);
+    }
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    vmovss_rrip(XMMRegisterID src)
+    {
+        return twoByteRipOpSimd("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, invalid_xmm, src);
+    }
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    vmovdqa_rrip(XMMRegisterID src)
+    {
+        return twoByteRipOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, invalid_xmm, src);
+    }
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    vmovaps_rrip(XMMRegisterID src)
+    {
+        return twoByteRipOpSimd("vmovdqa", VEX_PS, OP2_MOVAPS_WsdVsd, invalid_xmm, src);
+    }
+#endif
 
     void vmovaps_rr(XMMRegisterID src, XMMRegisterID dst)
     {
 #ifdef JS_CODEGEN_X64
         // There are two opcodes that can encode this instruction. If we have
         // one register in [xmm8,xmm15] and one in [xmm0,xmm7], use the
         // opcode which swaps the operands, as that way we can get a two-byte
         // VEX in that case.
@@ -2893,16 +3636,40 @@ public:
         if (src >= xmm8 && dst < xmm8) {
             twoByteOpSimd("vmovapd", VEX_PD, OP2_MOVAPS_WsdVsd, dst, invalid_xmm, src);
             return;
         }
 #endif
         twoByteOpSimd("vmovapd", VEX_PD, OP2_MOVAPD_VsdWsd, src, invalid_xmm, dst);
     }
 
+#ifdef JS_CODEGEN_X64
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    vmovaps_ripr(XMMRegisterID dst)
+    {
+        return twoByteRipOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, invalid_xmm, dst);
+    }
+
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    vmovdqa_ripr(XMMRegisterID dst)
+    {
+        return twoByteRipOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, invalid_xmm, dst);
+    }
+#else
+    void vmovaps_mr(const void* address, XMMRegisterID dst)
+    {
+        twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, address, invalid_xmm, dst);
+    }
+
+    void vmovdqa_mr(const void* address, XMMRegisterID dst)
+    {
+        twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, address, invalid_xmm, dst);
+    }
+#endif // JS_CODEGEN_X64
+
     void vmovdqu_rm(XMMRegisterID src, int32_t offset, RegisterID base)
     {
         twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, offset, base, invalid_xmm, src);
     }
 
     void vmovdqu_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base)
     {
         twoByteOpSimd_disp32("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, offset, base, invalid_xmm, src);
@@ -3265,16 +4032,30 @@ threeByteOpImmSimd("vblendps", VEX_PD, O
 
     void ret_i(int32_t imm)
     {
         spew("ret        $%d", imm);
         m_formatter.oneByteOp(OP_RET_Iz);
         m_formatter.immediate16u(imm);
     }
 
+#ifdef JS_CODEGEN_X86
+    void pusha()
+    {
+        spew("pusha");
+        m_formatter.oneByteOp(OP_PUSHA);
+    }
+
+    void popa()
+    {
+        spew("popa");
+        m_formatter.oneByteOp(OP_POPA);
+    }
+#endif
+
     void mfence() {
         spew("mfence");
         m_formatter.twoByteOp(OP_FENCE, (RegisterID)0, 6);
     }
 
     // Assembler admin methods:
 
     JmpDst label()
@@ -3408,17 +4189,17 @@ threeByteOpImmSimd("vblendps", VEX_PD, O
         SetRel32(code + from.offset(), code + to.offset());
     }
 
     void executableCopy(void* buffer)
     {
         memcpy(buffer, m_formatter.buffer(), size());
     }
 
-  protected:
+  private:
     static bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(int8_t)value; }
     static bool CAN_SIGN_EXTEND_16_32(int32_t value) { return value == (int32_t)(int16_t)value; }
     static bool CAN_ZERO_EXTEND_8_32(int32_t value) { return value == (int32_t)(uint8_t)value; }
     static bool CAN_ZERO_EXTEND_8H_32(int32_t value) { return value == (value & 0xff00); }
     static bool CAN_ZERO_EXTEND_16_32(int32_t value) { return value == (int32_t)(uint16_t)value; }
     static bool CAN_ZERO_EXTEND_32_64(int32_t value) { return value >= 0; }
 
     // Methods for encoding SIMD instructions via either legacy SSE encoding or
@@ -3464,16 +4245,46 @@ threeByteOpImmSimd("vblendps", VEX_PD, O
     }
 
     const char* legacySSEOpName(const char* name)
     {
         MOZ_ASSERT(name[0] == 'v');
         return name + 1;
     }
 
+ #ifdef JS_CODEGEN_X64
+    MOZ_WARN_UNUSED_RESULT JmpSrc
+    twoByteRipOpSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
+                     XMMRegisterID src0, XMMRegisterID dst)
+    {
+        if (useLegacySSEEncoding(src0, dst)) {
+            m_formatter.legacySSEPrefix(ty);
+            m_formatter.twoByteRipOp(opcode, 0, dst);
+            JmpSrc label(m_formatter.size());
+            if (IsXMMReversedOperands(opcode))
+                spew("%-11s%s, " MEM_o32r "", legacySSEOpName(name), XMMRegName(dst), ADDR_o32r(label.offset()));
+            else
+                spew("%-11s" MEM_o32r ", %s", legacySSEOpName(name), ADDR_o32r(label.offset()), XMMRegName(dst));
+            return label;
+        }
+
+        m_formatter.twoByteRipOpVex(ty, opcode, 0, src0, dst);
+        JmpSrc label(m_formatter.size());
+        if (src0 == invalid_xmm) {
+            if (IsXMMReversedOperands(opcode))
+                spew("%-11s%s, " MEM_o32r "", name, XMMRegName(dst), ADDR_o32r(label.offset()));
+            else
+                spew("%-11s" MEM_o32r ", %s", name, ADDR_o32r(label.offset()), XMMRegName(dst));
+        } else {
+            spew("%-11s" MEM_o32r ", %s, %s", name, ADDR_o32r(label.offset()), XMMRegName(src0), XMMRegName(dst));
+        }
+        return label;
+    }
+#endif
+
     void twoByteOpSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
                        XMMRegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
     {
         if (useLegacySSEEncoding(src0, dst)) {
             if (IsXMMReversedOperands(opcode))
                 spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(dst), XMMRegName(rm));
             else
                 spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), XMMRegName(dst));
@@ -3674,16 +4485,42 @@ threeByteOpImmSimd("vblendps", VEX_PD, O
             else
                 spew("%-11s%s, %s", name, GPReg32Name(rm), XMMRegName(dst));
         } else {
             spew("%-11s%s, %s, %s", name, GPReg32Name(rm), XMMRegName(src0), XMMRegName(dst));
         }
         m_formatter.twoByteOpVex(ty, opcode, rm, src0, dst);
     }
 
+#ifdef JS_CODEGEN_X64
+    void twoByteOpInt64Simd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
+                            RegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
+    {
+        if (useLegacySSEEncoding(src0, dst)) {
+            if (IsXMMReversedOperands(opcode))
+                spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(dst), GPRegName(rm));
+            else
+                spew("%-11s%s, %s", legacySSEOpName(name), GPRegName(rm), XMMRegName(dst));
+            m_formatter.legacySSEPrefix(ty);
+            m_formatter.twoByteOp64(opcode, rm, dst);
+            return;
+        }
+
+        if (src0 == invalid_xmm) {
+            if (IsXMMReversedOperands(opcode))
+                spew("%-11s%s, %s", name, XMMRegName(dst), GPRegName(rm));
+            else
+                spew("%-11s%s, %s", name, GPRegName(rm), XMMRegName(dst));
+        } else {
+            spew("%-11s%s, %s, %s", name, GPRegName(rm), XMMRegName(src0), XMMRegName(dst));
+        }
+        m_formatter.twoByteOpVex64(ty, opcode, rm, src0, dst);
+    }
+#endif
+
     void twoByteOpSimdInt32(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
                             XMMRegisterID rm, RegisterID dst)
     {
         if (useLegacySSEEncodingForOtherOutput()) {
             if (IsXMMReversedOperands(opcode))
                 spew("%-11s%s, %s", legacySSEOpName(name), GPReg32Name(dst), XMMRegName(rm));
             else if (opcode == OP2_MOVD_EdVd)
                 spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName((XMMRegisterID)dst), GPReg32Name((RegisterID)rm));
@@ -3714,16 +4551,42 @@ threeByteOpImmSimd("vblendps", VEX_PD, O
             return;
         }
 
         spew("%-11s$0x%x, %s, %s", name, imm, XMMRegName(rm), GPReg32Name(dst));
         m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, invalid_xmm, dst);
         m_formatter.immediate8u(imm);
     }
 
+#ifdef JS_CODEGEN_X64
+    void twoByteOpSimdInt64(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
+                            XMMRegisterID rm, RegisterID dst)
+    {
+        if (useLegacySSEEncodingForOtherOutput()) {
+            if (IsXMMReversedOperands(opcode))
+                spew("%-11s%s, %s", legacySSEOpName(name), GPRegName(dst), XMMRegName(rm));
+            else if (opcode == OP2_MOVD_EdVd)
+                spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName((XMMRegisterID)dst), GPRegName((RegisterID)rm));
+            else
+                spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), GPRegName(dst));
+            m_formatter.legacySSEPrefix(ty);
+            m_formatter.twoByteOp64(opcode, (RegisterID)rm, dst);
+            return;
+        }
+
+        if (IsXMMReversedOperands(opcode))
+            spew("%-11s%s, %s", name, GPRegName(dst), XMMRegName(rm));
+        else if (opcode == OP2_MOVD_EdVd)
+            spew("%-11s%s, %s", name, XMMRegName((XMMRegisterID)dst), GPRegName((RegisterID)rm));
+        else
+            spew("%-11s%s, %s", name, XMMRegName(rm), GPRegName(dst));
+        m_formatter.twoByteOpVex64(ty, opcode, (RegisterID)rm, invalid_xmm, (XMMRegisterID)dst);
+    }
+#endif
+
     void twoByteOpSimdFlags(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
                             XMMRegisterID rm, XMMRegisterID reg)
     {
         if (useLegacySSEEncodingForOtherOutput()) {
             spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), XMMRegName(reg));
             m_formatter.legacySSEPrefix(ty);
             m_formatter.twoByteOp(opcode, (RegisterID)rm, reg);
             return;
--- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
@@ -3322,23 +3322,10 @@ CodeGeneratorX86Shared::visitSimdSelect(
 
 void
 CodeGeneratorX86Shared::visitMemoryBarrier(LMemoryBarrier* ins)
 {
     if (ins->type() & MembarStoreLoad)
         masm.storeLoadFence();
 }
 
-void
-CodeGeneratorX86Shared::setReturnDoubleRegs(LiveRegisterSet* regs)
-{
-    MOZ_ASSERT(ReturnFloat32Reg.encoding() == X86Encoding::xmm0);
-    MOZ_ASSERT(ReturnDoubleReg.encoding() == X86Encoding::xmm0);
-    MOZ_ASSERT(ReturnInt32x4Reg.encoding() == X86Encoding::xmm0);
-    MOZ_ASSERT(ReturnFloat32x4Reg.encoding() == X86Encoding::xmm0);
-    regs->add(ReturnFloat32Reg);
-    regs->add(ReturnDoubleReg);
-    regs->add(ReturnInt32x4Reg);
-    regs->add(ReturnFloat32x4Reg);
-}
-
 } // namespace jit
 } // namespace js
--- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.h
+++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.h
@@ -284,18 +284,16 @@ class CodeGeneratorX86Shared : public Co
     void visitOutOfLineBailout(OutOfLineBailout* ool);
     void visitOutOfLineUndoALUOperation(OutOfLineUndoALUOperation* ool);
     void visitMulNegativeZeroCheck(MulNegativeZeroCheck* ool);
     void visitModOverflowCheck(ModOverflowCheck* ool);
     void visitReturnZero(ReturnZero* ool);
     void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool);
     void visitOutOfLineSimdFloatToIntCheck(OutOfLineSimdFloatToIntCheck* ool);
     void generateInvalidateEpilogue();
-
-    void setReturnDoubleRegs(LiveRegisterSet* regs);
 };
 
 // An out-of-line bailout thunk.
 class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorX86Shared>
 {
     LSnapshot* snapshot_;
 
   public:
--- a/js/src/jit/x86-shared/Encoding-x86-shared.h
+++ b/js/src/jit/x86-shared/Encoding-x86-shared.h
@@ -171,36 +171,32 @@ enum TwoByteOpcodeID {
     OP2_SQRTSD_VsdWsd   = 0x51,
     OP2_SQRTSS_VssWss   = 0x51,
     OP2_SQRTPS_VpsWps   = 0x51,
     OP2_RSQRTPS_VpsWps  = 0x52,
     OP2_RCPPS_VpsWps    = 0x53,
     OP2_ANDPD_VpdWpd    = 0x54,
     OP2_ORPD_VpdWpd     = 0x56,
     OP2_XORPD_VpdWpd    = 0x57,
-    OP2_PUNPCKLDQ       = 0x62,
     OP2_PCMPGTD_VdqWdq  = 0x66,
     OP2_MOVD_VdEd       = 0x6E,
     OP2_MOVDQ_VsdWsd    = 0x6F,
     OP2_MOVDQ_VdqWdq    = 0x6F,
     OP2_PSHUFD_VdqWdqIb = 0x70,
     OP2_PSLLD_UdqIb     = 0x72,
     OP2_PSRAD_UdqIb     = 0x72,
     OP2_PSRLD_UdqIb     = 0x72,
     OP2_PSRLDQ_Vd       = 0x73,
     OP2_PCMPEQW         = 0x75,
     OP2_PCMPEQD_VdqWdq  = 0x76,
-    OP2_HADDPD          = 0x7C,
     OP2_MOVD_EdVd       = 0x7E,
     OP2_MOVQ_VdWd       = 0x7E,
     OP2_MOVDQ_WdqVdq    = 0x7F,
     OP2_JCC_rel32       = 0x80,
     OP_SETCC            = 0x90,
-    OP2_SHLD            = 0xA4,
-    OP2_SHRD            = 0xAC,
     OP_FENCE            = 0xAE,
     OP2_IMUL_GvEv       = 0xAF,
     OP2_CMPXCHG_GvEb    = 0xB0,
     OP2_CMPXCHG_GvEw    = 0xB1,
     OP2_BSR_GvEv        = 0xBD,
     OP2_MOVSX_GvEb      = 0xBE,
     OP2_MOVSX_GvEw      = 0xBF,
     OP2_MOVZX_GvEb      = 0xB6,
--- a/js/src/jit/x86/Assembler-x86.h
+++ b/js/src/jit/x86/Assembler-x86.h
@@ -46,17 +46,16 @@ static MOZ_CONSTEXPR_VAR Register FrameP
 static MOZ_CONSTEXPR_VAR Register ReturnReg = eax;
 static MOZ_CONSTEXPR_VAR FloatRegister ReturnFloat32Reg = FloatRegister(X86Encoding::xmm0, FloatRegisters::Single);
 static MOZ_CONSTEXPR_VAR FloatRegister ReturnDoubleReg = FloatRegister(X86Encoding::xmm0, FloatRegisters::Double);
 static MOZ_CONSTEXPR_VAR FloatRegister ReturnInt32x4Reg = FloatRegister(X86Encoding::xmm0, FloatRegisters::Int32x4);
 static MOZ_CONSTEXPR_VAR FloatRegister ReturnFloat32x4Reg = FloatRegister(X86Encoding::xmm0, FloatRegisters::Float32x4);
 static MOZ_CONSTEXPR_VAR FloatRegister ScratchFloat32Reg = FloatRegister(X86Encoding::xmm7, FloatRegisters::Single);
 static MOZ_CONSTEXPR_VAR FloatRegister ScratchDoubleReg = FloatRegister(X86Encoding::xmm7, FloatRegisters::Double);
 static MOZ_CONSTEXPR_VAR FloatRegister ScratchSimdReg = xmm7;
-static MOZ_CONSTEXPR_VAR FloatRegister ScratchInt32x4Reg = FloatRegister(X86Encoding::xmm7, FloatRegisters::Int32x4);
 
 // Avoid ebp, which is the FramePointer, which is unavailable in some modes.
 static MOZ_CONSTEXPR_VAR Register ArgumentsRectifierReg = esi;
 static MOZ_CONSTEXPR_VAR Register CallTempReg0 = edi;
 static MOZ_CONSTEXPR_VAR Register CallTempReg1 = eax;
 static MOZ_CONSTEXPR_VAR Register CallTempReg2 = ebx;
 static MOZ_CONSTEXPR_VAR Register CallTempReg3 = ecx;
 static MOZ_CONSTEXPR_VAR Register CallTempReg4 = esi;
@@ -371,76 +370,16 @@ class Assembler : public AssemblerX86Sha
         masm.cmpl_rm_disp32(rhs.encoding(), (void*)-1);
         append(AsmJSAbsoluteLink(CodeOffsetLabel(masm.currentOffset()), lhs.kind()));
     }
     void cmpl(Imm32 rhs, AsmJSAbsoluteAddress lhs) {
         JmpSrc src = masm.cmpl_im_disp32(rhs.value, (void*)-1);
         append(AsmJSAbsoluteLink(CodeOffsetLabel(src.offset()), lhs.kind()));
     }
 
-    void adcl(Imm32 imm, Register dest) {
-        masm.adcl_ir(imm.value, dest.encoding());
-    }
-
-    void mull(Register multiplier) {
-        masm.mull_r(multiplier.encoding());
-    }
-
-    void shldl(const Imm32 imm, Register src, Register dest) {
-        masm.shldl_irr(imm.value, src.encoding(), dest.encoding());
-    }
-    void shrdl(const Imm32 imm, Register src, Register dest) {
-        masm.shrdl_irr(imm.value, src.encoding(), dest.encoding());
-    }
-
-    void vhaddpd(FloatRegister src, FloatRegister dest) {
-        MOZ_ASSERT(HasSSE2());
-        MOZ_ASSERT(src.size() == 16);
-        MOZ_ASSERT(dest.size() == 16);
-        masm.vhaddpd_rr(src.encoding(), dest.encoding());
-    }
-    void vsubpd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
-        MOZ_ASSERT(HasSSE2());
-        MOZ_ASSERT(src0.size() == 16);
-        MOZ_ASSERT(dest.size() == 16);
-        switch (src1.kind()) {
-          case Operand::MEM_REG_DISP:
-            masm.vsubpd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
-            break;
-          case Operand::MEM_ADDRESS32:
-            masm.vsubpd_mr(src1.address(), src0.encoding(), dest.encoding());
-            break;
-          default:
-            MOZ_CRASH("unexpected operand kind");
-        }
-    }
-
-    void vpunpckldq(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
-        MOZ_ASSERT(HasSSE2());
-        MOZ_ASSERT(src0.size() == 16);
-        MOZ_ASSERT(src1.size() == 16);
-        MOZ_ASSERT(dest.size() == 16);
-        masm.vpunpckldq_rr(src1.encoding(), src0.encoding(), dest.encoding());
-    }
-    void vpunpckldq(const Operand& src1, FloatRegister src0, FloatRegister dest) {
-        MOZ_ASSERT(HasSSE2());
-        MOZ_ASSERT(src0.size() == 16);
-        MOZ_ASSERT(dest.size() == 16);
-        switch (src1.kind()) {
-          case Operand::MEM_REG_DISP:
-            masm.vpunpckldq_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
-            break;
-          case Operand::MEM_ADDRESS32:
-            masm.vpunpckldq_mr(src1.address(), src0.encoding(), dest.encoding());
-            break;
-          default:
-            MOZ_CRASH("unexpected operand kind");
-        }
-    }
-
     void jmp(ImmPtr target, Relocation::Kind reloc = Relocation::HARDCODED) {
         JmpSrc src = masm.jmp();
         addPendingJump(src, target, reloc);
     }
     void j(Condition cond, ImmPtr target,
            Relocation::Kind reloc = Relocation::HARDCODED) {
         JmpSrc src = masm.jCC(static_cast<X86Encoding::Condition>(cond));
         addPendingJump(src, target, reloc);
deleted file mode 100644
--- a/js/src/jit/x86/BaseAssembler-x86.h
+++ /dev/null
@@ -1,170 +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/. */
-
-#ifndef jit_x86_BaseAssembler_x86_h
-#define jit_x86_BaseAssembler_x86_h
-
-#include "jit/x86-shared/BaseAssembler-x86-shared.h"
-
-namespace js {
-namespace jit {
-
-namespace X86Encoding {
-
-class BaseAssemblerX86 : public BaseAssembler
-{
-  public:
-
-    // Arithmetic operations:
-
-    void adcl_ir(int32_t imm, RegisterID dst)
-    {
-        spew("adcl       $%d, %s", imm, GPReg32Name(dst));
-        MOZ_ASSERT(CAN_SIGN_EXTEND_8_32(imm));
-        m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_ADC);
-        m_formatter.immediate8s(imm);
-    }
-
-    void adcl_im(int32_t imm, const void* addr)
-    {
-        spew("adcl       %d, %p", imm, addr);
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_ADC);
-            m_formatter.immediate8s(imm);
-        } else {
-            m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_ADC);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    using BaseAssembler::andl_im;
-    void andl_im(int32_t imm, const void* addr)
-    {
-        spew("andl       $0x%x, %p", imm, addr);
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_AND);
-            m_formatter.immediate8s(imm);
-        } else {
-            m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_AND);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    using BaseAssembler::orl_im;
-    void orl_im(int32_t imm, const void* addr)
-    {
-        spew("orl        $0x%x, %p", imm, addr);
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_OR);
-            m_formatter.immediate8s(imm);
-        } else {
-            m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_OR);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    using BaseAssembler::subl_im;
-    void subl_im(int32_t imm, const void* addr)
-    {
-        spew("subl       $%d, %p", imm, addr);
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_SUB);
-            m_formatter.immediate8s(imm);
-        } else {
-            m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_SUB);
-            m_formatter.immediate32(imm);
-        }
-    }
-
-    void shldl_irr(int32_t imm, RegisterID src, RegisterID dst)
-    {
-        MOZ_ASSERT(imm < 32);
-        spew("shldl      $%d, %s, %s", imm, GPReg32Name(src), GPReg32Name(dst));
-        m_formatter.twoByteOp8(OP2_SHLD, dst, src);
-        m_formatter.immediate8u(imm);
-    }
-
-    void shrdl_irr(int32_t imm, RegisterID src, RegisterID dst)
-    {
-        MOZ_ASSERT(imm < 32);
-        spew("shrdl      $%d, %s, %s", imm, GPReg32Name(src), GPReg32Name(dst));
-        m_formatter.twoByteOp8(OP2_SHRD, dst, src);
-        m_formatter.immediate8u(imm);
-    }
-
-    // SSE operations:
-
-    using BaseAssembler::vcvtsi2sd_mr;
-    void vcvtsi2sd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
-    {
-        twoByteOpSimd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, address, src0, dst);
-    }
-
-    using BaseAssembler::vmovaps_mr;
-    void vmovaps_mr(const void* address, XMMRegisterID dst)
-    {
-        twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, address, invalid_xmm, dst);
-    }
-
-    using BaseAssembler::vmovdqa_mr;
-    void vmovdqa_mr(const void* address, XMMRegisterID dst)
-    {
-        twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, address, invalid_xmm, dst);
-    }
-
-    void vhaddpd_rr(XMMRegisterID src, XMMRegisterID dst)
-    {
-        twoByteOpSimdFlags("vhaddpd", VEX_PD, OP2_HADDPD, src, dst);
-    }
-
-    void vsubpd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
-    {
-        twoByteOpSimd("vsubpd", VEX_PD, OP2_SUBPS_VpsWps, src1, src0, dst);
-    }
-    void vsubpd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
-    {
-        twoByteOpSimd("vsubpd", VEX_PD, OP2_SUBPS_VpsWps, offset, base, src0, dst);
-    }
-    void vsubpd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
-    {
-        twoByteOpSimd("vsubpd", VEX_PD, OP2_SUBPS_VpsWps, address, src0, dst);
-    }
-
-    void vpunpckldq_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) {
-        twoByteOpSimd("vpunpckldq", VEX_PD, OP2_PUNPCKLDQ, src1, src0, dst);
-    }
-    void vpunpckldq_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
-    {
-        twoByteOpSimd("vpunpckldq", VEX_PD, OP2_PUNPCKLDQ, offset, base, src0, dst);
-    }
-    void vpunpckldq_mr(const void* addr, XMMRegisterID src0, XMMRegisterID dst)
-    {
-        twoByteOpSimd("vpunpckldq", VEX_PD, OP2_PUNPCKLDQ, addr, src0, dst);
-    }
-
-    // Misc instructions:
-
-    void pusha()
-    {
-        spew("pusha");
-        m_formatter.oneByteOp(OP_PUSHA);
-    }
-
-    void popa()
-    {
-        spew("popa");
-        m_formatter.oneByteOp(OP_POPA);
-    }
-};
-
-typedef BaseAssemblerX86 BaseAssemblerSpecific;
-
-} // namespace X86Encoding
-
-} // namespace jit
-} // namespace js
-
-#endif /* jit_x86_BaseAssembler_x86_h */
--- a/js/src/jit/x86/CodeGenerator-x86.cpp
+++ b/js/src/jit/x86/CodeGenerator-x86.cpp
@@ -4,16 +4,17 @@
  * 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/x86/CodeGenerator-x86.h"
 
 #include "mozilla/Casting.h"
 #include "mozilla/DebugOnly.h"
 
+#include "jsmath.h"
 #include "jsnum.h"
 
 #include "jit/IonCaches.h"
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
 #include "js/Conversions.h"
 #include "vm/Shape.h"
 
@@ -1099,8 +1100,23 @@ CodeGeneratorX86::visitOutOfLineTruncate
         masm.storeCallResult(output);
         masm.pop(input);
 
         restoreVolatile(output);
     }
 
     masm.jump(ool->rejoin());
 }
+
+void
+CodeGeneratorX86::visitRandom(LRandom* ins)
+{
+    Register temp = ToRegister(ins->temp());
+    Register temp2 = ToRegister(ins->temp2());
+
+    masm.loadJSContext(temp);
+
+    masm.setupUnalignedABICall(temp2);
+    masm.passABIArg(temp);
+    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, math_random_no_outparam), MoveOp::DOUBLE);
+
+    MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg);
+}
--- a/js/src/jit/x86/CodeGenerator-x86.h
+++ b/js/src/jit/x86/CodeGenerator-x86.h
@@ -67,16 +67,18 @@ class CodeGeneratorX86 : public CodeGene
     void visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar* ins);
     void visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar* ins);
     void visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr* ins);
     void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins);
 
     void visitOutOfLineTruncate(OutOfLineTruncate* ool);
     void visitOutOfLineTruncateFloat32(OutOfLineTruncateFloat32* ool);
 
+    void visitRandom(LRandom* ins);
+
   private:
     void asmJSAtomicComputeAddress(Register addrTemp, Register ptrReg, bool boundsCheck,
                                    int32_t offset, int32_t endOffset);
 };
 
 typedef CodeGeneratorX86 CodeGeneratorSpecific;
 
 } // namespace jit
--- a/js/src/jit/x86/LIR-x86.h
+++ b/js/src/jit/x86/LIR-x86.h
@@ -117,12 +117,29 @@ class LAsmJSLoadFuncPtr : public LInstru
     MAsmJSLoadFuncPtr* mir() const {
         return mir_->toAsmJSLoadFuncPtr();
     }
     const LAllocation* index() {
         return getOperand(0);
     }
 };
 
+// Math.random().
+class LRandom : public LCallInstructionHelper<1, 0, 2>
+{
+  public:
+    LIR_HEADER(Random)
+    LRandom(const LDefinition& temp, const LDefinition& temp2) {
+        setTemp(0, temp);
+        setTemp(1, temp2);
+    }
+    const LDefinition* temp() {
+        return getTemp(0);
+    }
+    const LDefinition* temp2() {
+        return getTemp(1);
+    }
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_x86_LIR_x86_h */
--- a/js/src/jit/x86/Lowering-x86.cpp
+++ b/js/src/jit/x86/Lowering-x86.cpp
@@ -436,16 +436,11 @@ LIRGeneratorX86::visitSubstr(MSubstr* in
                                          tempByteOpRegister());
     define(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
 LIRGeneratorX86::visitRandom(MRandom* ins)
 {
-    // eax and edx are necessary for mull.
-    LRandom *lir = new(alloc()) LRandom(tempFixed(eax),
-                                        tempFixed(edx),
-                                        temp(),
-                                        temp(),
-                                        temp());
-    defineFixed(lir, ins, LFloatReg(ReturnDoubleReg));
+    LRandom* lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1));
+    defineReturn(lir, ins);
 }
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -1,87 +1,30 @@
 /* -*- 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/x86/MacroAssembler-x86.h"
 
-#include "mozilla/Alignment.h"
 #include "mozilla/Casting.h"
 
 #include "jit/Bailouts.h"
 #include "jit/BaselineFrame.h"
 #include "jit/JitFrames.h"
 #include "jit/MacroAssembler.h"
 #include "jit/MoveEmitter.h"
 
 #include "jsscriptinlines.h"
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
-// vpunpckldq requires 16-byte boundary for memory operand.
-// See convertUInt64ToDouble for the details.
-MOZ_ALIGNED_DECL(static const uint64_t, 16) TO_DOUBLE[4] = {
-    0x4530000043300000LL,
-    0x0LL,
-    0x4330000000000000LL,
-    0x4530000000000000LL
-};
-
-void
-MacroAssemblerX86::convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest)
-{
-    // Following operation uses entire 128-bit of dest XMM register.
-    // Currently higher 64-bit is free when we have access to lower 64-bit.
-    MOZ_ASSERT(dest.size() == 8);
-    FloatRegister dest128 = FloatRegister(dest.encoding(), FloatRegisters::Int32x4);
-
-    // Assume that src is represented as following:
-    //   src      = 0x HHHHHHHH LLLLLLLL
-
-    // Move src to dest (=dest128) and ScratchInt32x4Reg (=scratch):
-    //   dest     = 0x 00000000 00000000  00000000 LLLLLLLL
-    //   scratch  = 0x 00000000 00000000  00000000 HHHHHHHH
-    vmovd(src.low, dest128);
-    vmovd(src.high, ScratchInt32x4Reg);
-
-    // Unpack and interleave dest and scratch to dest:
-    //   dest     = 0x 00000000 00000000  HHHHHHHH LLLLLLLL
-    vpunpckldq(ScratchInt32x4Reg, dest128, dest128);
-
-    // Unpack and interleave dest and a constant C1 to dest:
-    //   C1       = 0x 00000000 00000000  45300000 43300000
-    //   dest     = 0x 45300000 HHHHHHHH  43300000 LLLLLLLL
-    // here, each 64-bit part of dest represents following double:
-    //   HI(dest) = 0x 1.00000HHHHHHHH * 2**84 == 2**84 + 0x HHHHHHHH 00000000
-    //   LO(dest) = 0x 1.00000LLLLLLLL * 2**52 == 2**52 + 0x 00000000 LLLLLLLL
-    movePtr(ImmPtr(TO_DOUBLE), temp);
-    vpunpckldq(Operand(temp, 0), dest128, dest128);
-
-    // Subtract a constant C2 from dest, for each 64-bit part:
-    //   C2       = 0x 45300000 00000000  43300000 00000000
-    // here, each 64-bit part of C2 represents following double:
-    //   HI(C2)   = 0x 1.0000000000000 * 2**84 == 2**84
-    //   LO(C2)   = 0x 1.0000000000000 * 2**52 == 2**52
-    // after the operation each 64-bit part of dest represents following:
-    //   HI(dest) = double(0x HHHHHHHH 00000000)
-    //   LO(dest) = double(0x 00000000 LLLLLLLL)
-    vsubpd(Operand(temp, sizeof(uint64_t) * 2), dest128, dest128);
-
-    // Add HI(dest) and LO(dest) in double and store it into LO(dest),
-    //   LO(dest) = double(0x HHHHHHHH 00000000) + double(0x 00000000 LLLLLLLL)
-    //            = double(0x HHHHHHHH LLLLLLLL)
-    //            = double(src)
-    vhaddpd(dest128, dest128);
-}
-
 MacroAssemblerX86::Double*
 MacroAssemblerX86::getDouble(double d)
 {
     if (!doubleMap_.initialized()) {
         enoughMemory_ &= doubleMap_.init();
         if (!enoughMemory_)
             return nullptr;
     }
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -235,24 +235,16 @@ class MacroAssemblerX86 : public MacroAs
     void pushValue(JSValueType type, Register reg) {
         push(ImmTag(JSVAL_TYPE_TO_TAG(type)));
         push(reg);
     }
     void pushValue(const Address& addr) {
         push(tagOf(addr));
         push(payloadOfAfterStackPush(addr));
     }
-    void push64(Register64 src) {
-        push(src.high);
-        push(src.low);
-    }
-    void pop64(Register64 dest) {
-        pop(dest.low);
-        pop(dest.high);
-    }
     void storePayload(const Value& val, Operand dest) {
         jsval_layout jv = JSVAL_TO_IMPL(val);
         if (val.isMarkable())
             movl(ImmGCPtr((gc::Cell*)jv.s.payload.ptr), ToPayload(dest));
         else
             movl(Imm32(jv.s.payload.i32), ToPayload(dest));
     }
     void storePayload(Register src, Operand dest) {
@@ -610,67 +602,31 @@ class MacroAssemblerX86 : public MacroAs
         add32(imm, Operand(dest));
     }
     void addPtr(Imm32 imm, const Operand& dest) {
         add32(imm, dest);
     }
     void addPtr(const Address& src, Register dest) {
         addl(Operand(src), dest);
     }
-    void add64(Imm32 imm, Register64 dest) {
-        addl(imm, dest.low);
-        adcl(Imm32(0), dest.high);
-    }
     void subPtr(Imm32 imm, Register dest) {
         sub32(imm, dest);
     }
     void subPtr(Register src, Register dest) {
         sub32(src, dest);
     }
     void subPtr(const Address& addr, Register dest) {
         sub32(Operand(addr), dest);
     }
     void subPtr(Register src, const Address& dest) {
         sub32(src, Operand(dest));
     }
     void mulBy3(const Register& src, const Register& dest) {
         lea(Operand(src, src, TimesTwo), dest);
     }
-    // Note: this function clobbers eax and edx.
-    void mul64(Imm64 imm, const Register64& dest) {
-        // LOW32  = LOW(LOW(dest) * LOW(imm));
-        // HIGH32 = LOW(HIGH(dest) * LOW(imm)) [multiply imm into upper bits]
-        //        + LOW(LOW(dest) * HIGH(imm)) [multiply dest into upper bits]
-        //        + HIGH(LOW(dest) * LOW(imm)) [carry]
-
-        MOZ_ASSERT(dest.low != eax && dest.low != edx);
-        MOZ_ASSERT(dest.high != eax && dest.high != edx);
-
-        // HIGH(dest) = LOW(HIGH(dest) * LOW(imm));
-        movl(Imm32(imm.value & 0xFFFFFFFFL), edx);
-        imull(edx, dest.high);
-
-        // edx:eax = LOW(dest) * LOW(imm);
-        movl(Imm32(imm.value & 0xFFFFFFFFL), edx);
-        movl(dest.low, eax);
-        mull(edx);
-
-        // HIGH(dest) += edx;
-        addl(edx, dest.high);
-
-        // HIGH(dest) += LOW(LOW(dest) * HIGH(imm));
-        if (((imm.value >> 32) & 0xFFFFFFFFL) == 5)
-            leal(Operand(dest.low, dest.low, TimesFour), edx);
-        else
-            MOZ_CRASH("Unsupported imm");
-        addl(edx, dest.high);
-
-        // LOW(dest) = eax;
-        movl(eax, dest.low);
-    }
 
     void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label* label) {
         cmp32(Operand(lhs), rhs);
         j(cond, label);
     }
     void branch32(Condition cond, AsmJSAbsoluteAddress lhs, Imm32 rhs, Label* label) {
         cmpl(rhs, lhs);
         j(cond, label);
@@ -751,44 +707,28 @@ class MacroAssemblerX86 : public MacroAs
         testPtr(Operand(lhs), imm);
         j(cond, label);
     }
     void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
         subPtr(imm, lhs);
         j(cond, label);
     }
 
-    void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, Label* label) {
-        if (cond == Assembler::Zero) {
-            MOZ_ASSERT(lhs.low == rhs.low);
-            MOZ_ASSERT(lhs.high == rhs.high);
-            movl(lhs.low, temp);
-            orl(lhs.high, temp);
-            branchTestPtr(cond, temp, temp, label);
-        } else {
-            MOZ_CRASH("Unsupported condition");
-        }
-    }
-
     void movePtr(ImmWord imm, Register dest) {
         movl(Imm32(imm.value), dest);
     }
     void movePtr(ImmPtr imm, Register dest) {
         movl(imm, dest);
     }
     void movePtr(AsmJSImmPtr imm, Register dest) {
         mov(imm, dest);
     }
     void movePtr(ImmGCPtr imm, Register dest) {
         movl(imm, dest);
     }
-    void move64(Register64 src, Register64 dest) {
-        movl(src.low, dest.low);
-        movl(src.high, dest.high);
-    }
     void loadPtr(const Address& address, Register dest) {
         movl(Operand(address), dest);
     }
     void loadPtr(const Operand& src, Register dest) {
         movl(src, dest);
     }
     void loadPtr(const BaseIndex& src, Register dest) {
         movl(Operand(src), dest);
@@ -797,20 +737,16 @@ class MacroAssemblerX86 : public MacroAs
         movl(Operand(address), dest);
     }
     void loadPrivate(const Address& src, Register dest) {
         movl(payloadOf(src), dest);
     }
     void load32(AbsoluteAddress address, Register dest) {
         movl(Operand(address), dest);
     }
-    void load64(const Address& address, Register64 dest) {
-        movl(Operand(address), dest.low);
-        movl(Operand(Address(address.base, address.offset + 4)), dest.high);
-    }
     template <typename T>
     void storePtr(ImmWord imm, T address) {
         movl(Imm32(imm.value), Operand(address));
     }
     template <typename T>
     void storePtr(ImmPtr imm, T address) {
         storePtr(ImmWord(uintptr_t(imm.value)), address);
     }
@@ -828,20 +764,16 @@ class MacroAssemblerX86 : public MacroAs
         movl(src, dest);
     }
     void storePtr(Register src, AbsoluteAddress address) {
         movl(src, Operand(address));
     }
     void store32(Register src, AbsoluteAddress address) {
         movl(src, Operand(address));
     }
-    void store64(Register64 src, Address address) {
-        movl(src.low, Operand(address));
-        movl(src.high, Operand(Address(address.base, address.offset + 4)));
-    }
 
     void setStackArg(Register reg, uint32_t arg) {
         movl(reg, Operand(esp, arg * sizeof(intptr_t)));
     }
 
     // Type testing instructions can take a tag in a register or a
     // ValueOperand.
     template <typename T>
@@ -1123,53 +1055,37 @@ class MacroAssemblerX86 : public MacroAs
     }
 
     void rshiftPtr(Imm32 imm, Register dest) {
         shrl(imm, dest);
     }
     void rshiftPtrArithmetic(Imm32 imm, Register dest) {
         sarl(imm, dest);
     }
-    void rshift64(Imm32 imm, Register64 dest) {
-        shrdl(imm, dest.high, dest.low);
-        shrl(imm, dest.high);
-    }
     void lshiftPtr(Imm32 imm, Register dest) {
         shll(imm, dest);
     }
-    void lshift64(Imm32 imm, Register64 dest) {
-        shldl(imm, dest.low, dest.high);
-        shll(imm, dest.low);
-    }
     void xorPtr(Imm32 imm, Register dest) {
         xorl(imm, dest);
     }
     void xorPtr(Register src, Register dest) {
         xorl(src, dest);
     }
     void orPtr(Imm32 imm, Register dest) {
         orl(imm, dest);
     }
     void orPtr(Register src, Register dest) {
         orl(src, dest);
     }
-    void or64(Register64 src, Register64 dest) {
-        orl(src.low, dest.low);
-        orl(src.high, dest.high);
-    }
     void andPtr(Imm32 imm, Register dest) {
         andl(imm, dest);
     }
     void andPtr(Register src, Register dest) {
         andl(src, dest);
     }
-    void and64(Imm64 imm, Register64 dest) {
-        andl(Imm32(imm.value & 0xFFFFFFFFL), dest.low);
-        andl(Imm32((imm.value >> 32) & 0xFFFFFFFFL), dest.high);
-    }
 
     void loadInstructionPointerAfterCall(Register dest) {
         movl(Operand(StackPointer, 0x0), dest);
     }
 
     // Note: this function clobbers the source register.
     void convertUInt32ToDouble(Register src, FloatRegister dest) {
         // src is [0, 2^32-1]
@@ -1184,23 +1100,16 @@ class MacroAssemblerX86 : public MacroAs
     }
 
     // Note: this function clobbers the source register.
     void convertUInt32ToFloat32(Register src, FloatRegister dest) {
         convertUInt32ToDouble(src, dest);
         convertDoubleToFloat32(dest, dest);
     }
 
-    void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
-
-    void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) {
-        movl(imm, temp);
-        vmulsd(Operand(temp, 0), dest, dest);
-    }
-
     void inc64(AbsoluteAddress dest) {
         addl(Imm32(1), Operand(dest));
         Label noOverflow;
         j(NonZero, &noOverflow);
         addl(Imm32(1), Operand(dest.offset(4)));
         bind(&noOverflow);
     }