Title: [214950] trunk
Revision
214950
Author
[email protected]
Date
2017-04-05 10:19:16 -0700 (Wed, 05 Apr 2017)

Log Message

WebAssembly: We shouldn't need to pin size registers if we have a fast memory.
https://bugs.webkit.org/show_bug.cgi?id=170504

Reviewed by Mark Lam.

JSTests:

* wasm/function-tests/trap-after-cross-instance-call.js: Added.
(b.new.WebAssembly.Memory):
(importObject.foo.bar):
(wasmFrameCountFromError):

Source/_javascript_Core:

* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):
* wasm/WasmMemoryInformation.h:
(JSC::Wasm::PinnedRegisterInfo::toSave):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (214949 => 214950)


--- trunk/JSTests/ChangeLog	2017-04-05 17:15:55 UTC (rev 214949)
+++ trunk/JSTests/ChangeLog	2017-04-05 17:19:16 UTC (rev 214950)
@@ -1,3 +1,15 @@
+2017-04-05  Keith Miller  <[email protected]>
+
+        WebAssembly: We shouldn't need to pin size registers if we have a fast memory.
+        https://bugs.webkit.org/show_bug.cgi?id=170504
+
+        Reviewed by Mark Lam.
+
+        * wasm/function-tests/trap-after-cross-instance-call.js: Added.
+        (b.new.WebAssembly.Memory):
+        (importObject.foo.bar):
+        (wasmFrameCountFromError):
+
 2017-03-16  Yusuke Suzuki  <[email protected]>
 
         [JSC] Generate TemplateObjects at linking time

Added: trunk/JSTests/wasm/function-tests/trap-after-cross-instance-call.js (0 => 214950)


--- trunk/JSTests/wasm/function-tests/trap-after-cross-instance-call.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/trap-after-cross-instance-call.js	2017-04-05 17:19:16 UTC (rev 214950)
@@ -0,0 +1,64 @@
+import Builder from '../Builder.js'
+import * as assert from '../assert.js'
+
+const pageSize = 64 * 1024;
+const numPages = 10;
+
+const builder = (new Builder())
+    .Type().End()
+    .Import()
+        .Memory("a", "b", {initial: numPages})
+        .Function("foo", "bar", { params: [], ret: "void" })
+    .End()
+    .Function().End()
+    .Export().Function("foo").End()
+    .Code()
+        .Function("foo", {params: ["i32"], ret: "i32"})
+            .Call(0)
+            .GetLocal(0)
+            .I32Load(2, 0)
+            .Return()
+        .End()
+    .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+
+let importObject = {a: {b: new WebAssembly.Memory({initial: numPages})}};
+
+{
+    const builder = (new Builder())
+          .Type().End()
+          .Import()
+              .Memory("a", "b", {initial: numPages})
+          .End()
+          .Function().End()
+          .Export().Function("bar").End()
+          .Code()
+              .Function("bar", { params: [], ret: "void" })
+                  .Return()
+              .End()
+          .End();
+
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+
+    importObject.foo = new WebAssembly.Instance(module, {a: {b: new WebAssembly.Memory({initial: numPages})}}).exports
+}
+
+let foo1 = new WebAssembly.Instance(module, importObject).exports.foo;
+importObject.foo = { bar() { } };
+let foo2 = new WebAssembly.Instance(module, importObject).exports.foo;
+
+
+function wasmFrameCountFromError(e) {
+    let stackFrames = e.stack.split("\n").filter((s) => s.indexOf("<wasm>@[wasm code]") !== -1);
+    return stackFrames.length;
+}
+
+for (let i = 0; i < 1000; i++) {
+    const e1 = assert.throws(() => foo1(numPages * pageSize + 1), WebAssembly.RuntimeError, "Out of bounds memory access");
+    assert.eq(wasmFrameCountFromError(e1), 2);
+    const e2 = assert.throws(() => foo1(numPages * pageSize + 1), WebAssembly.RuntimeError, "Out of bounds memory access");
+    assert.eq(wasmFrameCountFromError(e2), 2);
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (214949 => 214950)


--- trunk/Source/_javascript_Core/ChangeLog	2017-04-05 17:15:55 UTC (rev 214949)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-04-05 17:19:16 UTC (rev 214950)
@@ -1,3 +1,17 @@
+2017-04-05  Keith Miller  <[email protected]>
+
+        WebAssembly: We shouldn't need to pin size registers if we have a fast memory.
+        https://bugs.webkit.org/show_bug.cgi?id=170504
+
+        Reviewed by Mark Lam.
+
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::createJSToWasmWrapper):
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmMemoryInformation.h:
+        (JSC::Wasm::PinnedRegisterInfo::toSave):
+
 2017-04-05  Yusuke Suzuki  <[email protected]>
 
         [JSC] Suppress warnings in GCC

Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (214949 => 214950)


