Bug 1023297 - Use explicit constructors for ARM-specific classes. r=jandem
authorSean Stangl <sstangl@mozilla.com>
Thu, 28 May 2015 15:29:29 -0700
changeset 246436 3cc9e92e39049bf77e4d222b05ab77800c916fc8
parent 246435 57bd26cc44b9b50155308afd23c2c5c35bfcc2b5
child 246437 ab1b8c084cfb9d09b423d0e6b4c8371da7d5eade
push id28830
push usercbook@mozilla.com
push dateMon, 01 Jun 2015 13:02:44 +0000
treeherdermozilla-central@39c85ec2d644 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1023297
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1023297 - Use explicit constructors for ARM-specific classes. r=jandem
js/src/jit/arm/Assembler-arm.cpp
js/src/jit/arm/Assembler-arm.h
js/src/jit/arm/CodeGenerator-arm.cpp
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/arm/MoveEmitter-arm.cpp
js/src/jit/arm/MoveEmitter-arm.h
--- a/js/src/jit/arm/Assembler-arm.cpp
+++ b/js/src/jit/arm/Assembler-arm.cpp
@@ -21,22 +21,22 @@ using namespace js;
 using namespace js::jit;
 
 using mozilla::CountLeadingZeroes32;
 
 void dbg_break() {}
 
 // Note this is used for inter-AsmJS calls and may pass arguments and results in
 // floating point registers even if the system ABI does not.
-ABIArgGenerator::ABIArgGenerator() :
-    intRegIndex_(0),
+ABIArgGenerator::ABIArgGenerator()
+  : intRegIndex_(0),
     floatRegIndex_(0),
     stackOffset_(0),
     current_()
