Title: [215525] trunk
Revision
215525
Author
[email protected]
Date
2017-04-19 12:38:52 -0700 (Wed, 19 Apr 2017)

Log Message

WebAssembly: limit slow memories
https://bugs.webkit.org/show_bug.cgi?id=170825

Reviewed by Saam Barati.

JSTests:

* wasm.yaml:
* wasm/stress/oom.js: Added.
(try.true.WebAssemblyMemoryMode):
(catch):

Source/_javascript_Core:

We limits the number of fast memories, partly because ASLR. The
code then falls back to slow memories. It first tries to virtually
allocated any declared maximum (and in there, physically the
initial), and if that fails it tries to physically allocate the
initial without any extra.

This can still be used to cause a bunch of virtual
allocation. This patch imposes soft limit on slow memories as
well. The total virtual maximum for slow memories is set at the
same (theoretical) value as that for fast memories.

Anything exceeding that limit causes allocation/grow to fail.

* wasm/WasmMemory.cpp:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (215524 => 215525)


--- trunk/JSTests/ChangeLog	2017-04-19 19:11:25 UTC (rev 215524)
+++ trunk/JSTests/ChangeLog	2017-04-19 19:38:52 UTC (rev 215525)
@@ -1,5 +1,17 @@
 2017-04-19  JF Bastien  <[email protected]>
 
+        WebAssembly: limit slow memories
+        https://bugs.webkit.org/show_bug.cgi?id=170825
+
+        Reviewed by Saam Barati.
+
+        * wasm.yaml:
+        * wasm/stress/oom.js: Added.
+        (try.true.WebAssemblyMemoryMode):
+        (catch):
+
+2017-04-19  JF Bastien  <[email protected]>
+
         WebAssembly: don't expose any WebAssembly JS object if JIT is off
         https://bugs.webkit.org/show_bug.cgi?id=170782
 

Added: trunk/JSTests/wasm/stress/oom.js (0 => 215525)


--- trunk/JSTests/wasm/stress/oom.js	                        (rev 0)
+++ trunk/JSTests/wasm/stress/oom.js	2017-04-19 19:38:52 UTC (rev 215525)
@@ -0,0 +1,22 @@
+const verbose = true;
+
+// Use a full 4GiB so that exhaustion is likely to occur faster. We're not
+// guaranteed that we'll get that much virtually allocated to the memory so we
+// can't actually check that exhaustion occurs at a particular number of
+// memories.
+const maximumPages = 65536;
+
+let memories = [];
+try {
+    while (true) {
+        let m = new WebAssembly.Memory({ initial: 64, maximum: maximumPages });
+        memories.push(m);
+        if (verbose)
+            print(`${WebAssemblyMemoryMode(m)} ${memories.length}`);
+    }
+} catch (e) {
+    if (verbose)
+        print(`Caught: ${e}`);
+    if (e.message !== "Out of memory")
+        throw new Error(`Expected an out of memory error, got ${e} of type ${typeof e}`);
+}

Modified: trunk/JSTests/wasm.yaml (215524 => 215525)


--- trunk/JSTests/wasm.yaml	2017-04-19 19:11:25 UTC (rev 215524)
+++ trunk/JSTests/wasm.yaml	2017-04-19 19:38:52 UTC (rev 215525)
@@ -31,6 +31,8 @@
   cmd: runWebAssembly unless parseRunCommands
 - path: wasm/fuzz
   cmd: runWebAssembly unless parseRunCommands
+- path: wasm/stress
+  cmd: runWebAssembly unless parseRunCommands
 
 - path: wasm/spec-tests/address.wast.js
   cmd: runWebAssemblySpecTest :normal

Modified: trunk/Source/_javascript_Core/ChangeLog (215524 => 215525)


--- trunk/Source/_javascript_Core/ChangeLog	2017-04-19 19:11:25 UTC (rev 215524)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-04-19 19:38:52 UTC (rev 215525)
@@ -1,5 +1,27 @@
 2017-04-19  JF Bastien  <[email protected]>
 
