<!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>[208238] 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/208238">208238</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-11-01 13:40:40 -0700 (Tue, 01 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add a WASM function validator.
https://bugs.webkit.org/show_bug.cgi?id=161707

Reviewed by Saam Barati.

This is a new template specialization of the Wasm FunctionParser class.  Instead of having
the FunctionParser track what B3 values each stack entry refers to the validator has each
entry refer to the type of the stack entry. Additionally, the control stack tracks what type
of block the object is and what the result type of the block is. The validation functions
for unary, binary, and memory operations are autogenerated by the
generateWasmValidateInlinesHeader.py script.

There are still a couple issue with validating that will be addressed in follow-up patches.
1) We need to handle result types from basic blocks. https://bugs.webkit.org/show_bug.cgi?id=164100
2) We need to handle popping things from stacks when they don't exist. https://bugs.webkit.org/show_bug.cgi?id=164275

* CMakeLists.txt:
* DerivedSources.make:
* JavaScriptCore.xcodeproj/project.pbxproj:
* testWasm.cpp:
(runWasmTests):
* wasm/WasmB3IRGenerator.cpp:
* wasm/WasmFormat.cpp: Added.
(JSC::Wasm::toString):
* wasm/WasmFormat.h:
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser&lt;Context&gt;::parseExpression):
(JSC::Wasm::FunctionParser&lt;Context&gt;::parseUnreachableExpression):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::Plan):
* wasm/WasmValidate.cpp: Added.
(JSC::Wasm::Validate::ControlData::ControlData):
(JSC::Wasm::Validate::ControlData::dump):
(JSC::Wasm::Validate::ControlData::type):
(JSC::Wasm::Validate::ControlData::signature):
(JSC::Wasm::Validate::addConstant):
(JSC::Wasm::Validate::isContinuationReachable):
(JSC::Wasm::Validate::errorMessage):
(JSC::Wasm::Validate::Validate):
(JSC::Wasm::Validate::addArguments):
(JSC::Wasm::Validate::addLocal):
(JSC::Wasm::Validate::getLocal):
(JSC::Wasm::Validate::setLocal):
(JSC::Wasm::Validate::addBlock):
(JSC::Wasm::Validate::addLoop):
(JSC::Wasm::Validate::addIf):
(JSC::Wasm::Validate::addElse):
(JSC::Wasm::Validate::addReturn):
(JSC::Wasm::Validate::addBranch):
(JSC::Wasm::Validate::endBlock):
(JSC::Wasm::Validate::addCall):
(JSC::Wasm::Validate::unify):
(JSC::Wasm::Validate::dump):
(JSC::Wasm::validateFunction):
* wasm/WasmValidate.h: Added.
* wasm/generateWasmValidateInlinesHeader.py: Added.
(cppType):
(toCpp):
(unaryMacro):
(binaryMacro):
(loadMacro):
(storeMacro):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreDerivedSourcesmake">trunk/Source/JavaScriptCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoretestWasmcpp">trunk/Source/JavaScriptCore/testWasm.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFormath">trunk/Source/JavaScriptCore/wasm/WasmFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFunctionParserh">trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlancpp">trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorewasmWasmFormatcpp">trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmValidatecpp">trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmValidateh">trunk/Source/JavaScriptCore/wasm/WasmValidate.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmgenerateWasmValidateInlinesHeaderpy">trunk/Source/JavaScriptCore/wasm/generateWasmValidateInlinesHeader.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (208237 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-11-01 20:38:39 UTC (rev 208237)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -879,9 +879,11 @@
</span><span class="cx">     wasm/JSWebAssembly.cpp
</span><span class="cx">     wasm/WasmB3IRGenerator.cpp
</span><span class="cx">     wasm/WasmCallingConvention.cpp
</span><ins>+    wasm/WasmFormat.cpp
</ins><span class="cx">     wasm/WasmMemory.cpp
</span><span class="cx">     wasm/WasmModuleParser.cpp
</span><span class="cx">     wasm/WasmPlan.cpp
</span><ins>+    wasm/WasmValidate.cpp
</ins><span class="cx"> 
</span><span class="cx">     wasm/js/JSWebAssemblyCompileError.cpp
</span><span class="cx">     wasm/js/JSWebAssemblyInstance.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (208237 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-11-01 20:38:39 UTC (rev 208237)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -1,3 +1,68 @@
</span><ins>+2016-11-01  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add a WASM function validator.
+        https://bugs.webkit.org/show_bug.cgi?id=161707
+
+        Reviewed by Saam Barati.
+
+        This is a new template specialization of the Wasm FunctionParser class.  Instead of having
+        the FunctionParser track what B3 values each stack entry refers to the validator has each
+        entry refer to the type of the stack entry. Additionally, the control stack tracks what type
+        of block the object is and what the result type of the block is. The validation functions
+        for unary, binary, and memory operations are autogenerated by the
+        generateWasmValidateInlinesHeader.py script.
+
+        There are still a couple issue with validating that will be addressed in follow-up patches.
+        1) We need to handle result types from basic blocks. https://bugs.webkit.org/show_bug.cgi?id=164100
+        2) We need to handle popping things from stacks when they don't exist. https://bugs.webkit.org/show_bug.cgi?id=164275
+
+        * CMakeLists.txt:
+        * DerivedSources.make:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * testWasm.cpp:
+        (runWasmTests):
+        * wasm/WasmB3IRGenerator.cpp:
+        * wasm/WasmFormat.cpp: Added.
+        (JSC::Wasm::toString):
+        * wasm/WasmFormat.h:
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser&lt;Context&gt;::parseExpression):
+        (JSC::Wasm::FunctionParser&lt;Context&gt;::parseUnreachableExpression):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::Plan):
+        * wasm/WasmValidate.cpp: Added.
+        (JSC::Wasm::Validate::ControlData::ControlData):
+        (JSC::Wasm::Validate::ControlData::dump):
+        (JSC::Wasm::Validate::ControlData::type):
+        (JSC::Wasm::Validate::ControlData::signature):
+        (JSC::Wasm::Validate::addConstant):
+        (JSC::Wasm::Validate::isContinuationReachable):
+        (JSC::Wasm::Validate::errorMessage):
+        (JSC::Wasm::Validate::Validate):
+        (JSC::Wasm::Validate::addArguments):
+        (JSC::Wasm::Validate::addLocal):
+        (JSC::Wasm::Validate::getLocal):
+        (JSC::Wasm::Validate::setLocal):
+        (JSC::Wasm::Validate::addBlock):
+        (JSC::Wasm::Validate::addLoop):
+        (JSC::Wasm::Validate::addIf):
+        (JSC::Wasm::Validate::addElse):
+        (JSC::Wasm::Validate::addReturn):
+        (JSC::Wasm::Validate::addBranch):
+        (JSC::Wasm::Validate::endBlock):
+        (JSC::Wasm::Validate::addCall):
+        (JSC::Wasm::Validate::unify):
+        (JSC::Wasm::Validate::dump):
+        (JSC::Wasm::validateFunction):
+        * wasm/WasmValidate.h: Added.
+        * wasm/generateWasmValidateInlinesHeader.py: Added.
+        (cppType):
+        (toCpp):
+        (unaryMacro):
+        (binaryMacro):
+        (loadMacro):
+        (storeMacro):
+
</ins><span class="cx"> 2016-11-01  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         We should be able to eliminate rest parameter allocations
</span><span class="lines">@@ -1678,7 +1743,7 @@
</span><span class="cx"> 
</span><span class="cx">         Async functions generate bytecode equivalent to the following, which is
</span><span class="cx">         highly dependent on the Generator implementation:
</span><del>-        
</del><ins>+
</ins><span class="cx">         ```
</span><span class="cx">         // Before translation:
</span><span class="cx">         async function asyncfn() {}
</span><span class="lines">@@ -1700,9 +1765,9 @@
</span><span class="cx">         Await Expressions are equivalent to non-delegating Yield expressions, and emit identical bytecode.
</span><span class="cx"> 
</span><span class="cx">         There are some caveats to be addressed later:
</span><del>-        
</del><ins>+
</ins><span class="cx">         1) the `op_to_this` is always performed, whether it's used or not, like normal generators. (https://bugs.webkit.org/show_bug.cgi?id=151586)
</span><del>-        
</del><ins>+
</ins><span class="cx">         2) for async arrow functions, the home object is always stored on the &quot;body&quot; function, regardless of whether it's needed or
</span><span class="cx">         not, for the same reason as #1 (and should also be fixed as part of https://bugs.webkit.org/show_bug.cgi?id=151586)
</span><span class="cx"> 
</span><span class="lines">@@ -1810,7 +1875,7 @@
</span><span class="cx">            For lazily reified properties, JSFunction::put() implements complex conditional
</span><span class="cx">            behavior that is different than the set of cacheable put operations above.
</span><span class="cx">            Hence, it should not claim that the property put is cacheable.
</span><del>-    
</del><ins>+
</ins><span class="cx">         2. Cacheable puts are cached on the original structure of the object before the
</span><span class="cx">            put operation.
</span><span class="cx"> 
</span><span class="lines">@@ -2068,7 +2133,7 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163947
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoffrey Garen.
</span><del>-        
</del><ins>+
</ins><span class="cx">         I want to introduce another HeapTimer. Prior to this change, that would have meant writing
</span><span class="cx">         exact copies of that timer's logic for each platform that has a HeapTimer (CF, GLIB, and
</span><span class="cx">         EFL). That logic would in turn be a duplicate of the logic already present in
</span><span class="lines">@@ -2076,13 +2141,13 @@
</span><span class="cx">         own code for scheduling timers, so a new subclass would have to duplicate that code. Then,
</span><span class="cx">         to add insult to injury, the USE(CF) version of HeapTimer would have to have an extra case
</span><span class="cx">         for that new subclass since it doesn't use virtual methods effectively.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This changes HeapTimer on USE(CF) to know to get its runloop from Heap and to use virtual
</span><span class="cx">         methods effectively so that it doesn't have to know about all of its subclasses.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This also moves IncrementalSweeper's code for scheduling timers into HeapTimer. This means
</span><span class="cx">         that future subclasses of HeapTimer could simply use that logic.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This keeps changes to GCActivityCallback to a minimum. It still has a lot of
</span><span class="cx">         platform-specific code and I'm not sure that this code can be trivially deduplicated since
</span><span class="cx">         that code has more quirks. That's fine for now, since I mainly just need a sane way of
</span><span class="lines">@@ -2711,14 +2776,14 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163802
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Keith Miller.
</span><del>-        
</del><ins>+
</ins><span class="cx">         JSC often suffers from the inline cargo cult, and Heap is a prime example. This outlines a
</span><span class="cx">         bunch of Heap methods that are either already very big, or call out-of-line methods, or call
</span><span class="cx">         very big methods, or are not called often enough for inlining to matter.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This simplifies concurrent GC work because I'm so tired of recompiling the world when I touch
</span><span class="cx">         one of these methods.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This looks to be perf-neutral.
</span><span class="cx"> 
</span><span class="cx">         * heap/Heap.cpp:
</span><span class="lines">@@ -3088,7 +3153,7 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163738
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoffrey Garen.
</span><del>-        
</del><ins>+
</ins><span class="cx">         We need to know if we're currently in an allocation slow path, so that code can assert that
</span><span class="cx">         it's not being used from inside a destructor that runs during a sweep. We need to know if
</span><span class="cx">         we're currently collecting, because some code behaves differently during collection, and
</span><span class="lines">@@ -3096,7 +3161,7 @@
</span><span class="cx">         runs during marking. If we are collecting, we need to know if it's an eden collection or a
</span><span class="cx">         full collection. If we are requesting a collection, we need to know if we're requesting an
</span><span class="cx">         eden collection, a full collection, or any kind of collection.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Prior to this change, you would reason about all of these things using the HeapOperation. It
</span><span class="cx">         had the following states: NoOperation, Allocation, FullCollection, EdenCollection, and
</span><span class="cx">         AnyCollection. NoOperation versus Allocation was primarily for asserting that sweep didn't
</span><span class="lines">@@ -3104,7 +3169,7 @@
</span><span class="cx">         would even use HeapOperation in places where we knew that it could only be either Full or
</span><span class="cx">         Eden, because we just needed a variable to tell us which generation we were talking about.
</span><span class="cx">         It was all very confusing.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Where it completely breaks down is the fact that a concurrent GC has two logical threads, the
</span><span class="cx">         mutator and the collector, which can change state independently. The mutator can be
</span><span class="cx">         allocating. It can also be doing some work to help the GC. That's three states: running,
</span><span class="lines">@@ -3114,10 +3179,10 @@
</span><span class="cx">         states: every combination of mutator running, allocating, or helping GC, crossed with
</span><span class="cx">         collector not running, running eden, or running full. So, this change decouples mutator state
</span><span class="cx">         from collector state and uses two separate fields with two different types.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Mutator state is described using MutatorState, which can be either MutatorState::Running,
</span><span class="cx">         MutatorState::Allocating, or MutatorState::HelpingGC.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Collector state is described using Optional&lt;CollectionScope&gt;. CollectionScope describes how
</span><span class="cx">         big the scope of the collection is, and it can be either CollectionScope::Eden or
</span><span class="cx">         CollectionScope::Full. If the Optional is Nullopt, it means that we are not collecting. This
</span><span class="lines">@@ -3126,7 +3191,7 @@
</span><span class="cx">         want to know about the generation. Also, we can use Nullopt in methods that request
</span><span class="cx">         collection, which those methods take to mean that they can run any kind of collection (the
</span><span class="cx">         old AnyCollection).
</span><del>-        
</del><ins>+
</ins><span class="cx">         Another use of HeapOperation was to answer questions about whether the caller is running as
</span><span class="cx">         part of the GC or as part of the mutator. Optional&lt;CollectionScope&gt; does not answer this,
</span><span class="cx">         since code that runs in the mutator while the mutator is not HelpingGC at the same time as
</span><span class="lines">@@ -3143,7 +3208,7 @@
</span><span class="cx">         checks look for GCThreadType::Helper. The &quot;should I run as mutator&quot; query can now be answered
</span><span class="cx">         by checking with mayBeGCThread, which returns Optional&lt;GCThreadType&gt;; if engaged, then run as
</span><span class="cx">         GC, else run as GC if MutatorState is HelpingGC, else run as mutator.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This doesn't change the way that the GC behaves, but it does change how the GC represents a
</span><span class="cx">         fundamental piece of state. So, it's a big change. It should be perf-neutral (still testing).
</span><span class="cx"> 
</span><span class="lines">@@ -3703,10 +3768,10 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163686
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoffrey Garen.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Change the JITWorklist to use AutomaticThread, so that the Baseline JIT's concurrent
</span><span class="cx">         compiler thread shuts down automatically after inactivity.
</span><del>-        
</del><ins>+
</ins><span class="cx">         With this change, all of JSC's threads shut down automatically. If you run splay for a few
</span><span class="cx">         seconds (which fires up all threads - compiler and GC) and then go to sleep for a second,
</span><span class="cx">         you'll see that the only threads left are the main thread and the bmalloc thread.
</span><span class="lines">@@ -3749,16 +3814,16 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163615
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Mark Lam.
</span><del>-        
</del><ins>+
</ins><span class="cx">         AutomaticThread is a new feature in WTF that allows you to easily create worker threads that
</span><span class="cx">         shut down automatically. This changes DFG::Worklist to use AutomaticThread, so that its
</span><span class="cx">         threads shut down automatically, too. This has the potential to save a lot of memory.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This required some improvements to AutomaticThread: Worklist likes to be able to keep state
</span><span class="cx">         around for the whole lifetime of a thread, and so it likes knowing when threads are born and
</span><span class="cx">         when they die. I added virtual methods for that. Also, Worklist uses notifyOne() so I added
</span><span class="cx">         that, too.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This looks to be perf-neutral.
</span><span class="cx"> 
</span><span class="cx">         * dfg/DFGThreadData.cpp:
</span><span class="lines">@@ -3922,9 +3987,9 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163576
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Andreas Kling.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Added a sleepSeconds() function, which made it easier for me to test this change.
</span><del>-        
</del><ins>+
</ins><span class="cx">         The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now
</span><span class="cx">         shut down automatically after 1 second of inactivity. Maybe this will save some memory.
</span><span class="cx"> 
</span><span class="lines">@@ -3952,14 +4017,14 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163371
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoffrey Garen and Saam Barati.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This adds a new kind of call inline cache for when the DFG can prove what the callee
</span><span class="cx">         executable is. In those cases, we can skip some of the things that the traditional call IC
</span><span class="cx">         would do:
</span><del>-        
</del><ins>+
</ins><span class="cx">         - No need to check who the callee is.
</span><span class="cx">         - No need to do arity checks.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This case isn't as simple as just emitting a call instruction since the callee may not be
</span><span class="cx">         compiled at the time that the caller is compiled. So, we need lazy resolution. Also, the
</span><span class="cx">         callee may be jettisoned independently of the caller, so we need to be able to revert the
</span><span class="lines">@@ -3966,33 +4031,33 @@
</span><span class="cx">         call to an unlinked state. This means that we need almost all of the things that
</span><span class="cx">         CallLinkInfo has. CallLinkInfo already knows about different kinds of calls. This patch
</span><span class="cx">         teaches it about new &quot;Direct&quot; call types.
</span><del>-        
</del><ins>+
</ins><span class="cx">         The direct non-tail call IC looks like this:
</span><del>-        
</del><ins>+
</ins><span class="cx">                 set up arguments
</span><span class="cx">             FastPath:
</span><span class="cx">                 call _SlowPath
</span><span class="cx">                 lea -FrameSize(%rbp), %rsp
</span><del>-            
</del><ins>+
</ins><span class="cx">             SlowPath:
</span><span class="cx">                 pop
</span><span class="cx">                 call operationLinkDirectCall
</span><span class="cx">                 check exception
</span><span class="cx">                 jmp FastPath
</span><del>-        
</del><ins>+
</ins><span class="cx">         The job of operationLinkDirectCall is to link the fast path's call entrypoint of the callee.
</span><span class="cx">         This means that in steady state, a call is just that: a call. There are no extra branches or
</span><span class="cx">         checks.
</span><del>-        
</del><ins>+
</ins><span class="cx">         The direct tail call IC is a bit more complicated because the act of setting up arguments
</span><span class="cx">         destroys our frame, which would prevent us from being able to throw an exception if we
</span><span class="cx">         failed to compile the callee. So, direct tail call ICs look like this:
</span><del>-        
</del><ins>+
</ins><span class="cx">                 jmp _SlowPath
</span><span class="cx">             FastPath:
</span><span class="cx">                 set up arguments
</span><span class="cx">                 jmp 0 // patch to jump to callee
</span><del>-            
</del><ins>+
</ins><span class="cx">             SlowPath:
</span><span class="cx">                 silent spill
</span><span class="cx">                 call operationLinkDirectCall
</span><span class="lines">@@ -3999,9 +4064,9 @@
</span><span class="cx">                 silent fill
</span><span class="cx">                 check exception
</span><span class="cx">                 jmp FastPath
</span><del>-        
</del><ins>+
</ins><span class="cx">         The jmp to the slow path is patched to be a fall-through jmp when we link the call.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Direct calls mean less code at call sites, fewer checks on the steady state call fast path,
</span><span class="cx">         and no need for arity fixup. This looks like a slight speed-up (~0.8%) on both Octane and
</span><span class="cx">         AsmBench.
</span><span class="lines">@@ -4162,16 +4227,16 @@
</span><span class="cx">         Specific items which do not contain &quot;prototype&quot; include (most) built-in functions (such as Math.pow),
</span><span class="cx">         MethodDefinitions which are not either class &quot;constructor&quot; methods or GeneratorMethods, AsyncFunctions,
</span><span class="cx">         and ArrowFunctions.
</span><del>-        
</del><ins>+
</ins><span class="cx">         For details, see the following spec text, and the difference between GeneratorMethod evaluation and
</span><span class="cx">         the evaluation of other MethodDefinition forms.
</span><del>-        
</del><ins>+
</ins><span class="cx">         - https://tc39.github.io/ecma262/#sec-method-definitions-runtime-semantics-propertydefinitionevaluation
</span><span class="cx">         - https://tc39.github.io/ecma262/#sec-arrow-function-definitions-runtime-semantics-evaluation
</span><span class="cx">         - https://tc39.github.io/ecmascript-asyncawait/#async-function-instances
</span><span class="cx">         - https://tc39.github.io/ecma262/#sec-generator-function-definitions-runtime-semantics-propertydefinitionevaluation
</span><del>-        
</del><span class="cx"> 
</span><ins>+
</ins><span class="cx">         * runtime/Executable.h:
</span><span class="cx">         * runtime/JSFunction.cpp:
</span><span class="cx">         (JSC::JSFunction::callerGetter):
</span><span class="lines">@@ -4316,7 +4381,7 @@
</span><span class="cx">         &lt;rdar://problem/28804381&gt;
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoffrey Garen.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Before r207408, IRC had a mode where it would silently assign the first assignable register (so
</span><span class="cx">         %rax, %xmm0, etc) to any tmp that was not colorable due to a pathological interference fencepost.
</span><span class="cx">         We reason about interference at instruction boundaries. This means that if you have, for example,
</span><span class="lines">@@ -4327,19 +4392,19 @@
</span><span class="cx">         to only be hit by fuzzing, which may not then stress that code enough to shake out the register
</span><span class="cx">         corruption. Also, this can only happen for floating point registers, so it's hard to get an
</span><span class="cx">         exciting crash. The worst case is that your numbers get all messed up.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This change fixes the issue:
</span><del>-        
</del><ins>+
</ins><span class="cx">         - IRC will now crash if it can't color a tmp.
</span><del>-        
</del><ins>+
</ins><span class="cx">         - IRC doesn't crash on our tests anymore because I added a padInterference() utility that works
</span><span class="cx">           around the interference problem by inserting Nops to pad between those instructions where
</span><span class="cx">           conflating their early and late actions into one interference fencepost could create an
</span><span class="cx">           uncolorable graph.
</span><del>-        
</del><ins>+
</ins><span class="cx">         See https://bugs.webkit.org/show_bug.cgi?id=163548#c2 for a detailed discussion of how the
</span><span class="cx">         problem can arise.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This problem almost made me want to abandon our use of interference at instruction boundaries,
</span><span class="cx">         and introduce something more comprehensive, like interference at various stages of an
</span><span class="cx">         instruction's execution. The reason why I didn't do this is that this problem only arises in well
</span><span class="lines">@@ -4353,7 +4418,7 @@
</span><span class="cx">         padInterference() so the IR stays nice and compact. Those Nops get removed by any phase that does
</span><span class="cx">         DCE, which includes eliminateDeadCode(), allocateStack(), and reportUsedRegisters(). In practice
</span><span class="cx">         allocateStack() kills them.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This also finally refactors our passing of RegisterSet to pass it by value, since it's small
</span><span class="cx">         enough that we're not gaining anything by using references. On x86, RegisterSet ought to be
</span><span class="cx">         smaller than a pointer.
</span><span class="lines">@@ -4620,13 +4685,13 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163509
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Mark Lam.
</span><del>-        
</del><ins>+
</ins><span class="cx">         The worklist building function in IRC skips temporaries that have no degree. This doesn't appear
</span><span class="cx">         to be necessary. This has been there since the original IRC commit. It hasn't caused bugs because
</span><span class="cx">         ordinarily, the only way to have a tmp with no degree is to not have any mention of that tmp. But
</span><span class="cx">         while working on bug 163371, I hit a crazy corner case where a temporary would have no
</span><span class="cx">         interference edges (i.e. no degree). Here's how it happens:
</span><del>-        
</del><ins>+
</ins><span class="cx">         A spill tmp from a previous iteration of IRC may have no degree: imagine a tmp that is live
</span><span class="cx">         everywhere and interferes with everyone, but has one use like:
</span><span class="cx"> 
</span><span class="lines">@@ -4646,7 +4711,7 @@
</span><span class="cx"> 
</span><span class="cx">         Then, we might coalesce %someOtherTmp with %newTmp.  Once this happens, if we make the %newTmp be
</span><span class="cx">         the master, we're in deep trouble because %newTmp is not on any worklist.
</span><del>-        
</del><ins>+
</ins><span class="cx">         I don't know how to reproduce this except through the patch in bug 163371. Removing the two lines
</span><span class="cx">         of code that skipped no-degree tmps causes no regressions, and resolves the problem I was having.
</span><span class="cx"> 
</span><span class="lines">@@ -5030,21 +5095,21 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163343
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Mark Lam.
</span><del>-        
</del><ins>+
</ins><span class="cx">         When I first added the concept of NewGrey/OldGrey, I had the SlotVisitor store the old cell
</span><span class="cx">         state in itself, so that it could use it to decide what to do for reportExtraMemoryVisited().
</span><del>-        
</del><ins>+
</ins><span class="cx">         Then I changed it in a recent commit, because I wanted the freedom to have SlotVisitor visit
</span><span class="cx">         multiple objects in tandem. But I never ended up using this capability. Still, I liked the
</span><span class="cx">         new way better: instead of the SlotVisitor rembemering the state-before-blackening, we would
</span><span class="cx">         make the object's state reflect whether it was black for the first time or not. That seemed
</span><span class="cx">         convenient.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Unfortunately it's wrong. After we blacken the object, a concurrent barrier could instantly
</span><span class="cx">         grey it. Then we would forget that we are visiting this object for the first time.
</span><span class="cx">         Subsequent visits will think that they are not the first. So, we will fail to do the right
</span><span class="cx">         thing in reportExtraMemoryVisited().
</span><del>-        
</del><ins>+
</ins><span class="cx">         So, this reverts that change. This is a little more than just a revert, though. I've changed
</span><span class="cx">         the terminology a bit. For example, I got tired of reading Black and having to remind myself
</span><span class="cx">         that it really means that the object has begun being visited, instead of the more strict
</span><span class="lines">@@ -5051,7 +5116,7 @@
</span><span class="cx">         meaning that implies that it has already been visited. We want to say that it's Black or
</span><span class="cx">         currently being scanned. I'm going to adopt Siebert's term for this: Anthracite [1]. So, our
</span><span class="cx">         black CellState is now called AnthraciteOrBlack.
</span><del>-        
</del><ins>+
</ins><span class="cx">         [1] https://pdfs.semanticscholar.org/7ae4/633265aead1f8835cf7966e179d02c2c8a4b.pdf
</span><span class="cx"> 
</span><span class="cx">         * heap/CellState.h:
</span><span class="lines">@@ -5151,12 +5216,12 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163337
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Mark Lam.
</span><del>-        
</del><ins>+
</ins><span class="cx">         It turns out that HeapSnapshot was not down with revisiting. The concurrent GC is going to be
</span><span class="cx">         built around the idea that we can revisit objects many times. This means that any action that
</span><span class="cx">         should only take place once per object must check the object's state. This fixes the snapshot
</span><span class="cx">         code to do this.
</span><del>-        
</del><ins>+
</ins><span class="cx">         While writing this code, I realized that we're actually doing this check incorrectly, so I
</span><span class="cx">         filed bug 163343. That bug requires a race, so we aren't going to see it yet.
</span><span class="cx"> 
</span><span class="lines">@@ -5187,7 +5252,7 @@
</span><span class="cx"> 
</span><span class="cx">         (InjectedScript.prototype._describe):
</span><span class="cx">         Provide a friendlier name, &quot;Proxy&quot; instead of &quot;ProxyObject&quot;.
</span><del>-        
</del><ins>+
</ins><span class="cx">         (InjectedScript.RemoteObject):
</span><span class="cx">         When generating a preview for a Proxy object, generate it from the final target
</span><span class="cx">         and mark it as lossy so that the object can always be expanded to get the internal
</span><span class="lines">@@ -5226,7 +5291,7 @@
</span><span class="cx">         and we asserted that it matched a breakpoint location identified
</span><span class="cx">         by the parser. This could get out of sync, or nodes could forget to
</span><span class="cx">         emit debug hooks expected by the parser.
</span><del>-        
</del><ins>+
</ins><span class="cx">         With this change, we always check and emit a debug hook for any
</span><span class="cx">         node. The default behavior is for BytecodeGenerator::emitNode
</span><span class="cx">         to emit the debug hook when emitting the node itself. This covers
</span><span class="lines">@@ -5371,7 +5436,7 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163334
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Mark Lam.
</span><del>-        
</del><ins>+
</ins><span class="cx">         I guess that the idea of JITWriteBarrier was to make sure that if you slap some heap pointer
</span><span class="cx">         bits into machine code, then you better execute a barrier on the code block. But it's a
</span><span class="cx">         complicated piece of code, and I can never remember how it quite works. These days it looks
</span><span class="lines">@@ -5379,7 +5444,7 @@
</span><span class="cx">         not really necessary to have something like this, since our convention is that any pointer
</span><span class="cx">         stored in machine code must always be shadowed in the GC heap. I think that convention has
</span><span class="cx">         won by overwhelming majority, so we should finally remove JITWriteBarrier.
</span><del>-        
</del><ins>+
</ins><span class="cx">         A practical outcome of this change is that it makes it easier to implement DirectCall ICs,
</span><span class="cx">         which will have to store the callee in the CallLinkInfo but not in the machine code.
</span><span class="cx"> 
</span><span class="lines">@@ -5428,31 +5493,31 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162309
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoffrey Garen.
</span><del>-        
</del><ins>+
</ins><span class="cx">         It used to be that we would forget which objects are live the moment we started collection.
</span><span class="cx">         That's because the flip at the beginning clears all mark bits.
</span><del>-        
</del><ins>+
</ins><span class="cx">         But we already have a facility for tracking objects that are live-but-not-marked. It's called
</span><span class="cx">         newlyAllocated. So, instead of clearing mark bits, we want to just transfer them to
</span><span class="cx">         newlyAllocated. Then we want to clear all newlyAllocated after GC.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This implements such an approach, along with a versioning optimization for newlyAllocated.
</span><span class="cx">         Instead of walking the whole heap to clear newlyAllocated bits at the end of the GC, we bump
</span><span class="cx">         the newlyAllocatedVersion, which causes MarkedBlock to treat newlyAllocated as if it was
</span><span class="cx">         clear.
</span><del>-        
</del><ins>+
</ins><span class="cx">         We could have even avoided allocating newlyAllocated in most cases, since empirically most
</span><span class="cx">         blocks are either completely empty or completely full. An earlier version of this patch did
</span><span class="cx">         this, but it was not better than this patch. In fact, it seemed to actually be worse for PLT
</span><span class="cx">         and membuster.
</span><del>-        
</del><ins>+
</ins><span class="cx">         To validate this change, we now run the conservative scan after the beginMarking flip. And it
</span><span class="cx">         totally works!
</span><del>-        
</del><ins>+
</ins><span class="cx">         This is a huge step towards concurrent GC. It means that we ought to be able to run the
</span><span class="cx">         allocator while marking. Since we already separately made it possible to run the barrier
</span><span class="cx">         while marking, this means that we're pretty much ready for some serious concurrency action.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This appears to be perf-neutral and space-neutral.
</span><span class="cx"> 
</span><span class="cx">         * JavaScriptCore.xcodeproj/project.pbxproj:
</span><span class="lines">@@ -5609,7 +5674,7 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162749
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Yusuke Suzuki.
</span><del>-        
</del><ins>+
</ins><span class="cx">         We have a lot of defenses against emitting code that materializes huge contants. But if we do
</span><span class="cx">         end up with such code in the backend, it's better to convert those materializations into add
</span><span class="cx">         instructions by checking if other registers are known to contain nearby constants. That's
</span><span class="lines">@@ -5624,12 +5689,12 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163264
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Mark Lam.
</span><del>-        
</del><ins>+
</ins><span class="cx">         When writing the lea patch (r207039), I was very careful about how I convert a Shl into a
</span><span class="cx">         BaseIndex scale. But I forgot to check if the older code for creating BaseIndexes for
</span><span class="cx">         effectiveAddr() got this right. It turns out that the older code missed the &lt;&lt;32 corner
</span><span class="cx">         case.
</span><del>-        
</del><ins>+
</ins><span class="cx">         It's sad that the two paths can't share all of their code, but it's somewhat inevitable due
</span><span class="cx">         to how matching an address and matching a lea have to do very different things. Matching a
</span><span class="cx">         lea means creating an instruction that is distinct from other instructions to do multiple
</span><span class="lines">@@ -5639,7 +5704,7 @@
</span><span class="cx">         has to figure out Add(@value, $const) on its own. This change makes the situation slightly
</span><span class="cx">         more sane by adding a scaleForShl() helper that handles this weird case. It's based on the
</span><span class="cx">         new Shl handling from r207039, and exposes it as an API for effectiveAddr() to use.
</span><del>-        
</del><ins>+
</ins><span class="cx">         The testLoadBaseIndexShift32() used to crash. I don't think that this case affects JS
</span><span class="cx">         content, since &lt;&lt;32 is such a bizarre outlier. I don't think we even have a path along
</span><span class="cx">         which the FTL would emit a 64-bit &lt;&lt;32. It probably won't even affect WebAssembly since
</span><span class="lines">@@ -5690,9 +5755,9 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163234
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Saam Barati.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This adds comprehensive support for emitting lea on x86.
</span><del>-        
</del><ins>+
</ins><span class="cx">         When adding this, I found that it was useful to also finally add more reassociation. That
</span><span class="cx">         reduces the amount of patterns that the instruction selector has to deal with.
</span><span class="cx"> 
</span><span class="lines">@@ -5831,10 +5896,10 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163175
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Keith Miller.
</span><del>-        
</del><ins>+
</ins><span class="cx">         You can now call Procedure::pinRegister(), or Code::pinRegister(), and it will make this
</span><span class="cx">         register behave as follows:
</span><del>-        
</del><ins>+
</ins><span class="cx">         - B3 and Air will emit no code that modifies the value in this register, except if that
</span><span class="cx">           happens via a Patchpoint or stackmap constraint (i.e. the user explicitly asked for it).
</span><span class="cx">         - B3 and Air will allow others to modify the register. For example, if the register is not
</span><span class="lines">@@ -5845,17 +5910,17 @@
</span><span class="cx">           changing). For example, if we went back to having pinned tag registers, we would tell B3
</span><span class="cx">           to use them by (1) excluding them from any clobber set (easy, since they're callee save)
</span><span class="cx">           and (2) emitting ArgumentReg to grab their value. There's a test that does this.
</span><del>-        
-        This is accomplished by taking regsInPriorityOrder() and making it a method of Code. Air 
</del><ins>+
+        This is accomplished by taking regsInPriorityOrder() and making it a method of Code. Air
</ins><span class="cx">         already used this API when choosing registers in register allocation. Code now also vends a
</span><span class="cx">         mutableRegs() set, which is derived from regsInPriorityOrder(), that can quickly tell you if
</span><span class="cx">         a register can be mutated. Doing it this way means that most of this is a purely mechanical
</span><span class="cx">         change. The calls to mutableRegs() are the places where we had to change logic:
</span><del>-        
</del><ins>+
</ins><span class="cx">         - The register allocators needs to know that coalescing with a precolored pinned tmp is free.
</span><span class="cx">         - The callee-save handler needs to know that we're not supposed to save/restore pinned
</span><span class="cx">           registers.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Note that in this scheme, pinned registers are simply registers that do not appear in
</span><span class="cx">         regsInPriorityOrder(). This means, for example, that we will now say that FP is pinned. So,
</span><span class="cx">         this means that you can also pin registers by calling setRegsInPriorityOrder() and passing a
</span><span class="lines">@@ -5910,7 +5975,7 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=163172
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Keith Miller.
</span><del>-        
</del><ins>+
</ins><span class="cx">         If we have mutable pinned registers then we need to know which operations mutate them. At
</span><span class="cx">         first I considered making this into a heap range thing, but I think that this would be very
</span><span class="cx">         confusing. Also, in the future, we might want to make Effects track register sets of
</span><span class="lines">@@ -6911,7 +6976,7 @@
</span><span class="cx">         the instruction stream with NOPs to provide space for a jump.  This changes
</span><span class="cx">         Air::generate() to use labelIgnoringWatchpoints() to create pcToOriginMap
</span><span class="cx">         entries to eliminate unneccesary NOPs.
</span><del>-        
</del><ins>+
</ins><span class="cx">         * b3/air/AirGenerate.cpp:
</span><span class="cx">         (JSC::B3::Air::generate):
</span><span class="cx">         * b3/testb3.cpp:
</span><span class="lines">@@ -6945,7 +7010,7 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162845
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoffrey Garen.
</span><del>-        
</del><ins>+
</ins><span class="cx">         While writing some documentation, I found some small holes in the code.
</span><span class="cx"> 
</span><span class="cx">         * b3/B3Effects.cpp:
</span><span class="lines">@@ -7044,7 +7109,7 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162842
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Dan Bernstein.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This function has become dead code. This change removes it.
</span><span class="cx"> 
</span><span class="cx">         * heap/CellContainer.h:
</span><span class="lines">@@ -7099,16 +7164,16 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162689
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoffrey Garen.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This adds a traps flag to B3::Kind. It also makes B3::Kind work more like Air::Kind, in the
</span><span class="cx">         sense that it's a bag of distinct bits - it doesn't need to be a union unless we get enough
</span><span class="cx">         things that it would make a difference.
</span><del>-        
</del><ins>+
</ins><span class="cx">         The only analysis that needs to know about traps is effects. It now knows that traps implies
</span><span class="cx">         sideExits, which means that this turns off DCE. The only optimization that needs to know
</span><span class="cx">         about traps is eliminateCommonSubexpressions(), which needs to pessimize its store
</span><span class="cx">         elimination if the store traps.
</span><del>-        
</del><ins>+
</ins><span class="cx">         The hard part of this change is teaching the instruction selector to faithfully carry the
</span><span class="cx">         traps flag down to Air. I got this to work by making ArgPromise a non-copyable object that
</span><span class="cx">         knows whether you've used it in an instruction. It knows when you call consume(). If you do
</span><span class="lines">@@ -7116,10 +7181,10 @@
</span><span class="cx">         along with a few other hacks, means that all of the load-op and load-op-store fusions
</span><span class="cx">         correctly carry the trap bit: if any of the B3 loads or stores involved traps then you get
</span><span class="cx">         traps in Air.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This framework also sets us up to do bug 162688, since the ArgPromise::inst() hook is
</span><span class="cx">         powerful enough to allow wrapping the instruction with a Patch.
</span><del>-        
</del><ins>+
</ins><span class="cx">         I added some tests to testb3 that verify that optimizations are appropriately inhibited and
</span><span class="cx">         that the traps flag survives until the bitter end of Air.
</span><span class="cx"> 
</span><span class="lines">@@ -7190,19 +7255,19 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162764
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Saam Barati.
</span><del>-        
</del><ins>+
</ins><span class="cx">         There are some interesting cases where we can reduce the number of constant materializations if
</span><span class="cx">         we teach moveConstants() how to edit code. The two examples that this patch supports are:
</span><del>-        
</del><ins>+
</ins><span class="cx">             - Loads and stores from a constant pointer. Since loads and stores get an offset for free
</span><span class="cx">               and the instruction selector is really good at handling it, and since we can query Air to
</span><span class="cx">               see what kinds of offsets are legal, we can sometimes avoid using a constant pointer that
</span><span class="cx">               is specific to the absolute address of that load and instead pick some other constant
</span><span class="cx">               that is within offset distance of ours.
</span><del>-            
</del><ins>+
</ins><span class="cx">             - Add and Sub by a constant (x + c, x - c). Since x + c = x - -c and x - c = x + -c, we can
</span><span class="cx">               flip Add to Sub or vice versa if the negated constant is available.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This change makes moveConstants() pick the most dominant constant that works for an value. In
</span><span class="cx">         the case of memory accesses, it uses Air::Arg::isValidAddrForm() to work out what other
</span><span class="cx">         constants would work. In the case of Add/Sub, it simply looks for the negated constant. This
</span><span class="lines">@@ -7209,7 +7274,7 @@
</span><span class="cx">         should result in something like a minimal number of constants since these rules always pick the
</span><span class="cx">         most dominant constant that works - so if an Add's constant is already most dominant then
</span><span class="cx">         nothing changes, but if the negated one is more dominant then it becomes a Sub.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This is a 0.5% speed-up on LongSpider and neutral elsewhere. It's a speed-up because the
</span><span class="cx">         absolute address thing reduces the number of address materializations that we have to do, while
</span><span class="cx">         the add/sub thing prevents us from having to materialize 0x1000000000000 to box doubles.
</span><span class="lines">@@ -7505,18 +7570,18 @@
</span><span class="cx">         Ensure that once we have the Script that we always
</span><span class="cx">         resolve the breakpoint location before setting the
</span><span class="cx">         breakpoint. The different paths are:
</span><del>-        
</del><ins>+
</ins><span class="cx">         - setBreakpoint(scriptId, location)
</span><span class="cx">           - Here we know the SourceProvider by its SourceID
</span><span class="cx">             - resolve and set
</span><del>-        
</del><ins>+
</ins><span class="cx">         - setBreakpointByURL(url, location)
</span><span class="cx">           - Search for existing Scripts that match the URL
</span><span class="cx">             - resolve in each and set
</span><span class="cx">           - When new Scripts are parsed that match the URL
</span><span class="cx">             - resolve and set
</span><del>-            
</del><span class="cx"> 
</span><ins>+
</ins><span class="cx"> 2016-09-30  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Stepping out of a function finishes the line that called it.
</span><span class="lines">@@ -7654,7 +7719,7 @@
</span><span class="cx">         (JSC::Debugger::stepIntoStatement):
</span><span class="cx">         (JSC::Debugger::exception):
</span><span class="cx">         (JSC::Debugger::didReachBreakpoint):
</span><del>-        
</del><ins>+
</ins><span class="cx">         Use new variable names, and clarify if we should attempt
</span><span class="cx">         to pause or not.
</span><span class="cx"> 
</span><span class="lines">@@ -7666,7 +7731,7 @@
</span><span class="cx">         (JSC::Debugger::updateCallFrameInternal):
</span><span class="cx">         (JSC::Debugger::pauseIfNeeded):
</span><span class="cx">         Allow updateCallFrame to either attempt a pause or not.
</span><del>-        
</del><ins>+
</ins><span class="cx">         (JSC::Debugger::atStatement):
</span><span class="cx">         Attempt pause and reset the at first expression flag.
</span><span class="cx"> 
</span><span class="lines">@@ -7682,7 +7747,7 @@
</span><span class="cx">         Attempt pause when leaving a function.
</span><span class="cx">         If the user did a step-over and is leaving the
</span><span class="cx">         function, then behave like step-out.
</span><del>-        
</del><ins>+
</ins><span class="cx">         (JSC::Debugger::unwindEvent):
</span><span class="cx">         Behave like return except don't change any
</span><span class="cx">         pausing states. If we needed to pause the
</span><span class="lines">@@ -7701,7 +7766,7 @@
</span><span class="cx">         When the program doesn't have a parent, clear all
</span><span class="cx">         our state so we don't errantly pause on the next
</span><span class="cx">         JavaScript microtask that gets executed.
</span><del>-        
</del><ins>+
</ins><span class="cx">         (JSC::Debugger::clearNextPauseState):
</span><span class="cx">         Helper to clear all of the pause states now that
</span><span class="cx">         it happens in a couple places.
</span><span class="lines">@@ -7784,7 +7849,7 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162699
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Mark Lam.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This follows a similar change in B3 (r206595) and replaces Air::Opcode with Air::Kind,
</span><span class="cx">         which holds onto the opcode and some additional flags. Because Air is an orthogonal ISA
</span><span class="cx">         (the opcode tells you what the operation does but each operand is allowed to also contain
</span><span class="lines">@@ -7791,7 +7856,7 @@
</span><span class="cx">         effectively instructions for what to do to read or write that operand), the flags are
</span><span class="cx">         meant to be orthogonal to opcode. This allows us to say things like Add32&lt;Trap&gt;, which
</span><span class="cx">         makes sense if any of the operands to the Add32 are addresses.
</span><del>-        
</del><ins>+
</ins><span class="cx">         To demonstrate the flags facility this partly adds a trap flag to Air. B3 doesn't use it
</span><span class="cx">         yet, but I made sure that Air respects it. Basically that means blocking DCE when the flag
</span><span class="cx">         is set, by making it imply hasNonArgNonControlEffects.
</span><span class="lines">@@ -7875,10 +7940,10 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162721
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Keith Miller.
</span><del>-        
</del><ins>+
</ins><span class="cx">         The put_by_id-in-put_by_val optimization had the write barrier in the wrong place and
</span><span class="cx">         incorrectly filtered on value instead of base.
</span><del>-        
</del><ins>+
</ins><span class="cx">         No reduced test case. You really need to run Dromaeo/jslib to catch it. I love Dromaeo's
</span><span class="cx">         ability to catch GC bugs.
</span><span class="cx"> 
</span><span class="lines">@@ -7931,42 +7996,42 @@
</span><span class="cx">         Opcode was how you knew what subclass of Value you had. The opcode told you what the Value
</span><span class="cx">         actually did. This change replaces Opcode with Kind, which is a tuple of opcode and other
</span><span class="cx">         stuff.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Opcodes are great, and that's how most compilers work. But opcodes are one-dimensional. Here
</span><span class="cx">         is how this manifests. Say you have an opcode, like Load. You will be happy if your IR has
</span><span class="cx">         one Load opcode. But then, you might add Load8S/Load8Z/Load16S/Load16Z opcodes, as we have
</span><span class="cx">         done in B3. B3 has one dimension of Load opcodes, which determines something like the C type
</span><span class="cx">         of the load. But in the very near future, we will want to add two more dimensions to Loads:
</span><del>-        
</del><ins>+
</ins><span class="cx">         - A flag to say if the load traps.
</span><span class="cx">         - A flag to say if the load has acquire semantics.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Mapping these three dimensions (type, trap, acquire) onto the one-dimensional Opcode space
</span><span class="cx">         would create mayham: Load8S, Load8STrap, Load8SAcquire, Load8STrapAcquire, Load8Z,
</span><span class="cx">         Load8ZTrap, etc.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This happens in other parts of the IR. For example, we have a dimension of arithmetic
</span><span class="cx">         operations: add, sub, mul, div, mod, etc. Then we have the chill flag. But since opcodes
</span><span class="cx">         are one-dimensional, that means having ChillDiv and ChillMod, and tons of places in the
</span><span class="cx">         compiler that case on both Div and ChillDiv, or case on both Mod and ChillMod, since they
</span><span class="cx">         are only interested in the kind of arithmetic being done and not the chillness.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Though the examples all involve bits (chill or not, trapping or not, etc), I can imagine
</span><span class="cx">         other properties that behave more like small enums, like if we fill out more memory ordering
</span><span class="cx">         modes other than just &quot;acquire? yes/no&quot;. There will eventually have to be something like a
</span><span class="cx">         std::memory_order associated with memory accesses.
</span><del>-        
</del><ins>+
</ins><span class="cx">         One approach to this problem is to have a Value subclass that contains fields with the meta
</span><span class="cx">         data. I don't like this for two reasons:
</span><del>-        
</del><ins>+
</ins><span class="cx">         - In bug 162688, I want to make trapping memory accesses have stackmaps. This means that a
</span><span class="cx">           trapping memory access would have a different Value subclass than a non-trapping memory
</span><span class="cx">           access. So, this meta-data needs to channel into ValueType::accepts(). Currently that
</span><span class="cx">           takes Opcode and nothing else.
</span><del>-        
</del><ins>+
</ins><span class="cx">         - Compiler IRs are all about making common tasks easy. If it becomes commonplace for opcodes
</span><span class="cx">           to require a custom Value subclass just for a bit then that's not very easy.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This change addresses this problem by making the compiler pass around Kinds rather than
</span><span class="cx">         Opcodes. A Kind contains an Opcode as well as any number of opcode-specific bits. This
</span><span class="cx">         change demonstrates how Kind should be used by converting chillness to it. Kind has
</span><span class="lines">@@ -7975,10 +8040,10 @@
</span><span class="cx">         chill(Div). IR dumps will print it like this:
</span><span class="cx"> 
</span><span class="cx">             Int32 @38 = Div&lt;Chill&gt;(@36, @37, DFG:@24, ControlDependent)
</span><del>-        
</del><ins>+
</ins><span class="cx">         Where &quot;Div&lt;Chill&gt;&quot; is how a Kind that hasExtraBits() dumps itself. If a Kind does not
</span><span class="cx">         hasExtraBits() (the normal case) then it dumps like a normal Opcode (without the &quot;&lt;&gt;&quot;).
</span><del>-        
</del><ins>+
</ins><span class="cx">         I replaced many uses of Opcode with Kind. New code has to be mindful that Opcode may not be
</span><span class="cx">         the right way to summarize what a value does, and so in many cases it's better to carry
</span><span class="cx">         around a Kind instead - especially if you will use it to stamp out new Values. Opcode is no
</span><span class="lines">@@ -7986,7 +8051,7 @@
</span><span class="cx">         now wants a Kind instead of an Opcode. All Value constructors now take Kind instead of
</span><span class="cx">         Opcode. But most opcodes don't get any extra Kind bits, and so the code that operates on
</span><span class="cx">         those opcodes is largely unchanged.
</span><del>-        
</del><ins>+
</ins><span class="cx">         * CMakeLists.txt:
</span><span class="cx">         * JavaScriptCore.xcodeproj/project.pbxproj:
</span><span class="cx">         * b3/B3ArgumentRegValue.h:
</span><span class="lines">@@ -8113,29 +8178,29 @@
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162316
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Geoffrey Garen.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This makes our write barrier behave correctly when it races with the collector. The
</span><span class="cx">         collector wants to do this when visiting:
</span><del>-        
</del><ins>+
</ins><span class="cx">             object-&gt;cellState = black
</span><span class="cx">             visit(object)
</span><del>-        
</del><ins>+
</ins><span class="cx">         The mutator wants to do this when storing:
</span><del>-        
</del><ins>+
</ins><span class="cx">             object-&gt;property = newValue
</span><span class="cx">             if (object-&gt;cellState == black)
</span><span class="cx">                 remember(object)
</span><del>-        
</del><ins>+
</ins><span class="cx">         Prior to this change, this didn't work right because the compiler would sometimes place
</span><span class="cx">         barriers before the store to the property and because the mutator did not have adequate
</span><span class="cx">         fences.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Prior to this change, the DFG and FTL would emit this:
</span><del>-        
</del><ins>+
</ins><span class="cx">             if (object-&gt;cellState == black)
</span><span class="cx">                 remember(object)
</span><span class="cx">             object-&gt;property = newValue
</span><del>-        
</del><ins>+
</ins><span class="cx">         Which is wrong, because the object could start being scanned just after the cellState
</span><span class="cx">         check, at which point the store would be lost. We need to confirm that the state was not
</span><span class="cx">         black *after* the store! This change was harder than you'd expect: placing the barrier
</span><span class="lines">@@ -8146,7 +8211,7 @@
</span><span class="cx">         (because of the store-load fence) and it writes only cellState (because the B3 heap ranges
</span><span class="cx">         don't have any way to represent any of the GC's other state, which means that B3 does not
</span><span class="cx">         have to worry about aliasing with any of that).
</span><del>-        
</del><ins>+
</ins><span class="cx">         The collector already uses a store-load fence on x86 just after setting the cellState and
</span><span class="cx">         before visiting the object. The mutator needs to do the same. But we cannot put a
</span><span class="cx">         store-load fence of any kind before store barriers, because that causes enormous slow
</span><span class="lines">@@ -8155,10 +8220,10 @@
</span><span class="cx">         reasonable if the slow down only happened while the GC was running. Then, the concurrent GC
</span><span class="cx">         would lift throughput-while-collecting from 0% of peak to 85% of peak. This changes the
</span><span class="cx">         barrier so that it looks like this:
</span><del>-        
</del><ins>+
</ins><span class="cx">             if (object-&gt;cellState &lt;= heap.sneakyBlackThreshold)
</span><span class="cx">                 slowPath(object)
</span><del>-        
</del><ins>+
</ins><span class="cx">         Where sneakyBlackThreshold is the normal blackThreshold when we're not collecting, or a
</span><span class="cx">         tautoligical threshold (that makes everything look black) when we are collecting. This
</span><span class="cx">         turns out to not be any more expensive than the barrier in tip of tree when the GC is not
</span><span class="lines">@@ -8166,7 +8231,7 @@
</span><span class="cx">         concurrently yet. I still have more work to do.) The slowPath() does some extra work to
</span><span class="cx">         check if we are concurrently collecting; if so, it does a fence and rechecks if the object
</span><span class="cx">         really did need that barrier.
</span><del>-        
</del><ins>+
</ins><span class="cx">         This also reintroduces elimination of redundant store barriers, which was lost in the last
</span><span class="cx">         store barrier change. We can only do it when there is no possibility of GC, exit, or
</span><span class="cx">         exceptions between the two store barriers. We could remove the exit/exception limitation if
</span><span class="lines">@@ -8176,7 +8241,7 @@
</span><span class="cx">         same object. This same optimization also sometimes strength-reduces the store barrier so
</span><span class="cx">         that it uses a constant black threshold rather than the sneaky one, thereby saving one
</span><span class="cx">         load.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Even with all of those optimizations, I still had problems with barrier cost. I found that one
</span><span class="cx">         of the benchmarks that was being hit particularly hard was JetStream/regexp-2010. Fortunately
</span><span class="cx">         that benchmark does most of its barriers in a tight C++ loop in RegExpMatchesArray.h. When we
</span><span class="lines">@@ -8186,13 +8251,13 @@
</span><span class="cx">         optimization. The most efficient version of such an optimization that I could come up with was
</span><span class="cx">         to have a DeferralContext object that houses a boolean that is false by default, but the GC
</span><span class="cx">         writes true into it if it would have wanted to GC. You thread a pointer to the deferralContext
</span><del>-        through all of your allocations. This kind of mechanism has the overhead of a zero 
</del><ins>+        through all of your allocations. This kind of mechanism has the overhead of a zero
</ins><span class="cx">         initialization on the stack on entry and a zero check on exit. This is probably even efficient
</span><span class="cx">         enough that we could start thinking about having the DFG use it, for example if we found a
</span><span class="cx">         bounded-time section of code with a lot of barriers and entry/exit sites that aren't totally
</span><span class="cx">         wacky. This optimization took this patch from 0.68% JetStream regressed to neutral, according
</span><span class="cx">         to my latest data.
</span><del>-        
</del><ins>+
</ins><span class="cx">         Finally, an earlier version of this change put the store-load fence in B3 IR, so I ended up
</span><span class="cx">         adding FTLOutput support for it and AbstractHeapRepository magic for decorating the heaps.
</span><span class="cx">         I think we might as well keep that, it'll be useful.
</span><span class="lines">@@ -8568,7 +8633,7 @@
</span><span class="cx"> 
</span><span class="cx">         Make the subclass of CallSlowPathGenerator that takes arguments variadic
</span><span class="cx">         so it can take any number of arguments. Also updates the slowPathCall helper
</span><del>-        function to be variadic. I had to move the spill mode and exception check 
</del><ins>+        function to be variadic. I had to move the spill mode and exception check
</ins><span class="cx">         requirement parameters to before the arguments since the variadic arguments
</span><span class="cx">         must be at the end. As a convenience, I added an overload of slowPathCall that
</span><span class="cx">         doesn't take spill mode and exception check requirement parameters.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/DerivedSources.make (208237 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/DerivedSources.make        2016-11-01 20:38:39 UTC (rev 208237)
+++ trunk/Source/JavaScriptCore/DerivedSources.make        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -64,6 +64,7 @@
</span><span class="cx">     AirOpcode.h \
</span><span class="cx">     YarrCanonicalizeUnicode.cpp \
</span><span class="cx">     WasmOps.h \
</span><ins>+    WasmValidateInlines.h \
</ins><span class="cx"> #
</span><span class="cx"> 
</span><span class="cx"> # JavaScript builtins.
</span><span class="lines">@@ -301,6 +302,9 @@
</span><span class="cx"> WasmOps.h: $(JavaScriptCore)/wasm/generateWasmOpsHeader.py $(JavaScriptCore)/wasm/generateWasm.py $(JavaScriptCore)/wasm/wasm.json
</span><span class="cx">         $(PYTHON) $(JavaScriptCore)/wasm/generateWasmOpsHeader.py $(JavaScriptCore)/wasm/wasm.json ./WasmOps.h
</span><span class="cx"> 
</span><ins>+WasmValidateInlines.h: $(JavaScriptCore)/wasm/generateWasmValidateInlinesHeader.py $(JavaScriptCore)/wasm/generateWasm.py $(JavaScriptCore)/wasm/wasm.json
+        $(PYTHON) $(JavaScriptCore)/wasm/generateWasmValidateInlinesHeader.py $(JavaScriptCore)/wasm/wasm.json ./WasmValidateInlines.h
+
</ins><span class="cx"> # Dynamically-defined targets are listed below. Static targets belong up top.
</span><span class="cx"> 
</span><span class="cx"> all : \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (208237 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-11-01 20:38:39 UTC (rev 208237)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -1230,6 +1230,7 @@
</span><span class="cx">                 52C952B919A28A1C0069B386 /* TypeProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */; };
</span><span class="cx">                 531374BD1D5CE67600AF7A0B /* WasmPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WasmPlan.h */; };
</span><span class="cx">                 531374BF1D5CE95000AF7A0B /* WasmPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */; };
</span><ins>+                533B15DF1DC7F463004D500A /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; };
</ins><span class="cx">                 5341FC701DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5341FC6F1DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp */; };
</span><span class="cx">                 5341FC721DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */; };
</span><span class="cx">                 53486BB71C1795C300F6F3AF /* JSTypedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 53486BB61C1795C300F6F3AF /* JSTypedArray.h */; settings = {ATTRIBUTES = (Public, ); }; };
</span><span class="lines">@@ -1253,7 +1254,6 @@
</span><span class="cx">                 53F40E8B1D5901BB0099A1B6 /* WasmFunctionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */; };
</span><span class="cx">                 53F40E8D1D5901F20099A1B6 /* WasmParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8C1D5901F20099A1B6 /* WasmParser.h */; };
</span><span class="cx">                 53F40E8F1D5902820099A1B6 /* WasmB3IRGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F40E8E1D5902820099A1B6 /* WasmB3IRGenerator.cpp */; };
</span><del>-                53F40E911D5903020099A1B6 /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E901D5903020099A1B6 /* WasmOps.h */; };
</del><span class="cx">                 53F40E931D5A4AB30099A1B6 /* WasmB3IRGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E921D5A4AB30099A1B6 /* WasmB3IRGenerator.h */; };
</span><span class="cx">                 53F40E951D5A7AEF0099A1B6 /* WasmModuleParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */; };
</span><span class="cx">                 53F40E971D5A7BEC0099A1B6 /* WasmModuleParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */; };
</span><span class="lines">@@ -1262,7 +1262,9 @@
</span><span class="cx">                 53FA2AE31CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */; };
</span><span class="cx">                 53FD04D31D7AB277003287D3 /* WasmCallingConvention.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */; };
</span><span class="cx">                 53FD04D41D7AB291003287D3 /* WasmCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */; };
</span><del>-                5C4E8E961DBEBE620036F1FC /* JSONParseTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */; };
</del><ins>+                53FF7F991DBFCD9000A26CCC /* WasmValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */; };
+                53FF7F9B1DBFD2B900A26CCC /* WasmValidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */; };
+                53FF7F9D1DC00DB100A26CCC /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */; };
</ins><span class="cx">                 5B70CFDE1DB69E6600EC23F9 /* JSAsyncFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */; };
</span><span class="cx">                 5B70CFDF1DB69E6600EC23F9 /* JSAsyncFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */; };
</span><span class="cx">                 5B70CFE01DB69E6600EC23F9 /* AsyncFunctionPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFDA1DB69E5C00EC23F9 /* AsyncFunctionPrototype.h */; };
</span><span class="lines">@@ -1269,6 +1271,7 @@
</span><span class="cx">                 5B70CFE11DB69E6600EC23F9 /* AsyncFunctionPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B70CFDB1DB69E5C00EC23F9 /* AsyncFunctionPrototype.cpp */; };
</span><span class="cx">                 5B70CFE21DB69E6600EC23F9 /* AsyncFunctionConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFDC1DB69E5C00EC23F9 /* AsyncFunctionConstructor.h */; };
</span><span class="cx">                 5B70CFE31DB69E6600EC23F9 /* AsyncFunctionConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B70CFDD1DB69E5C00EC23F9 /* AsyncFunctionConstructor.cpp */; };
</span><ins>+                5C4E8E961DBEBE620036F1FC /* JSONParseTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */; };
</ins><span class="cx">                 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; };
</span><span class="cx">                 5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; };
</span><span class="cx">                 5DBB1525131D0BD70056AD36 /* minidom.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 1412110D0A48788700480255 /* minidom.js */; };
</span><span class="lines">@@ -3558,6 +3561,7 @@
</span><span class="cx">                 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeProfiler.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 531374BC1D5CE67600AF7A0B /* WasmPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmPlan.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmPlan.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                533B15DE1DC7F463004D500A /* WasmOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOps.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 5341FC6F1DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3WasmBoundsCheckValue.cpp; path = b3/B3WasmBoundsCheckValue.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3WasmBoundsCheckValue.h; path = b3/B3WasmBoundsCheckValue.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53486BB61C1795C300F6F3AF /* JSTypedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArray.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3585,7 +3589,6 @@
</span><span class="cx">                 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmFunctionParser.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53F40E8C1D5901F20099A1B6 /* WasmParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmParser.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53F40E8E1D5902820099A1B6 /* WasmB3IRGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmB3IRGenerator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                53F40E901D5903020099A1B6 /* WasmOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOps.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 53F40E921D5A4AB30099A1B6 /* WasmB3IRGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmB3IRGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmModuleParser.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmModuleParser.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3594,8 +3597,9 @@
</span><span class="cx">                 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmCallingConvention.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCallingConvention.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSONParseTest.cpp; path = API/tests/JSONParseTest.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
-                5C4E8E951DBEBDA20036F1FC /* JSONParseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSONParseTest.h; path = API/tests/JSONParseTest.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><ins>+                53FF7F981DBFCD9000A26CCC /* WasmValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmValidate.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmValidate.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFormat.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAsyncFunction.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAsyncFunction.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5B70CFDA1DB69E5C00EC23F9 /* AsyncFunctionPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncFunctionPrototype.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3603,6 +3607,8 @@
</span><span class="cx">                 5B70CFDC1DB69E5C00EC23F9 /* AsyncFunctionConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncFunctionConstructor.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5B70CFDD1DB69E5C00EC23F9 /* AsyncFunctionConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AsyncFunctionConstructor.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5B8243041DB7AA4900EA6384 /* AsyncFunctionPrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = AsyncFunctionPrototype.js; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSONParseTest.cpp; path = API/tests/JSONParseTest.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                5C4E8E951DBEBDA20036F1FC /* JSONParseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSONParseTest.h; path = API/tests/JSONParseTest.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = &quot;compiled.mach-o.dylib&quot;; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = &quot;&lt;absolute&gt;&quot;; };
</span><span class="cx">                 5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = JSC.xcconfig; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5DDDF44614FEE72200B4FB4D /* LLIntDesiredOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntDesiredOffsets.h; path = LLIntOffsets/LLIntDesiredOffsets.h; sourceTree = BUILT_PRODUCTS_DIR; };
</span><span class="lines">@@ -5845,6 +5851,7 @@
</span><span class="cx">                                 996B73131BD9FA2C00331B84 /* SymbolConstructor.lut.h */,
</span><span class="cx">                                 996B73141BD9FA2C00331B84 /* SymbolPrototype.lut.h */,
</span><span class="cx">                                 65A946141C8E9F6F00A7209A /* YarrCanonicalizeUnicode.cpp */,
</span><ins>+                                533B15DE1DC7F463004D500A /* WasmOps.h */,
</ins><span class="cx">                         );
</span><span class="cx">                         name = &quot;Derived Sources&quot;;
</span><span class="cx">                         path = DerivedSources/JavaScriptCore;
</span><span class="lines">@@ -5881,7 +5888,7 @@
</span><span class="cx">                                 53F40E921D5A4AB30099A1B6 /* WasmB3IRGenerator.h */,
</span><span class="cx">                                 53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */,
</span><span class="cx">                                 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */,
</span><del>-                                53F40E901D5903020099A1B6 /* WasmOps.h */,
</del><ins>+                                53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */,
</ins><span class="cx">                                 7BC547D21B69599B00959B58 /* WasmFormat.h */,
</span><span class="cx">                                 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */,
</span><span class="cx">                                 535557151D9DFA32006D583B /* WasmMemory.cpp */,
</span><span class="lines">@@ -5892,6 +5899,8 @@
</span><span class="cx">                                 531374BC1D5CE67600AF7A0B /* WasmPlan.h */,
</span><span class="cx">                                 53F40E8C1D5901F20099A1B6 /* WasmParser.h */,
</span><span class="cx">                                 53F40E841D58F9770099A1B6 /* WasmSections.h */,
</span><ins>+                                53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */,
+                                53FF7F981DBFCD9000A26CCC /* WasmValidate.h */,
</ins><span class="cx">                         );
</span><span class="cx">                         path = wasm;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="lines">@@ -7996,6 +8005,7 @@
</span><span class="cx">                                 0F2BDC491522809600CD8910 /* DFGVariableEvent.h in Headers */,
</span><span class="cx">                                 0F2BDC4B1522809D00CD8910 /* DFGVariableEventStream.h in Headers */,
</span><span class="cx">                                 0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */,
</span><ins>+                                53FF7F991DBFCD9000A26CCC /* WasmValidate.h in Headers */,
</ins><span class="cx">                                 0FC97F4218202119002C9B26 /* DFGWatchpointCollectionPhase.h in Headers */,
</span><span class="cx">                                 0FDB2CE8174830A2007B3C1B /* DFGWorklist.h in Headers */,
</span><span class="cx">                                 147341DA1DC0300100AA29BA /* WebAssemblyExecutable.h in Headers */,
</span><span class="lines">@@ -8399,7 +8409,6 @@
</span><span class="cx">                                 A7C0C4AC168103020017011D /* JSScriptRefPrivate.h in Headers */,
</span><span class="cx">                                 FE1220271BE7F58C0039E6F2 /* JITAddGenerator.h in Headers */,
</span><span class="cx">                                 0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */,
</span><del>-                                53F40E911D5903020099A1B6 /* WasmOps.h in Headers */,
</del><span class="cx">                                 A7299D9E17D12837005F5FF9 /* JSSet.h in Headers */,
</span><span class="cx">                                 A790DD70182F499700588807 /* JSSetIterator.h in Headers */,
</span><span class="cx">                                 BC18C45E0E16F5CD00B34460 /* CLoopStack.h in Headers */,
</span><span class="lines">@@ -8780,6 +8789,7 @@
</span><span class="cx">                                 14F7256614EE265E00B1652B /* WeakHandleOwner.h in Headers */,
</span><span class="cx">                                 14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */,
</span><span class="cx">                                 14BE7D3317135CF400D1807A /* WeakInlines.h in Headers */,
</span><ins>+                                533B15DF1DC7F463004D500A /* WasmOps.h in Headers */,
</ins><span class="cx">                                 A7CA3AE417DA41AE006538AF /* WeakMapConstructor.h in Headers */,
</span><span class="cx">                                 A7CA3AEC17DA5168006538AF /* WeakMapData.h in Headers */,
</span><span class="cx">                                 A7CA3AE617DA41AE006538AF /* WeakMapPrototype.h in Headers */,
</span><span class="lines">@@ -9941,6 +9951,7 @@
</span><span class="cx">                                 0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */,
</span><span class="cx">                                 A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */,
</span><span class="cx">                                 A5A1A0951D8CB341004C2EB8 /* DebuggerParseData.cpp in Sources */,
</span><ins>+                                53FF7F9D1DC00DB100A26CCC /* WasmFormat.cpp in Sources */,
</ins><span class="cx">                                 FE3913541B794F6E00EDAF71 /* LiveObjectList.cpp in Sources */,
</span><span class="cx">                                 FE20CE9D15F04A9500DF3430 /* LLIntCLoop.cpp in Sources */,
</span><span class="cx">                                 0F4680D214BBD16500BFE272 /* LLIntData.cpp in Sources */,
</span><span class="lines">@@ -10099,6 +10110,7 @@
</span><span class="cx">                                 14469DEB107EC7E700650446 /* StringConstructor.cpp in Sources */,
</span><span class="cx">                                 70EC0EC61AA0D7DA00B6AAFA /* StringIteratorPrototype.cpp in Sources */,
</span><span class="cx">                                 14469DEC107EC7E700650446 /* StringObject.cpp in Sources */,
</span><ins>+                                53FF7F9B1DBFD2B900A26CCC /* WasmValidate.cpp in Sources */,
</ins><span class="cx">                                 14469DED107EC7E700650446 /* StringPrototype.cpp in Sources */,
</span><span class="cx">                                 9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */,
</span><span class="cx">                                 BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestWasmcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/testWasm.cpp (208237 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/testWasm.cpp        2016-11-01 20:38:39 UTC (rev 208237)
+++ trunk/Source/JavaScriptCore/testWasm.cpp        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -269,6 +269,27 @@
</span><span class="cx">     return box(bitwise_cast&lt;uint64_t&gt;(value));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void checkPlan(Plan&amp; plan, unsigned expectedNumberOfFunctions)
+{
+    if (plan.failed()) {
+        dataLogLn(&quot;Module failed to compile with error: &quot;, plan.errorMessage());
+        CRASH();
+    }
+
+    if (plan.resultSize() != expectedNumberOfFunctions) {
+        dataLogLn(&quot;Incorrect number of functions&quot;);
+        CRASH();
+    }
+
+    for (unsigned i = 0; i &lt; expectedNumberOfFunctions; ++i) {
+        if (!plan.result(i)) {
+            dataLogLn(&quot;Function at index, &quot; , i, &quot; failed to compile correctly&quot;);
+            CRASH();
+        }
+    }
+
+}
+
</ins><span class="cx"> // For now we inline the test files.
</span><span class="cx"> static void runWasmTests()
</span><span class="cx"> {
</span><span class="lines">@@ -290,10 +311,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 2);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK(isIdentical(invoke&lt;float&gt;(*plan.result(1)-&gt;jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
</span><span class="lines">@@ -319,10 +337,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 2);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK(isIdentical(invoke&lt;float&gt;(*plan.result(1)-&gt;jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
</span><span class="lines">@@ -353,10 +368,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 2);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(1)-&gt;jsEntryPoint, { box(0) }), 0);
</span><span class="lines">@@ -387,10 +399,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0) }), 1);
</span><span class="lines">@@ -447,10 +456,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 2);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(1)-&gt;jsEntryPoint, { box(0) }), 0);
</span><span class="lines">@@ -463,27 +469,23 @@
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="cx">         // Generated from:
</span><del>-        // (module
-        //  (memory 1)
-        //  (func (export &quot;i32_load8_s&quot;) (param $i i32) (param $ptr i32) (result i32)
-        //   (i64.store (get_local $ptr) (get_local $i))
-        //   (return (i64.load (get_local $ptr)))
-        //   )
-        //  )
</del><ins>+        //    (module
+        //     (memory 1)
+        //     (func (export &quot;i64&quot;) (param $i i64) (param $ptr i32) (result i64)
+        //      (i64.store (get_local $ptr) (get_local $i))
+        //      (return (i64.load (get_local $ptr)))
+        //      )
+        //     )
</ins><span class="cx">         Vector&lt;uint8_t&gt; vector = {
</span><span class="cx">             0x00, 0x61, 0x73, 0x6d, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x40,
</span><span class="cx">             0x02, 0x02, 0x01, 0x01, 0x02, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x05, 0x83, 0x80,
</span><del>-            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0b, 0x69, 0x33,
-            0x32, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x38, 0x5f, 0x73, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80,
-            0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00, 0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14,
-            0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f
</del><ins>+            0x80, 0x80, 0x00, 0x01, 0x01, 0x01, 0x07, 0x87, 0x80, 0x80, 0x80, 0x00, 0x01, 0x03, 0x69, 0x36,
+            0x34, 0x00, 0x00, 0x0a, 0x95, 0x80, 0x80, 0x80, 0x00, 0x01, 0x8f, 0x80, 0x80, 0x80, 0x00, 0x00,
+            0x14, 0x01, 0x14, 0x00, 0x34, 0x03, 0x00, 0x14, 0x01, 0x2b, 0x03, 0x00, 0x09, 0x0f
</ins><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0), box(10) }), 0);
</span><span class="lines">@@ -510,10 +512,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0), box(10) }), 0);
</span><span class="lines">@@ -550,10 +549,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx">         ASSERT(plan.memory()-&gt;size());
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="lines">@@ -605,10 +601,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx">         ASSERT(plan.memory()-&gt;size());
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="lines">@@ -649,10 +642,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx">         ASSERT(plan.memory()-&gt;size());
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="lines">@@ -680,10 +670,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0) }), 0);
</span><span class="lines">@@ -710,10 +697,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0), box(10) }), 0);
</span><span class="lines">@@ -741,10 +725,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0), box(10) }), 0);
</span><span class="lines">@@ -781,10 +762,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx">         ASSERT(plan.memory()-&gt;size());
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="lines">@@ -836,10 +814,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx">         ASSERT(plan.memory()-&gt;size());
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="lines">@@ -880,10 +855,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx">         ASSERT(plan.memory()-&gt;size());
</span><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="lines">@@ -911,10 +883,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0) }), 0);
</span><span class="lines">@@ -941,10 +910,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0), box(1) }), 1);
</span><span class="lines">@@ -982,10 +948,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0), box(1) }), 1);
</span><span class="lines">@@ -1009,10 +972,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { }), 5);
</span><span class="lines">@@ -1030,10 +990,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { }), 11);
</span><span class="lines">@@ -1050,10 +1007,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { }), 11);
</span><span class="lines">@@ -1070,10 +1024,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { }), 11);
</span><span class="lines">@@ -1089,10 +1040,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0), box(1) }), 1);
</span><span class="lines">@@ -1118,10 +1066,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0) }), 0);
</span><span class="lines">@@ -1154,10 +1099,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0) }), 0);
</span><span class="lines">@@ -1198,10 +1140,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0), box(1) }), 0);
</span><span class="lines">@@ -1251,10 +1190,7 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Plan plan(*vm, vector);
</span><del>-        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
-            dataLogLn(&quot;Module failed to compile correctly.&quot;);
-            CRASH();
-        }
</del><ins>+        checkPlan(plan, 1);
</ins><span class="cx"> 
</span><span class="cx">         // Test this doesn't crash.
</span><span class="cx">         CHECK_EQ(invoke&lt;int&gt;(*plan.result(0)-&gt;jsEntryPoint, { box(0), box(1) }), 1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (208237 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-11-01 20:38:39 UTC (rev 208237)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -87,6 +87,10 @@
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        LazyBlock()
+        {
+        }
+
</ins><span class="cx">         explicit operator bool() const { return !!m_block; }
</span><span class="cx"> 
</span><span class="cx">         BasicBlock* get(Procedure&amp; proc)
</span><span class="lines">@@ -118,6 +122,10 @@
</span><span class="cx">                 result.append(proc.addVariable(toB3Type(signature)));
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        ControlData()
+        {
+        }
+
</ins><span class="cx">         void dump(PrintStream&amp; out) const
</span><span class="cx">         {
</span><span class="cx">             switch (type()) {
</span><span class="lines">@@ -172,8 +180,8 @@
</span><span class="cx"> 
</span><span class="cx">     B3IRGenerator(Memory*, Procedure&amp;, Vector&lt;UnlinkedCall&gt;&amp; unlinkedCalls);
</span><span class="cx"> 
</span><del>-    void addArguments(const Vector&lt;Type&gt;&amp;);
-    void addLocal(Type, uint32_t);
</del><ins>+    bool WARN_UNUSED_RETURN addArguments(const Vector&lt;Type&gt;&amp;);
+    bool WARN_UNUSED_RETURN addLocal(Type, uint32_t);
</ins><span class="cx">     ExpressionType addConstant(Type, uint64_t);
</span><span class="cx"> 
</span><span class="cx">     // Locals
</span><span class="lines">@@ -191,8 +199,8 @@
</span><span class="cx">     // Control flow
</span><span class="cx">     ControlData WARN_UNUSED_RETURN addBlock(Type signature);
</span><span class="cx">     ControlData WARN_UNUSED_RETURN addLoop(Type signature);
</span><del>-    ControlData WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature);
-    bool WARN_UNUSED_RETURN addElse(ControlData&amp;);
</del><ins>+    bool WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature, ControlData&amp; result);
+    bool WARN_UNUSED_RETURN addElse(ControlData&amp;, const ExpressionList&amp;);
</ins><span class="cx"> 
</span><span class="cx">     bool WARN_UNUSED_RETURN addReturn(const ExpressionList&amp; returnValues);
</span><span class="cx">     bool WARN_UNUSED_RETURN addBranch(ControlData&amp;, ExpressionType condition, const ExpressionList&amp; returnValues);
</span><span class="lines">@@ -245,16 +253,22 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void B3IRGenerator::addLocal(Type type, uint32_t count)
</del><ins>+bool B3IRGenerator::addLocal(Type type, uint32_t count)
</ins><span class="cx"> {
</span><del>-    m_locals.reserveCapacity(m_locals.size() + count);
</del><ins>+    if (!m_locals.tryReserveCapacity(m_locals.size() + count))
+        return false;
+
</ins><span class="cx">     for (uint32_t i = 0; i &lt; count; ++i)
</span><del>-        m_locals.append(m_proc.addVariable(toB3Type(type)));
</del><ins>+        m_locals.uncheckedAppend(m_proc.addVariable(toB3Type(type)));
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void B3IRGenerator::addArguments(const Vector&lt;Type&gt;&amp; types)
</del><ins>+bool B3IRGenerator::addArguments(const Vector&lt;Type&gt;&amp; types)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!m_locals.size());
</span><ins>+    if (!m_locals.tryReserveCapacity(types.size()))
+        return false;
+
</ins><span class="cx">     m_locals.grow(types.size());
</span><span class="cx">     wasmCallingConvention().loadArguments(types, m_proc, m_currentBlock, Origin(),
</span><span class="cx">         [&amp;] (ExpressionType argument, unsigned i) {
</span><span class="lines">@@ -262,6 +276,7 @@
</span><span class="cx">             m_locals[i] = argumentVariable;
</span><span class="cx">             m_currentBlock-&gt;appendNew&lt;VariableValue&gt;(m_proc, Set, Origin(), argumentVariable, argument);
</span><span class="cx">         });
</span><ins>+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool B3IRGenerator::getLocal(uint32_t index, ExpressionType&amp; result)
</span><span class="lines">@@ -493,7 +508,7 @@
</span><span class="cx">     return ControlData(m_proc, signature, body);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-B3IRGenerator::ControlData B3IRGenerator::addIf(ExpressionType condition, Type signature)
</del><ins>+bool B3IRGenerator::addIf(ExpressionType condition, Type signature, ControlType&amp; result)
</ins><span class="cx"> {
</span><span class="cx">     // FIXME: This needs to do some kind of stack passing.
</span><span class="cx"> 
</span><span class="lines">@@ -507,10 +522,11 @@
</span><span class="cx">     notTaken-&gt;addPredecessor(m_currentBlock);
</span><span class="cx"> 
</span><span class="cx">     m_currentBlock = taken;
</span><del>-    return ControlData(m_proc, signature, notTaken, continuation);
</del><ins>+    result = ControlData(m_proc, signature, notTaken, continuation);
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool B3IRGenerator::addElse(ControlData&amp; data)
</del><ins>+bool B3IRGenerator::addElse(ControlData&amp; data, const ExpressionList&amp;)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(data.continuation);
</span><span class="cx">     m_currentBlock = data.special;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormatcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp (0 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;WasmFormat.h&quot;
+
+#if ENABLE(WEBASSEMBLY)
+
+namespace JSC { namespace Wasm {
+
+const char* toString(Type type)
+{
+    switch (type) {
+    case Void:
+        return &quot;void&quot;;
+    case I32:
+        return &quot;i32&quot;;
+    case I64:
+        return &quot;i64&quot;;
+    case F32:
+        return &quot;f32&quot;;
+    case F64:
+        return &quot;f64&quot;;
+    }
+}
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(B3_JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (208237 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-11-01 20:38:39 UTC (rev 208237)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -97,6 +97,7 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+const char* toString(Type);
</ins><span class="cx"> 
</span><span class="cx"> struct Signature {
</span><span class="cx">     Type returnType;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h (208237 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-11-01 20:38:39 UTC (rev 208237)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -73,12 +73,14 @@
</span><span class="cx"> {
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLogLn(&quot;Parsing function starting at: &quot;, (uintptr_t)functionStart, &quot; of length: &quot;, functionLength);
</span><del>-    m_context.addArguments(m_signature-&gt;arguments);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Context&gt;
</span><span class="cx"> bool FunctionParser&lt;Context&gt;::parse()
</span><span class="cx"> {
</span><ins>+    if (!m_context.addArguments(m_signature-&gt;arguments))
+        return false;
+
</ins><span class="cx">     uint32_t localCount;
</span><span class="cx">     if (!parseVarUInt32(localCount))
</span><span class="cx">         return false;
</span><span class="lines">@@ -92,7 +94,8 @@
</span><span class="cx">         if (!parseValueType(typeOfLocal))
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        m_context.addLocal(typeOfLocal, numberOfLocals);
</del><ins>+        if (!m_context.addLocal(typeOfLocal, numberOfLocals))
+            return false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return parseBlock();
</span><span class="lines">@@ -282,12 +285,16 @@
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         ExpressionType condition = m_expressionStack.takeLast();
</span><del>-        m_controlStack.append(m_context.addIf(condition, inlineSignature));
</del><ins>+        ControlType control;
+        if (!m_context.addIf(condition, inlineSignature, control))
+            return false;
+
+        m_controlStack.append(control);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case OpType::Else: {
</span><del>-        return m_context.addElse(m_controlStack.last());
</del><ins>+        return m_context.addElse(m_controlStack.last(), m_expressionStack);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case OpType::Br:
</span><span class="lines">@@ -349,7 +356,7 @@
</span><span class="cx">         ControlType&amp; data = m_controlStack.last();
</span><span class="cx">         ASSERT(data.type() == BlockType::If);
</span><span class="cx">         m_unreachableBlocks = 0;
</span><del>-        return m_context.addElse(data);
</del><ins>+        return m_context.addElse(data, m_expressionStack);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case OpType::End: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp (208237 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2016-11-01 20:38:39 UTC (rev 208237)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;WasmB3IRGenerator.h&quot;
</span><span class="cx"> #include &quot;WasmCallingConvention.h&quot;
</span><span class="cx"> #include &quot;WasmModuleParser.h&quot;
</span><ins>+#include &quot;WasmValidate.h&quot;
</ins><span class="cx"> #include &lt;wtf/DataLog.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="lines">@@ -63,6 +64,13 @@
</span><span class="cx">         const uint8_t* functionStart = source + info.start;
</span><span class="cx">         size_t functionLength = info.end - info.start;
</span><span class="cx">         ASSERT(functionLength &lt;= sourceLength);
</span><ins>+
+        String error = validateFunction(functionStart, functionLength, info.signature, moduleParser.functionInformation());
+        if (!error.isNull()) {
+            m_errorMessage = error;
+            return;
+        }
+
</ins><span class="cx">         m_result.append(parseAndCompile(vm, functionStart, functionLength, moduleParser.memory().get(), info.signature, moduleParser.functionInformation()));
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidatecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp (0 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -0,0 +1,311 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;WasmValidate.h&quot;
+
+#if ENABLE(WEBASSEMBLY)
+
+#include &quot;WasmFunctionParser.h&quot;
+#include &lt;wtf/text/StringBuilder.h&gt;
+
+namespace JSC { namespace Wasm {
+
+class Validate {
+public:
+    class ControlData {
+    public:
+        ControlData(BlockType type, Type signature)
+            : m_blockType(type)
+            , m_signature(signature)
+        {
+        }
+
+        ControlData()
+        {
+        }
+
+        void dump(PrintStream&amp; out) const
+        {
+            switch (type()) {
+            case BlockType::If:
+                out.print(&quot;If:    &quot;);
+                break;
+            case BlockType::Block:
+                out.print(&quot;Block: &quot;);
+                break;
+            case BlockType::Loop:
+                out.print(&quot;Loop:  &quot;);
+                break;
+            }
+        }
+
+        BlockType type() const { return m_blockType; }
+        Type signature() const { return m_signature; }
+    private:
+        BlockType m_blockType;
+        Type m_signature;
+    };
+    typedef Type ExpressionType;
+    typedef ControlData ControlType;
+    typedef Vector&lt;ExpressionType, 1&gt; ExpressionList;
+    static const ExpressionType emptyExpression = Void;
+
+    bool WARN_UNUSED_RETURN addArguments(const Vector&lt;Type&gt;&amp;);
+    bool WARN_UNUSED_RETURN addLocal(Type, uint32_t);
+    ExpressionType addConstant(Type type, uint64_t) { return type; }
+
+    // Locals
+    bool WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType&amp; result);
+    bool WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
+
+    // Memory
+    bool WARN_UNUSED_RETURN load(LoadOpType, ExpressionType pointer, ExpressionType&amp; result, uint32_t offset);
+    bool WARN_UNUSED_RETURN store(StoreOpType, ExpressionType pointer, ExpressionType value, uint32_t offset);
+
+    // Basic operators
+    bool WARN_UNUSED_RETURN binaryOp(BinaryOpType, ExpressionType left, ExpressionType right, ExpressionType&amp; result);
+    bool WARN_UNUSED_RETURN unaryOp(UnaryOpType, ExpressionType arg, ExpressionType&amp; result);
+
+    // Control flow
+    ControlData WARN_UNUSED_RETURN addBlock(Type signature);
+    ControlData WARN_UNUSED_RETURN addLoop(Type signature);
+    bool WARN_UNUSED_RETURN addIf(ExpressionType condition, Type signature, ControlData&amp; result);
+    bool WARN_UNUSED_RETURN addElse(ControlData&amp;, const ExpressionList&amp;);
+
+    bool WARN_UNUSED_RETURN addReturn(const ExpressionList&amp; returnValues);
+    bool WARN_UNUSED_RETURN addBranch(ControlData&amp;, ExpressionType condition, const ExpressionList&amp; returnValues);
+    bool WARN_UNUSED_RETURN endBlock(ControlData&amp;, ExpressionList&amp; expressionStack);
+
+    bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const FunctionInformation&amp;, const Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result);
+    bool WARN_UNUSED_RETURN isContinuationReachable(ControlData&amp;) { return true; }
+
+    void dump(const Vector&lt;ControlType&gt;&amp; controlStack, const ExpressionList&amp; expressionStack);
+
+    String errorMessage() const { return m_errorMessage; }
+    Validate(ExpressionType returnType)
+        : m_returnType(returnType)
+    {
+    }
+
+private:
+    bool unify(Type, Type);
+    bool unify(const ExpressionList&amp;, const ControlData&amp;);
+
+    ExpressionType m_returnType;
+    Vector&lt;Type&gt; m_locals;
+    String m_errorMessage;
+};
+
+bool Validate::addArguments(const Vector&lt;Type&gt;&amp; args)
+{
+    for (Type arg : args) {
+        if (!addLocal(arg, 1))
+            return false;
+    }
+    return true;
+}
+
+bool Validate::addLocal(Type type, uint32_t count)
+{
+    if (!m_locals.tryReserveCapacity(m_locals.size() + count))
+        return false;
+
+    for (uint32_t i = 0; i &lt; count; ++i)
+        m_locals.uncheckedAppend(type);
+    return true;
+}
+
+bool Validate::getLocal(uint32_t index, ExpressionType&amp; result)
+{
+    if (index &lt; m_locals.size()) {
+        result = m_locals[index];
+        return true;
+    }
+    m_errorMessage = ASCIILiteral(&quot;Attempt to use unknown local.&quot;);
+    return false;
+}
+
+bool Validate::setLocal(uint32_t index, ExpressionType value)
+{
+    ExpressionType localType;
+    if (!getLocal(index, localType))
+        return false;
+
+    if (localType == value)
+        return true;
+
+    m_errorMessage = makeString(&quot;Attempt to set local with type: &quot;, toString(localType), &quot; with a variable of type: &quot;, toString(value));
+    return false;
+}
+
+Validate::ControlType Validate::addBlock(Type signature)
+{
+    return ControlData(BlockType::Block, signature);
+}
+
+Validate::ControlType Validate::addLoop(Type signature)
+{
+    return ControlData(BlockType::Loop, signature);
+}
+
+bool Validate::addIf(ExpressionType condition, Type signature, ControlType&amp; result)
+{
+    if (condition != I32) {
+        m_errorMessage = makeString(&quot;Attempting to use &quot;, toString(condition), &quot; as the condition for an if block&quot;);
+        return false;
+    }
+    result = ControlData(BlockType::If, signature);
+    return true;
+}
+
+bool Validate::addElse(ControlType&amp; current, const ExpressionList&amp; values)
+{
+    if (current.type() != BlockType::If) {
+        m_errorMessage = makeString(&quot;Attempting to add else block to something other than an if&quot;);
+        return false;
+    }
+
+    if (!unify(values, current)) {
+        ASSERT(errorMessage());
+        return false;
+    }
+
+    current = ControlData(BlockType::Block, current.signature());
+    return true;
+}
+
+bool Validate::addReturn(const ExpressionList&amp; returnValues)
+{
+    if (m_returnType == Void)
+        return true;
+    ASSERT(returnValues.size() == 1);
+
+    if (m_returnType == returnValues[0])
+        return true;
+
+    m_errorMessage = makeString(&quot;Attempting to add return with type: &quot;, toString(returnValues[0]), &quot; but function expects return with type: &quot;, toString(m_returnType));
+    return false;
+}
+
+bool Validate::addBranch(ControlType&amp; target, ExpressionType condition, const ExpressionList&amp; stack)
+{
+    // Void means this is not a conditional branch.
+    if (condition != Void &amp;&amp; condition != I32) {
+        m_errorMessage = makeString(&quot;Attempting to add a conditional branch with condition type: &quot;, toString(condition), &quot; but expected i32.&quot;);
+        return false;
+    }
+
+    if (target.type() == BlockType::If)
+        return true;
+
+    if (target.signature() == Void)
+        return true;
+
+    ASSERT(stack.size() == 1);
+    if (target.signature() == stack[0])
+        return true;
+
+    m_errorMessage = makeString(&quot;Attempting to branch to block with expected type: &quot;, toString(target.signature()), &quot; but branching with type: &quot;, toString(target.signature()));
+    return false;
+}
+
+bool Validate::endBlock(ControlType&amp; block, ExpressionList&amp; stack)
+{
+    if (block.signature() == Void)
+        return true;
+
+
+    ASSERT(stack.size() == 1);
+    if (block.signature() == stack[0])
+        return true;
+
+    m_errorMessage = makeString(&quot;Block fallthrough has expected type: &quot;, toString(block.signature()), &quot; but produced type: &quot;, toString(block.signature()));
+    return false;
+}
+
+bool Validate::addCall(unsigned, const FunctionInformation&amp; info, const Vector&lt;ExpressionType&gt;&amp; args, ExpressionType&amp; result)
+{
+    if (info.signature-&gt;arguments.size() != args.size()) {
+        StringBuilder builder;
+        builder.append(&quot;Arity mismatch in call, expected: &quot;);
+        builder.appendNumber(info.signature-&gt;arguments.size());
+        builder.append(&quot; but got: &quot;);
+        builder.appendNumber(args.size());
+        m_errorMessage = builder.toString();
+        return false;
+    }
+
+    for (unsigned i = 0; i &lt; args.size(); ++i) {
+        if (args[i] != info.signature-&gt;arguments[i]) {
+            m_errorMessage = makeString(&quot;Expected argument type: &quot;, toString(info.signature-&gt;arguments[i]), &quot; does not match passed argument type: &quot;, toString(args[i]));
+            return false;
+        }
+    }
+
+    result = info.signature-&gt;returnType;
+    return true;
+}
+
+bool Validate::unify(const ExpressionList&amp; values, const ControlType&amp; block)
+{
+    ASSERT(values.size() &lt;= 1);
+    if (block.signature() == Void)
+        return true;
+
+    if (!values.size()) {
+        m_errorMessage = makeString(&quot;Block has non-void signature but has no stack entries on exit&quot;);
+        return false;
+    }
+
+    if (values[0] == block.signature())
+        return true;
+
+    m_errorMessage = makeString(&quot;Expected control flow to return value with type: &quot;, toString(block.signature()), &quot; but got value with type: &quot;, toString(values[0]));
+    return false;
+}
+
+void Validate::dump(const Vector&lt;ControlType&gt;&amp;, const ExpressionList&amp;)
+{
+    dataLogLn(&quot;Validating&quot;);
+}
+
+String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const Vector&lt;FunctionInformation&gt;&amp; functions)
+{
+    Validate context(signature-&gt;returnType);
+    FunctionParser&lt;Validate&gt; validator(context, source, length, signature, functions);
+    if (!validator.parse()) {
+        // FIXME: add better location information here. see: https://bugs.webkit.org/show_bug.cgi?id=164288
+        return context.errorMessage();
+    }
+
+    return String();
+}
+
+} } // namespace JSC::Wasm
+
+#include &quot;WasmValidateInlines.h&quot;
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidateh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/WasmValidate.h (0 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.h        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBASSEMBLY)
+
+#include &quot;WasmFormat.h&quot;
+
+namespace JSC { namespace Wasm {
+
+String validateFunction(const uint8_t*, size_t, const Signature*, const Vector&lt;FunctionInformation&gt;&amp;);
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmgenerateWasmValidateInlinesHeaderpy"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/generateWasmValidateInlinesHeader.py (0 => 208238)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/generateWasmValidateInlinesHeader.py                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/generateWasmValidateInlinesHeader.py        2016-11-01 20:40:40 UTC (rev 208238)
</span><span class="lines">@@ -0,0 +1,174 @@
</span><ins>+#!/usr/bin/env python
+
+# Copyright (C) 2016 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This tool has a couple of helpful macros to process Wasm files from the wasm.json.
+
+from generateWasm import *
+import optparse
+import sys
+
+parser = optparse.OptionParser(usage=&quot;usage: %prog &lt;wasm.json&gt; &lt;WasmOps.h&gt;&quot;)
+(options, args) = parser.parse_args(sys.argv[0:])
+if len(args) != 3:
+    parser.error(parser.usage)
+
+wasm = Wasm(args[0], args[1])
+opcodes = wasm.opcodes
+wasmValidateInlinesHFile = open(args[2], &quot;w&quot;)
+
+
+def cppType(name):
+    result = {
+        &quot;bool&quot;: &quot;I32&quot;,
+        &quot;addr&quot;: &quot;I32&quot;,
+        &quot;i32&quot;: &quot;I32&quot;,
+        &quot;i64&quot;: &quot;I64&quot;,
+        &quot;f32&quot;: &quot;F32&quot;,
+        &quot;f64&quot;: &quot;F64&quot;,
+    }.get(name, None)
+    if result == None:
+        raise ValueError(&quot;Unknown type name: &quot; + name)
+    return result
+
+
+def toCpp(name):
+    return wasm.toCpp(name)
+
+
+def unaryMacro(name):
+    op = opcodes[name]
+    return &quot;&quot;&quot;
+    case UnaryOpType::&quot;&quot;&quot; + toCpp(name) + &quot;&quot;&quot;: {
+        if (value != &quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;) {
+            m_errorMessage = makeString(\&quot;&quot;&quot;&quot; + name + &quot;&quot;&quot; expects the value to be of type: &quot;, toString(&quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;), &quot; but got a value with type: &quot;, toString(value));
+            return false;
+        }
+
+        result = &quot;&quot;&quot; + cppType(op[&quot;return&quot;][0]) + &quot;&quot;&quot;;
+        return true;
+    }&quot;&quot;&quot;
+
+
+def binaryMacro(name):
+    op = opcodes[name]
+    return &quot;&quot;&quot;
+    case BinaryOpType::&quot;&quot;&quot; + toCpp(name) + &quot;&quot;&quot;: {
+        if (left != &quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;) {
+            m_errorMessage = makeString(\&quot;&quot;&quot;&quot; + name + &quot;&quot;&quot; expects the left value to be of type: &quot;, toString(&quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;), &quot; but got a value with type: &quot;, toString(left));
+            return false;
+        }
+
+        if (right != &quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][1]) + &quot;&quot;&quot;) {
+            m_errorMessage = makeString(\&quot;&quot;&quot;&quot; + name + &quot;&quot;&quot; expects the right value to be of type: &quot;, toString(&quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;), &quot; but got a value with type: &quot;, toString(right));
+            return false;
+        }
+
+        result = &quot;&quot;&quot; + cppType(op[&quot;return&quot;][0]) + &quot;&quot;&quot;;
+        return true;
+    }&quot;&quot;&quot;
+
+
+def loadMacro(name):
+    op = opcodes[name]
+    return &quot;&quot;&quot;
+    case LoadOpType::&quot;&quot;&quot; + toCpp(name) + &quot;&quot;&quot;: {
+        if (pointer != &quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;) {
+            m_errorMessage = makeString(\&quot;&quot;&quot;&quot; + name + &quot;&quot;&quot; expects the pointer to be of type: &quot;, toString(&quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;), &quot; but got a value with type: &quot;, toString(pointer));
+            return false;
+        }
+
+        result = &quot;&quot;&quot; + cppType(op[&quot;return&quot;][0]) + &quot;&quot;&quot;;
+        return true;
+    }&quot;&quot;&quot;
+
+
+def storeMacro(name):
+    op = opcodes[name]
+    return &quot;&quot;&quot;
+    case StoreOpType::&quot;&quot;&quot; + toCpp(name) + &quot;&quot;&quot;: {
+        if (pointer != &quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;) {
+            m_errorMessage = makeString(\&quot;&quot;&quot;&quot; + name + &quot;&quot;&quot; expects the pointer to be of type: &quot;, toString(&quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;), &quot; but got a value with type: &quot;, toString(pointer));
+            return false;
+        }
+
+        if (value != &quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][1]) + &quot;&quot;&quot;) {
+            m_errorMessage = makeString(\&quot;&quot;&quot;&quot; + name + &quot;&quot;&quot; expects the value to be of type: &quot;, toString(&quot;&quot;&quot; + cppType(op[&quot;parameter&quot;][0]) + &quot;&quot;&quot;), &quot; but got a value with type: &quot;, toString(value));
+            return false;
+        }
+
+        return true;
+    }&quot;&quot;&quot;
+
+
+unaryCases = &quot;&quot;.join([op for op in wasm.opcodeIterator(isUnary, unaryMacro)])
+binaryCases = &quot;&quot;.join([op for op in wasm.opcodeIterator(isBinary, binaryMacro)])
+loadCases = &quot;&quot;.join([op for op in wasm.opcodeIterator(lambda op: op[&quot;category&quot;] == &quot;memory&quot; and len(op[&quot;return&quot;]) == 1, loadMacro)])
+storeCases = &quot;&quot;.join([op for op in wasm.opcodeIterator(lambda op: op[&quot;category&quot;] == &quot;memory&quot; and len(op[&quot;return&quot;]) == 0, storeMacro)])
+
+contents = wasm.header + &quot;&quot;&quot;
+// This file is intended to be inlined by WasmValidate.cpp only! It should not be included elsewhere.
+
+#pragma once
+
+#if ENABLE(WEBASSEMBLY)
+
+namespace JSC { namespace Wasm {
+
+bool Validate::unaryOp(UnaryOpType op, ExpressionType value, ExpressionType&amp; result)
+{
+    switch (op) {
+&quot;&quot;&quot; + unaryCases + &quot;&quot;&quot;
+    }
+}
+
+bool Validate::binaryOp(BinaryOpType op, ExpressionType left, ExpressionType right, ExpressionType&amp; result)
+{
+    switch (op) {
+&quot;&quot;&quot; + binaryCases + &quot;&quot;&quot;
+    }
+}
+
+bool Validate::load(LoadOpType op, ExpressionType pointer, ExpressionType&amp; result, uint32_t)
+{
+    switch (op) {
+&quot;&quot;&quot; + loadCases + &quot;&quot;&quot;
+    }
+}
+
+bool Validate::store(StoreOpType op, ExpressionType pointer, ExpressionType value, uint32_t)
+{
+    switch (op) {
+&quot;&quot;&quot; + storeCases + &quot;&quot;&quot;
+    }
+}
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
+
+&quot;&quot;&quot;
+
+wasmValidateInlinesHFile.write(contents)
+wasmValidateInlinesHFile.close()
</ins><span class="cx">Property changes on: trunk/Source/JavaScriptCore/wasm/generateWasmValidateInlinesHeader.py
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<ins>+*
</ins><span class="cx">\ No newline at end of property
</span></div>

</body>
</html>