Bug 911254 - Odinmonkey: (ARM) use the 'compare immediate' instruction for bounds checks. r=mjrosenb
authorDouglas Crosher <dtc-moz@scieneer.com>
Sat, 07 Sep 2013 10:53:03 +1000
changeset 146058 4551a70c2fcfc5772302e2b68428fb1974eda648
parent 146057 ca38bd9ec80a215151259bc1f3db0e048b2c8b85
child 146059 b143f103d54ef43d45e3bca3ee9a157d4a72f38c
push id33449
push userryanvm@gmail.com
push dateSat, 07 Sep 2013 03:18:37 +0000
treeherdermozilla-inbound@4551a70c2fcf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmjrosenb
bugs911254
milestone26.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 911254 - Odinmonkey: (ARM) use the 'compare immediate' instruction for bounds checks. r=mjrosenb
js/src/jit/AsmJSModule.cpp
js/src/jit/arm/Assembler-arm.cpp
js/src/jit/arm/CodeGenerator-arm.cpp
js/src/jit/arm/MacroAssembler-arm.h
--- a/js/src/jit/AsmJSModule.cpp
+++ b/js/src/jit/AsmJSModule.cpp
@@ -32,19 +32,21 @@ AsmJSModule::patchHeapAccesses(ArrayBuff
         const jit::AsmJSHeapAccess &access = heapAccesses_[i];
         if (access.hasLengthCheck())
             JSC::X86Assembler::setPointer(access.patchLengthAt(code_), heapLength);
         void *addr = access.patchOffsetAt(code_);
         uint32_t disp = reinterpret_cast<uint32_t>(JSC::X86Assembler::getPointer(addr));
         JSC::X86Assembler::setPointer(addr, (void *)(heapOffset + disp));
     }
 #elif defined(JS_CPU_ARM)
-    uint32_t bits = mozilla::CeilingLog2(heap->byteLength());
-    for (unsigned i = 0; i < heapAccesses_.length(); i++)
-        jit::Assembler::updateBoundsCheck(bits, (jit::Instruction*)(heapAccesses_[i].offset() + code_));
+    uint32_t heapLength = heap->byteLength();
+    for (unsigned i = 0; i < heapAccesses_.length(); i++) {
+        jit::Assembler::updateBoundsCheck(heapLength,
+                                          (jit::Instruction*)(heapAccesses_[i].offset() + code_));
+    }
     // We already know the exact extent of areas that need to be patched, just make sure we
     // flush all of them at once.
     jit::AutoFlushCache::updateTop(uintptr_t(code_), pod.codeBytes_);
 #endif
 }
 
 static uint8_t *
 AllocateExecutableMemory(ExclusiveContext *cx, size_t totalBytes)
--- a/js/src/jit/arm/Assembler-arm.cpp
+++ b/js/src/jit/arm/Assembler-arm.cpp
@@ -2720,32 +2720,31 @@ Assembler::ToggleCall(CodeLocationLabel 
     if (enabled)
         *inst = InstBLXReg(ScratchRegister, Always);
     else
         *inst = InstNOP();
 
     AutoFlushCache::updateTop(uintptr_t(inst), 4);
 }
 
