Bug 1252019: Don't patch profiling entries for the BadIndirectCall exit; r=luke
authorBenjamin Bouvier <benj@benj.me>
Mon, 29 Feb 2016 15:09:53 +0100
changeset 322589 a3f70cbceb6c77d529e720d0aefa6c86b181c63b
parent 322588 758c1524bbd459e57b7c3a20f718f8383eb9a951
child 322590 ca8e9cc4f66153c1e82bbe9376b93b98a9dbcc5b
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1252019
milestone47.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 1252019: Don't patch profiling entries for the BadIndirectCall exit; r=luke
js/src/asmjs/WasmModule.cpp
js/src/asmjs/WasmModule.h
js/src/jit-test/tests/wasm/basic.js
--- a/js/src/asmjs/WasmModule.cpp
+++ b/js/src/asmjs/WasmModule.cpp
@@ -795,20 +795,23 @@ Module::setProfilingEnabled(JSContext* c
         for (const CallThunk& callThunk : module_->callThunks)
             EnableProfilingThunk(*this, callThunk, enabled);
 
         for (const CodeRange& codeRange : module_->codeRanges)
             EnableProfilingEpilogue(*this, codeRange, enabled);
     }
 
     // Update the function-pointer tables to point to profiling prologues.
-    for (FuncPtrTable& funcPtrTable : funcPtrTables_) {
-        auto array = reinterpret_cast<void**>(globalData() + funcPtrTable.globalDataOffset);
-        for (size_t i = 0; i < funcPtrTable.numElems; i++) {
+    for (FuncPtrTable& table : funcPtrTables_) {
+        auto array = reinterpret_cast<void**>(globalData() + table.globalDataOffset);
+        for (size_t i = 0; i < table.numElems; i++) {
             const CodeRange* codeRange = lookupCodeRange(array[i]);
+            // Don't update entries for the BadIndirectCall exit.
+            if (codeRange->isErrorExit())
+                continue;
             void* from = code() + codeRange->funcNonProfilingEntry();
             void* to = code() + codeRange->funcProfilingEntry();
             if (!enabled)
                 Swap(from, to);
             MOZ_ASSERT(array[i] == from);
             array[i] = to;
         }
     }
@@ -1052,18 +1055,19 @@ Module::staticallyLink(ExclusiveContext*
                                                PatchedImmPtr((void*)-1));
         }
     }
 
     for (const StaticLinkData::FuncPtrTable& table : linkData.funcPtrTables) {
         auto array = reinterpret_cast<void**>(globalData() + table.globalDataOffset);
         for (size_t i = 0; i < table.elemOffsets.length(); i++) {
             uint8_t* elem = code() + table.elemOffsets[i];
-            if (profilingEnabled_)
-                elem = code() + lookupCodeRange(elem)->funcProfilingEntry();
+            const CodeRange* codeRange = lookupCodeRange(elem);
+            if (profilingEnabled_ && !codeRange->isErrorExit())
+                elem = code() + codeRange->funcProfilingEntry();
             array[i] = elem;
         }
     }
 
     // CodeRangeVector, CallSiteVector and the code technically have all the
     // necessary info to do all the updates necessary in setProfilingEnabled.
     // However, to simplify the finding of function-pointer table sizes and
     // global-data offsets, save just that information here.
--- a/js/src/asmjs/WasmModule.h
+++ b/js/src/asmjs/WasmModule.h
@@ -244,16 +244,19 @@ class CodeRange
     // profiling prologues/epilogues.
 
     bool isFunction() const {
         return kind() == Function;
     }
     bool isImportExit() const {
         return kind() == ImportJitExit || kind() == ImportInterpExit;
     }
+    bool isErrorExit() const {
+        return kind() == ErrorExit;
+    }
     uint32_t funcProfilingEntry() const {
         MOZ_ASSERT(isFunction());
         return begin();
     }
     uint32_t funcNonProfilingEntry() const {
         MOZ_ASSERT(isFunction());
         return begin_ + u.func.beginToEntry_;
     }
