Bug 1320956 - wasm baseline, do not interrupt tableswitch's jump table with other constants. r=bbouvier
authorLars T Hansen <lhansen@mozilla.com>
Fri, 02 Dec 2016 19:42:54 +0100
changeset 370408 3193092d26a96dddb7f112a08d7277c83d9e8f3e
parent 370407 b0dae693fdbc687830ee450a88beec616c43f673
child 370409 9287824003f42411c84cdf4b7b3506371c57a582
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs1320956
milestone53.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 1320956 - wasm baseline, do not interrupt tableswitch's jump table with other constants. r=bbouvier
js/src/wasm/WasmBaselineCompile.cpp
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -2418,58 +2418,72 @@ class BaseCompiler
     // Sundry low-level code generators.
 
     void addInterruptCheck()
     {
         // Always use signals for interrupts with Asm.JS/Wasm
         MOZ_RELEASE_ASSERT(HaveSignalHandlers());
     }
 
-    void jumpTable(LabelVector& labels) {
+    void jumpTable(LabelVector& labels, Label* theTable) {
+        // Flush constant pools to ensure that the table is never interrupted by
+        // constant pool entries.
+        masm.flush();
+
+        masm.bind(theTable);
+
 #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
         for (uint32_t i = 0; i < labels.length(); i++) {
             CodeLabel cl;
             masm.writeCodePointer(cl.patchAt());
             cl.target()->bind(labels[i]->offset());
             masm.addCodeLabel(cl);
         }
 #else
         MOZ_CRASH("BaseCompiler platform hook: jumpTable");
 #endif
     }
 
-    void tableSwitch(Label* theTable, RegI32 switchValue) {
+    void tableSwitch(Label* theTable, RegI32 switchValue, Label* dispatchCode) {
+        masm.bind(dispatchCode);
+
 #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
         ScratchI32 scratch(*this);
         CodeLabel tableCl;
 
         masm.mov(tableCl.patchAt(), scratch);
 
         tableCl.target()->bind(theTable->offset());
         masm.addCodeLabel(tableCl);
 
         masm.jmp(Operand(scratch, switchValue, ScalePointer));
 #elif defined(JS_CODEGEN_ARM)
+        // Flush constant pools: offset must reflect the distance from the MOV
+        // to the start of the table; as the address of the MOV is given by the
+        // label, nothing must come between the bind() and the ma_mov().
+        masm.flush();
+
         ScratchI32 scratch(*this);
 
-        // Compute the offset from the next instruction to the jump table
+        // Compute the offset from the ma_mov instruction to the jump table.
         Label here;
         masm.bind(&here);
         uint32_t offset = here.offset() - theTable->offset();
 
         // Read PC+8
         masm.ma_mov(pc, scratch);
 
-        // Required by ma_sub.
+        // ARM scratch register is required by ma_sub.
         ScratchRegisterScope arm_scratch(*this);
 
-        // Compute the table base pointer
+        // Compute the absolute table base pointer into `scratch`, offset by 8
+        // to account for the fact that ma_mov read PC+8.
         masm.ma_sub(Imm32(offset + 8), scratch, arm_scratch);
 
-        // Jump indirect via table element
+        // Jump indirect via table element.
         masm.ma_ldr(DTRAddr(scratch, DtrRegImmShift(switchValue, LSL, 2)), pc, Offset,
                     Assembler::Always);
 #else
         MOZ_CRASH("BaseCompiler platform hook: tableSwitch");
 #endif
     }
 
     RegI32 captureReturnedI32() {
@@ -5530,23 +5544,21 @@ BaseCompiler::emitBrTable()
         uint32_t k = depths[i];
         popStackBeforeBranch(controlItem(k).framePushed);
         masm.jump(controlItem(k).label);
     }
 
     // Emit table.
 
     Label theTable;
-    masm.bind(&theTable);
-    jumpTable(stubs);
+    jumpTable(stubs, &theTable);
 
     // Emit indirect jump.  rc is live here.
 
-    masm.bind(&dispatchCode);
-    tableSwitch(&theTable, rc);
+    tableSwitch(&theTable, rc, &dispatchCode);
 
     deadCode_ = true;
 
     // Clean up.
 
     freeI32(rc);
     freeJoinRegUnlessVoid(r);