-void Assembler::updateBoundsCheck(uint32_t logHeapSize, Instruction *inst)
+void Assembler::updateBoundsCheck(uint32_t heapSize, Instruction *inst)
 {
-    JS_ASSERT(inst->is<InstMOV>());
-    InstMOV *mov = inst->as<InstMOV>();
-    JS_ASSERT(mov->checkDest(ScratchRegister));
+    JS_ASSERT(inst->is<InstCMP>());
+    InstCMP *cmp = inst->as<InstCMP>();
+
+    Register index;
+    cmp->extractOp1(&index);
 
-    Operand2 op = mov->extractOp2();
-    JS_ASSERT(op.isO2Reg());
+    Operand2 op = cmp->extractOp2();
+    JS_ASSERT(op.isImm8());
 
-    Op2Reg reg = op.toOp2Reg();
-    Register index;
-    reg.getRM(&index);
-    JS_ASSERT(reg.isO2RegImmShift());
-    // O2RegImmShift shift = reg.toO2RegImmShift();
+    Imm8 imm8 = Imm8(heapSize);
+    JS_ASSERT(!imm8.invalid);
 
-    *inst = InstALU(ScratchRegister, InvalidReg, lsr(index, logHeapSize), op_mov, SetCond, Always);
+    *inst = InstALU(InvalidReg, index, imm8, op_cmp, 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!
 }
 
 void
 AutoFlushCache::update(uintptr_t newStart, size_t len)
 {
     uintptr_t newStop = newStart + len;
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1826,28 +1826,29 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAs
             masm.ma_dataTransferN(IsLoad, size, isSigned, HeapReg, ptrReg,
                                   ToRegister(ins->output()), Offset, Assembler::Always);
         }
         return true;
     }
 
     BufferOffset bo = masm.ma_BoundsCheck(ptrReg);
     if (isFloat) {
-        VFPRegister vd(ToFloatRegister(ins->output()));
+        FloatRegister dst = ToFloatRegister(ins->output());
+        masm.ma_vmov(NANReg, dst, Assembler::AboveOrEqual);
+        VFPRegister vd(dst);
         if (size == 32) {
-            masm.ma_vldr(vd.singleOverlay(), HeapReg, ptrReg, 0, Assembler::Zero);
-            masm.as_vcvt(vd, vd.singleOverlay(), false, Assembler::Zero);
+            masm.ma_vldr(vd.singleOverlay(), HeapReg, ptrReg, 0, Assembler::Below);
+            masm.as_vcvt(vd, vd.singleOverlay(), false, Assembler::Below);
         } else {
-            masm.ma_vldr(vd, HeapReg, ptrReg, 0, Assembler::Zero);
+            masm.ma_vldr(vd, HeapReg, ptrReg, 0, Assembler::Below);
         }
-        masm.ma_vmov(NANReg, ToFloatRegister(ins->output()), Assembler::NonZero);
     } else {
-        masm.ma_dataTransferN(IsLoad, size, isSigned, HeapReg, ptrReg,
-                              ToRegister(ins->output()), Offset, Assembler::Zero);
-        masm.ma_mov(Imm32(0), ToRegister(ins->output()), NoSetCond, Assembler::NonZero);
+        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);
     }
     return gen->noteHeapAccess(AsmJSHeapAccess(bo.getOffset()));
 }
 
 bool
 CodeGeneratorARM::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins)
 {
     const MAsmJSStoreHeap *mir = ins->mir();
@@ -1901,22 +1902,22 @@ CodeGeneratorARM::visitAsmJSStoreHeap(LA
         }
         return true;
     }
 
     BufferOffset bo = masm.ma_BoundsCheck(ptrReg);
     if (isFloat) {
         VFPRegister vd(ToFloatRegister(ins->value()));
         if (size == 32)
-            masm.storeFloat(vd, HeapReg, ptrReg, Assembler::Zero);
+            masm.storeFloat(vd, HeapReg, ptrReg, Assembler::Below);
         else
-            masm.ma_vstr(vd, HeapReg, ptrReg, 0, Assembler::Zero);
+            masm.ma_vstr(vd, HeapReg, ptrReg, 0, Assembler::Below);
     } else {
         masm.ma_dataTransferN(IsStore, size, isSigned, HeapReg, ptrReg,
-                              ToRegister(ins->value()), Offset, Assembler::Zero);
+                              ToRegister(ins->value()), Offset, Assembler::Below);
     }
     return gen->noteHeapAccess(AsmJSHeapAccess(bo.getOffset()));
 }
 
 bool
 CodeGeneratorARM::visitAsmJSPassStackArg(LAsmJSPassStackArg *ins)
 {
     const MAsmJSPassStackArg *mir = ins->mir();
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1359,17 +1359,17 @@ class MacroAssemblerARMCompat : public M
         as_bx(lr);
     }
 
     void ma_storeImm(Imm32 c, const Operand &dest) {
         ma_mov(c, lr);
         ma_str(lr, dest);
     }
     BufferOffset ma_BoundsCheck(Register bounded) {
-        return as_mov(ScratchRegister, lsl(bounded, 0), SetCond);
+        return as_cmp(bounded, Imm8(0));
     }
 
     void storeFloat(VFPRegister src, Register base, Register index, Condition cond) {
         as_vcvt(VFPRegister(ScratchFloatReg).singleOverlay(), src, false, cond);
         ma_vstr(VFPRegister(ScratchFloatReg).singleOverlay(), base, index, 0, cond);
 
     }
 };