--- a/js/src/jit-test/tests/wasm/basic.js
+++ b/js/src/jit-test/tests/wasm/basic.js
@@ -320,36 +320,50 @@ var {v2i, i2i, i2v} = wasmEvalText(`(mod
     (func (param i32) (result i32) (call_indirect 0 (get_local 0)))
     (func (param i32) (param i32) (result i32) (call_indirect 1 (get_local 0) (get_local 1)))
     (func (param i32) (call_indirect 2 (get_local 0) (i32.const 0)))
     (export "v2i" 6)
     (export "i2i" 7)
     (export "i2v" 8)
 )`);
 
+const badIndirectCall = /wasm indirect call signature mismatch/;
+
 assertEq(v2i(0), 13);
 assertEq(v2i(1), 42);
-assertErrorMessage(() => v2i(2), Error, /wasm indirect call signature mismatch/);
-assertErrorMessage(() => v2i(3), Error, /wasm indirect call signature mismatch/);
-assertErrorMessage(() => v2i(4), Error, /wasm indirect call signature mismatch/);
-assertErrorMessage(() => v2i(5), Error, /wasm indirect call signature mismatch/);
+assertErrorMessage(() => v2i(2), Error, badIndirectCall);
+assertErrorMessage(() => v2i(3), Error, badIndirectCall);
+assertErrorMessage(() => v2i(4), Error, badIndirectCall);
+assertErrorMessage(() => v2i(5), Error, badIndirectCall);
 
-assertErrorMessage(() => i2i(0), Error, /wasm indirect call signature mismatch/);
-assertErrorMessage(() => i2i(1), Error, /wasm indirect call signature mismatch/);
+assertErrorMessage(() => i2i(0), Error, badIndirectCall);
+assertErrorMessage(() => i2i(1), Error, badIndirectCall);
 assertEq(i2i(2, 100), 101);
 assertEq(i2i(3, 100), 102);
 assertEq(i2i(4, 100), 103);
 assertEq(i2i(5, 100), 104);
 
-assertErrorMessage(() => i2v(0), Error, /wasm indirect call signature mismatch/);
-assertErrorMessage(() => i2v(1), Error, /wasm indirect call signature mismatch/);
-assertErrorMessage(() => i2v(2), Error, /wasm indirect call signature mismatch/);
-assertErrorMessage(() => i2v(3), Error, /wasm indirect call signature mismatch/);
-assertErrorMessage(() => i2v(4), Error, /wasm indirect call signature mismatch/);
-assertErrorMessage(() => i2v(5), Error, /wasm indirect call signature mismatch/);
+assertErrorMessage(() => i2v(0), Error, badIndirectCall);
+assertErrorMessage(() => i2v(1), Error, badIndirectCall);
+assertErrorMessage(() => i2v(2), Error, badIndirectCall);
+assertErrorMessage(() => i2v(3), Error, badIndirectCall);
+assertErrorMessage(() => i2v(4), Error, badIndirectCall);
+assertErrorMessage(() => i2v(5), Error, badIndirectCall);
+
+{
+    enableSPSProfiling();
+    wasmEvalText(`(
+        module
+        (func (result i32) (i32.const 0))
+        (func)
+        (table 1 0)
+        (export "" 0)
+    )`)();
+    disableSPSProfiling();
+}
 
 for (bad of [6, 7, 100, Math.pow(2,31)-1, Math.pow(2,31), Math.pow(2,31)+1, Math.pow(2,32)-2, Math.pow(2,32)-1]) {
     assertThrowsInstanceOf(() => v2i(bad), RangeError);
     assertThrowsInstanceOf(() => i2i(bad, 0), RangeError);
     assertThrowsInstanceOf(() => i2v(bad, 0), RangeError);
 }
 
 if (hasI64) {