-{}
+{ }
 
 ABIArg
 ABIArgGenerator::next(MIRType type)
 {
     switch (type) {
       case MIRType_Int32:
       case MIRType_Pointer:
         if (intRegIndex_ == NumIntArgRegs) {
@@ -493,25 +493,27 @@ InstMOV::AsTHIS(const Instruction& i)
 
 bool
 InstMOV::IsTHIS(const Instruction& i)
 {
     return InstALU::IsTHIS(i) && InstALU::AsTHIS(i)->checkOp1(r0) && InstALU::AsTHIS(i)->checkOp(OpMov);
 }
 
 Op2Reg
-Operand2::toOp2Reg() {
+Operand2::toOp2Reg() const {
     return *(Op2Reg*)this;
 }
+
 O2RegImmShift
-Op2Reg::toO2RegImmShift() {
+Op2Reg::toO2RegImmShift() const {
     return *(O2RegImmShift*)this;
 }
+
 O2RegRegShift
-Op2Reg::toO2RegRegShift() {
+Op2Reg::toO2RegRegShift() const {
     return *(O2RegRegShift*)this;
 }
 
 Imm16::Imm16(Instruction& inst)
   : lower(inst.encode() & 0xfff),
     upper(inst.encode() >> 16),
     invalid(0xfff)
 { }
@@ -1252,17 +1254,17 @@ js::jit::VFPImm::VFPImm(uint32_t top)
 }
 
 BOffImm::BOffImm(Instruction& inst)
   : data(inst.encode() & 0x00ffffff)
 {
 }
 
 Instruction*
-BOffImm::getDest(Instruction* src)
+BOffImm::getDest(Instruction* src) const
 {
     // TODO: It is probably worthwhile to verify that src is actually a branch.
     // NOTE: This does not explicitly shift the offset of the destination left by 2,
     // since it is indexing into an array of instruction sized objects.
     return &src[(((int32_t)data << 8) >> 8) + 2];
 }
 
 const js::jit::DoubleEncoder::DoubleEntry js::jit::DoubleEncoder::table[256] = {
@@ -1711,17 +1713,18 @@ Assembler::as_dtr(LoadStore ls, int size
 
 /* static */ void
 Assembler::as_dtr_patch(LoadStore ls, int size, Index mode, Register rt, DTRAddr addr, Condition c,
                         uint32_t* dest)
 {
     WriteInstStatic(EncodeDtr(ls, size, mode, rt, addr, c), dest);
 }
 
-class PoolHintData {
+class PoolHintData
+{
   public:
     enum LoadType {
         // Set 0 to bogus, since that is the value most likely to be
         // accidentally left somewhere.
         PoolBOGUS  = 0,
         PoolDTR    = 1,
         PoolBranch = 2,
         PoolVDTR   = 3
@@ -1754,57 +1757,58 @@ class PoolHintData {
         MOZ_ASSERT(index_ == index);
         cond_ = cond >> 28;
         MOZ_ASSERT(cond_ == cond >> 28);
         loadType_ = lt;
         ONES = ExpectedOnes;
         destReg_ = destReg.id();
         destType_ = destReg.isDouble();
     }
-    Assembler::Condition getCond() {
+    Assembler::Condition getCond() const {
         return Assembler::Condition(cond_ << 28);
     }
 
-    Register getReg() {
+    Register getReg() const {
         return Register::FromCode(destReg_);
     }
-    VFPRegister getVFPReg() {
+    VFPRegister getVFPReg() const {
         VFPRegister r = VFPRegister(destReg_, destType_ ? VFPRegister::Double : VFPRegister::Single);
         return r;
     }
 
-    int32_t getIndex() {
+    int32_t getIndex() const {
         return index_;
     }
     void setIndex(uint32_t index) {
         MOZ_ASSERT(ONES == ExpectedOnes && loadType_ != PoolBOGUS);
         index_ = index;
         MOZ_ASSERT(index_ == index);
     }
 
-    LoadType getLoadType() {
+    LoadType getLoadType() const {
         // If this *was* a PoolBranch, but the branch has already been bound
         // then this isn't going to look like a real poolhintdata, but we still
         // want to lie about it so everyone knows it *used* to be a branch.
         if (ONES != ExpectedOnes)
             return PoolHintData::PoolBranch;
         return loadType_;
     }
 
-    bool isValidPoolHint() {
+    bool isValidPoolHint() const {
         // Most instructions cannot have a condition that is 0xf. Notable
         // exceptions are blx and the entire NEON instruction set. For the
         // purposes of pool loads, and possibly patched branches, the possible
         // instructions are ldr and b, neither of which can have a condition
         // code of 0xf.
         return ONES == ExpectedOnes;
     }
 };
 
-union PoolHintPun {
+union PoolHintPun
+{
     PoolHintData phd;
     uint32_t raw;
 };
 
 // Handles all of the other integral data transferring functions: ldrsb, ldrsh,
 // ldrd, etc. The size is given in bits.
 BufferOffset
 Assembler::as_extdtr(LoadStore ls, int size, bool IsSigned, Index mode,
@@ -1839,18 +1843,17 @@ Assembler::as_extdtr(LoadStore ls, int s
     return writeInst(extra_bits2 << 5 | extra_bits1 << 20 | 0x90 |
                      addr.encode() | RT(rt) | mode | c);
 }
 
 BufferOffset
 Assembler::as_dtm(LoadStore ls, Register rn, uint32_t mask,
                 DTMMode mode, DTMWriteBack wb, Condition c)
 {
-    return writeInst(0x08000000 | RN(rn) | ls |
-                     mode | mask | c | wb);
+    return writeInst(0x08000000 | RN(rn) | ls | mode | mask | c | wb);
 }
 
 BufferOffset
 Assembler::as_Imm32Pool(Register dest, uint32_t value, Condition c)
 {
     PoolHintPun php;
     php.phd.init(0, c, PoolHintData::PoolDTR, dest);
     return m_buffer.allocEntry(1, 1, (uint8_t*)&php.raw, (uint8_t*)&value);
@@ -2051,22 +2054,24 @@ Assembler::as_isb_trap()
 
 // bx can *only* branch to a register, never to an immediate.
 BufferOffset
 Assembler::as_bx(Register r, Condition c)
 {
     BufferOffset ret = writeInst(((int) c) | OpBx | r.code());
     return ret;
 }
+
 void
 Assembler::WritePoolGuard(BufferOffset branch, Instruction* dest, BufferOffset afterPool)
 {
     BOffImm off = afterPool.diffB<BOffImm>(branch);
     *dest = InstBImm(off, Always);
 }
+
 // Branch can branch to an immediate *or* to a register.
 // Branches to immediates are pc relative, branches to registers are absolute.
 BufferOffset
 Assembler::as_b(BOffImm off, Condition c)
 {
     BufferOffset ret = writeBranchInst(((int)c) | OpB | off.encode());
     return ret;
 }
@@ -2101,16 +2106,17 @@ Assembler::as_b(Label* l, Condition c)
         old = LabelBase::INVALID_OFFSET;
         BOffImm inv;
         ret = as_b(inv, c);
     }
     DebugOnly<int32_t> check = l->use(ret.getOffset());
     MOZ_ASSERT(check == old);
     return ret;
 }
+
 BufferOffset
 Assembler::as_b(BOffImm off, Condition c, BufferOffset inst)
 {
     *editSrc(inst) = InstBImm(off, c);
     return inst;
 }
 
 // blx can go to either an immediate or a register.
@@ -2163,16 +2169,17 @@ Assembler::as_bl(Label* l, Condition c)
         old = LabelBase::INVALID_OFFSET;
         BOffImm inv;
         ret = as_bl(inv, c);
     }
     DebugOnly<int32_t> check = l->use(ret.getOffset());
     MOZ_ASSERT(check == old);
     return ret;
 }
+
 BufferOffset
 Assembler::as_bl(BOffImm off, Condition c, BufferOffset inst)
 {
     *editSrc(inst) = InstBLImm(off, c);
     return inst;
 }
 
 BufferOffset
@@ -2190,16 +2197,17 @@ Assembler::as_msr(Register r, Condition 
     return writeInst(0x012cf000 | int(c) | r.code());
 }
 
 // VFP instructions!
 enum vfp_tags {
     VfpTag   = 0x0C000A00,
     VfpArith = 0x02000000
 };
+
 BufferOffset
 Assembler::writeVFPInst(vfp_size sz, uint32_t blob)
 {
     MOZ_ASSERT((sz & blob) == 0);
     MOZ_ASSERT((VfpTag & blob) == 0);
     return writeInst(VfpTag | sz | blob);
 }
 
@@ -2220,53 +2228,47 @@ Assembler::as_vfp_float(VFPRegister vd, 
     // Make sure we believe that all of our operands are the same kind.
     MOZ_ASSERT_IF(!vn.isMissing(), vd.equiv(vn));
     MOZ_ASSERT_IF(!vm.isMissing(), vd.equiv(vm));
     vfp_size sz = vd.isDouble() ? IsDouble : IsSingle;
     return writeVFPInst(sz, VD(vd) | VN(vn) | VM(vm) | op | VfpArith | c);
 }
 
 BufferOffset
-Assembler::as_vadd(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                 Condition c)
+Assembler::as_vadd(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c)
 {
     return as_vfp_float(vd, vn, vm, OpvAdd, c);
 }
 
 BufferOffset
-Assembler::as_vdiv(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                 Condition c)
+Assembler::as_vdiv(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c)
 {
     return as_vfp_float(vd, vn, vm, OpvDiv, c);
 }
 
 BufferOffset
-Assembler::as_vmul(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                 Condition c)
+Assembler::as_vmul(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c)
 {
     return as_vfp_float(vd, vn, vm, OpvMul, c);
 }
 
 BufferOffset
-Assembler::as_vnmul(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                  Condition c)
+Assembler::as_vnmul(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c)
 {
     return as_vfp_float(vd, vn, vm, OpvMul, c);
 }
 
 BufferOffset
-Assembler::as_vnmla(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                  Condition c)
+Assembler::as_vnmla(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c)
 {
     MOZ_CRASH("Feature NYI");
 }
 
 BufferOffset
-Assembler::as_vnmls(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                  Condition c)
+Assembler::as_vnmls(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c)
 {
     MOZ_CRASH("Feature NYI");
 }
 
 BufferOffset
 Assembler::as_vneg(VFPRegister vd, VFPRegister vm, Condition c)
 {
     return as_vfp_float(vd, NoVFPRegister, vm, OpvNeg, c);
@@ -2280,40 +2282,40 @@ Assembler::as_vsqrt(VFPRegister vd, VFPR
 
 BufferOffset
 Assembler::as_vabs(VFPRegister vd, VFPRegister vm, Condition c)
 {
     return as_vfp_float(vd, NoVFPRegister, vm, OpvAbs, c);
 }
 
 BufferOffset
-Assembler::as_vsub(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                 Condition c)
+Assembler::as_vsub(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c)
 {
     return as_vfp_float(vd, vn, vm, OpvSub, c);
 }
 
 BufferOffset
-Assembler::as_vcmp(VFPRegister vd, VFPRegister vm,
-                 Condition c)
+Assembler::as_vcmp(VFPRegister vd, VFPRegister vm, Condition c)
 {
     return as_vfp_float(vd, NoVFPRegister, vm, OpvCmp, c);
 }
+
 BufferOffset
 Assembler::as_vcmpz(VFPRegister vd, Condition c)
 {
     return as_vfp_float(vd, NoVFPRegister, NoVFPRegister, OpvCmpz, c);
 }
 
 // Specifically, a move between two same sized-registers.
 BufferOffset
 Assembler::as_vmov(VFPRegister vd, VFPRegister vsrc, Condition c)
 {
     return as_vfp_float(vd, NoVFPRegister, vsrc, OpvMov, c);
 }
+
 // Transfer between Core and VFP.
 
 // Unlike the next function, moving between the core registers and vfp registers
 // can't be *that* properly typed. Namely, since I don't want to munge the type
 // VFPRegister to also include core registers. Thus, the core and vfp registers
 // are passed in based on their type, and src/dest is determined by the
 // float2core.
 
@@ -2334,25 +2336,23 @@ Assembler::as_vxfer(Register vt1, Regist
         // If we are transferring a single half of the double then it must be
         // moving a VFP reg to a core reg.
         MOZ_ASSERT_IF(vt2 == InvalidReg, f2c == FloatToCore);
         idx = idx << 21;
     } else {
         MOZ_ASSERT(idx == 0);
     }
 
-    if (vt2 == InvalidReg) {
-        return writeVFPInst(sz, WordTransfer | f2c | c |
-                            RT(vt1) | maybeRN(vt2) | VN(vm) | idx);
-    } else {
-        // We are doing a 64 bit transfer.
-        return writeVFPInst(sz, DoubleTransfer | f2c | c |
-                            RT(vt1) | maybeRN(vt2) | VM(vm) | idx);
-    }
+    if (vt2 == InvalidReg)
+        return writeVFPInst(sz, WordTransfer | f2c | c | RT(vt1) | maybeRN(vt2) | VN(vm) | idx);
+
+    // We are doing a 64 bit transfer.
+    return writeVFPInst(sz, DoubleTransfer | f2c | c | RT(vt1) | maybeRN(vt2) | VM(vm) | idx);
 }
+
 enum vcvt_destFloatness {
     VcvtToInteger = 1 << 18,
     VcvtToFloat  = 0 << 18
 };
 enum vcvt_toZero {
     VcvtToZero = 1 << 7, // Use the default rounding mode, which rounds truncates.
     VcvtToFPSCR = 0 << 7 // Use whatever rounding mode the fpscr specifies.
 };
@@ -2379,19 +2379,19 @@ Assembler::as_vcvt(VFPRegister vd, VFPRe
         return writeVFPInst(sz, c | 0x02B700C0 | VM(vm) | VD(vd));
     }
 
     // At least one of the registers should be a float.
     vcvt_destFloatness destFloat;
     vcvt_Signedness opSign;
     vcvt_toZero doToZero = VcvtToFPSCR;
     MOZ_ASSERT(vd.isFloat() || vm.isFloat());
-    if (vd.isSingle() || vm.isSingle()) {
+    if (vd.isSingle() || vm.isSingle())
         sz = IsSingle;
-    }
+
     if (vd.isFloat()) {
         destFloat = VcvtToFloat;
         opSign = (vm.isSInt()) ? VcvtFromSigned : VcvtFromUnsigned;
     } else {
         destFloat = VcvtToInteger;
         opSign = (vd.isSInt()) ? VcvtToSigned : VcvtToUnsigned;
         doToZero = useFPSCR ? VcvtToFPSCR : VcvtToZero;
     }
@@ -2454,16 +2454,17 @@ Assembler::as_vdtm(LoadStore st, Registe
 BufferOffset
 Assembler::as_vimm(VFPRegister vd, VFPImm imm, Condition c)
 {
     MOZ_ASSERT(imm.isValid());
     vfp_size sz = vd.isDouble() ? IsDouble : IsSingle;
     return writeVFPInst(sz,  c | imm.encode() | VD(vd) | 0x02B00000);
 
 }
+
 BufferOffset
 Assembler::as_vmrs(Register r, Condition c)
 {
     return writeInst(c | 0x0ef10a10 | RT(r));
 }
 
 BufferOffset
 Assembler::as_vmsr(Register r, Condition c)
@@ -2572,17 +2573,16 @@ Assembler::retarget(Label* label, Label*
             DebugOnly<uint32_t> prev = target->use(label->offset());
             MOZ_ASSERT((int32_t)prev == Label::INVALID_OFFSET);
         }
     }
     label->reset();
 
 }
 
-
 static int stopBKPT = -1;
 void
 Assembler::as_bkpt()
 {
     // This is a count of how many times a breakpoint instruction has been
     // generated. It is embedded into the instruction for debugging
     // purposes. Gdb will print "bkpt xxx" when you attempt to dissassemble a
     // breakpoint with the number xxx embedded into it. If this breakpoint is
@@ -2627,16 +2627,17 @@ ptrdiff_t
 Assembler::GetBranchOffset(const Instruction* i_)
 {
     MOZ_ASSERT(i_->is<InstBranchImm>());
     InstBranchImm* i = i_->as<InstBranchImm>();
     BOffImm dest;
     i->extractImm(&dest);
     return dest.decode();
 }
+
 void
 Assembler::RetargetNearBranch(Instruction* i, int offset, bool final)
 {
     Assembler::Condition c;
     i->extractCond(&c);
     RetargetNearBranch(i, offset, c, final);
 }
 
@@ -2662,17 +2663,18 @@ Assembler::RetargetFarBranch(Instruction
     if (!i->is<InstLDR>()) {
         new (i) InstLDR(Offset, pc, DTRAddr(pc, DtrOffImm(offset - 8)), cond);
         AutoFlushICache::flush(uintptr_t(i), 4);
     }
     *slot = dest;
 
 }
 
-struct PoolHeader : Instruction {
+struct PoolHeader : Instruction
+{
     struct Header
     {
         // The size should take into account the pool header.
         // The size is in units of Instruction (4 bytes), not byte.
         uint32_t size : 15;
         bool isNatural : 1;
         uint32_t ONES : 16;
 
@@ -2703,64 +2705,63 @@ struct PoolHeader : Instruction {
     uint32_t size() const {
         Header tmp(this);
         return tmp.size;
     }
     uint32_t isNatural() const {
         Header tmp(this);
         return tmp.isNatural;
     }
+
     static bool IsTHIS(const Instruction& i) {
         return (*i.raw() & 0xffff0000) == 0xffff0000;
     }
     static const PoolHeader* AsTHIS(const Instruction& i) {
         if (!IsTHIS(i))
             return nullptr;
         return static_cast<const PoolHeader*>(&i);
     }
 };
 
-
 void
 Assembler::WritePoolHeader(uint8_t* start, Pool* p, bool isNatural)
 {
-    static_assert(sizeof(PoolHeader) == 4,
-                  "PoolHandler must have the correct size.");
+    static_assert(sizeof(PoolHeader) == 4, "PoolHandler must have the correct size.");
     uint8_t* pool = start + 4;
     // Go through the usual rigmarole to get the size of the pool.
     pool += p->getPoolSize();
     uint32_t size = pool - start;
     MOZ_ASSERT((size & 3) == 0);
     size = size >> 2;
     MOZ_ASSERT(size < (1 << 15));
     PoolHeader header(size, isNatural);
     *(PoolHeader*)start = header;
 }
 
-
 // The size of an arbitrary 32-bit call in the instruction stream. On ARM this
 // sequence is |pc = ldr pc - 4; imm32| given that we never reach the imm32.
 uint32_t
 Assembler::PatchWrite_NearCallSize()
 {
     return sizeof(uint32_t);
 }
+
 void
 Assembler::PatchWrite_NearCall(CodeLocationLabel start, CodeLocationLabel toCall)
 {
     Instruction* inst = (Instruction*) start.raw();
     // Overwrite whatever instruction used to be here with a call. Since the
     // destination is in the same function, it will be within range of the
     // 24 << 2 byte bl instruction.
     uint8_t* dest = toCall.raw();
     new (inst) InstBLImm(BOffImm(dest - (uint8_t*)inst) , Always);
     // Ensure everyone sees the code that was just written into memory.
     AutoFlushICache::flush(uintptr_t(inst), 4);
-
 }
+
 void
 Assembler::PatchDataWithValueCheck(CodeLocationLabel label, PatchedImmPtr newValue,
                                    PatchedImmPtr expectedValue)
 {
     Instruction* ptr = (Instruction*) label.raw();
     InstructionIterator iter(ptr);
     Register dest;
     Assembler::RelocStyle rs;
@@ -2791,17 +2792,16 @@ void
 Assembler::PatchWrite_Imm32(CodeLocationLabel label, Imm32 imm) {
     // Raw is going to be the return address.
     uint32_t* raw = (uint32_t*)label.raw();
     // Overwrite the 4 bytes before the return address, which will end up being
     // the call instruction.
     *(raw - 1) = imm.value;
 }
 
-
 uint8_t*
 Assembler::NextInstruction(uint8_t* inst_, uint32_t* count)
 {
     Instruction* inst = reinterpret_cast<Instruction*>(inst_);
     if (count != nullptr)
         *count += sizeof(Instruction);
     return reinterpret_cast<uint8_t*>(inst->next());
 }
@@ -2816,17 +2816,18 @@ InstIsGuard(Instruction* inst, const Poo
     if (!(inst->is<InstBXReg>() || inst->is<InstBImm>()))
         return false;
     // See if the next instruction is a pool header.
     *ph = (inst + 1)->as<const PoolHeader>();
     return *ph != nullptr;
 }
 
 static bool
-InstIsBNop(Instruction* inst) {
+InstIsBNop(Instruction* inst)
+{
     // In some special situations, it is necessary to insert a NOP into the
     // instruction stream that nobody knows about, since nobody should know
     // about it, make sure it gets skipped when Instruction::next() is called.
     // this generates a very specific nop, namely a branch to the next
     // instruction.
     Assembler::Condition c;
     inst->extractCond(&c);
     if (c != Assembler::Always)
@@ -3025,17 +3026,18 @@ void Assembler::UpdateBoundsCheck(uint32
     MOZ_ASSERT(!imm8.invalid);
 
     *inst = InstALU(InvalidReg, index, imm8, OpCmp, SetCond, Always);
     // NOTE: we don't update the Auto Flush Cache!  this function is currently
     // only called from within AsmJSModule::patchHeapAccesses, which does that
     // for us. Don't call this!
 }
 
-InstructionIterator::InstructionIterator(Instruction* i_) : i(i_)
+InstructionIterator::InstructionIterator(Instruction* i_)
+  : i(i_)
 {
     // Work around pools with an artificial pool guard and around nop-fill.
     i = i->skipPool();
 }
 
 uint32_t Assembler::NopFill = 0;
 
 uint32_t
--- a/js/src/jit/arm/Assembler-arm.h
+++ b/js/src/jit/arm/Assembler-arm.h
@@ -69,19 +69,21 @@ class ABIArgGenerator
 {
     unsigned intRegIndex_;
     unsigned floatRegIndex_;
     uint32_t stackOffset_;
     ABIArg current_;
 
   public:
     ABIArgGenerator();
+
     ABIArg next(MIRType argType);
     ABIArg& current() { return current_; }
     uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
+
     static const Register NonArgReturnReg0;
     static const Register NonArgReturnReg1;
     static const Register NonReturn_VolatileReg0;
     static const Register NonReturn_VolatileReg1;
 };
 
 static MOZ_CONSTEXPR_VAR Register PreBarrierReg = r1;
 
@@ -232,17 +234,16 @@ enum IsImmDTR_ {
     IsNotImmDTR = 1 << 25
 };
 // For the extra memory operations, ldrd, ldrsb, ldrh.
 enum IsImmEDTR_ {
     IsImmEDTR    = 1 << 22,
     IsNotImmEDTR = 0 << 22
 };
 
-
 enum ShiftType {
     LSL = 0, // << 5
     LSR = 1, // << 5
     ASR = 2, // << 5
     ROR = 3, // << 5
     RRX = ROR // RRX is encoded as ROR with a 0 offset.
 };
 
@@ -276,16 +277,17 @@ enum DTMWriteBack {
 enum SetCond_ {
     SetCond   = 1 << 20,
     NoSetCond = 0 << 20
 };
 enum LoadStore {
     IsLoad  = 1 << 20,
     IsStore = 0 << 20
 };
+
 // You almost never want to use this directly. Instead, you wantto pass in a
 // signed constant, and let this bit be implicitly set for you. This is however,
 // necessary if we want a negative index.
 enum IsUp_ {
     IsUp   = 1 << 23,
     IsDown = 0 << 23
 };
 enum ALUOp {
@@ -336,26 +338,29 @@ enum VFPOp {
     OpvDiv  = 0x8 << 20,
     OpvMov  = 0xB << 20 | 0x1 << 6,
     OpvAbs  = 0xB << 20 | 0x3 << 6,
     OpvNeg  = 0xB << 20 | 0x1 << 6 | 0x1 << 16,
     OpvSqrt = 0xB << 20 | 0x3 << 6 | 0x1 << 16,
     OpvCmp  = 0xB << 20 | 0x1 << 6 | 0x4 << 16,
     OpvCmpz  = 0xB << 20 | 0x1 << 6 | 0x5 << 16
 };
+
 // Negate the operation, AND negate the immediate that we were passed in.
 ALUOp ALUNeg(ALUOp op, Register dest, Imm32* imm, Register* negDest);
 bool can_dbl(ALUOp op);
 bool condsAreSafe(ALUOp op);
+
 // If there is a variant of op that has a dest (think cmp/sub) return that
 // variant of it.
 ALUOp getDestVariant(ALUOp op);
 
 static const ValueOperand JSReturnOperand = ValueOperand(JSReturnReg_Type, JSReturnReg_Data);
 static const ValueOperand softfpReturnOperand = ValueOperand(r1, r0);
+
 // All of these classes exist solely to shuffle data into the various operands.
 // For example Operand2 can be an imm8, a register-shifted-by-a-constant or a
 // register-shifted-by-a-register. We represent this in C++ by having a base
 // class Operand2, which just stores the 32 bits of data as they will be encoded
 // in the instruction. You cannot directly create an Operand2 since it is
 // tricky, and not entirely sane to do so. Instead, you create one of its child
 // classes, e.g. Imm8. Imm8's constructor takes a single integer argument. Imm8
 // will verify that its argument can be encoded as an ARM 12 bit imm8, encode it
@@ -367,57 +372,62 @@ static const ValueOperand softfpReturnOp
 // it for its component Imm8data structures. The reason this is so horribly
 // round-about is we wanted to have Imm8 and RegisterShiftedRegister inherit
 // directly from Operand2 but have all of them take up only a single word of
 // storage. We also wanted to avoid passing around raw integers at all since
 // they are error prone.
 class Op2Reg;
 class O2RegImmShift;
 class O2RegRegShift;
+
 namespace datastore {
+
 struct Reg
 {
     // The "second register".
     uint32_t RM : 4;
     // Do we get another register for shifting.
     uint32_t RRS : 1;
     ShiftType Type : 2;
     // We'd like this to be a more sensible encoding, but that would need to be
     // a struct and that would not pack :(
     uint32_t ShiftAmount : 5;
     uint32_t pad : 20;
 
     Reg(uint32_t rm, ShiftType type, uint32_t rsr, uint32_t shiftamount)
       : RM(rm), RRS(rsr), Type(type), ShiftAmount(shiftamount), pad(0)
     { }
 
-    uint32_t encode() {
-        return RM | RRS << 4 | Type << 5 | ShiftAmount << 7;
-    }
     explicit Reg(const Op2Reg& op) {
         memcpy(this, &op, sizeof(*this));
     }
+
+    uint32_t encode() const {
+        return RM | RRS << 4 | Type << 5 | ShiftAmount << 7;
+    }
 };
 
 // Op2 has a mode labelled "<imm8m>", which is arm's magical immediate encoding.
 // Some instructions actually get 8 bits of data, which is called Imm8Data
 // below. These should have edit distance > 1, but this is how it is for now.
 struct Imm8mData
 {
   private:
     uint32_t data : 8;
     uint32_t rot : 4;
     // Throw in an extra bit that will be 1 if we can't encode this properly.
     // if we can encode it properly, a simple "|" will still suffice to meld it
     // into the instruction.
     uint32_t buff : 19;
+
   public:
     uint32_t invalid : 1;
 
-    uint32_t encode() {
+  public:
+    uint32_t encode() const {
         MOZ_ASSERT(!invalid);
         return data | rot << 8;
     };
 
     // Default constructor makes an invalid immediate.
     Imm8mData()
       : data(0xff), rot(0xf), invalid(1)
     { }
@@ -433,37 +443,45 @@ struct Imm8mData
 struct Imm8Data
 {
   private:
     uint32_t imm4L : 4;
     uint32_t pad : 4;
     uint32_t imm4H : 4;
 
   public:
-    uint32_t encode() {
+    Imm8Data(uint32_t imm)
+      : imm4L(imm & 0xf), imm4H(imm >> 4)
+    {
+        MOZ_ASSERT(imm <= 0xff);
+    }
+
+  public:
+    uint32_t encode() const {
         return imm4L | (imm4H << 8);
     };
-    Imm8Data(uint32_t imm) : imm4L(imm & 0xf), imm4H(imm >> 4) {
-        MOZ_ASSERT(imm <= 0xff);
-    }
 };
 
 // VLDR/VSTR take an 8 bit offset, which is implicitly left shifted by 2.
 struct Imm8VFPOffData
 {
   private:
     uint32_t data;
 
   public:
-    uint32_t encode() {
+    Imm8VFPOffData(uint32_t imm)
+      : data (imm)
+    {
+        MOZ_ASSERT((imm & ~(0xff)) == 0);
+    }
+
+  public:
+    uint32_t encode() const {
         return data;
     };
-    Imm8VFPOffData(uint32_t imm) : data (imm) {
-        MOZ_ASSERT((imm & ~(0xff)) == 0);
-    }
 };
 
 // ARM can magically encode 256 very special immediates to be moved into a
 // register.
 struct Imm8VFPImmData
 {
     // This structure's members are public and it has no constructor to
     // initialize them, for a very special reason. Were this structure to
@@ -473,115 +491,128 @@ struct Imm8VFPImmData
     // the constructor MOZ_CONSTEXPR, but, again, some of our supported
     // compilers don't support MOZ_CONSTEXPR! So we are reduced to public
     // members and eschewing a constructor in hopes that the initialization
     // of DoubleEncoder's table is correct.
     uint32_t imm4L : 4;
     uint32_t imm4H : 4;
     int32_t isInvalid : 24;
 
-    uint32_t encode() {
+    uint32_t encode() const {
         // This assert is an attempting at ensuring that we don't create random
         // instances of this structure and then asking to encode() it.
         MOZ_ASSERT(isInvalid == 0);
         return imm4L | (imm4H << 16);
     };
 };
 
 struct Imm12Data
 {
     uint32_t data : 12;
-    uint32_t encode() {
-        return data;
-    }
 
     Imm12Data(uint32_t imm)
       : data(imm)
     {
         MOZ_ASSERT(data == imm);
     }
 
+    uint32_t encode() const {
+        return data;
+    }
 };
 
 struct RIS
 {
     uint32_t ShiftAmount : 5;
-    uint32_t encode () {
-        return ShiftAmount;
-    }
 
     RIS(uint32_t imm)
       : ShiftAmount(imm)
     {
         MOZ_ASSERT(ShiftAmount == imm);
     }
-    explicit RIS(Reg r) : ShiftAmount(r.ShiftAmount) {}
+
+    explicit RIS(Reg r)
+      : ShiftAmount(r.ShiftAmount)
+    { }
+
+    uint32_t encode() const {
+        return ShiftAmount;
+    }
 };
 
 struct RRS
 {
     uint32_t MustZero : 1;
     // The register that holds the shift amount.
     uint32_t RS : 4;
 
     RRS(uint32_t rs)
       : RS(rs)
     {
         MOZ_ASSERT(rs == RS);
     }
 
-    uint32_t encode () {
+    uint32_t encode() const {
         return RS << 1;
     }
 };
 
 } // namespace datastore
 
 class MacroAssemblerARM;
 class Operand;
 class Operand2
 {
     friend class Operand;
     friend class MacroAssemblerARM;
     friend class InstALU;
+
   public:
     uint32_t oper : 31;
     uint32_t invalid : 1;
-    bool isO2Reg() {
-        return !(oper & IsImmOp2);
-    }
-    Op2Reg toOp2Reg();
-    bool isImm8() {
-        return oper & IsImmOp2;
-    }
 
   protected:
-    Operand2(datastore::Imm8mData base)
+    explicit Operand2(datastore::Imm8mData base)
       : oper(base.invalid ? -1 : (base.encode() | (uint32_t)IsImmOp2)),
         invalid(base.invalid)
     { }
 
-    Operand2(datastore::Reg base)
+    explicit Operand2(datastore::Reg base)
       : oper(base.encode() | (uint32_t)IsNotImmOp2)
     { }
 
   private:
-    Operand2(int blob)
+    explicit Operand2(int blob)
       : oper(blob)
     { }
 
   public:
-    uint32_t encode() {
+    bool isO2Reg() const {
+        return !(oper & IsImmOp2);
+    }
+
+    Op2Reg toOp2Reg() const;
+
+    bool isImm8() const {
+        return oper & IsImmOp2;
+    }
+
+    uint32_t encode() const {
         return oper;
     }
 };
 
 class Imm8 : public Operand2
 {
   public:
+    explicit Imm8(uint32_t imm)
+      : Operand2(EncodeImm(imm))
+    { }
+
+  public:
     static datastore::Imm8mData EncodeImm(uint32_t imm) {
         // mozilla::CountLeadingZeroes32(imm) requires imm != 0.
         if (imm == 0)
             return datastore::Imm8mData(0, 0);
         int left = mozilla::CountLeadingZeroes32(imm) & 30;
         // See if imm is a simple value that can be encoded with a rotate of 0.
         // This is effectively imm <= 0xff, but I assume this can be optimized
         // more.
@@ -602,372 +633,387 @@ class Imm8 : public Operand2
             return datastore::Imm8mData();
         // Rather than masking out bits and checking for 0, just rotate the
         // immediate that we were passed in, and see if it fits into 8 bits.
         unsigned int mask = imm << (8 - right) | imm >> (24 + right);
         if (mask <= 0xff)
             return datastore::Imm8mData(mask, (8 - right) >> 1);
         return datastore::Imm8mData();
     }
+
     // Pair template?
     struct TwoImm8mData
     {
         datastore::Imm8mData fst, snd;
 
         TwoImm8mData()
           : fst(), snd()
         { }
 
         TwoImm8mData(datastore::Imm8mData _fst, datastore::Imm8mData _snd)
           : fst(_fst), snd(_snd)
         { }
     };
 
     static TwoImm8mData EncodeTwoImms(uint32_t);
-    Imm8(uint32_t imm)
-      : Operand2(EncodeImm(imm))
-    { }
 };
 
 class Op2Reg : public Operand2
 {
   public:
-    Op2Reg(Register rm, ShiftType type, datastore::RIS shiftImm)
+    explicit Op2Reg(Register rm, ShiftType type, datastore::RIS shiftImm)
       : Operand2(datastore::Reg(rm.code(), type, 0, shiftImm.encode()))
     { }
 
-    Op2Reg(Register rm, ShiftType type, datastore::RRS shiftReg)
+    explicit Op2Reg(Register rm, ShiftType type, datastore::RRS shiftReg)
       : Operand2(datastore::Reg(rm.code(), type, 1, shiftReg.encode()))
     { }
-    bool isO2RegImmShift() {
+
+  public:
+    bool isO2RegImmShift() const {
         datastore::Reg r(*this);
         return !r.RRS;
     }
-    O2RegImmShift toO2RegImmShift();
-    bool isO2RegRegShift() {
+    O2RegImmShift toO2RegImmShift() const;
+
+    bool isO2RegRegShift() const {
         datastore::Reg r(*this);
         return r.RRS;
     }
-    O2RegRegShift toO2RegRegShift();
+    O2RegRegShift toO2RegRegShift() const;
 
-    bool checkType(ShiftType type) {
+    bool checkType(ShiftType type) const {
         datastore::Reg r(*this);
         return r.Type == type;
     }
-    bool checkRM(Register rm) {
+    bool checkRM(Register rm) const {
         datastore::Reg r(*this);
         return r.RM == rm.code();
     }
-    bool getRM(Register* rm) {
+    bool getRM(Register* rm) const {
         datastore::Reg r(*this);
         *rm = Register::FromCode(r.RM);
         return true;
     }
 };
 
 class O2RegImmShift : public Op2Reg
 {
   public:
-    O2RegImmShift(Register rn, ShiftType type, uint32_t shift)
+    explicit O2RegImmShift(Register rn, ShiftType type, uint32_t shift)
       : Op2Reg(rn, type, datastore::RIS(shift))
     { }
-    int getShift() {
+
+  public:
+    int getShift() const {
         datastore::Reg r(*this);
         datastore::RIS ris(r);
         return ris.ShiftAmount;
     }
 };
 
 class O2RegRegShift : public Op2Reg
 {
   public:
-    O2RegRegShift(Register rn, ShiftType type, Register rs)
+    explicit O2RegRegShift(Register rn, ShiftType type, Register rs)
       : Op2Reg(rn, type, datastore::RRS(rs.code()))
     { }
 };
 
 O2RegImmShift O2Reg(Register r);
-O2RegImmShift lsl (Register r, int amt);
-O2RegImmShift lsr (Register r, int amt);
-O2RegImmShift asr (Register r, int amt);
-O2RegImmShift rol (Register r, int amt);
-O2RegImmShift ror (Register r, int amt);
+O2RegImmShift lsl(Register r, int amt);
+O2RegImmShift lsr(Register r, int amt);
+O2RegImmShift asr(Register r, int amt);
+O2RegImmShift rol(Register r, int amt);
+O2RegImmShift ror(Register r, int amt);
 
-O2RegRegShift lsl (Register r, Register amt);
-O2RegRegShift lsr (Register r, Register amt);
-O2RegRegShift asr (Register r, Register amt);
-O2RegRegShift ror (Register r, Register amt);
+O2RegRegShift lsl(Register r, Register amt);
+O2RegRegShift lsr(Register r, Register amt);
+O2RegRegShift asr(Register r, Register amt);
+O2RegRegShift ror(Register r, Register amt);
 
 // An offset from a register to be used for ldr/str. This should include the
 // sign bit, since ARM has "signed-magnitude" offsets. That is it encodes an
 // unsigned offset, then the instruction specifies if the offset is positive or
 // negative. The +/- bit is necessary if the instruction set wants to be able to
 // have a negative register offset e.g. ldr pc, [r1,-r2];
 class DtrOff
 {
     uint32_t data;
 
   protected:
-    DtrOff(datastore::Imm12Data immdata, IsUp_ iu)
+    explicit DtrOff(datastore::Imm12Data immdata, IsUp_ iu)
       : data(immdata.encode() | (uint32_t)IsImmDTR | ((uint32_t)iu))
     { }
 
-    DtrOff(datastore::Reg reg, IsUp_ iu = IsUp)
+    explicit DtrOff(datastore::Reg reg, IsUp_ iu = IsUp)
       : data(reg.encode() | (uint32_t) IsNotImmDTR | iu)
     { }
 
   public:
-    uint32_t encode() { return data; }
+    uint32_t encode() const { return data; }
 };
 
 class DtrOffImm : public DtrOff
 {
   public:
-    DtrOffImm(int32_t imm)
+    explicit DtrOffImm(int32_t imm)
       : DtrOff(datastore::Imm12Data(mozilla::Abs(imm)), imm >= 0 ? IsUp : IsDown)
     {
         MOZ_ASSERT(mozilla::Abs(imm) < 4096);
     }
 };
 
 class DtrOffReg : public DtrOff
 {
     // These are designed to be called by a constructor of a subclass.
     // Constructing the necessary RIS/RRS structures are annoying.
   protected:
-    DtrOffReg(Register rn, ShiftType type, datastore::RIS shiftImm, IsUp_ iu = IsUp)
+    explicit DtrOffReg(Register rn, ShiftType type, datastore::RIS shiftImm, IsUp_ iu = IsUp)
       : DtrOff(datastore::Reg(rn.code(), type, 0, shiftImm.encode()), iu)
     { }
 
-    DtrOffReg(Register rn, ShiftType type, datastore::RRS shiftReg, IsUp_ iu = IsUp)
+    explicit DtrOffReg(Register rn, ShiftType type, datastore::RRS shiftReg, IsUp_ iu = IsUp)
       : DtrOff(datastore::Reg(rn.code(), type, 1, shiftReg.encode()), iu)
     { }
 };
 
 class DtrRegImmShift : public DtrOffReg
 {
   public:
-    DtrRegImmShift(Register rn, ShiftType type, uint32_t shift, IsUp_ iu = IsUp)
+    explicit DtrRegImmShift(Register rn, ShiftType type, uint32_t shift, IsUp_ iu = IsUp)
       : DtrOffReg(rn, type, datastore::RIS(shift), iu)
     { }
 };
 
 class DtrRegRegShift : public DtrOffReg
 {
   public:
-    DtrRegRegShift(Register rn, ShiftType type, Register rs, IsUp_ iu = IsUp)
+    explicit DtrRegRegShift(Register rn, ShiftType type, Register rs, IsUp_ iu = IsUp)
       : DtrOffReg(rn, type, datastore::RRS(rs.code()), iu)
     { }
 };
 
 // We will frequently want to bundle a register with its offset so that we have
 // an "operand" to a load instruction.
 class DTRAddr
 {
+    friend class Operand;
+
     uint32_t data;
 
   public:
-    DTRAddr(Register reg, DtrOff dtr)
+    explicit DTRAddr(Register reg, DtrOff dtr)
       : data(dtr.encode() | (reg.code() << 16))
     { }
 
-    uint32_t encode() {
+  private:
+    explicit DTRAddr(uint32_t blob)
+      : data(blob)
+    { }
+
+  public:
+    uint32_t encode() const {
         return data;
     }
-    Register getBase() {
+
+    Register getBase() const {
         return Register::FromCode((data >> 16) &0xf);
     }
-  private:
-    friend class Operand;
-    DTRAddr(uint32_t blob)
-      : data(blob)
-    { }
 };
 
 // Offsets for the extended data transfer instructions:
 // ldrsh, ldrd, ldrsb, etc.
 class EDtrOff
 {
     uint32_t data;
 
   protected:
-    EDtrOff(datastore::Imm8Data imm8, IsUp_ iu = IsUp)
+    explicit EDtrOff(datastore::Imm8Data imm8, IsUp_ iu = IsUp)
       : data(imm8.encode() | IsImmEDTR | (uint32_t)iu)
     { }
 
-    EDtrOff(Register rm, IsUp_ iu = IsUp)
+    explicit EDtrOff(Register rm, IsUp_ iu = IsUp)
       : data(rm.code() | IsNotImmEDTR | iu)
     { }
 
   public:
-    uint32_t encode() {
+    uint32_t encode() const {
         return data;
     }
 };
 
 class EDtrOffImm : public EDtrOff
 {
   public:
-    EDtrOffImm(int32_t imm)
+    explicit EDtrOffImm(int32_t imm)
       : EDtrOff(datastore::Imm8Data(mozilla::Abs(imm)), (imm >= 0) ? IsUp : IsDown)
     {
         MOZ_ASSERT(mozilla::Abs(imm) < 256);
     }
 };
 
 // This is the most-derived class, since the extended data transfer instructions
 // don't support any sort of modifying the "index" operand.
 class EDtrOffReg : public EDtrOff
 {
   public:
-    EDtrOffReg(Register rm)
+    explicit EDtrOffReg(Register rm)
       : EDtrOff(rm)
     { }
 };
 
 class EDtrAddr
 {
     uint32_t data;
 
   public:
-    EDtrAddr(Register r, EDtrOff off)
+    explicit EDtrAddr(Register r, EDtrOff off)
       : data(RN(r) | off.encode())
     { }
 
-    uint32_t encode() {
+    uint32_t encode() const {
         return data;
     }
 };
 
 class VFPOff
 {
     uint32_t data;
 
   protected:
-    VFPOff(datastore::Imm8VFPOffData imm, IsUp_ isup)
+    explicit VFPOff(datastore::Imm8VFPOffData imm, IsUp_ isup)
       : data(imm.encode() | (uint32_t)isup)
     { }
 
   public:
-    uint32_t encode() {
+    uint32_t encode() const {
         return data;
     }
 };
 
 class VFPOffImm : public VFPOff
 {
   public:
-    VFPOffImm(int32_t imm)
+    explicit VFPOffImm(int32_t imm)
       : VFPOff(datastore::Imm8VFPOffData(mozilla::Abs(imm) / 4), imm < 0 ? IsDown : IsUp)
     {
         MOZ_ASSERT(mozilla::Abs(imm) <= 255 * 4);
     }
 };
+
 class VFPAddr
 {
     friend class Operand;
 
     uint32_t data;
 
+  public:
+    explicit VFPAddr(Register base, VFPOff off)
+      : data(RN(base) | off.encode())
+    { }
+
   protected:
     VFPAddr(uint32_t blob)
       : data(blob)
     { }
 
   public:
-    VFPAddr(Register base, VFPOff off)
-      : data(RN(base) | off.encode())
-    { }
-
-    uint32_t encode() {
+    uint32_t encode() const {
         return data;
     }
 };
 
-class VFPImm {
+class VFPImm
+{
     uint32_t data;
 
   public:
+    explicit VFPImm(uint32_t topWordOfDouble);
+
+  public:
     static const VFPImm One;
 
-    VFPImm(uint32_t topWordOfDouble);
-
-    uint32_t encode() {
+    uint32_t encode() const {
         return data;
     }
-    bool isValid() {
+    bool isValid() const {
         return data != -1U;
     }
 };
 
 // A BOffImm is an immediate that is used for branches. Namely, it is the offset
 // that will be encoded in the branch instruction. This is the only sane way of
 // constructing a branch.
 class BOffImm
 {
+    friend class InstBranchImm;
+
     uint32_t data;
 
   public:
-    uint32_t encode() {
-        return data;
-    }
-    int32_t decode() {
-        return ((((int32_t)data) << 8) >> 6) + 8;
-    }
-
     explicit BOffImm(int offset)
       : data ((offset - 8) >> 2 & 0x00ffffff)
     {
         MOZ_ASSERT((offset & 0x3) == 0);
         if (!IsInRange(offset))
             CrashAtUnhandlableOOM("BOffImm");
     }
-    static bool IsInRange(int offset)
-    {
+
+    explicit BOffImm()
+      : data(INVALID)
+    { }
+
+  private:
+    BOffImm(Instruction& inst);
+
+  public:
+    static const int INVALID = 0x00800000;
+
+    uint32_t encode() const {
+        return data;
+    }
+    int32_t decode() const {
+        return ((((int32_t)data) << 8) >> 6) + 8;
+    }
+
+    static bool IsInRange(int offset) {
         if ((offset - 8) < -33554432)
             return false;
         if ((offset - 8) > 33554428)
             return false;
         return true;
     }
-    static const int INVALID = 0x00800000;
-    BOffImm()
-      : data(INVALID)
-    { }
 
-    bool isInvalid() {
+    bool isInvalid() const {
         return data == uint32_t(INVALID);
     }
-    Instruction* getDest(Instruction* src);
-
-  private:
-    friend class InstBranchImm;
-    BOffImm(Instruction& inst);
+    Instruction* getDest(Instruction* src) const;
 };
 
 class Imm16
 {
     uint32_t lower : 12;
     uint32_t pad : 4;
     uint32_t upper : 4;
     uint32_t invalid : 12;
 
   public:
-    Imm16();
-    Imm16(uint32_t imm);
-    Imm16(Instruction& inst);
+    explicit Imm16();
+    explicit Imm16(uint32_t imm);
+    explicit Imm16(Instruction& inst);
 
-    uint32_t encode() {
+    uint32_t encode() const {
         return lower | upper << 16;
     }
-    uint32_t decode() {
+    uint32_t decode() const {
         return lower | upper << 12;
     }
 
-    bool isInvalid () {
+    bool isInvalid () const {
         return invalid;
     }
 };
 
 // I would preffer that these do not exist, since there are essentially no
 // instructions that would ever take more than one of these, however, the MIR
 // wants to only have one type of arguments to functions, so bugger.
 class Operand
@@ -983,36 +1029,37 @@ class Operand
 
   private:
     Tag_ Tag : 3;
     uint32_t reg : 5;
     int32_t offset;
     uint32_t data;
 
   public:
-    Operand (Register reg_)
+    explicit Operand(Register reg_)
       : Tag(OP2), reg(reg_.code())
     { }
 
-    Operand (FloatRegister freg)
+    explicit Operand(FloatRegister freg)
       : Tag(FOP), reg(freg.code())
     { }
 
-    Operand (Register base, Imm32 off)
+    explicit Operand(Register base, Imm32 off)
       : Tag(MEM), reg(base.code()), offset(off.value)
     { }
 
-    Operand (Register base, int32_t off)
+    explicit Operand(Register base, int32_t off)
       : Tag(MEM), reg(base.code()), offset(off)
     { }
 
-    Operand (const Address& addr)
+    explicit Operand(const Address& addr)
       : Tag(MEM), reg(addr.base.code()), offset(addr.offset)
     { }
 
+  public:
     Tag_ getTag() const {
         return Tag;
     }
 
     Operand2 toOp2() const {
         MOZ_ASSERT(Tag == OP2);
         return O2Reg(Register::FromCode(reg));
     }
@@ -1023,16 +1070,17 @@ class Operand
     }
 
     void toAddr(Register* r, Imm32* dest) const {
         MOZ_ASSERT(Tag == MEM);
         *r = Register::FromCode(reg);
         *dest = Imm32(offset);
     }
     Address toAddress() const {
+        MOZ_ASSERT(Tag == MEM);
         return Address(Register::FromCode(reg), offset);
     }
     int32_t disp() const {
         MOZ_ASSERT(Tag == MEM);
         return offset;
     }
 
     int32_t base() const {
@@ -1047,16 +1095,17 @@ class Operand
     }
     VFPAddr toVFPAddr() const {
         return VFPAddr(baseReg(), VFPOffImm(offset));
     }
 };
 
 void
 PatchJump(CodeLocationJump& jump_, CodeLocationLabel label);
+
 static inline void
 PatchBackedge(CodeLocationJump& jump_, CodeLocationLabel label, JitRuntime::BackedgeTarget target)
 {
     PatchJump(jump_, label);
 }
 
 class InstructionIterator;
 class Assembler;
@@ -1174,18 +1223,18 @@ class Assembler : public AssemblerShared
     uint32_t actualOffset(uint32_t) const;
     uint32_t actualIndex(uint32_t) const;
     static uint8_t* PatchableJumpAddress(JitCode* code, uint32_t index);
     BufferOffset actualOffset(BufferOffset) const;
     static uint32_t NopFill;
     static uint32_t GetNopFill();
     static uint32_t AsmPoolMaxOffset;
     static uint32_t GetPoolMaxOffset();
+
   protected:
-
     // Structure for fixing up pc-relative loads/jumps when a the machine code
     // gets moved (executable copy, gc, etc.).
     struct RelativePatch
     {
         void* target;
         Relocation::Kind kind;
         RelativePatch(void* target, Relocation::Kind kind)
             : target(target), kind(kind)
@@ -1209,18 +1258,17 @@ class Assembler : public AssemblerShared
   public:
     // For the alignment fill use NOP: 0x0320f000 or (Always | InstNOP::NopInst).
     // For the nopFill use a branch to the next instruction: 0xeaffffff.
     Assembler()
       : m_buffer(1, 1, 8, GetPoolMaxOffset(), 8, 0xe320f000, 0xeaffffff, GetNopFill()),
         isFinished(false),
         dtmActive(false),
         dtmCond(Always)
-    {
-    }
+    { }
 
     // We need to wait until an AutoJitContextAlloc is created by the
     // MacroAssembler, before allocating any space.
     void initWithAllocator() {
         m_buffer.initWithAllocator();
     }
 
     static Condition InvertCondition(Condition cond);
@@ -1347,33 +1395,29 @@ class Assembler : public AssemblerShared
                 Operand2 op2, SetCond_ sc = NoSetCond, Condition c = Always);
     BufferOffset as_sub(Register dest, Register src1,
                 Operand2 op2, SetCond_ sc = NoSetCond, Condition c = Always);
     BufferOffset as_rsb(Register dest, Register src1,
                 Operand2 op2, SetCond_ sc = NoSetCond, Condition c = Always);
     BufferOffset as_rsc(Register dest, Register src1,
                 Operand2 op2, SetCond_ sc = NoSetCond, Condition c = Always);
     // Test operations:
-    BufferOffset as_cmn(Register src1, Operand2 op2,
-                Condition c = Always);
-    BufferOffset as_cmp(Register src1, Operand2 op2,
-                Condition c = Always);
-    BufferOffset as_teq(Register src1, Operand2 op2,
-                Condition c = Always);
-    BufferOffset as_tst(Register src1, Operand2 op2,
-                Condition c = Always);
+    BufferOffset as_cmn(Register src1, Operand2 op2, Condition c = Always);
+    BufferOffset as_cmp(Register src1, Operand2 op2, Condition c = Always);
+    BufferOffset as_teq(Register src1, Operand2 op2, Condition c = Always);
+    BufferOffset as_tst(Register src1, Operand2 op2, Condition c = Always);
+
     // Sign extension operations:
     BufferOffset as_sxtb(Register dest, Register src, int rotate, Condition c = Always);
     BufferOffset as_sxth(Register dest, Register src, int rotate, Condition c = Always);
     BufferOffset as_uxtb(Register dest, Register src, int rotate, Condition c = Always);
     BufferOffset as_uxth(Register dest, Register src, int rotate, Condition c = Always);
 
     // Not quite ALU worthy, but useful none the less: These also have the issue
-    // of these being formatted completly differently from the standard ALU
-    // operations.
+    // of these being formatted completly differently from the standard ALU operations.
     BufferOffset as_movw(Register dest, Imm16 imm, Condition c = Always);
     BufferOffset as_movt(Register dest, Imm16 imm, Condition c = Always);
 
     static void as_movw_patch(Register dest, Imm16 imm, Condition c, Instruction* pos);
     static void as_movt_patch(Register dest, Imm16 imm, Condition c, Instruction* pos);
 
     BufferOffset as_genmul(Register d1, Register d2, Register rm, Register rn,
                    MULOp op, SetCond_ sc, Condition c = Always);
@@ -1415,17 +1459,18 @@ class Assembler : public AssemblerShared
                 DTMMode mode, DTMWriteBack wb, Condition c = Always);
 
     // Overwrite a pool entry with new data.
     static void WritePoolEntry(Instruction* addr, Condition c, uint32_t data);
 
     // Load a 32 bit immediate from a pool into a register.
     BufferOffset as_Imm32Pool(Register dest, uint32_t value, Condition c = Always);
     // Make a patchable jump that can target the entire 32 bit address space.
-    BufferOffset as_BranchPool(uint32_t value, RepatchLabel* label, ARMBuffer::PoolEntry* pe = nullptr, Condition c = Always);
+    BufferOffset as_BranchPool(uint32_t value, RepatchLabel* label,
+                               ARMBuffer::PoolEntry* pe = nullptr, Condition c = Always);
 
     // Load a 64 bit floating point immediate from a pool into a register.
     BufferOffset as_FImm64Pool(VFPRegister dest, double value, Condition c = Always);
     // Load a 32 bit floating point immediate from a pool into a register.
     BufferOffset as_FImm32Pool(VFPRegister dest, float value, Condition c = Always);
 
     // Atomic instructions: ldrex, ldrexh, ldrexb, strex, strexh, strexb.
     //
@@ -1439,20 +1484,18 @@ class Assembler : public AssemblerShared
     BufferOffset as_ldrexh(Register rt, Register rn, Condition c = Always);
     BufferOffset as_ldrexb(Register rt, Register rn, Condition c = Always);
 
     // STREX rd, rt, [rn]
     BufferOffset as_strex(Register rd, Register rt, Register rn, Condition c = Always);
     BufferOffset as_strexh(Register rd, Register rt, Register rn, Condition c = Always);
     BufferOffset as_strexb(Register rd, Register rt, Register rn, Condition c = Always);
 
-    // Memory synchronization: dmb, dsb, isb.
-    //
+    // Memory synchronization.
     // These are available from ARMv7 forward.
-
     BufferOffset as_dmb(BarrierOption option = BarrierSY);
     BufferOffset as_dsb(BarrierOption option = BarrierSY);
     BufferOffset as_isb();
 
     // Memory synchronization for architectures before ARMv7.
     BufferOffset as_dsb_trap();
     BufferOffset as_dmb_trap();
     BufferOffset as_isb_trap();
@@ -1482,67 +1525,50 @@ class Assembler : public AssemblerShared
     BufferOffset as_bl();
     // bl #imm can have a condition code, blx #imm cannot.
     // blx reg can be conditional.
     BufferOffset as_bl(Label* l, Condition c);
     BufferOffset as_bl(BOffImm off, Condition c, BufferOffset inst);
 
     BufferOffset as_mrs(Register r, Condition c = Always);
     BufferOffset as_msr(Register r, Condition c = Always);
+
     // VFP instructions!
   private:
-
     enum vfp_size {
         IsDouble = 1 << 8,
         IsSingle = 0 << 8
     };
 
     BufferOffset writeVFPInst(vfp_size sz, uint32_t blob);
 
     static void WriteVFPInstStatic(vfp_size sz, uint32_t blob, uint32_t* dest);
 
     // Unityped variants: all registers hold the same (ieee754 single/double)
     // notably not included are vcvt; vmov vd, #imm; vmov rt, vn.
     BufferOffset as_vfp_float(VFPRegister vd, VFPRegister vn, VFPRegister vm,
                               VFPOp op, Condition c = Always);
 
   public:
-    BufferOffset as_vadd(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                 Condition c = Always);
-
-    BufferOffset as_vdiv(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                 Condition c = Always);
-
-    BufferOffset as_vmul(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                 Condition c = Always);
-
-    BufferOffset as_vnmul(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                  Condition c = Always);
-
-    BufferOffset as_vnmla(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                  Condition c = Always);
-
-    BufferOffset as_vnmls(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                  Condition c = Always);
-
+    BufferOffset as_vadd(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c = Always);
+    BufferOffset as_vdiv(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c = Always);
+    BufferOffset as_vmul(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c = Always);
+    BufferOffset as_vnmul(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c = Always);
+    BufferOffset as_vnmla(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c = Always);
+    BufferOffset as_vnmls(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c = Always);
     BufferOffset as_vneg(VFPRegister vd, VFPRegister vm, Condition c = Always);
-
     BufferOffset as_vsqrt(VFPRegister vd, VFPRegister vm, Condition c = Always);
-
     BufferOffset as_vabs(VFPRegister vd, VFPRegister vm, Condition c = Always);
-
-    BufferOffset as_vsub(VFPRegister vd, VFPRegister vn, VFPRegister vm,
-                 Condition c = Always);
-
-    BufferOffset as_vcmp(VFPRegister vd, VFPRegister vm,
-                 Condition c = Always);
+    BufferOffset as_vsub(VFPRegister vd, VFPRegister vn, VFPRegister vm, Condition c = Always);
+    BufferOffset as_vcmp(VFPRegister vd, VFPRegister vm, Condition c = Always);
     BufferOffset as_vcmpz(VFPRegister vd,  Condition c = Always);
 
     // Specifically, a move between two same sized-registers.
     BufferOffset as_vmov(VFPRegister vd, VFPRegister vsrc, Condition c = Always);
+
     // Transfer between Core and VFP.
     enum FloatToCore_ {
         FloatToCore = 1 << 20,
         CoreToFloat = 0 << 20
     };
 
   private:
     enum VFPXferSize {
@@ -1559,36 +1585,39 @@ class Assembler : public AssemblerShared
 
     BufferOffset as_vxfer(Register vt1, Register vt2, VFPRegister vm, FloatToCore_ f2c,
                   Condition c = Always, int idx = 0);
 
     // Our encoding actually allows just the src and the dest (and their types)
     // to uniquely specify the encoding that we are going to use.
     BufferOffset as_vcvt(VFPRegister vd, VFPRegister vm, bool useFPSCR = false,
                          Condition c = Always);
+
     // Hard coded to a 32 bit fixed width result for now.
-    BufferOffset as_vcvtFixed(VFPRegister vd, bool isSigned, uint32_t fixedPoint, bool toFixed, Condition c = Always);
+    BufferOffset as_vcvtFixed(VFPRegister vd, bool isSigned, uint32_t fixedPoint,
+                              bool toFixed, Condition c = Always);
 
     // Transfer between VFP and memory.
     BufferOffset as_vdtr(LoadStore ls, VFPRegister vd, VFPAddr addr,
                          Condition c = Always /* vfp doesn't have a wb option*/);
 
     static void as_vdtr_patch(LoadStore ls, VFPRegister vd, VFPAddr addr,
-                              Condition c  /* vfp doesn't have a wb option*/, uint32_t* dest);
+                              Condition c /* vfp doesn't have a wb option */, uint32_t* dest);
 
     // VFP's ldm/stm work differently from the standard arm ones. You can only
     // transfer a range.
 
     BufferOffset as_vdtm(LoadStore st, Register rn, VFPRegister vd, int length,
-                 /*also has update conditions*/Condition c = Always);
+                 /* also has update conditions */ Condition c = Always);
 
     BufferOffset as_vimm(VFPRegister vd, VFPImm imm, Condition c = Always);
 
     BufferOffset as_vmrs(Register r, Condition c = Always);
     BufferOffset as_vmsr(Register r, Condition c = Always);
+
     // Label operations.
     bool nextLink(BufferOffset b, BufferOffset* next);
     void bind(Label* label, BufferOffset boff = BufferOffset());
     void bind(RepatchLabel* label);
     uint32_t currentOffset() {
         return nextOffset().getOffset();
     }
     void retarget(Label* label, Label* target);
@@ -1906,16 +1935,17 @@ class InstDTR : public Instruction
 JS_STATIC_ASSERT(sizeof(InstDTR) == sizeof(Instruction));
 
 class InstLDR : public InstDTR
 {
   public:
     InstLDR(Index mode, Register rt, DTRAddr addr, Assembler::Condition c)
         : InstDTR(IsLoad, IsWord, mode, rt, addr, c)
     { }
+
     static bool IsTHIS(const Instruction& i);
     static InstLDR* AsTHIS(const Instruction& i);
 
 };
 JS_STATIC_ASSERT(sizeof(InstDTR) == sizeof(InstLDR));
 
 class InstNOP : public Instruction
 {
@@ -1934,78 +1964,87 @@ class InstNOP : public Instruction
 class InstBranchReg : public Instruction
 {
   protected:
     // Don't use BranchTag yourself, use a derived instruction.
     enum BranchTag {
         IsBX  = 0x012fff10,
         IsBLX = 0x012fff30
     };
+
     static const uint32_t IsBRegMask = 0x0ffffff0;
+
     InstBranchReg(BranchTag tag, Register rm, Assembler::Condition c)
       : Instruction(tag | rm.code(), c)
     { }
+
   public:
     static bool IsTHIS (const Instruction& i);
     static InstBranchReg* AsTHIS (const Instruction& i);
+
     // Get the register that is being branched to
     void extractDest(Register* dest);
     // Make sure we are branching to a pre-known register
     bool checkDest(Register dest);
 };
 JS_STATIC_ASSERT(sizeof(InstBranchReg) == sizeof(Instruction));
 
 // Branching to an immediate offset, or calling an immediate offset
 class InstBranchImm : public Instruction
 {
   protected:
     enum BranchTag {
         IsB   = 0x0a000000,
         IsBL  = 0x0b000000
     };
+
     static const uint32_t IsBImmMask = 0x0f000000;
 
     InstBranchImm(BranchTag tag, BOffImm off, Assembler::Condition c)
       : Instruction(tag | off.encode(), c)
     { }
 
   public:
     static bool IsTHIS (const Instruction& i);
     static InstBranchImm* AsTHIS (const Instruction& i);
+
     void extractImm(BOffImm* dest);
 };
 JS_STATIC_ASSERT(sizeof(InstBranchImm) == sizeof(Instruction));
 
 // Very specific branching instructions.
 class InstBXReg : public InstBranchReg
 {
   public:
     static bool IsTHIS (const Instruction& i);
     static InstBXReg* AsTHIS (const Instruction& i);
 };
+
 class InstBLXReg : public InstBranchReg
 {
   public:
     InstBLXReg(Register reg, Assembler::Condition c)
       : InstBranchReg(IsBLX, reg, c)
     { }
 
     static bool IsTHIS (const Instruction& i);
     static InstBLXReg* AsTHIS (const Instruction& i);
 };
+
 class InstBImm : public InstBranchImm
 {
   public:
     InstBImm(BOffImm off, Assembler::Condition c)
       : InstBranchImm(IsB, off, c)
     { }
 
     static bool IsTHIS (const Instruction& i);
     static InstBImm* AsTHIS (const Instruction& i);
 };
+
 class InstBLImm : public InstBranchImm
 {
   public:
     InstBLImm(BOffImm off, Assembler::Condition c)
       : InstBranchImm(IsBL, off, c)
     { }
 
     static bool IsTHIS (const Instruction& i);
@@ -2051,29 +2090,33 @@ class InstMovW : public InstMovWT
 };
 
 class InstMovT : public InstMovWT
 {
   public:
     InstMovT (Register rd, Imm16 imm, Assembler::Condition c)
       : InstMovWT(rd, imm, IsT, c)
     { }
+
     static bool IsTHIS (const Instruction& i);
     static InstMovT* AsTHIS (const Instruction& i);
 };
 
 class InstALU : public Instruction
 {
     static const int32_t ALUMask = 0xc << 24;
+
   public:
     InstALU (Register rd, Register rn, Operand2 op2, ALUOp op, SetCond_ sc, Assembler::Condition c)
         : Instruction(maybeRD(rd) | maybeRN(rn) | op2.encode() | op | sc, c)
     { }
+
     static bool IsTHIS (const Instruction& i);
     static InstALU* AsTHIS (const Instruction& i);
+
     void extractOp(ALUOp* ret);
     bool checkOp(ALUOp op);
     void extractDest(Register* ret);
     bool checkDest(Register rd);
     void extractOp1(Register* ret);
     bool checkOp1(Register rn);
     Operand2 extractOp2();
 };
@@ -2088,60 +2131,67 @@ class InstCMP : public InstALU
 class InstMOV : public InstALU
 {
   public:
     static bool IsTHIS (const Instruction& i);
     static InstMOV* AsTHIS (const Instruction& i);
 };
 
 
-class InstructionIterator {
+class InstructionIterator
+{
   private:
     Instruction* i;
+
   public:
-    InstructionIterator(Instruction* i_);
+    explicit InstructionIterator(Instruction* i_);
+
     Instruction* next() {
         i = i->next();
         return cur();
     }
     Instruction* cur() const {
         return i;
     }
 };
 
 static const uint32_t NumIntArgRegs = 4;
+
 // There are 16 *float* registers available for arguments
 // If doubles are used, only half the number of registers are available.
 static const uint32_t NumFloatArgRegs = 16;
 
 static inline bool
 GetIntArgReg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register* out)
 {
     if (usedIntArgs >= NumIntArgRegs)
         return false;
+
     *out = Register::FromCode(usedIntArgs);
     return true;
 }
 
 // Get a register in which we plan to put a quantity that will be used as an
 // integer argument. This differs from GetIntArgReg in that if we have no more
 // actual argument registers to use we will fall back on using whatever
 // CallTempReg* don't overlap the argument registers, and only fail once those
 // run out too.
 static inline bool
 GetTempRegForIntArg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register* out)
 {
     if (GetIntArgReg(usedIntArgs, usedFloatArgs, out))
         return true;
+
     // Unfortunately, we have to assume things about the point at which
     // GetIntArgReg returns false, because we need to know how many registers it
     // can allocate.
     usedIntArgs -= NumIntArgRegs;
     if (usedIntArgs >= NumCallTempNonArgRegs)
         return false;
+
     *out = CallTempNonArgRegs[usedIntArgs];
     return true;
 }
 
 
 #if !defined(JS_CODEGEN_ARM_HARDFP) || defined(JS_ARM_SIMULATOR)
 
 static inline uint32_t
@@ -2215,50 +2265,56 @@ GetDoubleArgStackDisp(uint32_t usedIntAr
     doubleSlots *= 2;
     return (intSlots + doubleSlots + *padding) * sizeof(intptr_t);
 }
 
 #endif
 
 
 
-class DoubleEncoder {
+class DoubleEncoder
+{
     struct DoubleEntry
     {
         uint32_t dblTop;
         datastore::Imm8VFPImmData data;
     };
 
     static const DoubleEntry table[256];
 
   public:
-    bool lookup(uint32_t top, datastore::Imm8VFPImmData* ret) {
+    bool lookup(uint32_t top, datastore::Imm8VFPImmData* ret) const {
         for (int i = 0; i < 256; i++) {
             if (table[i].dblTop == top) {
                 *ret = table[i].data;
                 return true;
             }
         }
         return false;
     }
 };
 
-class AutoForbidPools {
+class AutoForbidPools
+{
     Assembler* masm_;
+
   public:
     // The maxInst argument is the maximum number of word sized instructions
     // that will be allocated within this context. It is used to determine if
     // the pool needs to be dumped before entering this content. The debug code
     // checks that no more than maxInst instructions are actually allocated.
     //
     // Allocation of pool entries is not supported within this content so the
     // code can not use large integers or float constants etc.
-    AutoForbidPools(Assembler* masm, size_t maxInst) : masm_(masm) {
+    AutoForbidPools(Assembler* masm, size_t maxInst)
+      : masm_(masm)
+    {
         masm_->enterNoPool(maxInst);
     }
+
     ~AutoForbidPools() {
         masm_->leaveNoPool();
     }
 };
 
 } // namespace jit
 } // namespace js
 
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1788,19 +1788,19 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAs
 
     if (ptr->isConstant()) {
         MOZ_ASSERT(!mir->needsBoundsCheck());
         int32_t ptrImm = ptr->toConstant()->toInt32();
         MOZ_ASSERT(ptrImm >= 0);
         if (isFloat) {
             VFPRegister vd(ToFloatRegister(ins->output()));
             if (size == 32)
-                masm.ma_vldr(Operand(HeapReg, ptrImm), vd.singleOverlay(), Assembler::Always);
+                masm.ma_vldr(Address(HeapReg, ptrImm), vd.singleOverlay(), Assembler::Always);
             else
-                masm.ma_vldr(Operand(HeapReg, ptrImm), vd, Assembler::Always);
+                masm.ma_vldr(Address(HeapReg, ptrImm), vd, Assembler::Always);
         }  else {
             masm.ma_dataTransferN(IsLoad, size, isSigned, HeapReg, Imm32(ptrImm),
                                   ToRegister(ins->output()), Offset, Assembler::Always);
         }
         memoryBarrier(mir->barrierAfter());
         return;
     }
 
@@ -1821,21 +1821,21 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAs
         return;
     }
 
     BufferOffset bo = masm.ma_BoundsCheck(ptrReg);
     if (isFloat) {
         FloatRegister dst = ToFloatRegister(ins->output());
         VFPRegister vd(dst);
         if (size == 32) {
-            masm.ma_vldr(Operand(GlobalReg, AsmJSNaN32GlobalDataOffset - AsmJSGlobalRegBias),
+            masm.ma_vldr(Address(GlobalReg, AsmJSNaN32GlobalDataOffset - AsmJSGlobalRegBias),
                          vd.singleOverlay(), Assembler::AboveOrEqual);
             masm.ma_vldr(vd.singleOverlay(), HeapReg, ptrReg, 0, Assembler::Below);
         } else {
-            masm.ma_vldr(Operand(GlobalReg, AsmJSNaN64GlobalDataOffset - AsmJSGlobalRegBias),
+            masm.ma_vldr(Address(GlobalReg, AsmJSNaN64GlobalDataOffset - AsmJSGlobalRegBias),
                          vd, Assembler::AboveOrEqual);
             masm.ma_vldr(vd, HeapReg, ptrReg, 0, Assembler::Below);
         }
     } else {
         Register d = ToRegister(ins->output());
         masm.ma_mov(Imm32(0), d, NoSetCond, Assembler::AboveOrEqual);
         masm.ma_dataTransferN(IsLoad, size, isSigned, HeapReg, ptrReg, d, Offset, Assembler::Below);
     }
@@ -1865,19 +1865,19 @@ CodeGeneratorARM::visitAsmJSStoreHeap(LA
     memoryBarrier(mir->barrierBefore());
     if (ptr->isConstant()) {
         MOZ_ASSERT(!mir->needsBoundsCheck());
         int32_t ptrImm = ptr->toConstant()->toInt32();
         MOZ_ASSERT(ptrImm >= 0);
         if (isFloat) {
             VFPRegister vd(ToFloatRegister(ins->value()));
             if (size == 32)
-                masm.ma_vstr(vd.singleOverlay(), Operand(HeapReg, ptrImm), Assembler::Always);
+                masm.ma_vstr(vd.singleOverlay(), Address(HeapReg, ptrImm), Assembler::Always);
             else
-                masm.ma_vstr(vd, Operand(HeapReg, ptrImm), Assembler::Always);
+                masm.ma_vstr(vd, Address(HeapReg, ptrImm), Assembler::Always);
         } else {
             masm.ma_dataTransferN(IsStore, size, isSigned, HeapReg, Imm32(ptrImm),
                                   ToRegister(ins->value()), Offset, Assembler::Always);
         }
         memoryBarrier(mir->barrierAfter());
         return;
     }
 
@@ -2084,17 +2084,17 @@ CodeGeneratorARM::visitAsmJSAtomicBinopC
         MOZ_CRASH("Unknown op");
     }
 }
 
 void
 CodeGeneratorARM::visitAsmJSPassStackArg(LAsmJSPassStackArg* ins)
 {
     const MAsmJSPassStackArg* mir = ins->mir();
-    Operand dst(StackPointer, mir->spOffset());
+    Address dst(StackPointer, mir->spOffset());
     if (ins->arg()->isConstant()) {
         //masm.as_bkpt();
         masm.ma_storeImm(Imm32(ToInt32(ins->arg())), dst);
     } else {
         if (ins->arg()->isGeneralReg())
             masm.ma_str(ToRegister(ins->arg()), dst);
         else
             masm.ma_vstr(ToFloatRegister(ins->arg()), dst);
@@ -2226,38 +2226,38 @@ void
 CodeGeneratorARM::visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar* ins)
 {
     const MAsmJSLoadGlobalVar* mir = ins->mir();
     unsigned addr = mir->globalDataOffset() - AsmJSGlobalRegBias;
     if (mir->type() == MIRType_Int32) {
         masm.ma_dtr(IsLoad, GlobalReg, Imm32(addr), ToRegister(ins->output()));
     } else if (mir->type() == MIRType_Float32) {
         VFPRegister vd(ToFloatRegister(ins->output()));
-        masm.ma_vldr(Operand(GlobalReg, addr), vd.singleOverlay());
+        masm.ma_vldr(Address(GlobalReg, addr), vd.singleOverlay());
     } else {
-        masm.ma_vldr(Operand(GlobalReg, addr), ToFloatRegister(ins->output()));
+        masm.ma_vldr(Address(GlobalReg, addr), ToFloatRegister(ins->output()));
     }
 }
 
 void
 CodeGeneratorARM::visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar* ins)
 {
     const MAsmJSStoreGlobalVar* mir = ins->mir();
 
     MIRType type = mir->value()->type();
     MOZ_ASSERT(IsNumberType(type));
 
     unsigned addr = mir->globalDataOffset() - AsmJSGlobalRegBias;
     if (type == MIRType_Int32) {
         masm.ma_dtr(IsStore, GlobalReg, Imm32(addr), ToRegister(ins->value()));
     } else if (type == MIRType_Float32) {
         VFPRegister vd(ToFloatRegister(ins->value()));
-        masm.ma_vstr(vd.singleOverlay(), Operand(GlobalReg, addr));
+        masm.ma_vstr(vd.singleOverlay(), Address(GlobalReg, addr));
     } else {
-        masm.ma_vstr(ToFloatRegister(ins->value()), Operand(GlobalReg, addr));
+        masm.ma_vstr(ToFloatRegister(ins->value()), Address(GlobalReg, addr));
     }
 }
 
 void
 CodeGeneratorARM::visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr* ins)
 {
     const MAsmJSLoadFuncPtr* mir = ins->mir();
 
@@ -2270,17 +2270,17 @@ CodeGeneratorARM::visitAsmJSLoadFuncPtr(
     masm.ma_ldr(DTRAddr(GlobalReg, DtrRegImmShift(tmp, LSL, 0)), out);
 }
 
 void
 CodeGeneratorARM::visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins)
 {
     const MAsmJSLoadFFIFunc* mir = ins->mir();
 
-    masm.ma_ldr(Operand(GlobalReg, mir->globalDataOffset() - AsmJSGlobalRegBias),
+    masm.ma_ldr(Address(GlobalReg, mir->globalDataOffset() - AsmJSGlobalRegBias),
                 ToRegister(ins->output()));
 }
 
 void
 CodeGeneratorARM::visitNegI(LNegI* ins)
 {
     Register input = ToRegister(ins->input());
     masm.ma_neg(input, ToRegister(ins->output()));
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -52,17 +52,17 @@ MacroAssemblerARM::convertInt32ToDouble(
     as_vxfer(src, InvalidReg, dest.sintOverlay(),
              CoreToFloat);
     as_vcvt(dest, dest.sintOverlay());
 }
 
 void
 MacroAssemblerARM::convertInt32ToDouble(const Address& src, FloatRegister dest)
 {
-    ma_vldr(Operand(src), ScratchDoubleReg);
+    ma_vldr(src, ScratchDoubleReg);
     as_vcvt(dest, VFPRegister(ScratchDoubleReg).sintOverlay());
 }
 
 void
 MacroAssemblerARM::convertInt32ToDouble(const BaseIndex& src, FloatRegister dest)
 {
     Register base = src.base;
     uint32_t scale = Imm32::ShiftOf(src.scale).value;
@@ -209,17 +209,17 @@ MacroAssemblerARM::convertInt32ToFloat32
     // Direct conversions aren't possible.
     as_vxfer(src, InvalidReg, dest.sintOverlay(),
              CoreToFloat);
     as_vcvt(dest.singleOverlay(), dest.sintOverlay());
 }
 
 void
 MacroAssemblerARM::convertInt32ToFloat32(const Address& src, FloatRegister dest) {
-    ma_vldr(Operand(src), ScratchFloat32Reg);
+    ma_vldr(src, ScratchFloat32Reg);
     as_vcvt(dest, VFPRegister(ScratchFloat32Reg).sintOverlay());
 }
 
 void
 MacroAssemblerARM::addDouble(FloatRegister src, FloatRegister dest)
 {
     ma_vadd(dest, src, dest);
 }
@@ -277,18 +277,18 @@ MacroAssemblerARM::alu_dbl(Register src1
     Imm8::TwoImm8mData both = Imm8::EncodeTwoImms(imm.value);
     if (both.fst.invalid)
         return false;
     // For the most part, there is no good reason to set the condition codes for
     // the first instruction. We can do better things if the second instruction
     // doesn't have a dest, such as check for overflow by doing first operation
     // don't do second operation if first operation overflowed. This preserves
     // the overflow condition code. Unfortunately, it is horribly brittle.
-    as_alu(ScratchRegister, src1, both.fst, interop, NoSetCond, c);
-    as_alu(dest, ScratchRegister, both.snd, op, sc, c);
+    as_alu(ScratchRegister, src1, Operand2(both.fst), interop, NoSetCond, c);
+    as_alu(dest, ScratchRegister, Operand2(both.snd), op, sc, c);
     return true;
 }
 
 
 void
 MacroAssemblerARM::ma_alu(Register src1, Imm32 imm, Register dest,
                           ALUOp op,
                           SetCond_ sc, Condition c)
@@ -327,40 +327,40 @@ MacroAssemblerARM::ma_alu(Register src1,
         // a multi-instruction format :(
         // movw/movt does not set condition codes, so don't hold your breath.
         if (sc == NoSetCond && (op == OpMov || op == OpMvn)) {
             // ARMv7 supports movw/movt. movw zero-extends its 16 bit argument,
             // so we can set the register this way. movt leaves the bottom 16
             // bits in tact, so it is unsuitable to move a constant that
             if (op == OpMov && ((imm.value & ~ 0xffff) == 0)) {
                 MOZ_ASSERT(src1 == InvalidReg);
-                as_movw(dest, (uint16_t)imm.value, c);
+                as_movw(dest, Imm16((uint16_t)imm.value), c);
                 return;
             }
 
             // If they asked for a mvn rfoo, imm, where ~imm fits into 16 bits
             // then do it.
             if (op == OpMvn && (((~imm.value) & ~ 0xffff) == 0)) {
                 MOZ_ASSERT(src1 == InvalidReg);
-                as_movw(dest, (uint16_t)~imm.value, c);
+                as_movw(dest, Imm16((uint16_t)~imm.value), c);
                 return;
             }
 
             // TODO: constant dedup may enable us to add dest, r0, 23 *if* we
             // are attempting to load a constant that looks similar to one that
             // already exists. If it can't be done with a single movw then we
             // *need* to use two instructions since this must be some sort of a
             // move operation, we can just use a movw/movt pair and get the
             // whole thing done in two moves. This does not work for ops like
             // add, since we'd need to do: movw tmp; movt tmp; add dest, tmp,
             // src1.
             if (op == OpMvn)
                 imm.value = ~imm.value;
-            as_movw(dest, imm.value & 0xffff, c);
-            as_movt(dest, (imm.value >> 16) & 0xffff, c);
+            as_movw(dest, Imm16(imm.value & 0xffff), c);
+            as_movt(dest, Imm16((imm.value >> 16) & 0xffff), c);
             return;
         }
         // If we weren't doing a movalike, a 16 bit immediate will require 2
         // instructions. With the same amount of space and (less)time, we can do
         // two 8 bit operations, reusing the dest register. e.g.
         //  movw tmp, 0xffff; add dest, src, tmp ror 4
         // vs.
         //  add dest, src, 0xff0; add dest, dest, 0xf000000f
@@ -387,19 +387,19 @@ MacroAssemblerARM::ma_alu(Register src1,
     if (negOp != OpInvalid &&
         alu_dbl(src1, negImm, negDest, negOp, sc, c))
         return;
 
     // Well, damn. We can use two 16 bit mov's, then do the op or we can do a
     // single load from a pool then op.
     if (HasMOVWT()) {
         // Try to load the immediate into a scratch register then use that
-        as_movw(ScratchRegister, imm.value & 0xffff, c);
+        as_movw(ScratchRegister, Imm16(imm.value & 0xffff), c);
         if ((imm.value >> 16) != 0)
-            as_movt(ScratchRegister, (imm.value >> 16) & 0xffff, c);
+            as_movt(ScratchRegister, Imm16((imm.value >> 16) & 0xffff), c);
     } else {
         // Going to have to use a load. If the operation is a move, then just
         // move it into the destination register
         if (op == OpMov) {
             as_Imm32Pool(dest, imm.value, c);
             return;
         } else {
             // If this isn't just going into a register, then stick it in a
@@ -842,17 +842,17 @@ MacroAssemblerARM::ma_cmp(Register src1,
 void
 MacroAssemblerARM::ma_cmp(Register src1, Operand op, Condition c)
 {
     switch (op.getTag()) {
       case Operand::OP2:
         as_cmp(src1, op.toOp2(), c);
         break;
       case Operand::MEM:
-        ma_ldr(op, ScratchRegister);
+        ma_ldr(op.toAddress(), ScratchRegister);
         as_cmp(src1, O2Reg(ScratchRegister), c);
         break;
       default:
         MOZ_CRASH("trying to compare FP and integer registers");
     }
 }
 void
 MacroAssemblerARM::ma_cmp(Register src1, Register src2, Condition c)
@@ -1063,25 +1063,23 @@ MacroAssemblerARM::ma_dtr(LoadStore ls, 
 
 void
 MacroAssemblerARM::ma_str(Register rt, DTRAddr addr, Index mode, Condition cc)
 {
     as_dtr(IsStore, 32, mode, rt, addr, cc);
 }
 
 void
-MacroAssemblerARM::ma_dtr(LoadStore ls, Register rt, const Operand& addr, Index mode, Condition cc)
-{
-    ma_dataTransferN(ls, 32, true,
-                     Register::FromCode(addr.base()), Imm32(addr.disp()),
-                     rt, mode, cc);
-}
-
-void
-MacroAssemblerARM::ma_str(Register rt, const Operand& addr, Index mode, Condition cc)
+MacroAssemblerARM::ma_dtr(LoadStore ls, Register rt, const Address& addr, Index mode, Condition cc)
+{
+    ma_dataTransferN(ls, 32, true, addr.base, Imm32(addr.offset), rt, mode, cc);
+}
+
+void
+MacroAssemblerARM::ma_str(Register rt, const Address& addr, Index mode, Condition cc)
 {
     ma_dtr(IsStore, rt, addr, mode, cc);
 }
 void
 MacroAssemblerARM::ma_strd(Register rt, DebugOnly<Register> rt2, EDtrAddr addr, Index mode, Condition cc)
 {
     MOZ_ASSERT((rt.code() & 1) == 0);
     MOZ_ASSERT(rt2.value.code() == rt.code() + 1);
@@ -1089,17 +1087,17 @@ MacroAssemblerARM::ma_strd(Register rt, 
 }
 
 void
 MacroAssemblerARM::ma_ldr(DTRAddr addr, Register rt, Index mode, Condition cc)
 {
     as_dtr(IsLoad, 32, mode, rt, addr, cc);
 }
 void
-MacroAssemblerARM::ma_ldr(const Operand& addr, Register rt, Index mode, Condition cc)
+MacroAssemblerARM::ma_ldr(const Address& addr, Register rt, Index mode, Condition cc)
 {
     ma_dtr(IsLoad, rt, addr, mode, cc);
 }
 
 void
 MacroAssemblerARM::ma_ldrb(DTRAddr addr, Register rt, Index mode, Condition cc)
 {
     as_dtr(IsLoad, 8, mode, rt, addr, cc);
@@ -1704,23 +1702,23 @@ MacroAssemblerARM::ma_vxfer(FloatRegiste
 
 void
 MacroAssemblerARM::ma_vxfer(Register src1, Register src2, FloatRegister dest, Condition cc)
 {
     as_vxfer(src1, src2, VFPRegister(dest), CoreToFloat, cc);
 }
 
 BufferOffset
-MacroAssemblerARM::ma_vdtr(LoadStore ls, const Operand& addr, VFPRegister rt, Condition cc)
-{
-    int off = addr.disp();
+MacroAssemblerARM::ma_vdtr(LoadStore ls, const Address& addr, VFPRegister rt, Condition cc)
+{
+    int off = addr.offset;
     MOZ_ASSERT((off & 3) == 0);
-    Register base = Register::FromCode(addr.base());
+    Register base = addr.base;
     if (off > -1024 && off < 1024)
-        return as_vdtr(ls, rt, addr.toVFPAddr(), cc);
+        return as_vdtr(ls, rt, Operand(addr).toVFPAddr(), cc);
 
     // We cannot encode this offset in a a single ldr. Try to encode it as an
     // add scratch, base, imm; ldr dest, [scratch, +offset].
     int bottom = off & (0xff << 2);
     int neg_bottom = (0x100 << 2) - bottom;
     // At this point, both off - bottom and off + neg_bottom will be
     // reasonable-ish quantities.
     //
@@ -1767,44 +1765,44 @@ MacroAssemblerARM::ma_vdtr(LoadStore ls,
 }
 
 BufferOffset
 MacroAssemblerARM::ma_vldr(VFPAddr addr, VFPRegister dest, Condition cc)
 {
     return as_vdtr(IsLoad, dest, addr, cc);
 }
 BufferOffset
-MacroAssemblerARM::ma_vldr(const Operand& addr, VFPRegister dest, Condition cc)
+MacroAssemblerARM::ma_vldr(const Address& addr, VFPRegister dest, Condition cc)
 {
     return ma_vdtr(IsLoad, addr, dest, cc);
 }
 BufferOffset
 MacroAssemblerARM::ma_vldr(VFPRegister src, Register base, Register index, int32_t shift, Condition cc)
 {
     as_add(ScratchRegister, base, lsl(index, shift), NoSetCond, cc);
-    return ma_vldr(Operand(ScratchRegister, 0), src, cc);
+    return ma_vldr(Address(ScratchRegister, 0), src, cc);
 }
 
 BufferOffset
 MacroAssemblerARM::ma_vstr(VFPRegister src, VFPAddr addr, Condition cc)
 {
     return as_vdtr(IsStore, src, addr, cc);
 }
 
 BufferOffset
-MacroAssemblerARM::ma_vstr(VFPRegister src, const Operand& addr, Condition cc)
+MacroAssemblerARM::ma_vstr(VFPRegister src, const Address& addr, Condition cc)
 {
     return ma_vdtr(IsStore, addr, src, cc);
 }
 BufferOffset
 MacroAssemblerARM::ma_vstr(VFPRegister src, Register base, Register index, int32_t shift,
                            int32_t offset, Condition cc)
 {
     as_add(ScratchRegister, base, lsl(index, shift), NoSetCond, cc);
-    return ma_vstr(src, Operand(ScratchRegister, offset), cc);
+    return ma_vstr(src, Address(ScratchRegister, offset), cc);
 }
 
 void
 MacroAssemblerARMCompat::buildFakeExitFrame(Register scratch, uint32_t* offset)
 {
     DebugOnly<uint32_t> initialDepth = framePushed();
     uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS);
 
@@ -2227,17 +2225,17 @@ MacroAssemblerARMCompat::load32(const Ba
 void
 MacroAssemblerARMCompat::load32(AbsoluteAddress address, Register dest)
 {
     loadPtr(address, dest);
 }
 void
 MacroAssemblerARMCompat::loadPtr(const Address& address, Register dest)
 {
-    ma_ldr(Operand(address), dest);
+    ma_ldr(address, dest);
 }
 
 void
 MacroAssemblerARMCompat::loadPtr(const BaseIndex& src, Register dest)
 {
     Register base = src.base;
     uint32_t scale = Imm32::ShiftOf(src.scale).value;
 
@@ -2256,91 +2254,84 @@ MacroAssemblerARMCompat::loadPtr(Absolut
 }
 void
 MacroAssemblerARMCompat::loadPtr(AsmJSAbsoluteAddress address, Register dest)
 {
     movePtr(AsmJSImmPtr(address.kind()), ScratchRegister);
     loadPtr(Address(ScratchRegister, 0x0), dest);
 }
 
-Operand payloadOf(const Address& address) {
-    return Operand(address.base, address.offset);
-}
-Operand tagOf(const Address& address) {
-    return Operand(address.base, address.offset + 4);
-}
-
 void
 MacroAssemblerARMCompat::loadPrivate(const Address& address, Register dest)
 {
-    ma_ldr(payloadOf(address), dest);
+    ma_ldr(ToPayload(address), dest);
 }
 
 void
 MacroAssemblerARMCompat::loadDouble(const Address& address, FloatRegister dest)
 {
-    ma_vldr(Operand(address), dest);
+    ma_vldr(address, dest);
 }
 
 void
 MacroAssemblerARMCompat::loadDouble(const BaseIndex& src, FloatRegister dest)
 {
     // VFP instructions don't even support register Base + register Index modes,
     // so just add the index, then handle the offset like normal.
     Register base = src.base;
     Register index = src.index;
     uint32_t scale = Imm32::ShiftOf(src.scale).value;
     int32_t offset = src.offset;
     as_add(ScratchRegister, base, lsl(index, scale));
 
-    ma_vldr(Operand(ScratchRegister, offset), dest);
+    ma_vldr(Address(ScratchRegister, offset), dest);
 }
 
 void
 MacroAssemblerARMCompat::loadFloatAsDouble(const Address& address, FloatRegister dest)
 {
     VFPRegister rt = dest;
-    ma_vldr(Operand(address), rt.singleOverlay());
+    ma_vldr(address, rt.singleOverlay());
     as_vcvt(rt, rt.singleOverlay());
 }
 
 void
 MacroAssemblerARMCompat::loadFloatAsDouble(const BaseIndex& src, FloatRegister dest)
 {
     // VFP instructions don't even support register Base + register Index modes,
     // so just add the index, then handle the offset like normal.
     Register base = src.base;
     Register index = src.index;
     uint32_t scale = Imm32::ShiftOf(src.scale).value;
     int32_t offset = src.offset;
     VFPRegister rt = dest;
     as_add(ScratchRegister, base, lsl(index, scale));
 
-    ma_vldr(Operand(ScratchRegister, offset), rt.singleOverlay());
+    ma_vldr(Address(ScratchRegister, offset), rt.singleOverlay());
     as_vcvt(rt, rt.singleOverlay());
 }
 
 void
 MacroAssemblerARMCompat::loadFloat32(const Address& address, FloatRegister dest)
 {
-    ma_vldr(Operand(address), VFPRegister(dest).singleOverlay());
+    ma_vldr(address, VFPRegister(dest).singleOverlay());
 }
 
 void
 MacroAssemblerARMCompat::loadFloat32(const BaseIndex& src, FloatRegister dest)
 {
     // VFP instructions don't even support register Base + register Index modes,
     // so just add the index, then handle the offset like normal.
     Register base = src.base;
     Register index = src.index;
     uint32_t scale = Imm32::ShiftOf(src.scale).value;
     int32_t offset = src.offset;
     as_add(ScratchRegister, base, lsl(index, scale));
 
-    ma_vldr(Operand(ScratchRegister, offset), VFPRegister(dest).singleOverlay());
+    ma_vldr(Address(ScratchRegister, offset), VFPRegister(dest).singleOverlay());
 }
 
 void
 MacroAssemblerARMCompat::store8(Imm32 imm, const Address& address)
 {
     ma_mov(imm, secondScratchReg_);
     store8(secondScratchReg_, address);
 }
@@ -2483,17 +2474,17 @@ MacroAssemblerARMCompat::storePtr(ImmGCP
 }
 
 template void MacroAssemblerARMCompat::storePtr<Address>(ImmGCPtr imm, Address address);
 template void MacroAssemblerARMCompat::storePtr<BaseIndex>(ImmGCPtr imm, BaseIndex address);
 
 void
 MacroAssemblerARMCompat::storePtr(Register src, const Address& address)
 {
-    ma_str(src, Operand(address));
+    ma_str(src, address);
 }
 
 void
 MacroAssemblerARMCompat::storePtr(Register src, const BaseIndex& address)
 {
     store32(src, address);
 }
 
@@ -3142,29 +3133,29 @@ MacroAssemblerARMCompat::branchTestValue
 void
 MacroAssemblerARMCompat::branchTestValue(Condition cond, const Address& valaddr,
                                          const ValueOperand& value, Label* label)
 {
     MOZ_ASSERT(cond == Equal || cond == NotEqual);
 
     // Check payload before tag, since payload is more likely to differ.
     if (cond == NotEqual) {
-        ma_ldr(payloadOf(valaddr), ScratchRegister);
+        ma_ldr(ToPayload(valaddr), ScratchRegister);
         branchPtr(NotEqual, ScratchRegister, value.payloadReg(), label);
 
-        ma_ldr(tagOf(valaddr), ScratchRegister);
+        ma_ldr(ToType(valaddr), ScratchRegister);
         branchPtr(NotEqual, ScratchRegister, value.typeReg(), label);
 
     } else {
         Label fallthrough;
 
-        ma_ldr(payloadOf(valaddr), ScratchRegister);
+        ma_ldr(ToPayload(valaddr), ScratchRegister);
         branchPtr(NotEqual, ScratchRegister, value.payloadReg(), &fallthrough);
 
-        ma_ldr(tagOf(valaddr), ScratchRegister);
+        ma_ldr(ToType(valaddr), ScratchRegister);
         branchPtr(Equal, ScratchRegister, value.typeReg(), label);
 
         bind(&fallthrough);
     }
 }
 
 // Unboxing code.
 void
@@ -3172,17 +3163,17 @@ MacroAssemblerARMCompat::unboxNonDouble(
 {
     if (operand.payloadReg() != dest)
         ma_mov(operand.payloadReg(), dest);
 }
 
 void
 MacroAssemblerARMCompat::unboxNonDouble(const Address& src, Register dest)
 {
-    ma_ldr(payloadOf(src), dest);
+    ma_ldr(ToPayload(src), dest);
 }
 
 void
 MacroAssemblerARMCompat::unboxNonDouble(const BaseIndex& src, Register dest)
 {
     ma_alu(src.base, lsl(src.index, src.scale), ScratchRegister, OpAdd);
     ma_ldr(Address(ScratchRegister, src.offset), dest);
 }
@@ -3194,17 +3185,17 @@ MacroAssemblerARMCompat::unboxDouble(con
     as_vxfer(operand.payloadReg(), operand.typeReg(),
              VFPRegister(dest), CoreToFloat);
 }
 
 void
 MacroAssemblerARMCompat::unboxDouble(const Address& src, FloatRegister dest)
 {
     MOZ_ASSERT(dest.isDouble());
-    ma_vldr(Operand(src), dest);
+    ma_vldr(src, dest);
 }
 
 void
 MacroAssemblerARMCompat::unboxValue(const ValueOperand& src, AnyRegister dest)
 {
     if (dest.isFloat()) {
         Label notInt32, end;
         branchTestInt32(Assembler::NotEqual, src, &notInt32);
@@ -3281,17 +3272,17 @@ MacroAssemblerARMCompat::int32ValueToFlo
 
 void
 MacroAssemblerARMCompat::loadConstantFloat32(float f, FloatRegister dest)
 {
     ma_vimm_f32(f, dest);
 }
 
 void
-MacroAssemblerARMCompat::loadInt32OrDouble(const Operand& src, FloatRegister dest)
+MacroAssemblerARMCompat::loadInt32OrDouble(const Address& src, FloatRegister dest)
 {
     Label notInt32, end;
     // If it's an int, convert it to double.
     ma_ldr(ToType(src), ScratchRegister);
     branchTestInt32(Assembler::NotEqual, ScratchRegister, &notInt32);
     ma_ldr(ToPayload(src), ScratchRegister);
     convertInt32ToDouble(ScratchRegister, dest);
     ma_b(&end);
@@ -3360,24 +3351,24 @@ MacroAssemblerARMCompat::testDoubleTruth
     as_vmrs(pc);
     as_cmp(r0, O2Reg(r0), Overflow);
     return truthy ? NonZero : Zero;
 }
 
 Register
 MacroAssemblerARMCompat::extractObject(const Address& address, Register scratch)
 {
-    ma_ldr(payloadOf(address), scratch);
+    ma_ldr(ToPayload(address), scratch);
     return scratch;
 }
 
 Register
 MacroAssemblerARMCompat::extractTag(const Address& address, Register scratch)
 {
-    ma_ldr(tagOf(address), scratch);
+    ma_ldr(ToType(address), scratch);
     return scratch;
 }
 
 Register
 MacroAssemblerARMCompat::extractTag(const BaseIndex& address, Register scratch)
 {
     ma_alu(address.base, lsl(address.index, address.scale), scratch, OpAdd, NoSetCond);
     return extractTag(Address(scratch, address.offset), scratch);
@@ -3427,17 +3418,17 @@ MacroAssemblerARMCompat::moveValue(const
 {
     moveValue(val, dest.typeReg(), dest.payloadReg());
 }
 
 /////////////////////////////////////////////////////////////////
 // X86/X64-common (ARM too now) interface.
 /////////////////////////////////////////////////////////////////
 void
-MacroAssemblerARMCompat::storeValue(ValueOperand val, Operand dst)
+MacroAssemblerARMCompat::storeValue(ValueOperand val, const Address& dst)
 {
     ma_str(val.payloadReg(), ToPayload(dst));
     ma_str(val.typeReg(), ToType(dst));
 }
 
 void
 MacroAssemblerARMCompat::storeValue(ValueOperand val, const BaseIndex& dest)
 {
@@ -3484,64 +3475,64 @@ MacroAssemblerARMCompat::loadValue(const
         ma_alu(addr.base, lsl(addr.index, addr.scale), ScratchRegister, OpAdd);
         loadValue(Address(ScratchRegister, addr.offset), val);
     }
 }
 
 void
 MacroAssemblerARMCompat::loadValue(Address src, ValueOperand val)
 {
-    Operand srcOp = Operand(src);
-    Operand payload = ToPayload(srcOp);
-    Operand type = ToType(srcOp);
+    Address payload = ToPayload(src);
+    Address type = ToType(src);
+
     // TODO: copy this code into a generic function that acts on all sequences
     // of memory accesses
     if (isValueDTRDCandidate(val)) {
         // If the value we want is in two consecutive registers starting with an
         // even register, they can be combined as a single ldrd.
-        int offset = srcOp.disp();
+        int offset = src.offset;
         if (offset < 256 && offset > -256) {
-            ma_ldrd(EDtrAddr(Register::FromCode(srcOp.base()), EDtrOffImm(srcOp.disp())), val.payloadReg(), val.typeReg());
+            ma_ldrd(EDtrAddr(src.base, EDtrOffImm(src.offset)), val.payloadReg(), val.typeReg());
             return;
         }
     }
     // If the value is lower than the type, then we may be able to use an ldm
     // instruction.
 
     if (val.payloadReg().code() < val.typeReg().code()) {
-        if (srcOp.disp() <= 4 && srcOp.disp() >= -8 && (srcOp.disp() & 3) == 0) {
+        if (src.offset <= 4 && src.offset >= -8 && (src.offset & 3) == 0) {
             // Turns out each of the 4 value -8, -4, 0, 4 corresponds exactly
             // with one of LDM{DB, DA, IA, IB}
             DTMMode mode;
-            switch(srcOp.disp()) {
+            switch (src.offset) {
               case -8:
                 mode = DB;
                 break;
               case -4:
                 mode = DA;
                 break;
               case 0:
                 mode = IA;
                 break;
               case 4:
                 mode = IB;
                 break;
               default:
                 MOZ_CRASH("Bogus Offset for LoadValue as DTM");
             }
-            startDataTransferM(IsLoad, Register::FromCode(srcOp.base()), mode);
+            startDataTransferM(IsLoad, src.base, mode);
             transferReg(val.payloadReg());
             transferReg(val.typeReg());
             finishDataTransfer();
             return;
         }
     }
     // Ensure that loading the payload does not erase the pointer to the Value
     // in memory.
-    if (Register::FromCode(type.base()) != val.payloadReg()) {
+    if (type.base != val.payloadReg()) {
         ma_ldr(payload, val.payloadReg());
         ma_ldr(type, val.typeReg());
     } else {
         ma_ldr(type, val.typeReg());
         ma_ldr(payload, val.payloadReg());
     }
 }
 
@@ -3557,50 +3548,42 @@ MacroAssemblerARMCompat::tagValue(JSValu
 void
 MacroAssemblerARMCompat::pushValue(ValueOperand val) {
     ma_push(val.typeReg());
     ma_push(val.payloadReg());
 }
 void
 MacroAssemblerARMCompat::pushValue(const Address& addr)
 {
-    Operand srcOp = Operand(addr);
-    Operand type = ToType(srcOp);
-    Operand payload = ToPayloadAfterStackPush(srcOp);
-
-    ma_ldr(type, ScratchRegister);
+    ma_ldr(ToType(addr), ScratchRegister);
     ma_push(ScratchRegister);
-    ma_ldr(payload, ScratchRegister);
+    ma_ldr(ToPayloadAfterStackPush(addr), ScratchRegister);
     ma_push(ScratchRegister);
 }
 
 void
 MacroAssemblerARMCompat::popValue(ValueOperand val) {
     ma_pop(val.payloadReg());
     ma_pop(val.typeReg());
 }
 void
-MacroAssemblerARMCompat::storePayload(const Value& val, Operand dest)
+MacroAssemblerARMCompat::storePayload(const Value& val, const Address& dest)
 {
     jsval_layout jv = JSVAL_TO_IMPL(val);
     if (val.isMarkable())
         ma_mov(ImmGCPtr((gc::Cell*)jv.s.payload.ptr), secondScratchReg_);
     else
         ma_mov(Imm32(jv.s.payload.i32), secondScratchReg_);
     ma_str(secondScratchReg_, ToPayload(dest));
 }
-void
-MacroAssemblerARMCompat::storePayload(Register src, Operand dest)
-{
-    if (dest.getTag() == Operand::MEM) {
-        ma_str(src, ToPayload(dest));
-        return;
-    }
-    MOZ_CRASH("why do we do all of these things?");
-
+
+void
+MacroAssemblerARMCompat::storePayload(Register src, const Address& dest)
+{
+    ma_str(src, ToPayload(dest));
 }
 
 void
 MacroAssemblerARMCompat::storePayload(const Value& val, const BaseIndex& dest)
 {
     unsigned shift = ScaleToShift(dest.scale);
 
     jsval_layout jv = JSVAL_TO_IMPL(val);
@@ -3646,25 +3629,20 @@ MacroAssemblerARMCompat::storePayload(Re
     // never come up, and this is one less code path to get wrong.
     as_dtr(IsStore, 32, Offset, src, DTRAddr(dest.base, DtrRegImmShift(dest.index, LSL, shift)));
 
     if (dest.offset != 0)
         ma_sub(dest.base, Imm32(dest.offset), dest.base);
 }
 
 void
-MacroAssemblerARMCompat::storeTypeTag(ImmTag tag, Operand dest) {
-    if (dest.getTag() == Operand::MEM) {
-        ma_mov(tag, secondScratchReg_);
-        ma_str(secondScratchReg_, ToType(dest));
-        return;
-    }
-
-    MOZ_CRASH("why do we do all of these things?");
-
+MacroAssemblerARMCompat::storeTypeTag(ImmTag tag, const Address& dest)
+{
+    ma_mov(tag, secondScratchReg_);
+    ma_str(secondScratchReg_, ToType(dest));
 }
 
 void
 MacroAssemblerARMCompat::storeTypeTag(ImmTag tag, const BaseIndex& dest)
 {
     Register base = dest.base;
     Register index = dest.index;
     unsigned shift = ScaleToShift(dest.scale);
@@ -4205,62 +4183,62 @@ MacroAssemblerARMCompat::handleFailureWi
     callWithABI(handler);
 
     Label entryFrame;
     Label catch_;
     Label finally;
     Label return_;
     Label bailout;
 
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, kind)), r0);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, kind)), r0);
     branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_ENTRY_FRAME), &entryFrame);
     branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_CATCH), &catch_);
     branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_FINALLY), &finally);
     branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_FORCED_RETURN), &return_);
     branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_BAILOUT), &bailout);
 
     breakpoint(); // Invalid kind.
 
     // No exception handler. Load the error value, load the new stack pointer
     // and return from the entry frame.
     bind(&entryFrame);
     moveValue(MagicValue(JS_ION_ERROR), JSReturnOperand);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, stackPointer)), sp);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, stackPointer)), sp);
 
     // We're going to be returning by the ion calling convention, which returns
     // by ??? (for now, I think ldr pc, [sp]!)
     as_dtr(IsLoad, 32, PostIndex, pc, DTRAddr(sp, DtrOffImm(4)));
 
     // If we found a catch handler, this must be a baseline frame. Restore state
     // and jump to the catch block.
     bind(&catch_);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, target)), r0);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, framePointer)), r11);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, stackPointer)), sp);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, target)), r0);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, framePointer)), r11);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, stackPointer)), sp);
     jump(r0);
 
     // If we found a finally block, this must be a baseline frame. Push two
     // values expected by JSOP_RETSUB: BooleanValue(true) and the exception.
     bind(&finally);
     ValueOperand exception = ValueOperand(r1, r2);
     loadValue(Operand(sp, offsetof(ResumeFromException, exception)), exception);
 
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, target)), r0);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, framePointer)), r11);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, stackPointer)), sp);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, target)), r0);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, framePointer)), r11);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, stackPointer)), sp);
 
     pushValue(BooleanValue(true));
     pushValue(exception);
     jump(r0);
 
     // Only used in debug mode. Return BaselineFrame->returnValue() to the
     // caller.
     bind(&return_);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, framePointer)), r11);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, stackPointer)), sp);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, framePointer)), r11);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, stackPointer)), sp);
     loadValue(Address(r11, BaselineFrame::reverseOffsetOfReturnValue()), JSReturnOperand);
     ma_mov(r11, sp);
     pop(r11);
 
     // If profiling is enabled, then update the lastProfilingFrame to refer to caller
     // frame before returning.
     {
         Label skipProfilingInstrumentation;
@@ -4271,19 +4249,19 @@ MacroAssemblerARMCompat::handleFailureWi
         bind(&skipProfilingInstrumentation);
     }
 
     ret();
 
     // If we are bailing out to baseline to handle an exception, jump to the
     // bailout tail stub.
     bind(&bailout);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, bailoutInfo)), r2);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, bailoutInfo)), r2);
     ma_mov(Imm32(BAILOUT_RETURN_OK), r0);
