Bug 1518210 - Wasm: Bounds checking support for ARM64. r=lth
☠☠ backed out by ea9924171afd ☠ ☠
authorRyan Hunt <rhunt@eqrion.net>
Fri, 30 Aug 2019 02:35:42 +0000
changeset 551294 12ea41537e05b07fccf665e4fe69d692804b5b70
parent 551293 4c8fe76ad293573a6a0e9eac934b99028e6da20d
child 551295 dc63fd0bbe584922c065ea58c368c6bfa601e24f
push id11865
push userbtara@mozilla.com
push dateMon, 02 Sep 2019 08:54:37 +0000
treeherdermozilla-beta@37f59c4671b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1518210
milestone70.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 1518210 - Wasm: Bounds checking support for ARM64. r=lth The only observed change needed to get bounds checking working on ARM64 was to implement `wasmBoundsCheck` in MacroAssembler-arm64. ARM64 doesn't support predicated instructions like ARM32, so to support spectre mitigations `wasmBoundsCheck` emits a 'csel' instruction. I'm not familiar with how ARM performs speculative execution or how spidermonkey mitigates it, so this was only a guess. Differential Revision: https://phabricator.services.mozilla.com/D41864
js/src/jit/MacroAssembler.h
js/src/jit/arm64/MacroAssembler-arm64-inl.h
js/src/jit/arm64/MacroAssembler-arm64.cpp
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -1111,16 +1111,19 @@ class MacroAssembler : public MacroAssem
 
   template <class L>
   inline void branch32(Condition cond, Register lhs, Register rhs,
                        L label) PER_SHARED_ARCH;
   template <class L>
   inline void branch32(Condition cond, Register lhs, Imm32 rhs,
                        L label) PER_SHARED_ARCH;
 
+  inline void branch32(Condition cond, Register lhs, const Address& rhs,
+                       Label* label) DEFINED_ON(arm64);
+
   inline void branch32(Condition cond, const Address& lhs, Register rhs,
                        Label* label) PER_SHARED_ARCH;
   inline void branch32(Condition cond, const Address& lhs, Imm32 rhs,
                        Label* label) PER_SHARED_ARCH;
 
   inline void branch32(Condition cond, const AbsoluteAddress& lhs, Register rhs,
                        Label* label)
       DEFINED_ON(arm, arm64, mips_shared, x86, x64);
--- a/js/src/jit/arm64/MacroAssembler-arm64-inl.h
+++ b/js/src/jit/arm64/MacroAssembler-arm64-inl.h
@@ -795,16 +795,26 @@ void MacroAssembler::branch32(Condition 
 
 template <class L>
 void MacroAssembler::branch32(Condition cond, Register lhs, Imm32 imm,
                               L label) {
   cmp32(lhs, imm);
   B(label, cond);
 }
 
+void MacroAssembler::branch32(Condition cond, Register lhs, const Address& rhs,
+                              Label* label) {
+  vixl::UseScratchRegisterScope temps(this);
+  const Register scratch = temps.AcquireX().asUnsized();
+  MOZ_ASSERT(scratch != lhs);
+  MOZ_ASSERT(scratch != rhs.base);
+  load32(rhs, scratch);
+  branch32(cond, lhs, scratch, label);
+}
+
 void MacroAssembler::branch32(Condition cond, const Address& lhs, Register rhs,
                               Label* label) {
   vixl::UseScratchRegisterScope temps(this);
   const Register scratch = temps.AcquireX().asUnsized();
   MOZ_ASSERT(scratch != lhs.base);
   MOZ_ASSERT(scratch != rhs);
   load32(lhs, scratch);
   branch32(cond, scratch, rhs, label);
--- a/js/src/jit/arm64/MacroAssembler-arm64.cpp
+++ b/js/src/jit/arm64/MacroAssembler-arm64.cpp
@@ -1086,24 +1086,31 @@ CodeOffset MacroAssembler::wasmTrapInstr
                              /* max number of instructions in scope = */ 1);
   CodeOffset offs(currentOffset());
   Unreachable();
   return offs;
 }
 
 void MacroAssembler::wasmBoundsCheck(Condition cond, Register index,
                                      Register boundsCheckLimit, Label* label) {
-  // Not used on ARM64, we rely on signal handling instead
-  MOZ_CRASH("NYI - wasmBoundsCheck");
+  branch32(cond, index, boundsCheckLimit, label);
+  if (JitOptions.spectreIndexMasking) {
+    csel(ARMRegister(index, 32), vixl::wzr, ARMRegister(index, 32), cond);
+  }
 }
 
 void MacroAssembler::wasmBoundsCheck(Condition cond, Register index,
                                      Address boundsCheckLimit, Label* label) {
-  // Not used on ARM64, we rely on signal handling instead
-  MOZ_CRASH("NYI - wasmBoundsCheck");
+  MOZ_ASSERT(boundsCheckLimit.offset ==
+             offsetof(wasm::TlsData, boundsCheckLimit));
+
+  branch32(cond, index, boundsCheckLimit, label);
+  if (JitOptions.spectreIndexMasking) {
+    csel(ARMRegister(index, 32), vixl::wzr, ARMRegister(index, 32), cond);
+  }
 }
 
 // FCVTZU behaves as follows:
 //
 // on NaN it produces zero
 // on too large it produces UINT_MAX (for appropriate type)
 // on too small it produces zero
 //