[Linux] Clear WasmMemory with madvice instead of memset
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Aug 2017 13:11:00 +0000 (13:11 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Aug 2017 13:11:00 +0000 (13:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=175150

Reviewed by Filip Pizlo.

In Linux, zeroing pages with memset populates backing store.
Instead, we should use madvise with MADV_DONTNEED. It discards
pages. And if you access these pages, on-demand-zero-pages will
be shown.

We also commit grown pages in all OSes.

* wasm/WasmMemory.cpp:
(JSC::Wasm::commitZeroPages):
(JSC::Wasm::Memory::create):
(JSC::Wasm::Memory::grow):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@220401 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/wasm/WasmMemory.cpp

index eda4fc5..45570b4 100644 (file)
@@ -1,3 +1,22 @@
+2017-08-06  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [Linux] Clear WasmMemory with madvice instead of memset
+        https://bugs.webkit.org/show_bug.cgi?id=175150
+
+        Reviewed by Filip Pizlo.
+
+        In Linux, zeroing pages with memset populates backing store.
+        Instead, we should use madvise with MADV_DONTNEED. It discards
+        pages. And if you access these pages, on-demand-zero-pages will
+        be shown.
+
+        We also commit grown pages in all OSes.
+
+        * wasm/WasmMemory.cpp:
+        (JSC::Wasm::commitZeroPages):
+        (JSC::Wasm::Memory::create):
+        (JSC::Wasm::Memory::grow):
+
 2017-08-07  Robin Morisset  <rmorisset@apple.com>
 
         GetOwnProperty of TypedArray indexed fields is wrongly configurable
index 94d064c..c6be975 100644 (file)
@@ -255,6 +255,21 @@ Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mapped
     dataLogLnIf(verbose, "Memory::Memory allocating ", *this);
 }
 
+static void commitZeroPages(void* startAddress, size_t sizeInBytes)
+{
+    bool writable = true;
+    bool executable = false;
+#if OS(LINUX)
+    // In Linux, MADV_DONTNEED clears backing pages with zero. Be Careful that MADV_DONTNEED shows different semantics in different OSes.
+    // For example, FreeBSD does not clear backing pages immediately.
+    while (madvise(startAddress, sizeInBytes, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
+    OSAllocator::commit(startAddress, sizeInBytes, writable, executable);
+#else
+    OSAllocator::commit(startAddress, sizeInBytes, writable, executable);
+    memset(startAddress, 0, sizeInBytes);
+#endif
+}
+
 RefPtr<Memory> Memory::create(VM& vm, PageCount initial, PageCount maximum)
 {
     ASSERT(initial);
@@ -293,16 +308,14 @@ RefPtr<Memory> Memory::create(VM& vm, PageCount initial, PageCount maximum)
     }
     
     if (fastMemory) {
-        bool writable = true;
-        bool executable = false;
-        OSAllocator::commit(fastMemory, initialBytes, writable, executable);
         
         if (mprotect(fastMemory + initialBytes, Memory::fastMappedBytes() - initialBytes, PROT_NONE)) {
             dataLog("mprotect failed: ", strerror(errno), "\n");
             RELEASE_ASSERT_NOT_REACHED();
         }
+
+        commitZeroPages(fastMemory, initialBytes);
         
-        memset(fastMemory, 0, initialBytes);
         return adoptRef(new Memory(fastMemory, initial, maximum, Memory::fastMappedBytes(), MemoryMode::Signaling));
     }
     
@@ -400,7 +413,7 @@ bool Memory::grow(VM& vm, PageCount newSize)
             dataLogLnIf(verbose, "Memory::grow in-place failed ", *this);
             return false;
         }
-        memset(startAddress, 0, extraBytes);
+        commitZeroPages(startAddress, extraBytes);
         m_size = desiredSize;
         return true;
     } }