+        WebAssembly: limit slow memories
+        https://bugs.webkit.org/show_bug.cgi?id=170825
+
+        Reviewed by Saam Barati.
+
+        We limits the number of fast memories, partly because ASLR. The
+        code then falls back to slow memories. It first tries to virtually
+        allocated any declared maximum (and in there, physically the
+        initial), and if that fails it tries to physically allocate the
+        initial without any extra.
+
+        This can still be used to cause a bunch of virtual
+        allocation. This patch imposes soft limit on slow memories as
+        well. The total virtual maximum for slow memories is set at the
+        same (theoretical) value as that for fast memories.
+
+        Anything exceeding that limit causes allocation/grow to fail.
+
+        * wasm/WasmMemory.cpp:
+
+2017-04-19  JF Bastien  <[email protected]>
+
         Cannot compile _javascript_Core/runtime/VMTraps.cpp on FreeBSD because std::pair has a non-trivial copy constructor
         https://bugs.webkit.org/show_bug.cgi?id=170875
 

Modified: trunk/Source/_javascript_Core/wasm/WasmMemory.cpp (215524 => 215525)


--- trunk/Source/_javascript_Core/wasm/WasmMemory.cpp	2017-04-19 19:11:25 UTC (rev 215524)
+++ trunk/Source/_javascript_Core/wasm/WasmMemory.cpp	2017-04-19 19:38:52 UTC (rev 215525)
@@ -93,7 +93,13 @@
 std::atomic<void*> currentlyActiveFastMemories[fastMemoryAllocationSoftLimit] = { ATOMIC_VAR_INIT(nullptr) };
 std::atomic<size_t> currentlyAllocatedFastMemories = ATOMIC_VAR_INIT(0);
 std::atomic<size_t> observedMaximumFastMemory = ATOMIC_VAR_INIT(0);
+std::atomic<size_t> currentSlowMemoryCapacity = ATOMIC_VAR_INIT(0);
 
+size_t fastMemoryAllocatedBytesSoftLimit()
+{
+    return fastMemoryAllocationSoftLimit * Memory::fastMappedBytes();
+}
+
 void* tryGetCachedFastMemory()
 {
     for (unsigned idx = 0; idx < fastMemoryPreallocateCount; ++idx) {
@@ -194,9 +200,27 @@
     return memory;
 }
 
+bool slowMemoryCapacitySoftMaximumExceeded()
+{
+    // The limit on slow memory capacity is arbitrary. Its purpose is to limit
+    // virtual memory allocation. We choose to set the limit at the same virtual
+    // memory limit imposed on fast memories.
+    size_t maximum = fastMemoryAllocatedBytesSoftLimit();
+    size_t currentCapacity = currentSlowMemoryCapacity.load(std::memory_order_acquire);
+    if (UNLIKELY(currentCapacity > maximum)) {
+        dataLogLnIf(verbose, "Slow memory capacity limit reached");
+        return true;
+    }
+    return false;
+}
+
 void* tryGetSlowMemory(size_t bytes)
 {
+    if (slowMemoryCapacitySoftMaximumExceeded())
+        return nullptr;
     void* memory = mmapBytes(bytes);
+    if (memory)
+        currentSlowMemoryCapacity.fetch_add(bytes, std::memory_order_acq_rel);
     dataLogLnIf(memory && verbose, "Obtained slow memory ", RawPointer(memory), " with capacity ", bytes);
     dataLogLnIf(!memory && verbose, "Failed obtaining slow memory with capacity ", bytes);
     return memory;
@@ -228,6 +252,7 @@
     case MemoryMode::BoundsChecking:
         dataLogLnIf(verbose, "relinquishFastMemory freeing slow memory ", RawPointer(memory));
         munmapBytes(memory, mappedCapacity);
+        currentSlowMemoryCapacity.fetch_sub(mappedCapacity, std::memory_order_acq_rel);
         return;
 
     case MemoryMode::NumberOfMemoryModes:
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to