--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-04-05 17:15:55 UTC (rev 214949)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-04-05 17:19:16 UTC (rev 214950)
@@ -243,7 +243,7 @@
     HashMap<ValueKey, Value*> m_constantPool;
     InsertionSet m_constantInsertionValues;
     GPRReg m_memoryBaseGPR;
-    GPRReg m_memorySizeGPR;
+    GPRReg m_memorySizeGPR { InvalidGPRReg };
     GPRReg m_wasmContextGPR;
     Value* m_instanceValue; // FIXME: make this lazy https://bugs.webkit.org/show_bug.cgi?id=169792
 };
@@ -313,16 +313,21 @@
 
     // FIXME we don't really need to pin registers here if there's no memory. It makes wasm -> wasm thunks simpler for now. https://bugs.webkit.org/show_bug.cgi?id=166623
     const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
+
     m_memoryBaseGPR = pinnedRegs.baseMemoryPointer;
+    m_proc.pinRegister(m_memoryBaseGPR);
+
     m_wasmContextGPR = pinnedRegs.wasmContextPointer;
-    m_proc.pinRegister(m_memoryBaseGPR);
     if (!useFastTLSForContext())
         m_proc.pinRegister(m_wasmContextGPR);
-    ASSERT(!pinnedRegs.sizeRegisters[0].sizeOffset);
-    m_memorySizeGPR = pinnedRegs.sizeRegisters[0].sizeRegister;
-    for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
-        m_proc.pinRegister(regInfo.sizeRegister);
 
+    if (mode != MemoryMode::Signaling) {
+        ASSERT(!pinnedRegs.sizeRegisters[0].sizeOffset);
+        m_memorySizeGPR = pinnedRegs.sizeRegisters[0].sizeRegister;
+        for (const PinnedSizeRegisterInfo& regInfo : pinnedRegs.sizeRegisters)
+            m_proc.pinRegister(regInfo.sizeRegister);
+    }
+
     if (info.memory) {
         m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned) {
             AllowMacroScratchRegisterUsage allowScratch(jit);
@@ -903,6 +908,7 @@
             [=] (PatchpointValue* patchpoint) {
                 patchpoint->effects.writesPinned = true;
                 patchpoint->effects.readsPinned = true;
+                // We need to clobber all potential pinned registers since we might be leaving the instance.
                 patchpoint->clobberLate(PinnedRegisterInfo::get().toSave());
                 patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
                     AllowMacroScratchRegisterUsage allowScratch(jit);
@@ -928,6 +934,7 @@
                 patchpoint->effects.writesPinned = true;
                 patchpoint->effects.readsPinned = true;
                 patchpoint->append(jumpDestination, ValueRep::SomeRegister);
+                // We need to clobber all potential pinned registers since we might be leaving the instance.
                 patchpoint->clobberLate(PinnedRegisterInfo::get().toSave());
                 patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex, returnType] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
                     AllowMacroScratchRegisterUsage allowScratch(jit);
@@ -1032,6 +1039,7 @@
         [=] (PatchpointValue* patchpoint) {
             patchpoint->effects.writesPinned = true;
             patchpoint->effects.readsPinned = true;
+            // We need to clobber all potential pinned registers since we might be leaving the instance.
             patchpoint->clobberLate(PinnedRegisterInfo::get().toSave());
 
             patchpoint->append(calleeCode, ValueRep::SomeRegister);
@@ -1088,7 +1096,7 @@
     dataLogLn();
 }
 
-static void createJSToWasmWrapper(CompilationContext& compilationContext, WasmInternalFunction& function, const Signature& signature, const ModuleInformation& info)
+static void createJSToWasmWrapper(CompilationContext& compilationContext, WasmInternalFunction& function, const Signature& signature, const ModuleInformation& info, MemoryMode mode)
 {
     CCallHelpers& jit = *compilationContext.jsEntrypointJIT;
 
@@ -1104,7 +1112,7 @@
     });
 
     const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get();