-    ma_ldr(Operand(sp, offsetof(ResumeFromException, target)), r1);
+    ma_ldr(Address(sp, offsetof(ResumeFromException, target)), r1);
     jump(r1);
 }
 
 Assembler::Condition
 MacroAssemblerARMCompat::testStringTruthy(bool truthy, const ValueOperand& value)
 {
     Register string = value.payloadReg();
     ma_dtr(IsLoad, string, Imm32(JSString::offsetOfLength()), ScratchRegister);
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -35,38 +35,37 @@ class MacroAssemblerARM : public Assembl
     // register defaults to lr, since it's non-allocatable (as it can be
     // clobbered by some instructions). Allow the baseline compiler to override
     // this though, since baseline IC stubs rely on lr holding the return
     // address.
     Register secondScratchReg_;
 
   public:
     // Higher level tag testing code.
-    Operand ToPayload(Operand base) {
+    // TODO: Can probably remove the Operand versions.
+    Operand ToPayload(Operand base) const {
         return Operand(Register::FromCode(base.base()), base.disp());
     }
-    Address ToPayload(Address base) {
-        return ToPayload(Operand(base)).toAddress();
+    Address ToPayload(const Address& base) const {
+        return base;
     }
 
   protected:
-    Operand ToType(Operand base) {
+    Operand ToType(Operand base) const {
         return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void*));
     }
-    Address ToType(Address base) {
+    Address ToType(const Address& base) const {
         return ToType(Operand(base)).toAddress();
     }
 
-    Operand ToPayloadAfterStackPush(Operand base) {
-        Register baseReg = Register::FromCode(base.base());
+    Address ToPayloadAfterStackPush(const Address& base) const {
         // If we are based on StackPointer, pass over the type tag just pushed.
-        if (baseReg == StackPointer)
-            return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void*));
-        else
-            return ToPayload(base);
+        if (base.base == StackPointer)
+            return Address(base.base, base.offset + sizeof(void *));
+        return ToPayload(base);
     }
 
   public:
     MacroAssemblerARM()
       : secondScratchReg_(lr)
     { }
 
     void setSecondScratchReg(Register reg) {
@@ -304,21 +303,21 @@ class MacroAssemblerARM : public Assembl
     void ma_dtr(LoadStore ls, Register rn, Imm32 offset, Register rt,
                 Index mode = Offset, Condition cc = Always);
 
     void ma_dtr(LoadStore ls, Register rn, Register rm, Register rt,
                 Index mode = Offset, Condition cc = Always);
 
 
     void ma_str(Register rt, DTRAddr addr, Index mode = Offset, Condition cc = Always);
-    void ma_str(Register rt, const Operand& addr, Index mode = Offset, Condition cc = Always);
-    void ma_dtr(LoadStore ls, Register rt, const Operand& addr, Index mode, Condition cc);
+    void ma_str(Register rt, const Address& addr, Index mode = Offset, Condition cc = Always);
+    void ma_dtr(LoadStore ls, Register rt, const Address& addr, Index mode, Condition cc);
 
     void ma_ldr(DTRAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
-    void ma_ldr(const Operand& addr, Register rt, Index mode = Offset, Condition cc = Always);
+    void ma_ldr(const Address& addr, Register rt, Index mode = Offset, Condition cc = Always);
 
     void ma_ldrb(DTRAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
     void ma_ldrh(EDtrAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
     void ma_ldrsh(EDtrAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
     void ma_ldrsb(EDtrAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
     void ma_ldrd(EDtrAddr addr, Register rt, DebugOnly<Register> rt2, Index mode = Offset, Condition cc = Always);
     void ma_strb(Register rt, DTRAddr addr, Index mode = Offset, Condition cc = Always);
     void ma_strh(Register rt, EDtrAddr addr, Index mode = Offset, Condition cc = Always);
@@ -402,25 +401,25 @@ class MacroAssemblerARM : public Assembl
     void ma_vcvt_U32_F32(FloatRegister src, FloatRegister dest, Condition cc = Always);
 
 
     void ma_vxfer(VFPRegister src, Register dest, Condition cc = Always);
     void ma_vxfer(VFPRegister src, Register dest1, Register dest2, Condition cc = Always);
 
     void ma_vxfer(Register src1, Register src2, FloatRegister dest, Condition cc = Always);
 
-    BufferOffset ma_vdtr(LoadStore ls, const Operand& addr, VFPRegister dest, Condition cc = Always);
+    BufferOffset ma_vdtr(LoadStore ls, const Address& addr, VFPRegister dest, Condition cc = Always);
 
 
     BufferOffset ma_vldr(VFPAddr addr, VFPRegister dest, Condition cc = Always);
-    BufferOffset ma_vldr(const Operand& addr, VFPRegister dest, Condition cc = Always);
+    BufferOffset ma_vldr(const Address& addr, VFPRegister dest, Condition cc = Always);
     BufferOffset ma_vldr(VFPRegister src, Register base, Register index, int32_t shift = defaultShift, Condition cc = Always);
 
     BufferOffset ma_vstr(VFPRegister src, VFPAddr addr, Condition cc = Always);
-    BufferOffset ma_vstr(VFPRegister src, const Operand& addr, Condition cc = Always);
+    BufferOffset ma_vstr(VFPRegister src, const Address& addr, Condition cc = Always);
 
     BufferOffset ma_vstr(VFPRegister src, Register base, Register index, int32_t shift,
                          int32_t offset, Condition cc = Always);
     // Calls an Ion function, assumes that the stack is untouched (8 byte
     // aligned).
     void ma_callJit(const Register reg);
     // Calls an Ion function, assuming that sp has already been decremented.
     void ma_callJitNoPush(const Register reg);
@@ -660,18 +659,18 @@ class MacroAssemblerARMCompat : public M
     }
     void push(ImmGCPtr imm) {
         ma_mov(imm, ScratchRegister);
         ma_push(ScratchRegister);
     }
     void push(ImmMaybeNurseryPtr imm) {
         push(noteMaybeNurseryPtr(imm));
     }
-    void push(const Address& address) {
-        ma_ldr(Operand(address.base, address.offset), ScratchRegister);
+    void push(const Address& addr) {
+        ma_ldr(addr, ScratchRegister);
         ma_push(ScratchRegister);
     }
     void push(Register reg) {
         ma_push(reg);
     }
     void push(FloatRegister reg) {
         ma_vpush(VFPRegister(reg));
     }
@@ -724,35 +723,35 @@ class MacroAssemblerARMCompat : public M
         as_b(label);
     }
     void jump(JitCode* code) {
         branch(code);
     }
     void jump(Register reg) {
         ma_bx(reg);
     }
-    void jump(const Address& address) {
-        ma_ldr(Operand(address.base, address.offset), ScratchRegister);
+    void jump(const Address& addr) {
+        ma_ldr(addr, ScratchRegister);
         ma_bx(ScratchRegister);
     }
 
     void neg32(Register reg) {
         ma_neg(reg, reg, SetCond);
     }
     void negl(Register reg) {
         ma_neg(reg, reg, SetCond);
     }
     void test32(Register lhs, Register rhs) {
         ma_tst(lhs, rhs);
     }
     void test32(Register lhs, Imm32 imm) {
         ma_tst(lhs, imm);
     }
-    void test32(const Address& address, Imm32 imm) {
-        ma_ldr(Operand(address.base, address.offset), ScratchRegister);
+    void test32(const Address& addr, Imm32 imm) {
+        ma_ldr(addr, ScratchRegister);
         ma_tst(ScratchRegister, imm);
     }
     void testPtr(Register lhs, Register rhs) {
         test32(lhs, rhs);
     }
 
     // Returns the register containing the type tag.
     Register splitTagForTest(const ValueOperand& value) {
@@ -868,17 +867,17 @@ class MacroAssemblerARMCompat : public M
     Register extractTag(const Address& address, Register scratch);
     Register extractTag(const BaseIndex& address, Register scratch);
     Register extractTag(const ValueOperand& value, Register scratch) {
         return value.typeReg();
     }
 
     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest);
     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest);
-    void loadInt32OrDouble(const Operand& src, FloatRegister dest);
+    void loadInt32OrDouble(const Address& src, FloatRegister dest);
     void loadInt32OrDouble(Register base, Register index,
                            FloatRegister dest, int32_t shift = defaultShift);
     void loadConstantDouble(double dp, FloatRegister dest);
     // Treat the value as a boolean, and set condition codes accordingly.
     Condition testInt32Truthy(bool truthy, const ValueOperand& operand);
     Condition testBooleanTruthy(bool truthy, const ValueOperand& operand);
     Condition testDoubleTruthy(bool truthy, FloatRegister reg);
     Condition testStringTruthy(bool truthy, const ValueOperand& value);
@@ -904,26 +903,26 @@ class MacroAssemblerARMCompat : public M
     void branch32(Condition cond, Register lhs, Imm32 imm, Label* label) {
         ma_cmp(lhs, imm);
         ma_b(label, cond);
     }
     void branch32(Condition cond, const Operand& lhs, Register rhs, Label* label) {
         if (lhs.getTag() == Operand::OP2) {
             branch32(cond, lhs.toReg(), rhs, label);
         } else {
-            ma_ldr(lhs, ScratchRegister);
+            ma_ldr(lhs.toAddress(), ScratchRegister);
             branch32(cond, ScratchRegister, rhs, label);
         }
     }
     void branch32(Condition cond, const Operand& lhs, Imm32 rhs, Label* label) {
         if (lhs.getTag() == Operand::OP2) {
             branch32(cond, lhs.toReg(), rhs, label);
         } else {
             // branch32 will use ScratchRegister.
-            ma_ldr(lhs, secondScratchReg_);
+            ma_ldr(lhs.toAddress(), secondScratchReg_);
             branch32(cond, secondScratchReg_, rhs, label);
         }
     }
     void branch32(Condition cond, const Address& lhs, Register rhs, Label* label) {
         load32(lhs, ScratchRegister);
         branch32(cond, ScratchRegister, rhs, label);
     }
     void branch32(Condition cond, const Address& lhs, Imm32 rhs, Label* label) {
@@ -1132,17 +1131,17 @@ class MacroAssemblerARMCompat : public M
     void branch32(Condition cond, AsmJSAbsoluteAddress addr, Imm32 imm, Label* label) {
         loadPtr(addr, ScratchRegister);
         ma_cmp(ScratchRegister, imm);
         ma_b(label, cond);
     }
 
     void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) {
         if (dest.isFloat())
-            loadInt32OrDouble(Operand(address), dest.fpu());
+            loadInt32OrDouble(address, dest.fpu());
         else
             ma_ldr(address, dest.gpr());
     }
 
     void loadUnboxedValue(BaseIndex address, MIRType type, AnyRegister dest) {
         if (dest.isFloat())
             loadInt32OrDouble(address.base, address.index, dest.fpu(), address.scale);
         else
@@ -1190,39 +1189,36 @@ class MacroAssemblerARMCompat : public M
         }
 
         if (s0 != d0)
             ma_mov(s0, d0);
         if (s1 != d1)
             ma_mov(s1, d1);
     }
 
-    void storeValue(ValueOperand val, Operand dst);
+    void storeValue(ValueOperand val, const Address& dst);
     void storeValue(ValueOperand val, const BaseIndex& dest);
     void storeValue(JSValueType type, Register reg, BaseIndex dest) {
         ma_alu(dest.base, lsl(dest.index, dest.scale), ScratchRegister, OpAdd);
         storeValue(type, reg, Address(ScratchRegister, dest.offset));
     }
-    void storeValue(ValueOperand val, const Address& dest) {
-        storeValue(val, Operand(dest));
-    }
     void storeValue(JSValueType type, Register reg, Address dest) {
         ma_str(reg, dest);
         ma_mov(ImmTag(JSVAL_TYPE_TO_TAG(type)), secondScratchReg_);
         ma_str(secondScratchReg_, Address(dest.base, dest.offset + 4));
     }
-    void storeValue(const Value& val, Address dest) {
+    void storeValue(const Value& val, const Address& dest) {
         jsval_layout jv = JSVAL_TO_IMPL(val);
         ma_mov(Imm32(jv.s.tag), secondScratchReg_);
-        ma_str(secondScratchReg_, Address(dest.base, dest.offset + 4));
+        ma_str(secondScratchReg_, ToType(dest));
         if (val.isMarkable())
             ma_mov(ImmGCPtr(reinterpret_cast<gc::Cell*>(val.toGCThing())), secondScratchReg_);
         else
             ma_mov(Imm32(jv.s.payload.i32), secondScratchReg_);
-        ma_str(secondScratchReg_, dest);
+        ma_str(secondScratchReg_, ToPayload(dest));
     }
     void storeValue(const Value& val, BaseIndex dest) {
         ma_alu(dest.base, lsl(dest.index, dest.scale), ScratchRegister, OpAdd);
         storeValue(val, Address(ScratchRegister, dest.offset));
     }
 
     void loadValue(Address src, ValueOperand val);
     void loadValue(Operand dest, ValueOperand val) {
@@ -1242,21 +1238,21 @@ class MacroAssemblerARMCompat : public M
             push(Imm32(jv.s.payload.i32));
     }
     void pushValue(JSValueType type, Register reg) {
         push(ImmTag(JSVAL_TYPE_TO_TAG(type)));
         ma_push(reg);
     }
     void pushValue(const Address& addr);
 
-    void storePayload(const Value& val, Operand dest);
-    void storePayload(Register src, Operand dest);
+    void storePayload(const Value& val, const Address& dest);
+    void storePayload(Register src, const Address& dest);
     void storePayload(const Value& val, const BaseIndex& dest);
     void storePayload(Register src, const BaseIndex& dest);
-    void storeTypeTag(ImmTag tag, Operand dest);
+    void storeTypeTag(ImmTag tag, const Address& dest);
     void storeTypeTag(ImmTag tag, const BaseIndex& dest);
 
     void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
         ma_lsl(Imm32(FRAMESIZE_SHIFT), frameSizeReg, frameSizeReg);
         ma_orr(Imm32(type), frameSizeReg);
     }
 
     void handleFailureWithHandlerTail(void* handler);
@@ -1438,30 +1434,30 @@ class MacroAssemblerARMCompat : public M
 
     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, Operand(addr));
+        ma_vstr(src, addr);
     }
     void storeDouble(FloatRegister src, BaseIndex addr) {
         uint32_t scale = Imm32::ShiftOf(addr.scale).value;
         ma_vstr(src, addr.base, addr.index, scale, addr.offset);
     }
     void moveDouble(FloatRegister src, FloatRegister dest) {
         ma_vmov(src, dest);
     }
 
-    void storeFloat32(FloatRegister src, Address addr) {
-        ma_vstr(VFPRegister(src).singleOverlay(), Operand(addr));
+    void storeFloat32(FloatRegister src, const Address& addr) {
+        ma_vstr(VFPRegister(src).singleOverlay(), addr);
     }
-    void storeFloat32(FloatRegister src, BaseIndex addr) {
+    void storeFloat32(FloatRegister src, const BaseIndex& addr) {
         uint32_t scale = Imm32::ShiftOf(addr.scale).value;
         ma_vstr(VFPRegister(src).singleOverlay(), addr.base, addr.index, scale, addr.offset);
     }
 
   private:
     template<typename T>
     Register computePointer(const T& src, Register r);
 
@@ -1896,29 +1892,21 @@ class MacroAssemblerARMCompat : public M
         loadPtr(Address(Source.base, Source.offset+4), lr);
         storePtr(lr, Address(Dest.base, Dest.offset+4));
     }
 
     void lea(Operand addr, Register dest) {
         ma_add(addr.baseReg(), Imm32(addr.disp()), dest);
     }
 
-    void stackCheck(ImmWord limitAddr, Label* label) {
-        int* foo = 0;
-        *foo = 5;
-        movePtr(limitAddr, ScratchRegister);
-        ma_ldr(Address(ScratchRegister, 0), ScratchRegister);
-        ma_cmp(ScratchRegister, StackPointer);
-        ma_b(label, Assembler::AboveOrEqual);
-    }
     void abiret() {
         as_bx(lr);
     }
 
-    void ma_storeImm(Imm32 c, const Operand& dest) {
+    void ma_storeImm(Imm32 c, const Address& dest) {
         ma_mov(c, lr);
         ma_str(lr, dest);
     }
     BufferOffset ma_BoundsCheck(Register bounded) {
         return as_cmp(bounded, Imm8(0));
     }
 
     void moveFloat32(FloatRegister src, FloatRegister dest) {
--- a/js/src/jit/arm/MoveEmitter-arm.cpp
+++ b/js/src/jit/arm/MoveEmitter-arm.cpp
@@ -33,53 +33,46 @@ MoveEmitterARM::emit(const MoveResolver&
         emit(moves.getMove(i));
 }
 
 MoveEmitterARM::~MoveEmitterARM()
 {
     assertDone();
 }
 
-Operand
+Address
 MoveEmitterARM::cycleSlot(uint32_t slot, uint32_t subslot) const
 {
     int32_t offset =  masm.framePushed() - pushedAtCycle_;
     MOZ_ASSERT(offset < 4096 && offset > -4096);
-    return Operand(StackPointer, offset + slot * sizeof(double) + subslot);
+    return Address(StackPointer, offset + slot * sizeof(double) + subslot);
 }
 
-// THIS IS ALWAYS AN LDRAddr. It should not be wrapped in an operand, methinks.
-Operand
+Address
 MoveEmitterARM::spillSlot() const
 {
     int32_t offset =  masm.framePushed() - pushedAtSpill_;
     MOZ_ASSERT(offset < 4096 && offset > -4096);
-    return Operand(StackPointer, offset);
+    return Address(StackPointer, offset);
 }
 
-Operand
-MoveEmitterARM::toOperand(const MoveOperand& operand, bool isFloat) const
+Address
+MoveEmitterARM::toAddress(const MoveOperand& operand) const
 {
-    if (operand.isMemoryOrEffectiveAddress()) {
-        if (operand.base() != StackPointer) {
-            MOZ_ASSERT(operand.disp() < 1024 && operand.disp() > -1024);
-            return Operand(operand.base(), operand.disp());
-        }
+    MOZ_ASSERT(operand.isMemoryOrEffectiveAddress());
 
-        MOZ_ASSERT(operand.disp() >= 0);
-
-        // Otherwise, the stack offset may need to be adjusted.
-        return Operand(StackPointer, operand.disp() + (masm.framePushed() - pushedAtStart_));
+    if (operand.base() != StackPointer) {
+        MOZ_ASSERT(operand.disp() < 1024 && operand.disp() > -1024);
+        return Operand(operand.base(), operand.disp()).toAddress();
     }
 
-    if (operand.isGeneralReg())
-        return Operand(operand.reg());
+    MOZ_ASSERT(operand.disp() >= 0);
 
-    MOZ_ASSERT(operand.isFloatReg());
-    return Operand(operand.floatReg());
+    // Otherwise, the stack offset may need to be adjusted.
+    return Address(StackPointer, operand.disp() + (masm.framePushed() - pushedAtStart_));
 }
 
 Register
 MoveEmitterARM::tempReg()
 {
     if (spilledReg_ != InvalidReg)
         return spilledReg_;
 
@@ -108,43 +101,43 @@ MoveEmitterARM::breakCycle(const MoveOpe
     //   (B -> A)
     //
     // This case handles (A -> B), which we reach first. We save B, then allow
     // the original move to continue.
     switch (type) {
       case MoveOp::FLOAT32:
         if (to.isMemory()) {
             VFPRegister temp = ScratchFloat32Reg;
-            masm.ma_vldr(toOperand(to, true), temp);
+            masm.ma_vldr(toAddress(to), temp);
             // Since it is uncertain if the load will be aligned or not
             // just fill both of them with the same value.
             masm.ma_vstr(temp, cycleSlot(slotId, 0));
             masm.ma_vstr(temp, cycleSlot(slotId, 4));
         } else {
             FloatRegister src = to.floatReg();
             // Just always store the largest possible size. Currently, this is
             // a double. When SIMD is added, two doubles will need to be stored.
             masm.ma_vstr(src.doubleOverlay(), cycleSlot(slotId, 0));
         }
         break;
       case MoveOp::DOUBLE:
         if (to.isMemory()) {
             FloatRegister temp = ScratchDoubleReg;
-            masm.ma_vldr(toOperand(to, true), temp);
+            masm.ma_vldr(toAddress(to), temp);
             masm.ma_vstr(temp, cycleSlot(slotId, 0));
         } else {
             masm.ma_vstr(to.floatReg().doubleOverlay(), cycleSlot(slotId, 0));
         }
         break;
       case MoveOp::INT32:
       case MoveOp::GENERAL:
         // an non-vfp value
         if (to.isMemory()) {
             Register temp = tempReg();
-            masm.ma_ldr(toOperand(to, false), temp);
+            masm.ma_ldr(toAddress(to), temp);
             masm.ma_str(temp, cycleSlot(0,0));
         } else {
             if (to.reg() == spilledReg_) {
                 // If the destination was spilled, restore it first.
                 masm.ma_ldr(spillSlot(), spilledReg_);
                 spilledReg_ = InvalidReg;
             }
             masm.ma_str(to.reg(), cycleSlot(0,0));
@@ -165,31 +158,31 @@ MoveEmitterARM::completeCycle(const Move
     // This case handles (B -> A), which we reach last. We emit a move from the
     // saved value of B, to A.
     switch (type) {
       case MoveOp::FLOAT32:
       case MoveOp::DOUBLE:
         if (to.isMemory()) {
             FloatRegister temp = ScratchDoubleReg;
             masm.ma_vldr(cycleSlot(slotId, 0), temp);
-            masm.ma_vstr(temp, toOperand(to, true));
+            masm.ma_vstr(temp, toAddress(to));
         } else {
             uint32_t offset = 0;
             if ((!from.isMemory()) && from.floatReg().numAlignedAliased() == 1)
                 offset = sizeof(float);
             masm.ma_vldr(cycleSlot(slotId, offset), to.floatReg());
         }
         break;
       case MoveOp::INT32:
       case MoveOp::GENERAL:
         MOZ_ASSERT(slotId == 0);
         if (to.isMemory()) {
             Register temp = tempReg();
             masm.ma_ldr(cycleSlot(slotId, 0), temp);
-            masm.ma_str(temp, toOperand(to, false));
+            masm.ma_str(temp, toAddress(to));
         } else {
             if (to.reg() == spilledReg_) {
                 // Make sure we don't re-clobber the spilled register later.
                 spilledReg_ = InvalidReg;
             }
             masm.ma_ldr(cycleSlot(slotId, 0), to.reg());
         }
         break;
@@ -209,86 +202,75 @@ MoveEmitterARM::emitMove(const MoveOpera
 
     if (from.isGeneralReg()) {
         if (from.reg() == spilledReg_) {
             // If the source is a register that has been spilled, make sure
             // to load the source back into that register.
             masm.ma_ldr(spillSlot(), spilledReg_);
             spilledReg_ = InvalidReg;
         }
-        switch (toOperand(to, false).getTag()) {
-          case Operand::OP2:
-            // secretly must be a register
+        if (to.isMemoryOrEffectiveAddress())
+            masm.ma_str(from.reg(), toAddress(to));
+        else
             masm.ma_mov(from.reg(), to.reg());
-            break;
-          case Operand::MEM:
-            masm.ma_str(from.reg(), toOperand(to, false));
-            break;
-          default:
-            MOZ_CRASH("strange move!");
-        }
     } else if (to.isGeneralReg()) {
         MOZ_ASSERT(from.isMemoryOrEffectiveAddress());
         if (from.isMemory())
-            masm.ma_ldr(toOperand(from, false), to.reg());
+            masm.ma_ldr(toAddress(from), to.reg());
         else
             masm.ma_add(from.base(), Imm32(from.disp()), to.reg());
     } else {
         // Memory to memory gpr move.
         Register reg = tempReg();
 
         MOZ_ASSERT(from.isMemoryOrEffectiveAddress());
         if (from.isMemory())
-            masm.ma_ldr(toOperand(from, false), reg);
+            masm.ma_ldr(toAddress(from), reg);
         else
             masm.ma_add(from.base(), Imm32(from.disp()), reg);
         MOZ_ASSERT(to.base() != reg);
-        masm.ma_str(reg, toOperand(to, false));
+        masm.ma_str(reg, toAddress(to));
     }
 }
 
 void
 MoveEmitterARM::emitFloat32Move(const MoveOperand& from, const MoveOperand& to)
 {
     if (from.isFloatReg()) {
         if (to.isFloatReg())
             masm.ma_vmov_f32(from.floatReg(), to.floatReg());
         else
-            masm.ma_vstr(VFPRegister(from.floatReg()).singleOverlay(),
-                         toOperand(to, true));
+            masm.ma_vstr(VFPRegister(from.floatReg()).singleOverlay(), toAddress(to));
     } else if (to.isFloatReg()) {
-        masm.ma_vldr(toOperand(from, true),
-                     VFPRegister(to.floatReg()).singleOverlay());
+        masm.ma_vldr(toAddress(from), VFPRegister(to.floatReg()).singleOverlay());
     } else {
         // Memory to memory move.
         MOZ_ASSERT(from.isMemory());
         FloatRegister reg = ScratchFloat32Reg;
-        masm.ma_vldr(toOperand(from, true),
-                     VFPRegister(reg).singleOverlay());
-        masm.ma_vstr(VFPRegister(reg).singleOverlay(),
-                     toOperand(to, true));
+        masm.ma_vldr(toAddress(from), VFPRegister(reg).singleOverlay());
+        masm.ma_vstr(VFPRegister(reg).singleOverlay(), toAddress(to));
     }
 }
 
 void
 MoveEmitterARM::emitDoubleMove(const MoveOperand& from, const MoveOperand& to)
 {
     if (from.isFloatReg()) {
         if (to.isFloatReg())
             masm.ma_vmov(from.floatReg(), to.floatReg());
         else
-            masm.ma_vstr(from.floatReg(), toOperand(to, true));
+            masm.ma_vstr(from.floatReg(), toAddress(to));
     } else if (to.isFloatReg()) {
-        masm.ma_vldr(toOperand(from, true), to.floatReg());
+        masm.ma_vldr(toAddress(from), to.floatReg());
     } else {
         // Memory to memory move.
         MOZ_ASSERT(from.isMemory());
         FloatRegister reg = ScratchDoubleReg;
-        masm.ma_vldr(toOperand(from, true), reg);
-        masm.ma_vstr(reg, toOperand(to, true));
+        masm.ma_vldr(toAddress(from), reg);
+        masm.ma_vstr(reg, toAddress(to));
     }
 }
 
 void
 MoveEmitterARM::emit(const MoveOp& move)
 {
     const MoveOperand& from = move.from();
     const MoveOperand& to = move.to();
--- a/js/src/jit/arm/MoveEmitter-arm.h
+++ b/js/src/jit/arm/MoveEmitter-arm.h
@@ -31,19 +31,19 @@ class MoveEmitterARM
     // assigned InvalidReg. If no corresponding spill space has been assigned,
     // then these registers do not need to be spilled.
     Register spilledReg_;
     FloatRegister spilledFloatReg_;
 
     void assertDone();
     Register tempReg();
     FloatRegister tempFloatReg();
-    Operand cycleSlot(uint32_t slot, uint32_t subslot) const;
-    Operand spillSlot() const;
-    Operand toOperand(const MoveOperand& operand, bool isFloat) const;
+    Address cycleSlot(uint32_t slot, uint32_t subslot) const;
+    Address spillSlot() const;
+    Address toAddress(const MoveOperand& operand) const;
 
     void emitMove(const MoveOperand& from, const MoveOperand& to);
     void emitFloat32Move(const MoveOperand& from, const MoveOperand& to);
     void emitDoubleMove(const MoveOperand& from, const MoveOperand& to);
     void breakCycle(const MoveOperand& from, const MoveOperand& to,
                     MoveOp::Type type, uint32_t slot);
     void completeCycle(const MoveOperand& from, const MoveOperand& to,
                        MoveOp::Type type, uint32_t slot);