<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[214380] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/214380">214380</a></dd>
<dt>Author</dt> <dd>jfbastien@apple.com</dd>
<dt>Date</dt> <dd>2017-03-24 15:09:15 -0700 (Fri, 24 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebAssembly: spec-tests/memory.wast.js fails in debug
https://bugs.webkit.org/show_bug.cgi?id=169794

Reviewed by Keith Miller.

The failure was due to empty memories (with maximum size 0). Those
only occur in tests and in code that's trying to trip us. This
patch adds memory mode &quot;none&quot; which represents no memory. It can
work with either bounds checked or signaling code because it never
contains loads and stores.

The spec tests which were failing did the following:
    &gt; (module (memory (data)) (func (export &quot;memsize&quot;) (result i32) (current_memory)))
    &gt; (assert_return (invoke &quot;memsize&quot;) (i32.const 0))
    &gt; (module (memory (data &quot;&quot;)) (func (export &quot;memsize&quot;) (result i32) (current_memory)))
    &gt; (assert_return (invoke &quot;memsize&quot;) (i32.const 0))
    &gt; (module (memory (data &quot;x&quot;)) (func (export &quot;memsize&quot;) (result i32) (current_memory)))
    &gt; (assert_return (invoke &quot;memsize&quot;) (i32.const 1))

* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::memoryKind):
* wasm/WasmMemory.cpp:
(JSC::Wasm::tryGetFastMemory):
(JSC::Wasm::releaseFastMemory):
(JSC::Wasm::Memory::Memory):
(JSC::Wasm::Memory::createImpl):
(JSC::Wasm::Memory::create):
(JSC::Wasm::Memory::grow):
(JSC::Wasm::Memory::makeString):
* wasm/WasmMemory.h:
* wasm/WasmMemoryInformation.cpp:
(JSC::Wasm::MemoryInformation::MemoryInformation):
* wasm/js/JSWebAssemblyCodeBlock.cpp:
(JSC::JSWebAssemblyCodeBlock::isSafeToRun):
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::codeBlock):
(JSC::JSWebAssemblyModule::finishCreation):
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::codeBlock):
(JSC::JSWebAssemblyModule::codeBlockFor):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmJSWebAssemblyCodeBlockh">trunk/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemorycpp">trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryh">trunk/Source/JavaScriptCore/wasm/WasmMemory.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryInformationcpp">trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryInformationh">trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParserh">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlancpp">trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlanh">trunk/Source/JavaScriptCore/wasm/WasmPlan.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyCodeBlockcpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -1,3 +1,46 @@
</span><ins>+2017-03-24  JF Bastien  &lt;jfbastien@apple.com&gt;
+
+        WebAssembly: spec-tests/memory.wast.js fails in debug
+        https://bugs.webkit.org/show_bug.cgi?id=169794
+
+        Reviewed by Keith Miller.
+
+        The failure was due to empty memories (with maximum size 0). Those
+        only occur in tests and in code that's trying to trip us. This
+        patch adds memory mode &quot;none&quot; which represents no memory. It can
+        work with either bounds checked or signaling code because it never
+        contains loads and stores.
+
+        The spec tests which were failing did the following:
+            &gt; (module (memory (data)) (func (export &quot;memsize&quot;) (result i32) (current_memory)))
+            &gt; (assert_return (invoke &quot;memsize&quot;) (i32.const 0))
+            &gt; (module (memory (data &quot;&quot;)) (func (export &quot;memsize&quot;) (result i32) (current_memory)))
+            &gt; (assert_return (invoke &quot;memsize&quot;) (i32.const 0))
+            &gt; (module (memory (data &quot;x&quot;)) (func (export &quot;memsize&quot;) (result i32) (current_memory)))
+            &gt; (assert_return (invoke &quot;memsize&quot;) (i32.const 1))
+
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::memoryKind):
+        * wasm/WasmMemory.cpp:
+        (JSC::Wasm::tryGetFastMemory):
+        (JSC::Wasm::releaseFastMemory):
+        (JSC::Wasm::Memory::Memory):
+        (JSC::Wasm::Memory::createImpl):
+        (JSC::Wasm::Memory::create):
+        (JSC::Wasm::Memory::grow):
+        (JSC::Wasm::Memory::makeString):
+        * wasm/WasmMemory.h:
+        * wasm/WasmMemoryInformation.cpp:
+        (JSC::Wasm::MemoryInformation::MemoryInformation):
+        * wasm/js/JSWebAssemblyCodeBlock.cpp:
+        (JSC::JSWebAssemblyCodeBlock::isSafeToRun):
+        * wasm/js/JSWebAssemblyModule.cpp:
+        (JSC::JSWebAssemblyModule::codeBlock):
+        (JSC::JSWebAssemblyModule::finishCreation):
+        * wasm/js/JSWebAssemblyModule.h:
+        (JSC::JSWebAssemblyModule::codeBlock):
+        (JSC::JSWebAssemblyModule::codeBlockFor):
+
</ins><span class="cx"> 2017-03-24  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Array memcpy'ing fast paths should check if we're having a bad time if they cannot handle it.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmJSWebAssemblyCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/JSWebAssemblyCodeBlock.h        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">     typedef JSCell Base;
</span><span class="cx">     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyCodeBlock* create(VM&amp; vm, JSWebAssemblyModule* owner, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; exitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
</del><ins>+    static JSWebAssemblyCodeBlock* create(VM&amp; vm, JSWebAssemblyModule* owner, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; exitStubs, Wasm::MemoryMode mode, unsigned calleeCount)
</ins><span class="cx">     {
</span><span class="cx">         auto* result = new (NotNull, allocateCell&lt;JSWebAssemblyCodeBlock&gt;(vm.heap, allocationSize(calleeCount))) JSWebAssemblyCodeBlock(vm, owner, std::forward&lt;Bag&lt;CallLinkInfo&gt;&gt;(callLinkInfos), std::forward&lt;Vector&lt;Wasm::WasmExitStubs&gt;&gt;(exitStubs), mode, calleeCount);
</span><span class="cx">         result-&gt;finishCreation(vm);
</span><span class="lines">@@ -57,7 +57,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     unsigned functionImportCount() const { return m_wasmExitStubs.size(); }
</span><del>-    Wasm::Memory::Mode mode() const { return m_mode; }
</del><ins>+    Wasm::MemoryMode mode() const { return m_mode; }
</ins><span class="cx">     JSWebAssemblyModule* module() const { return m_module.get(); }
</span><span class="cx">     bool isSafeToRun(JSWebAssemblyMemory*);
</span><span class="cx"> 
</span><span class="lines">@@ -101,7 +101,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    JSWebAssemblyCodeBlock(VM&amp;, JSWebAssemblyModule*, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp;, Wasm::Memory::Mode, unsigned calleeCount);
</del><ins>+    JSWebAssemblyCodeBlock(VM&amp;, JSWebAssemblyModule*, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp;, Wasm::MemoryMode, unsigned calleeCount);
</ins><span class="cx">     DECLARE_EXPORT_INFO;
</span><span class="cx">     static const bool needsDestruction = true;
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="lines">@@ -125,7 +125,7 @@
</span><span class="cx">     UnconditionalFinalizer m_unconditionalFinalizer;
</span><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><span class="cx">     Vector&lt;Wasm::WasmExitStubs&gt; m_wasmExitStubs;
</span><del>-    Wasm::Memory::Mode m_mode;
</del><ins>+    Wasm::MemoryMode m_mode;
</ins><span class="cx">     unsigned m_calleeCount;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -458,7 +458,7 @@
</span><span class="cx"> inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_memoryBaseGPR);
</span><del>-    if (m_info.memory.mode() == Memory::Mode::BoundsChecking) {
</del><ins>+    if (m_info.memory.mode() == MemoryMode::BoundsChecking) {
</ins><span class="cx">         ASSERT(m_memorySizeGPR);
</span><span class="cx">         ASSERT(sizeOfOperation + offset &gt; offset);
</span><span class="cx">         m_currentBlock-&gt;appendNew&lt;WasmBoundsCheckValue&gt;(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1);
</span><span class="lines">@@ -494,7 +494,7 @@
</span><span class="cx"> 
</span><span class="cx"> inline B3::Kind B3IRGenerator::memoryKind(B3::Opcode memoryOp)
</span><span class="cx"> {
</span><del>-    if (m_info.memory.mode() == Memory::Signaling)
</del><ins>+    if (m_info.memory.mode() == MemoryMode::Signaling)
</ins><span class="cx">         return trapping(memoryOp);
</span><span class="cx">     return memoryOp;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemorycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -56,11 +56,22 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+const char* makeString(MemoryMode mode)
+{
+    switch (mode) {
+    case MemoryMode::BoundsChecking: return &quot;BoundsChecking&quot;;
+    case MemoryMode::Signaling: return &quot;Signaling&quot;;
+    case MemoryMode::NumberOfMemoryModes: break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return &quot;&quot;;
+}
+
</ins><span class="cx"> // We use this as a heuristic to guess what mode a memory import will be. Most of the time we expect users to
</span><span class="cx"> // allocate the memory they are going to pass to all their modules right before compilation.
</span><del>-static Memory::Mode lastAllocatedMemoryMode { Memory::Mode::Signaling };
</del><ins>+static MemoryMode lastAllocatedMemoryMode { MemoryMode::Signaling };
</ins><span class="cx"> 
</span><del>-Memory::Mode Memory::lastAllocatedMode()
</del><ins>+MemoryMode Memory::lastAllocatedMode()
</ins><span class="cx"> {
</span><span class="cx">     return lastAllocatedMemoryMode;
</span><span class="cx"> }
</span><span class="lines">@@ -85,7 +96,7 @@
</span><span class="cx">     return activeFastMemories(locker);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool tryGetFastMemory(VM&amp; vm, void*&amp; memory, size_t&amp; mappedCapacity, Memory::Mode&amp; mode)
</del><ins>+inline bool tryGetFastMemory(VM&amp; vm, void*&amp; memory, size_t&amp; mappedCapacity, MemoryMode&amp; mode)
</ins><span class="cx"> {
</span><span class="cx">     // We might GC here so we should be holding the API lock.
</span><span class="cx">     // FIXME: We should be able to syncronously trigger the GC from another thread.
</span><span class="lines">@@ -106,7 +117,7 @@
</span><span class="cx">             auto result = activeFastMemories(locker).add(memory);
</span><span class="cx">             ASSERT_UNUSED(result, result.isNewEntry);
</span><span class="cx">             mappedCapacity = fastMemoryMappedBytes;
</span><del>-            mode = Memory::Signaling;
</del><ins>+            mode = MemoryMode::Signaling;
</ins><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx">         return false;
</span><span class="lines">@@ -125,7 +136,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (mmapBytes(fastMemoryMappedBytes, memory)) {
</span><span class="cx">         mappedCapacity = fastMemoryMappedBytes;
</span><del>-        mode = Memory::Signaling;
</del><ins>+        mode = MemoryMode::Signaling;
</ins><span class="cx">         LockHolder locker(memoryLock);
</span><span class="cx">         allocatedFastMemories++;
</span><span class="cx">         auto result = activeFastMemories(locker).add(memory);
</span><span class="lines">@@ -134,9 +145,9 @@
</span><span class="cx">     return memory;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void releaseFastMemory(void*&amp; memory, size_t writableSize, size_t mappedCapacity, Memory::Mode mode)
</del><ins>+inline void releaseFastMemory(void*&amp; memory, size_t writableSize, size_t mappedCapacity, MemoryMode mode)
</ins><span class="cx"> {
</span><del>-    if (mode != Memory::Signaling || !memory)
</del><ins>+    if (mode != MemoryMode::Signaling || !memory)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(memory &amp;&amp; mappedCapacity == fastMemoryMappedBytes);
</span><span class="lines">@@ -159,9 +170,11 @@
</span><span class="cx">     , m_maximum(maximum)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!initial.bytes());
</span><ins>+    ASSERT(m_mode == MemoryMode::BoundsChecking);
+    dataLogLnIf(verbose, &quot;Memory::Memory allocating &quot;, *this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode mode)
</del><ins>+Memory::Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, MemoryMode mode)
</ins><span class="cx">     : m_memory(memory)
</span><span class="cx">     , m_size(initial.bytes())
</span><span class="cx">     , m_initial(initial)
</span><span class="lines">@@ -172,20 +185,20 @@
</span><span class="cx">     dataLogLnIf(verbose, &quot;Memory::Memory allocating &quot;, *this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;Memory&gt; Memory::createImpl(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;Mode&gt; requiredMode)
</del><ins>+RefPtr&lt;Memory&gt; Memory::createImpl(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;MemoryMode&gt; requiredMode)
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!maximum || maximum &gt;= initial); // This should be guaranteed by our caller.
</span><span class="cx"> 
</span><del>-    Mode mode = requiredMode ? *requiredMode : BoundsChecking;
</del><ins>+    MemoryMode mode = requiredMode ? *requiredMode : MemoryMode::BoundsChecking;
</ins><span class="cx">     const size_t size = initial.bytes();
</span><span class="cx">     size_t mappedCapacity = maximum ? maximum.bytes() : PageCount::max().bytes();
</span><span class="cx">     void* memory = nullptr;
</span><span class="cx"> 
</span><span class="cx">     auto makeEmptyMemory = [&amp;] () -&gt; RefPtr&lt;Memory&gt; {
</span><del>-        if (mode == Signaling)
</del><ins>+        if (mode == MemoryMode::Signaling)
</ins><span class="cx">             return nullptr;
</span><span class="cx"> 
</span><del>-        lastAllocatedMemoryMode = BoundsChecking;
</del><ins>+        lastAllocatedMemoryMode = MemoryMode::BoundsChecking;
</ins><span class="cx">         return adoptRef(new Memory(initial, maximum));
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -196,9 +209,9 @@
</span><span class="cx">         return makeEmptyMemory();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool canUseFastMemory = !requiredMode || requiredMode == Signaling;
</del><ins>+    bool canUseFastMemory = !requiredMode || requiredMode == MemoryMode::Signaling;
</ins><span class="cx">     if (!canUseFastMemory || !tryGetFastMemory(vm, memory, mappedCapacity, mode)) {
</span><del>-        if (mode == Signaling)
</del><ins>+        if (mode == MemoryMode::Signaling)
</ins><span class="cx">             return nullptr;
</span><span class="cx"> 
</span><span class="cx">         if (Options::simulateWebAssemblyLowMemory() ? true : !mmapBytes(mappedCapacity, memory)) {
</span><span class="lines">@@ -219,6 +232,7 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(memory &amp;&amp; size &lt;= mappedCapacity);
</span><span class="cx">     if (mprotect(memory, size, PROT_READ | PROT_WRITE)) {
</span><ins>+        // FIXME: should this ever occur? https://bugs.webkit.org/show_bug.cgi?id=169890
</ins><span class="cx">         dataLogLnIf(verbose, &quot;Memory::create mprotect failed&quot;);
</span><span class="cx">         releaseFastMemory(memory, 0, mappedCapacity, mode);
</span><span class="cx">         if (memory) {
</span><span class="lines">@@ -227,22 +241,21 @@
</span><span class="cx">         }
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     lastAllocatedMemoryMode = mode;
</span><span class="cx">     dataLogLnIf(verbose, &quot;Memory::create mmap succeeded&quot;);
</span><span class="cx">     return adoptRef(new Memory(memory, initial, maximum, mappedCapacity, mode));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;Memory&gt; Memory::create(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;Mode&gt; mode)
</del><ins>+RefPtr&lt;Memory&gt; Memory::create(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;MemoryMode&gt; mode)
</ins><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!maximum || maximum &gt;= initial); // This should be guaranteed by our caller.
</span><span class="cx">     RefPtr&lt;Memory&gt; result = createImpl(vm, initial, maximum, mode);
</span><span class="cx">     if (result) {
</span><del>-        if (result-&gt;mode() == Signaling)
</del><ins>+        if (result-&gt;mode() == MemoryMode::Signaling)
</ins><span class="cx">             RELEASE_ASSERT(result-&gt;m_mappedCapacity == fastMemoryMappedBytes);
</span><span class="cx">         if (mode)
</span><span class="cx">             ASSERT(*mode == result-&gt;mode());
</span><del>-        ASSERT(lastAllocatedMemoryMode == result-&gt;mode());
</del><span class="cx">     }
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="lines">@@ -268,8 +281,21 @@
</span><span class="cx"> 
</span><span class="cx">     size_t desiredSize = newSize.bytes();
</span><span class="cx"> 
</span><ins>+    switch (mode()) {
+    case MemoryMode::BoundsChecking:
+        RELEASE_ASSERT(maximum().bytes() != 0);
+        break;
+    case MemoryMode::Signaling:
+        // Signaling memory must have been pre-allocated virtually.
+        RELEASE_ASSERT(m_memory);
+        break;
+    case MemoryMode::NumberOfMemoryModes:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+
</ins><span class="cx">     if (m_memory &amp;&amp; desiredSize &lt;= m_mappedCapacity) {
</span><span class="cx">         if (mprotect(static_cast&lt;uint8_t*&gt;(m_memory) + m_size, static_cast&lt;size_t&gt;(desiredSize - m_size), PROT_READ | PROT_WRITE)) {
</span><ins>+            // FIXME: should this ever occur? https://bugs.webkit.org/show_bug.cgi?id=169890
</ins><span class="cx">             dataLogLnIf(verbose, &quot;Memory::grow in-place failed &quot;, *this);
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="lines">@@ -279,8 +305,11 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ASSERT(mode() != Signaling);
</del><ins>+    // Signaling memory can't grow past its already-mapped size.
+    RELEASE_ASSERT(mode() != MemoryMode::Signaling);
+
</ins><span class="cx">     // Otherwise, let's try to make some new memory.
</span><ins>+    // FIXME: It would be nice if we had a VM tag for wasm memory. https://bugs.webkit.org/show_bug.cgi?id=163600
</ins><span class="cx">     void* newMemory = mmap(nullptr, desiredSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
</span><span class="cx">     if (newMemory == MAP_FAILED)
</span><span class="cx">         return false;
</span><span class="lines">@@ -303,17 +332,6 @@
</span><span class="cx">     out.print(&quot;Memory at &quot;, RawPointer(m_memory), &quot;, size &quot;, m_size, &quot;B capacity &quot;, m_mappedCapacity, &quot;B, initial &quot;, m_initial, &quot; maximum &quot;, m_maximum, &quot; mode &quot;, makeString(m_mode));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const char* Memory::makeString(Mode mode) const
-{
-    switch (mode) {
-    case Mode::BoundsChecking: return &quot;BoundsChecking&quot;;
-    case Mode::Signaling: return &quot;Signaling&quot;;
-    case Mode::NumberOfModes: break;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return &quot;&quot;;
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> } // namespace Wasm
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.h (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -44,6 +44,15 @@
</span><span class="cx"> 
</span><span class="cx"> namespace Wasm {
</span><span class="cx"> 
</span><ins>+// FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
+enum class MemoryMode {
+    BoundsChecking,
+    Signaling,
+    NumberOfMemoryModes
+};
+static constexpr size_t NumberOfMemoryModes = static_cast&lt;size_t&gt;(MemoryMode::NumberOfMemoryModes);
+const char* makeString(MemoryMode);
+
</ins><span class="cx"> class Memory : public RefCounted&lt;Memory&gt; {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(Memory);
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="lines">@@ -50,17 +59,9 @@
</span><span class="cx"> public:
</span><span class="cx">     void dump(WTF::PrintStream&amp;) const;
</span><span class="cx"> 
</span><del>-    // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
-    enum Mode {
-        BoundsChecking,
-        Signaling,
-        NumberOfModes
-    };
-    const char* makeString(Mode) const;
-
</del><span class="cx">     explicit operator bool() const { return !!m_memory; }
</span><span class="cx"> 
</span><del>-    static RefPtr&lt;Memory&gt; create(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;Mode&gt; requiredMode = std::nullopt);
</del><ins>+    static RefPtr&lt;Memory&gt; create(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;MemoryMode&gt; requiredMode = std::nullopt);
</ins><span class="cx"> 
</span><span class="cx">     Memory() = default;
</span><span class="cx">     ~Memory();
</span><span class="lines">@@ -72,8 +73,8 @@
</span><span class="cx">     PageCount initial() const { return m_initial; }
</span><span class="cx">     PageCount maximum() const { return m_maximum; }
</span><span class="cx"> 
</span><del>-    static Mode lastAllocatedMode();
-    Mode mode() const { return m_mode; }
</del><ins>+    static MemoryMode lastAllocatedMode();
+    MemoryMode mode() const { return m_mode; }
</ins><span class="cx"> 
</span><span class="cx">     // grow() should only be called from the JSWebAssemblyMemory object since that object needs to update internal
</span><span class="cx">     // pointers with the current base and size.
</span><span class="lines">@@ -81,8 +82,8 @@
</span><span class="cx"> 
</span><span class="cx">     void check() {  ASSERT(!deletionHasBegun()); }
</span><span class="cx"> private:
</span><del>-    static RefPtr&lt;Memory&gt; createImpl(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;Mode&gt; requiredMode = std::nullopt);
-    Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, Mode);
</del><ins>+    static RefPtr&lt;Memory&gt; createImpl(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;MemoryMode&gt; requiredMode = std::nullopt);
+    Memory(void* memory, PageCount initial, PageCount maximum, size_t mappedCapacity, MemoryMode);
</ins><span class="cx">     Memory(PageCount initial, PageCount maximum);
</span><span class="cx"> 
</span><span class="cx">     // FIXME: we should move these to the instance to avoid a load on instance-&gt;instance calls.
</span><span class="lines">@@ -91,7 +92,7 @@
</span><span class="cx">     PageCount m_initial;
</span><span class="cx">     PageCount m_maximum;
</span><span class="cx">     size_t m_mappedCapacity { 0 };
</span><del>-    Mode m_mode { Mode::BoundsChecking };
</del><ins>+    MemoryMode m_mode { MemoryMode::BoundsChecking };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static_assert(sizeof(uint64_t) == sizeof(size_t), &quot;We rely on allowing the maximum size of Memory we map to be 2^33 which is larger than fits in a 32-bit integer that we'd pass to mprotect if this didn't hold.&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryInformationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -74,7 +74,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MemoryInformation::MemoryInformation(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;Memory::Mode&gt; recompileMode, bool isImport)
</del><ins>+MemoryInformation::MemoryInformation(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;MemoryMode&gt; recompileMode, bool isImport)
</ins><span class="cx">     : m_initial(initial)
</span><span class="cx">     , m_maximum(maximum)
</span><span class="cx">     , m_isImport(isImport)
</span><span class="lines">@@ -85,7 +85,16 @@
</span><span class="cx"> 
</span><span class="cx">     if (!recompileMode) {
</span><span class="cx">         if (!isImport) {
</span><del>-            m_reservedMemory = Memory::create(vm, initial, maximum, Memory::Signaling);
</del><ins>+            if (maximum &amp;&amp; maximum.bytes() == 0) {
+                m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::BoundsChecking);
+                RELEASE_ASSERT(m_reservedMemory);
+                RELEASE_ASSERT(m_reservedMemory-&gt;maximum());
+                RELEASE_ASSERT(m_reservedMemory-&gt;maximum().bytes() == 0);
+                m_mode = m_reservedMemory-&gt;mode();
+                return;
+            }
+
+            m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::Signaling);
</ins><span class="cx">             if (m_reservedMemory) {
</span><span class="cx">                 ASSERT(!!*m_reservedMemory);
</span><span class="cx">                 m_mode = m_reservedMemory-&gt;mode();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryInformationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -54,13 +54,13 @@
</span><span class="cx">         ASSERT(!*this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MemoryInformation(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;Memory::Mode&gt;, bool isImport);
</del><ins>+    MemoryInformation(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;MemoryMode&gt;, bool isImport);
</ins><span class="cx"> 
</span><span class="cx">     PageCount initial() const { return m_initial; }
</span><span class="cx">     PageCount maximum() const { return m_maximum; }
</span><span class="cx">     bool hasReservedMemory() const { return m_reservedMemory; }
</span><span class="cx">     RefPtr&lt;Memory&gt; takeReservedMemory() { ASSERT(hasReservedMemory()); return m_reservedMemory.release(); }
</span><del>-    Memory::Mode mode() const { return m_mode; }
</del><ins>+    MemoryMode mode() const { return m_mode; }
</ins><span class="cx">     bool isImport() const { return m_isImport; }
</span><span class="cx"> 
</span><span class="cx">     explicit operator bool() const { return !!m_initial; }
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">     RefPtr&lt;Memory&gt; m_reservedMemory;
</span><span class="cx">     PageCount m_initial { };
</span><span class="cx">     PageCount m_maximum { };
</span><del>-    Memory::Mode m_mode { Memory::Mode::BoundsChecking };
</del><ins>+    MemoryMode m_mode { MemoryMode::BoundsChecking };
</ins><span class="cx">     bool m_isImport { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> class ModuleParser : public Parser&lt;ModuleParserResult&gt; {
</span><span class="cx"> public:
</span><span class="cx"> 
</span><del>-    ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional&lt;Memory::Mode&gt; mode)
</del><ins>+    ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional&lt;MemoryMode&gt; mode)
</ins><span class="cx">         : Parser(vm, sourceBuffer, sourceLength)
</span><span class="cx">         , m_mode(mode)
</span><span class="cx">     {
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&amp;, uint64_t&amp;, Type&amp; initExprType);
</span><span class="cx"> 
</span><span class="cx">     ModuleParserResult m_result;
</span><del>-    std::optional&lt;Memory::Mode&gt; m_mode { std::nullopt };
</del><ins>+    std::optional&lt;MemoryMode&gt; m_mode { std::nullopt };
</ins><span class="cx">     bool m_hasTable { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -63,7 +63,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Plan::parseAndValidateModule(std::optional&lt;Memory::Mode&gt; recompileMode)
</del><ins>+bool Plan::parseAndValidateModule(std::optional&lt;MemoryMode&gt; recompileMode)
</ins><span class="cx"> {
</span><span class="cx">     MonotonicTime startTime;
</span><span class="cx">     if (verbose || Options::reportCompileTimes())
</span><span class="lines">@@ -111,7 +111,7 @@
</span><span class="cx"> // The reason this is OK is that we guarantee that the main thread doesn't continue until all threads
</span><span class="cx"> // that could touch its stack are done executing.
</span><span class="cx"> SUPPRESS_ASAN 
</span><del>-void Plan::run(std::optional&lt;Memory::Mode&gt; recompileMode)
</del><ins>+void Plan::run(std::optional&lt;MemoryMode&gt; recompileMode)
</ins><span class="cx"> {
</span><span class="cx">     if (!parseAndValidateModule(recompileMode))
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlanh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.h (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -49,9 +49,9 @@
</span><span class="cx">     JS_EXPORT_PRIVATE Plan(VM*, const uint8_t*, size_t);
</span><span class="cx">     JS_EXPORT_PRIVATE ~Plan();
</span><span class="cx"> 
</span><del>-    bool parseAndValidateModule(std::optional&lt;Memory::Mode&gt; = std::nullopt);
</del><ins>+    bool parseAndValidateModule(std::optional&lt;MemoryMode&gt; = std::nullopt);
</ins><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE void run(std::optional&lt;Memory::Mode&gt; = std::nullopt);
</del><ins>+    JS_EXPORT_PRIVATE void run(std::optional&lt;MemoryMode&gt; = std::nullopt);
</ins><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function&lt;void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)&gt;);
</span><span class="cx"> 
</span><span class="lines">@@ -92,7 +92,7 @@
</span><span class="cx">         return WTFMove(m_wasmExitStubs);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Memory::Mode mode() const { return m_moduleInformation-&gt;memory.mode(); }
</del><ins>+    MemoryMode mode() const { return m_moduleInformation-&gt;memory.mode(); }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     std::unique_ptr&lt;ModuleInformation&gt; m_moduleInformation;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSWebAssemblyCodeBlock::s_info = { &quot;WebAssemblyCodeBlock&quot;, nullptr, 0, CREATE_METHOD_TABLE(JSWebAssemblyCodeBlock) };
</span><span class="cx"> 
</span><del>-JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM&amp; vm, JSWebAssemblyModule* owner, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; wasmExitStubs, Wasm::Memory::Mode mode, unsigned calleeCount)
</del><ins>+JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM&amp; vm, JSWebAssemblyModule* owner, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; wasmExitStubs, Wasm::MemoryMode mode, unsigned calleeCount)
</ins><span class="cx">     : Base(vm, vm.webAssemblyCodeBlockStructure.get())
</span><span class="cx">     , m_callLinkInfos(WTFMove(callLinkInfos))
</span><span class="cx">     , m_wasmExitStubs(WTFMove(wasmExitStubs))
</span><span class="lines">@@ -54,9 +54,21 @@
</span><span class="cx"> 
</span><span class="cx"> bool JSWebAssemblyCodeBlock::isSafeToRun(JSWebAssemblyMemory* memory)
</span><span class="cx"> {
</span><del>-    if (mode() == Wasm::Memory::Signaling)
-        return memory-&gt;memory().mode() == mode();
-    return true;
</del><ins>+    Wasm::MemoryMode codeMode = mode();
+    Wasm::MemoryMode memoryMode = memory-&gt;memory().mode();
+    switch (codeMode) {
+    case Wasm::MemoryMode::BoundsChecking:
+        return true;
+    case Wasm::MemoryMode::Signaling:
+        // Code being in Signaling mode means that it performs no bounds checks.
+        // Its memory, even if empty, absolutely must also be in Signaling mode
+        // because the page protection detects out-of-bounds accesses.
+        return memoryMode == Wasm::MemoryMode::Signaling;
+    case Wasm::MemoryMode::NumberOfMemoryModes:
+        break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSWebAssemblyCodeBlock::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -79,7 +79,7 @@
</span><span class="cx">     JSWebAssemblyMemory* memory() { return m_memory.get(); }
</span><span class="cx">     // Calling this might trigger a recompile.
</span><span class="cx">     void setMemory(VM&amp;, ExecState*, JSWebAssemblyMemory*);
</span><del>-    Wasm::Memory::Mode memoryMode() { return memory()-&gt;memory().mode(); }
</del><ins>+    Wasm::MemoryMode memoryMode() { return memory()-&gt;memory().mode(); }
</ins><span class="cx"> 
</span><span class="cx">     JSWebAssemblyTable* table() { return m_table.get(); }
</span><span class="cx">     void setTable(VM&amp; vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSWebAssemblyModule::s_info = { &quot;WebAssembly.Module&quot;, &amp;Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
</span><span class="cx"> 
</span><del>-JSWebAssemblyCodeBlock* JSWebAssemblyModule::buildCodeBlock(VM&amp; vm, ExecState* exec, Wasm::Plan&amp; plan, std::optional&lt;Wasm::Memory::Mode&gt; mode)
</del><ins>+JSWebAssemblyCodeBlock* JSWebAssemblyModule::buildCodeBlock(VM&amp; vm, ExecState* exec, Wasm::Plan&amp; plan, std::optional&lt;Wasm::MemoryMode&gt; mode)
</ins><span class="cx"> {
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx">     // On failure, a new WebAssembly.CompileError is thrown.
</span><span class="lines">@@ -85,14 +85,14 @@
</span><span class="cx"> 
</span><span class="cx"> JSWebAssemblyCodeBlock* JSWebAssemblyModule::codeBlock(VM&amp; vm, ExecState* exec, JSWebAssemblyMemory* memory)
</span><span class="cx"> {
</span><del>-    Wasm::Memory::Mode mode = memory-&gt;memory().mode();
</del><ins>+    Wasm::MemoryMode mode = memory-&gt;memory().mode();
</ins><span class="cx"> 
</span><del>-    for (unsigned i = 0; i &lt; Wasm::Memory::NumberOfModes; ++i) {
</del><ins>+    for (unsigned i = 0; i &lt; Wasm::NumberOfMemoryModes; ++i) {
</ins><span class="cx">         if (m_codeBlocks[i] &amp;&amp; m_codeBlocks[i]-&gt;isSafeToRun(memory))
</span><span class="cx">             return m_codeBlocks[i].get();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ASSERT(!m_codeBlocks[mode]);
</del><ins>+    ASSERT(!codeBlockFor(mode));
</ins><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx">     // We don't have a code block for this mode, we need to recompile...
</span><span class="cx">     Wasm::Plan plan(&amp;vm, static_cast&lt;uint8_t*&gt;(m_sourceBuffer-&gt;data()), m_sourceBuffer-&gt;byteLength());
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ASSERT(mode == codeBlock-&gt;mode());
</span><del>-    m_codeBlocks[mode].set(vm, this, codeBlock);
</del><ins>+    codeBlockFor(mode).set(vm, this, codeBlock);
</ins><span class="cx">     return codeBlock;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -132,7 +132,7 @@
</span><span class="cx">     m_sourceBuffer = ArrayBuffer::create(source, byteSize);
</span><span class="cx">     m_moduleInformation = plan.takeModuleInformation();
</span><span class="cx">     m_exportSymbolTable.set(vm, this, exportSymbolTable);
</span><del>-    m_codeBlocks[codeBlock-&gt;mode()].set(vm, this, codeBlock);
</del><ins>+    codeBlockFor(codeBlock-&gt;mode()).set(vm, this, codeBlock);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSWebAssemblyModule::destroy(JSCell* cell)
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx"> 
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><span class="cx">     visitor.append(thisObject-&gt;m_exportSymbolTable);
</span><del>-    for (unsigned i = 0; i &lt; Wasm::Memory::NumberOfModes; ++i)
</del><ins>+    for (unsigned i = 0; i &lt; Wasm::NumberOfMemoryModes; ++i)
</ins><span class="cx">         visitor.append(thisObject-&gt;m_codeBlocks[i]);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h (214379 => 214380)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2017-03-24 21:57:08 UTC (rev 214379)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2017-03-24 22:09:15 UTC (rev 214380)
</span><span class="lines">@@ -62,12 +62,13 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Returns the code block that this module was originally compiled expecting to use. This won't need to recompile.
</span><del>-    JSWebAssemblyCodeBlock* codeBlock() { return m_codeBlocks[m_moduleInformation-&gt;memory.mode()].get(); }
</del><ins>+    JSWebAssemblyCodeBlock* codeBlock() { return codeBlockFor(m_moduleInformation-&gt;memory.mode()).get(); }
</ins><span class="cx">     // Returns the appropriate code block for the given memory, possibly triggering a recompile.
</span><span class="cx">     JSWebAssemblyCodeBlock* codeBlock(VM&amp;, ExecState*, JSWebAssemblyMemory*);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    JSWebAssemblyCodeBlock* buildCodeBlock(VM&amp;, ExecState*, Wasm::Plan&amp;, std::optional&lt;Wasm::Memory::Mode&gt; mode = std::nullopt);
</del><ins>+    WriteBarrier&lt;JSWebAssemblyCodeBlock&gt;&amp; codeBlockFor(Wasm::MemoryMode mode) { return m_codeBlocks[static_cast&lt;size_t&gt;(mode)]; }
+    JSWebAssemblyCodeBlock* buildCodeBlock(VM&amp;, ExecState*, Wasm::Plan&amp;, std::optional&lt;Wasm::MemoryMode&gt; mode = std::nullopt);
</ins><span class="cx"> 
</span><span class="cx">     JSWebAssemblyModule(VM&amp;, Structure*);
</span><span class="cx">     void finishCreation(VM&amp;, ExecState*, uint8_t* source, size_t byteSize);
</span><span class="lines">@@ -77,7 +78,7 @@
</span><span class="cx">     RefPtr&lt;ArrayBuffer&gt; m_sourceBuffer;
</span><span class="cx">     std::unique_ptr&lt;Wasm::ModuleInformation&gt; m_moduleInformation;
</span><span class="cx">     WriteBarrier&lt;SymbolTable&gt; m_exportSymbolTable;
</span><del>-    WriteBarrier&lt;JSWebAssemblyCodeBlock&gt; m_codeBlocks[Wasm::Memory::NumberOfModes];
</del><ins>+    WriteBarrier&lt;JSWebAssemblyCodeBlock&gt; m_codeBlocks[Wasm::NumberOfMemoryModes];
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre>
</div>
</div>

</body>
</html>