-    RegisterSet toSave = pinnedRegs.toSave();
+    RegisterSet toSave = pinnedRegs.toSave(mode);
 
 #if !ASSERT_DISABLED
     unsigned toSaveSize = toSave.numberOfSetGPRs();
@@ -1230,13 +1238,17 @@
             jit.loadWasmContext(baseMemory);
             jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyInstance::offsetOfMemory()), baseMemory);
         }
-        const auto& sizeRegs = pinnedRegs.sizeRegisters;
-        ASSERT(sizeRegs.size() >= 1);
-        ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
-        jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister);
+
+        if (mode != MemoryMode::Signaling) {
+            const auto& sizeRegs = pinnedRegs.sizeRegisters;
+            ASSERT(sizeRegs.size() >= 1);
+            ASSERT(!sizeRegs[0].sizeOffset); // The following code assumes we start at 0, and calculates subsequent size registers relative to 0.
+            jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfSize()), sizeRegs[0].sizeRegister);
+            for (unsigned i = 1; i < sizeRegs.size(); ++i)
+                jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
+        }
+
         jit.loadPtr(CCallHelpers::Address(baseMemory, JSWebAssemblyMemory::offsetOfMemory()), baseMemory);
-        for (unsigned i = 1; i < sizeRegs.size(); ++i)
-            jit.add64(CCallHelpers::TrustedImm32(-sizeRegs[i].sizeOffset), sizeRegs[0].sizeRegister, sizeRegs[i].sizeRegister);
     }
 
     compilationContext.jsEntrypointToWasmEntrypointCall = jit.call();
@@ -1311,7 +1323,7 @@
         result->wasmEntrypoint.calleeSaveRegisters = procedure.calleeSaveRegisters();
     }
 
-    createJSToWasmWrapper(compilationContext, *result, signature, info);
+    createJSToWasmWrapper(compilationContext, *result, signature, info, mode);
     return WTFMove(result);
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h (214949 => 214950)


--- trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h	2017-04-05 17:15:55 UTC (rev 214949)
+++ trunk/Source/_javascript_Core/wasm/WasmMemoryInformation.h	2017-04-05 17:19:16 UTC (rev 214950)
@@ -48,14 +48,16 @@
     static const PinnedRegisterInfo& get();
     PinnedRegisterInfo(Vector<PinnedSizeRegisterInfo>&&, GPRReg, GPRReg);
 
-    RegisterSet toSave() const
+    RegisterSet toSave(MemoryMode mode = MemoryMode::BoundsChecking) const
     {
         RegisterSet result;
         result.set(baseMemoryPointer);
         if (wasmContextPointer != InvalidGPRReg)
             result.set(wasmContextPointer);
-        for (const auto& info : sizeRegisters)
-            result.set(info.sizeRegister);
+        if (mode != MemoryMode::Signaling) {
+            for (const auto& info : sizeRegisters)
+                result.set(info.sizeRegister);
+        }
         return result;
     }
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to