<!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>[214504] trunk</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/214504">214504</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2017-03-28 16:12:11 -0700 (Tue, 28 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebAssembly: Make WebAssembly.instantiate/compile truly asynchronous
https://bugs.webkit.org/show_bug.cgi?id=169187

Reviewed by Saam Barati.

JSTests:

* wasm/assert.js:
* wasm/js-api/Module-compile.js:
(async.testPromiseAPI):
* wasm/js-api/web-assembly-compile-parallel.js: Added.
(async.throwExn):
(async.test):
* wasm/js-api/web-assembly-instantiate-parallel.js: Added.
(async.test):
* wasm/js-api/web-assembly-instantiate.js:
(assert.eq.async.test):
(assert.eq):
(assert.asyncTest.async.test):
(assert.asyncTest):
(assert.truthy.async.test): Deleted.
(assert.truthy): Deleted.

Source/JavaScriptCore:

This patch allows WebAssembly compilations to happen asynchronously.
To do so, it refactors how much of the compilation happens and adds
new infrastructure for async promises.

First, there is a new class, PromiseDeferredTimer that lives on
the VM.  PromiseDeferredTimer will manage the life-cycle of async
pending promises and any dependencies that promise
needs. PromiseDeferredTimer automagically releases the pending
promise and dependencies once the JSPromiseDeferred is resolved or
rejected. Additionally, PromiseDeferredTimer provides a mechanism
to poll the run-loop whenever the async task needs to synchronize
with the JS thread. Normally, that will be whenever the async task
finishes. In the case of Web Assembly we also use this feature for
the compile + instantiate case, where we might have more work
after the first async task completes (more on that later).

The next class is Wasm::Worklist, which is used to manage Wasm
compilation tasks. The worklist class works similarly to the
DFG/FTL Worklists. It has a pool of threads that it manages. One
interesting aspect of Wasm Worklist is that it can synchronously
compile a plan that is already potentially running
asynchronously. This can occur if a user calls
WebAssembly.instantiate() then new WebAssembly.instantiate() on
the same module. In that case the Wasm Worklist will bump the
priority of the running pending Plan and block the JS thread.

This patch also makes some of the Wasm Plan code cleaner. Since we
now defer all compilation to instantiation time, we no longer need
to guess at which memory we are going to get. Also, Wasm Plans now
track the work they have done with a state enum.

Finally, this patch makes renamed HeapTimer to JSRunLoopTimer. It
also adds changes test262AsyncTest to a more generic testing
infrastructure. Now, in addition to the old functionality, you can
call asyncTest() with the number of tests you expect. When the jsc
CLI exits, it will guarantee that asyncTestPassed() is called that
many times.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* heap/GCActivityCallback.h:
* heap/IncrementalSweeper.cpp:
(JSC::IncrementalSweeper::scheduleTimer):
(JSC::IncrementalSweeper::IncrementalSweeper):
* heap/IncrementalSweeper.h:
* heap/StopIfNecessaryTimer.cpp:
(JSC::StopIfNecessaryTimer::StopIfNecessaryTimer):
* heap/StopIfNecessaryTimer.h:
* heap/StrongInlines.h:
* jsc.cpp:
(GlobalObject::finishCreation):
(printInternal):
(functionAsyncTestStart):
(functionAsyncTestPassed):
(functionTestWasmModuleFunctions):
(CommandLine::parseArguments):
(runJSC):
* runtime/JSPromiseDeferred.cpp:
(JSC::JSPromiseDeferred::resolve):
(JSC::JSPromiseDeferred::reject):
* runtime/JSPromiseDeferred.h:
(JSC::JSPromiseDeferred::promiseAsyncPending):
* runtime/JSRunLoopTimer.cpp: Renamed from Source/JavaScriptCore/heap/HeapTimer.cpp.
(JSC::JSRunLoopTimer::JSRunLoopTimer):
(JSC::JSRunLoopTimer::setRunLoop):
(JSC::JSRunLoopTimer::~JSRunLoopTimer):
(JSC::JSRunLoopTimer::timerDidFire):
(JSC::JSRunLoopTimer::scheduleTimer):
(JSC::JSRunLoopTimer::cancelTimer):
(JSC::JSRunLoopTimer::invalidate):
* runtime/JSRunLoopTimer.h: Copied from Source/JavaScriptCore/heap/HeapTimer.h.
* runtime/Options.h:
* runtime/PromiseDeferredTimer.cpp: Added.
(JSC::PromiseDeferredTimer::PromiseDeferredTimer):
(JSC::PromiseDeferredTimer::doWork):
(JSC::PromiseDeferredTimer::runRunLoop):
(JSC::PromiseDeferredTimer::addPendingPromise):
(JSC::PromiseDeferredTimer::cancelPendingPromise):
(JSC::PromiseDeferredTimer::scheduleWorkSoon):
(JSC::PromiseDeferredTimer::scheduleBlockedTask):
* runtime/PromiseDeferredTimer.h: Renamed from Source/JavaScriptCore/heap/HeapTimer.h.
(JSC::PromiseDeferredTimer::stopRunningTasks):
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::~VM):
* runtime/VM.h:
* wasm/JSWebAssembly.cpp:
(JSC::reject):
(JSC::webAssemblyCompileFunc):
(JSC::resolve):
(JSC::instantiate):
(JSC::compileAndInstantiate):
(JSC::webAssemblyInstantiateFunc):
(JSC::webAssemblyValidateFunc):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::B3IRGenerator::memoryKind):
(JSC::Wasm::parseAndCompile):
* wasm/WasmB3IRGenerator.h:
* wasm/WasmFormat.h:
(JSC::Wasm::ModuleInformation::internalFunctionCount):
* wasm/WasmFunctionParser.h:
* wasm/WasmMemory.h:
* wasm/WasmMemoryInformation.cpp:
(JSC::Wasm::MemoryInformation::MemoryInformation):
* wasm/WasmMemoryInformation.h:
(JSC::Wasm::MemoryInformation::maximum):
(JSC::Wasm::MemoryInformation::hasReservedMemory): Deleted.
(JSC::Wasm::MemoryInformation::takeReservedMemory): Deleted.
(JSC::Wasm::MemoryInformation::mode): Deleted.
* wasm/WasmModuleParser.cpp:
* wasm/WasmModuleParser.h:
(JSC::Wasm::ModuleParser::ModuleParser):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::Plan):
(JSC::Wasm::Plan::stateString):
(JSC::Wasm::Plan::moveToState):
(JSC::Wasm::Plan::fail):
(JSC::Wasm::Plan::parseAndValidateModule):
(JSC::Wasm::Plan::prepare):
(JSC::Wasm::Plan::ThreadCountHolder::ThreadCountHolder):
(JSC::Wasm::Plan::ThreadCountHolder::~ThreadCountHolder):
(JSC::Wasm::Plan::compileFunctions):
(JSC::Wasm::Plan::complete):
(JSC::Wasm::Plan::waitForCompletion):
(JSC::Wasm::Plan::cancel):
(JSC::Wasm::Plan::run): Deleted.
(JSC::Wasm::Plan::initializeCallees): Deleted.
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::dontFinalize):
(JSC::Wasm::Plan::exports):
(JSC::Wasm::Plan::internalFunctionCount):
(JSC::Wasm::Plan::takeModuleInformation):
(JSC::Wasm::Plan::takeCallLinkInfos):
(JSC::Wasm::Plan::takeWasmExitStubs):
(JSC::Wasm::Plan::setModeAndPromise):
(JSC::Wasm::Plan::mode):
(JSC::Wasm::Plan::pendingPromise):
(JSC::Wasm::Plan::vm):
(JSC::Wasm::Plan::errorMessage):
(JSC::Wasm::Plan::failed):
(JSC::Wasm::Plan::hasWork):
(JSC::Wasm::Plan::hasBeenPrepared):
* wasm/WasmPlanInlines.h: Copied from Source/JavaScriptCore/wasm/WasmB3IRGenerator.h.
(JSC::Wasm::Plan::initializeCallees):
* wasm/WasmValidate.cpp:
* wasm/WasmWorklist.cpp: Added.
(JSC::Wasm::Worklist::priorityString):
(JSC::Wasm::Worklist::QueueElement::setToNextPriority):
(JSC::Wasm::Worklist::iterate):
(JSC::Wasm::Worklist::enqueue):
(JSC::Wasm::Worklist::completePlanSynchronously):
(JSC::Wasm::Worklist::stopAllPlansForVM):
(JSC::Wasm::Worklist::Worklist):
(JSC::Wasm::Worklist::~Worklist):
(JSC::Wasm::existingWorklistOrNull):
(JSC::Wasm::ensureWorklist):
* wasm/WasmWorklist.h: Added.
(JSC::Wasm::Worklist::nextTicket):
(JSC::Wasm::Worklist::Comparator::operator()):
* wasm/js/JSWebAssemblyCallee.h:
* wasm/js/JSWebAssemblyCodeBlock.cpp:
(JSC::JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock):
(JSC::JSWebAssemblyCodeBlock::initialize):
(JSC::JSWebAssemblyCodeBlock::isSafeToRun):
* wasm/js/JSWebAssemblyCodeBlock.h:
(JSC::JSWebAssemblyCodeBlock::create):
(JSC::JSWebAssemblyCodeBlock::initialized):
(JSC::JSWebAssemblyCodeBlock::plan):
(JSC::JSWebAssemblyCodeBlock::runnable):
(JSC::JSWebAssemblyCodeBlock::errorMessage):
(JSC::JSWebAssemblyCodeBlock::callees):
* wasm/js/JSWebAssemblyHelpers.h:
(JSC::createSourceBufferFromValue):
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::finishCreation):
(JSC::JSWebAssemblyInstance::visitChildren):
(JSC::JSWebAssemblyInstance::addUnitializedCodeBlock):
(JSC::JSWebAssemblyInstance::finalizeCreation):
(JSC::JSWebAssemblyInstance::create):
(JSC::JSWebAssemblyInstance::setMemory): Deleted.
* wasm/js/JSWebAssemblyInstance.h:
(JSC::JSWebAssemblyInstance::codeBlock):
(JSC::JSWebAssemblyInstance::initialized):
(JSC::JSWebAssemblyInstance::module):
(JSC::JSWebAssemblyInstance::importFunction):
(JSC::JSWebAssemblyInstance::setMemory):
(JSC::JSWebAssemblyInstance::table):
(JSC::JSWebAssemblyInstance::importFunctions):
(JSC::JSWebAssemblyInstance::setImportFunction): Deleted.
(JSC::JSWebAssemblyInstance::setTable): Deleted.
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::createStub):
(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
(JSC::JSWebAssemblyModule::finishCreation):
(JSC::JSWebAssemblyModule::setCodeBlock):
(JSC::JSWebAssemblyModule::buildCodeBlock): Deleted.
(JSC::JSWebAssemblyModule::create): Deleted.
(JSC::JSWebAssemblyModule::codeBlock): Deleted.
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::moduleInformation):
(JSC::JSWebAssemblyModule::codeBlock):
(JSC::JSWebAssemblyModule::source):
(JSC::JSWebAssemblyModule::takeReservedMemory): Deleted.
(JSC::JSWebAssemblyModule::codeBlockFor): Deleted.
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
(JSC::WebAssemblyInstanceConstructor::createInstance): Deleted.
* wasm/js/WebAssemblyModuleConstructor.cpp:
(JSC::WebAssemblyModuleConstructor::createModule):
* wasm/js/WebAssemblyModulePrototype.cpp:
(JSC::webAssemblyModuleProtoImports):
(JSC::webAssemblyModuleProtoExports):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::finishCreation):
(JSC::WebAssemblyModuleRecord::link):
(JSC::WebAssemblyModuleRecord::evaluate):
* wasm/js/WebAssemblyModuleRecord.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestswasmassertjs">trunk/JSTests/wasm/assert.js</a></li>
<li><a href="#trunkJSTestswasmjsapiModulecompilejs">trunk/JSTests/wasm/js-api/Module-compile.js</a></li>
<li><a href="#trunkJSTestswasmjsapiwebassemblyinstantiatejs">trunk/JSTests/wasm/js-api/web-assembly-instantiate.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCActivityCallbackh">trunk/Source/JavaScriptCore/heap/GCActivityCallback.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapIncrementalSweepercpp">trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapIncrementalSweeperh">trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapStopIfNecessaryTimercpp">trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapStopIfNecessaryTimerh">trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapStrongInlinesh">trunk/Source/JavaScriptCore/heap/StrongInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSPromiseDeferredcpp">trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSPromiseDeferredh">trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmJSWebAssemblycpp">trunk/Source/JavaScriptCore/wasm/JSWebAssembly.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmB3IRGeneratorh">trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h</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="#trunkSourceJavaScriptCorewasmWasmMemoryh">trunk/Source/JavaScriptCore/wasm/WasmMemory.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryInformationcpp">trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmMemoryInformationh">trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParsercpp">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmModuleParserh">trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlancpp">trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlanh">trunk/Source/JavaScriptCore/wasm/WasmPlan.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmValidatecpp">trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyCalleeh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyCodeBlockcpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyCodeBlockh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyHelpersh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstancecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh">trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleConstructorcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModulePrototypecpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModulePrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordh">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestswasmjsapiwebassemblycompileparalleljs">trunk/JSTests/wasm/js-api/web-assembly-compile-parallel.js</a></li>
<li><a href="#trunkJSTestswasmjsapiwebassemblyinstantiateparalleljs">trunk/JSTests/wasm/js-api/web-assembly-instantiate-parallel.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSRunLoopTimercpp">trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSRunLoopTimerh">trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimePromiseDeferredTimercpp">trunk/Source/JavaScriptCore/runtime/PromiseDeferredTimer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimePromiseDeferredTimerh">trunk/Source/JavaScriptCore/runtime/PromiseDeferredTimer.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPlanInlinesh">trunk/Source/JavaScriptCore/wasm/WasmPlanInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmWorklistcpp">trunk/Source/JavaScriptCore/wasm/WasmWorklist.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmWorklisth">trunk/Source/JavaScriptCore/wasm/WasmWorklist.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreheapHeapTimercpp">trunk/Source/JavaScriptCore/heap/HeapTimer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapTimerh">trunk/Source/JavaScriptCore/heap/HeapTimer.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/JSTests/ChangeLog        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2017-03-28  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        WebAssembly: Make WebAssembly.instantiate/compile truly asynchronous
+        https://bugs.webkit.org/show_bug.cgi?id=169187
+
+        Reviewed by Saam Barati.
+
+        * wasm/assert.js:
+        * wasm/js-api/Module-compile.js:
+        (async.testPromiseAPI):
+        * wasm/js-api/web-assembly-compile-parallel.js: Added.
+        (async.throwExn):
+        (async.test):
+        * wasm/js-api/web-assembly-instantiate-parallel.js: Added.
+        (async.test):
+        * wasm/js-api/web-assembly-instantiate.js:
+        (assert.eq.async.test):
+        (assert.eq):
+        (assert.asyncTest.async.test):
+        (assert.asyncTest):
+        (assert.truthy.async.test): Deleted.
+        (assert.truthy): Deleted.
+
</ins><span class="cx"> 2017-03-28  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: implement Module imports/exports
</span></span></pre></div>
<a id="trunkJSTestswasmassertjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/assert.js (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/assert.js        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/JSTests/wasm/assert.js        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -144,3 +144,24 @@
</span><span class="cx">     _throws as throws,
</span><span class="cx">     _instanceof as instanceof,
</span><span class="cx"> };
</span><ins>+
+const asyncTestImpl = (promise, thenFunc, catchFunc) =&gt; {
+    asyncTestStart(1);
+    promise.then(thenFunc).catch(catchFunc);
+};
+
+const printExn = (e) =&gt; {
+    print(&quot;Failed: &quot;, e);
+    print(e.stack);
+};
+
+export const asyncTest = (promise) =&gt; asyncTestImpl(promise, asyncTestPassed, printExn);
+export const asyncTestEq = (promise, expected) =&gt; {
+    const thenCheck = (value) =&gt; {
+        if (value === expected)
+            return asyncTestPassed();
+        print(&quot;Failed: got &quot;, value, &quot; but expected &quot;, expected);
+
+    }
+    asyncTestImpl(promise, thenCheck, printExn);
+};
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiModulecompilejs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/js-api/Module-compile.js (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/Module-compile.js        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/JSTests/wasm/js-api/Module-compile.js        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -1,7 +1,6 @@
</span><span class="cx"> import * as assert from '../assert.js';
</span><span class="cx"> import Builder from '../Builder.js';
</span><span class="cx"> 
</span><del>-let done = false;
</del><span class="cx"> async function testPromiseAPI() {
</span><span class="cx">     {
</span><span class="cx">         // Can't declare more than one memory.
</span><span class="lines">@@ -14,39 +13,30 @@
</span><span class="cx">             .Code()
</span><span class="cx">             .End();
</span><span class="cx"> 
</span><del>-        let threw = false;
</del><span class="cx">         try {
</span><span class="cx">             await WebAssembly.compile(builder.WebAssembly().get());
</span><span class="cx">         } catch(e) {
</span><del>-            threw = true;
</del><span class="cx">             assert.truthy(e instanceof WebAssembly.CompileError);
</span><del>-            assert.truthy(e.message === &quot;WebAssembly.Module doesn't parse at byte 34 / 43: Memory section cannot exist if an Import has a memory (evaluating 'WebAssembly.compile(builder.WebAssembly().get())')&quot;);
</del><ins>+            assert.truthy(e.message === &quot;WebAssembly.Module doesn't parse at byte 34 / 43: Memory section cannot exist if an Import has a memory&quot;);
</ins><span class="cx">         }
</span><del>-        assert.truthy(threw);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><del>-        let threw = false;
</del><span class="cx">         try {
</span><span class="cx">             await WebAssembly.compile();
</span><span class="cx">         } catch(e) {
</span><del>-            threw = true;
</del><span class="cx">             assert.truthy(e instanceof TypeError);
</span><span class="cx">             assert.eq(e.message, &quot;first argument must be an ArrayBufferView or an ArrayBuffer (evaluating 'WebAssembly.compile()')&quot;);
</span><span class="cx">         }
</span><del>-        assert.truthy(threw);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><del>-        let threw = false;
</del><span class="cx">         try {
</span><span class="cx">             await WebAssembly.compile(20);
</span><span class="cx">         } catch(e) {
</span><del>-            threw = true;
</del><span class="cx">             assert.truthy(e instanceof TypeError);
</span><span class="cx">             assert.eq(e.message, &quot;first argument must be an ArrayBufferView or an ArrayBuffer (evaluating 'WebAssembly.compile(20)')&quot;);
</span><span class="cx">         }
</span><del>-        assert.truthy(threw);
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -61,10 +51,6 @@
</span><span class="cx">         let module = await WebAssembly.compile(builder.WebAssembly().get());
</span><span class="cx">         assert.truthy(module instanceof WebAssembly.Module);
</span><span class="cx">     }
</span><del>-
-    done = true;
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-testPromiseAPI();
-drainMicrotasks();
-assert.truthy(done);
</del><ins>+assert.asyncTest(testPromiseAPI());
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiwebassemblycompileparalleljs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/web-assembly-compile-parallel.js (0 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/web-assembly-compile-parallel.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/web-assembly-compile-parallel.js        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+async function throwExn() {
+    throw new Error();
+}
+
+async function test() {
+    const loopDepth = 10;
+    const numCompilations = 1;
+    const numVars = 30;
+    const params = [];
+    params.length = numVars;
+    params.fill(&quot;i32&quot;);
+
+    let builder = (new Builder())
+          .Type().End()
+          .Function().End()
+          .Export()
+              .Function(&quot;foo&quot;)
+          .End()
+          .Code()
+          .Function(&quot;foo&quot;, { params, ret: &quot;i32&quot; });
+
+    const makeLoop = (builder, depth) =&gt; {
+        if (depth === 0)
+            return builder;
+
+        builder = builder
+            .Loop(&quot;i32&quot;, (b) =&gt; {
+                  b.GetLocal(0)
+                    .I32Const(1)
+                    .I32Sub()
+                    .TeeLocal(0)
+                    .GetLocal(0)
+                    .I32Eqz()
+                    .BrIf(1);
+
+                return makeLoop(b, depth - 1).Br(0);
+            });
+        return builder
+
+    }
+
+    builder = makeLoop(builder, loopDepth);
+    builder = builder.End().End();
+
+    const bin = builder.WebAssembly().get();
+
+    let compilations = [];
+    for (let i = 0; i &lt; numCompilations; ++i) {
+        compilations.push(WebAssembly.compile(bin));
+    }
+
+    await Promise.all(compilations);
+}
+
+assert.asyncTest(test());
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiwebassemblyinstantiateparalleljs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/wasm/js-api/web-assembly-instantiate-parallel.js (0 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/web-assembly-instantiate-parallel.js                                (rev 0)
+++ trunk/JSTests/wasm/js-api/web-assembly-instantiate-parallel.js        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -0,0 +1,75 @@
</span><ins>+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+async function test() {
+    const loopDepth = 100;
+    const numCompilations = 1;
+    const numVars = 30;
+    const params = [];
+    params.length = numVars;
+    params.fill(&quot;i32&quot;);
+
+    let builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Memory(&quot;imp&quot;, &quot;memory&quot;, { initial: 0 })
+        .End()
+        .Function().End()
+        .Export()
+            .Function(&quot;foo&quot;)
+        .End()
+        .Code()
+        .Function(&quot;foo&quot;, { params, ret: &quot;i32&quot; });
+
+    const makeLoop = (builder, depth) =&gt; {
+        if (depth === 0)
+            return builder;
+
+        builder = builder
+            .Loop(&quot;i32&quot;, (b) =&gt; {
+                b.GetLocal(0)
+                    .I32Const(1)
+                    .I32Sub()
+                    .TeeLocal(0)
+                    .GetLocal(0)
+                    .I32Eqz()
+                    .BrIf(1);
+
+                return makeLoop(b, depth - 1).Br(0);
+            });
+        return builder;
+    }
+
+    builder = makeLoop(builder, loopDepth);
+    builder = builder.End().End();
+
+    const bin = builder.WebAssembly().get();
+    const memory = new WebAssembly.Memory({ initial: 0 });
+    const importObject = { &quot;imp&quot;: { &quot;memory&quot;: memory } };
+
+    // Compile a bunch of instances in parallel.
+    let compilations = [];
+    for (let i = 0; i &lt; numCompilations; ++i) {
+        compilations.push(WebAssembly.instantiate(bin, importObject));
+    }
+
+    let [inst] = await Promise.all(compilations);
+    let module = inst.module;
+
+    // Compile a bunch of instances from modules in parallel.
+    compilations = [];
+    for (let i = 0; i &lt; numCompilations; ++i) {
+        compilations.push(WebAssembly.instantiate(module, importObject));
+    }
+
+    await Promise.all(compilations);
+
+    // Compile an instance from a module in parallel, have sync compilation steal it.
+    compilations = [];
+    compilations.push(WebAssembly.instantiate(module, importObject));
+    inst = new WebAssembly.Instance(module, importObject);
+
+    await Promise.all(compilations);
+}
+
+assert.asyncTest(test());
</ins></span></pre></div>
<a id="trunkJSTestswasmjsapiwebassemblyinstantiatejs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/js-api/web-assembly-instantiate.js (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/js-api/web-assembly-instantiate.js        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/JSTests/wasm/js-api/web-assembly-instantiate.js        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -19,18 +19,14 @@
</span><span class="cx"> 
</span><span class="cx">     const bin = builder.WebAssembly().get();
</span><span class="cx"> 
</span><del>-    let done = false;
</del><span class="cx">     async function test() {
</span><span class="cx">         let {module, instance} = await WebAssembly.instantiate(bin);
</span><span class="cx">         assert.truthy(module instanceof WebAssembly.Module);
</span><span class="cx">         assert.truthy(instance instanceof WebAssembly.Instance);
</span><span class="cx">         assert.eq(instance.exports.foo(20), 1);
</span><del>-        done = true;
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    test();
-    drainMicrotasks();
-    assert.truthy(done);
</del><ins>+    assert.asyncTest(test());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><span class="lines">@@ -48,7 +44,6 @@
</span><span class="cx"> 
</span><span class="cx">     const bin = builder.WebAssembly().get();
</span><span class="cx"> 
</span><del>-    let done = false;
</del><span class="cx">     async function test() {
</span><span class="cx">         try {
</span><span class="cx">             let {module, instance} = await WebAssembly.instantiate(bin, null);
</span><span class="lines">@@ -55,12 +50,9 @@
</span><span class="cx">         } catch(e) {
</span><span class="cx">             assert.eq(e.message, &quot;second argument to WebAssembly.instantiate must be undefined or an Object (evaluating 'WebAssembly.instantiate(bin, null)')&quot;);
</span><span class="cx">         }
</span><del>-        done = true;
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    test();
-    drainMicrotasks();
-    assert.truthy(done);
</del><ins>+    assert.asyncTest(test());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><span class="lines">@@ -78,20 +70,16 @@
</span><span class="cx"> 
</span><span class="cx">     const bin = builder.WebAssembly().get();
</span><span class="cx"> 
</span><del>-    let done = false;
</del><span class="cx">     async function test() {
</span><span class="cx">         try {
</span><span class="cx">             let {module, instance} = await WebAssembly.instantiate(bin);
</span><span class="cx">         } catch(e) {
</span><span class="cx">             assert.truthy(e instanceof WebAssembly.CompileError);
</span><del>-            assert.eq(e.message, &quot;WebAssembly.Module doesn't validate: control flow returns with unexpected type, in function at index 0 (evaluating 'WebAssembly.instantiate(bin)')&quot;);
</del><ins>+            assert.eq(e.message, &quot;WebAssembly.Module doesn't validate: control flow returns with unexpected type, in function at index 0&quot;);
</ins><span class="cx">         }
</span><del>-        done = true;
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    test();
-    drainMicrotasks();
-    assert.truthy(done);
</del><ins>+    assert.asyncTest(test());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><span class="lines">@@ -110,19 +98,15 @@
</span><span class="cx"> 
</span><span class="cx">     const bin = builder.WebAssembly().get();
</span><span class="cx"> 
</span><del>-    let done = false;
</del><span class="cx">     async function test() {
</span><span class="cx">         try {
</span><span class="cx">             let {module, instance} = await WebAssembly.instantiate(bin, {imp: {memory: 20}});
</span><span class="cx">         } catch(e) {
</span><del>-            assert.eq(e.message, &quot;Memory import is not an instance of WebAssembly.Memory (evaluating 'WebAssembly.instantiate(bin, {imp: {memory: 20}})')&quot;);
</del><ins>+            assert.eq(e.message, &quot;Memory import is not an instance of WebAssembly.Memory&quot;);
</ins><span class="cx">         }
</span><del>-        done = true;
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    test();
-    drainMicrotasks();
-    assert.truthy(done);
</del><ins>+    assert.asyncTest(test());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><span class="lines">@@ -141,20 +125,16 @@
</span><span class="cx"> 
</span><span class="cx">     const bin = builder.WebAssembly().get();
</span><span class="cx"> 
</span><del>-    let done = false;
</del><span class="cx">     async function test() {
</span><span class="cx">         try {
</span><span class="cx">             const module = new WebAssembly.Module(bin);
</span><span class="cx">             let instance = await WebAssembly.instantiate(bin, {imp: {memory: 20}});
</span><span class="cx">         } catch(e) {
</span><del>-            assert.eq(e.message, &quot;Memory import is not an instance of WebAssembly.Memory (evaluating 'WebAssembly.instantiate(bin, {imp: {memory: 20}})')&quot;);
</del><ins>+            assert.eq(e.message, &quot;Memory import is not an instance of WebAssembly.Memory&quot;);
</ins><span class="cx">         }
</span><del>-        done = true;
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    test();
-    drainMicrotasks();
-    assert.truthy(done);
</del><ins>+    assert.asyncTest(test());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><span class="lines">@@ -172,18 +152,14 @@
</span><span class="cx"> 
</span><span class="cx">     const bin = builder.WebAssembly().get();
</span><span class="cx"> 
</span><del>-    let done = false;
</del><span class="cx">     async function test() {
</span><span class="cx">         let module = new WebAssembly.Module(bin);
</span><span class="cx">         let instance = await WebAssembly.instantiate(module);
</span><span class="cx">         assert.truthy(instance instanceof WebAssembly.Instance);
</span><span class="cx">         assert.eq(instance.exports.foo(20), 1);
</span><del>-        done = true;
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    test();
-    drainMicrotasks();
-    assert.truthy(done);
</del><ins>+    assert.asyncTest(test());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> {
</span><span class="lines">@@ -202,7 +178,6 @@
</span><span class="cx"> 
</span><span class="cx">     const bin = builder.WebAssembly().get();
</span><span class="cx"> 
</span><del>-    let done = false;
</del><span class="cx">     async function test() {
</span><span class="cx">         try {
</span><span class="cx">             await WebAssembly.instantiate(25);
</span><span class="lines">@@ -210,10 +185,7 @@
</span><span class="cx">             // FIXME: Better error message here.
</span><span class="cx">             assert.eq(e.message, &quot;first argument must be an ArrayBufferView or an ArrayBuffer (evaluating 'WebAssembly.instantiate(25)')&quot;);
</span><span class="cx">         }
</span><del>-        done = true;
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    test();
-    drainMicrotasks();
-    assert.truthy(done);
</del><ins>+    assert.asyncTest(test());
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -503,7 +503,6 @@
</span><span class="cx">     heap/HeapProfiler.cpp
</span><span class="cx">     heap/HeapSnapshot.cpp
</span><span class="cx">     heap/HeapSnapshotBuilder.cpp
</span><del>-    heap/HeapTimer.cpp
</del><span class="cx">     heap/IncrementalSweeper.cpp
</span><span class="cx">     heap/JITStubRoutineSet.cpp
</span><span class="cx">     heap/LargeAllocation.cpp
</span><span class="lines">@@ -802,6 +801,7 @@
</span><span class="cx">     runtime/JSPropertyNameEnumerator.cpp
</span><span class="cx">     runtime/JSPropertyNameIterator.cpp
</span><span class="cx">     runtime/JSProxy.cpp
</span><ins>+    runtime/JSRunLoopTimer.cpp
</ins><span class="cx">     runtime/JSScope.cpp
</span><span class="cx">     runtime/JSScriptFetcher.cpp
</span><span class="cx">     runtime/JSSegmentedVariableObject.cpp
</span><span class="lines">@@ -851,6 +851,7 @@
</span><span class="cx">     runtime/Operations.cpp
</span><span class="cx">     runtime/Options.cpp
</span><span class="cx">     runtime/ProgramExecutable.cpp
</span><ins>+    runtime/PromiseDeferredTimer.cpp
</ins><span class="cx">     runtime/PropertyDescriptor.cpp
</span><span class="cx">     runtime/PropertySlot.cpp
</span><span class="cx">     runtime/PropertyTable.cpp
</span><span class="lines">@@ -944,6 +945,7 @@
</span><span class="cx">     wasm/WasmPlan.cpp
</span><span class="cx">     wasm/WasmSignature.cpp
</span><span class="cx">     wasm/WasmValidate.cpp
</span><ins>+    wasm/WasmWorklist.cpp
</ins><span class="cx"> 
</span><span class="cx">     wasm/js/JSWebAssemblyCallee.cpp
</span><span class="cx">     wasm/js/JSWebAssemblyCodeBlock.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -1,3 +1,230 @@
</span><ins>+2017-03-28  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        WebAssembly: Make WebAssembly.instantiate/compile truly asynchronous
+        https://bugs.webkit.org/show_bug.cgi?id=169187
+
+        Reviewed by Saam Barati.
+
+        This patch allows WebAssembly compilations to happen asynchronously.
+        To do so, it refactors how much of the compilation happens and adds
+        new infrastructure for async promises.
+
+        First, there is a new class, PromiseDeferredTimer that lives on
+        the VM.  PromiseDeferredTimer will manage the life-cycle of async
+        pending promises and any dependencies that promise
+        needs. PromiseDeferredTimer automagically releases the pending
+        promise and dependencies once the JSPromiseDeferred is resolved or
+        rejected. Additionally, PromiseDeferredTimer provides a mechanism
+        to poll the run-loop whenever the async task needs to synchronize
+        with the JS thread. Normally, that will be whenever the async task
+        finishes. In the case of Web Assembly we also use this feature for
+        the compile + instantiate case, where we might have more work
+        after the first async task completes (more on that later).
+
+        The next class is Wasm::Worklist, which is used to manage Wasm
+        compilation tasks. The worklist class works similarly to the
+        DFG/FTL Worklists. It has a pool of threads that it manages. One
+        interesting aspect of Wasm Worklist is that it can synchronously
+        compile a plan that is already potentially running
+        asynchronously. This can occur if a user calls
+        WebAssembly.instantiate() then new WebAssembly.instantiate() on
+        the same module. In that case the Wasm Worklist will bump the
+        priority of the running pending Plan and block the JS thread.
+
+        This patch also makes some of the Wasm Plan code cleaner. Since we
+        now defer all compilation to instantiation time, we no longer need
+        to guess at which memory we are going to get. Also, Wasm Plans now
+        track the work they have done with a state enum.
+
+        Finally, this patch makes renamed HeapTimer to JSRunLoopTimer. It
+        also adds changes test262AsyncTest to a more generic testing
+        infrastructure. Now, in addition to the old functionality, you can
+        call asyncTest() with the number of tests you expect. When the jsc
+        CLI exits, it will guarantee that asyncTestPassed() is called that
+        many times.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * heap/GCActivityCallback.h:
+        * heap/IncrementalSweeper.cpp:
+        (JSC::IncrementalSweeper::scheduleTimer):
+        (JSC::IncrementalSweeper::IncrementalSweeper):
+        * heap/IncrementalSweeper.h:
+        * heap/StopIfNecessaryTimer.cpp:
+        (JSC::StopIfNecessaryTimer::StopIfNecessaryTimer):
+        * heap/StopIfNecessaryTimer.h:
+        * heap/StrongInlines.h:
+        * jsc.cpp:
+        (GlobalObject::finishCreation):
+        (printInternal):
+        (functionAsyncTestStart):
+        (functionAsyncTestPassed):
+        (functionTestWasmModuleFunctions):
+        (CommandLine::parseArguments):
+        (runJSC):
+        * runtime/JSPromiseDeferred.cpp:
+        (JSC::JSPromiseDeferred::resolve):
+        (JSC::JSPromiseDeferred::reject):
+        * runtime/JSPromiseDeferred.h:
+        (JSC::JSPromiseDeferred::promiseAsyncPending):
+        * runtime/JSRunLoopTimer.cpp: Renamed from Source/JavaScriptCore/heap/HeapTimer.cpp.
+        (JSC::JSRunLoopTimer::JSRunLoopTimer):
+        (JSC::JSRunLoopTimer::setRunLoop):
+        (JSC::JSRunLoopTimer::~JSRunLoopTimer):
+        (JSC::JSRunLoopTimer::timerDidFire):
+        (JSC::JSRunLoopTimer::scheduleTimer):
+        (JSC::JSRunLoopTimer::cancelTimer):
+        (JSC::JSRunLoopTimer::invalidate):
+        * runtime/JSRunLoopTimer.h: Copied from Source/JavaScriptCore/heap/HeapTimer.h.
+        * runtime/Options.h:
+        * runtime/PromiseDeferredTimer.cpp: Added.
+        (JSC::PromiseDeferredTimer::PromiseDeferredTimer):
+        (JSC::PromiseDeferredTimer::doWork):
+        (JSC::PromiseDeferredTimer::runRunLoop):
+        (JSC::PromiseDeferredTimer::addPendingPromise):
+        (JSC::PromiseDeferredTimer::cancelPendingPromise):
+        (JSC::PromiseDeferredTimer::scheduleWorkSoon):
+        (JSC::PromiseDeferredTimer::scheduleBlockedTask):
+        * runtime/PromiseDeferredTimer.h: Renamed from Source/JavaScriptCore/heap/HeapTimer.h.
+        (JSC::PromiseDeferredTimer::stopRunningTasks):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::VM::~VM):
+        * runtime/VM.h:
+        * wasm/JSWebAssembly.cpp:
+        (JSC::reject):
+        (JSC::webAssemblyCompileFunc):
+        (JSC::resolve):
+        (JSC::instantiate):
+        (JSC::compileAndInstantiate):
+        (JSC::webAssemblyInstantiateFunc):
+        (JSC::webAssemblyValidateFunc):
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
+        (JSC::Wasm::B3IRGenerator::memoryKind):
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmB3IRGenerator.h:
+        * wasm/WasmFormat.h:
+        (JSC::Wasm::ModuleInformation::internalFunctionCount):
+        * wasm/WasmFunctionParser.h:
+        * wasm/WasmMemory.h:
+        * wasm/WasmMemoryInformation.cpp:
+        (JSC::Wasm::MemoryInformation::MemoryInformation):
+        * wasm/WasmMemoryInformation.h:
+        (JSC::Wasm::MemoryInformation::maximum):
+        (JSC::Wasm::MemoryInformation::hasReservedMemory): Deleted.
+        (JSC::Wasm::MemoryInformation::takeReservedMemory): Deleted.
+        (JSC::Wasm::MemoryInformation::mode): Deleted.
+        * wasm/WasmModuleParser.cpp:
+        * wasm/WasmModuleParser.h:
+        (JSC::Wasm::ModuleParser::ModuleParser):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::Plan):
+        (JSC::Wasm::Plan::stateString):
+        (JSC::Wasm::Plan::moveToState):
+        (JSC::Wasm::Plan::fail):
+        (JSC::Wasm::Plan::parseAndValidateModule):
+        (JSC::Wasm::Plan::prepare):
+        (JSC::Wasm::Plan::ThreadCountHolder::ThreadCountHolder):
+        (JSC::Wasm::Plan::ThreadCountHolder::~ThreadCountHolder):
+        (JSC::Wasm::Plan::compileFunctions):
+        (JSC::Wasm::Plan::complete):
+        (JSC::Wasm::Plan::waitForCompletion):
+        (JSC::Wasm::Plan::cancel):
+        (JSC::Wasm::Plan::run): Deleted.
+        (JSC::Wasm::Plan::initializeCallees): Deleted.
+        * wasm/WasmPlan.h:
+        (JSC::Wasm::Plan::dontFinalize):
+        (JSC::Wasm::Plan::exports):
+        (JSC::Wasm::Plan::internalFunctionCount):
+        (JSC::Wasm::Plan::takeModuleInformation):
+        (JSC::Wasm::Plan::takeCallLinkInfos):
+        (JSC::Wasm::Plan::takeWasmExitStubs):
+        (JSC::Wasm::Plan::setModeAndPromise):
+        (JSC::Wasm::Plan::mode):
+        (JSC::Wasm::Plan::pendingPromise):
+        (JSC::Wasm::Plan::vm):
+        (JSC::Wasm::Plan::errorMessage):
+        (JSC::Wasm::Plan::failed):
+        (JSC::Wasm::Plan::hasWork):
+        (JSC::Wasm::Plan::hasBeenPrepared):
+        * wasm/WasmPlanInlines.h: Copied from Source/JavaScriptCore/wasm/WasmB3IRGenerator.h.
+        (JSC::Wasm::Plan::initializeCallees):
+        * wasm/WasmValidate.cpp:
+        * wasm/WasmWorklist.cpp: Added.
+        (JSC::Wasm::Worklist::priorityString):
+        (JSC::Wasm::Worklist::QueueElement::setToNextPriority):
+        (JSC::Wasm::Worklist::iterate):
+        (JSC::Wasm::Worklist::enqueue):
+        (JSC::Wasm::Worklist::completePlanSynchronously):
+        (JSC::Wasm::Worklist::stopAllPlansForVM):
+        (JSC::Wasm::Worklist::Worklist):
+        (JSC::Wasm::Worklist::~Worklist):
+        (JSC::Wasm::existingWorklistOrNull):
+        (JSC::Wasm::ensureWorklist):
+        * wasm/WasmWorklist.h: Added.
+        (JSC::Wasm::Worklist::nextTicket):
+        (JSC::Wasm::Worklist::Comparator::operator()):
+        * wasm/js/JSWebAssemblyCallee.h:
+        * wasm/js/JSWebAssemblyCodeBlock.cpp:
+        (JSC::JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock):
+        (JSC::JSWebAssemblyCodeBlock::initialize):
+        (JSC::JSWebAssemblyCodeBlock::isSafeToRun):
+        * wasm/js/JSWebAssemblyCodeBlock.h:
+        (JSC::JSWebAssemblyCodeBlock::create):
+        (JSC::JSWebAssemblyCodeBlock::initialized):
+        (JSC::JSWebAssemblyCodeBlock::plan):
+        (JSC::JSWebAssemblyCodeBlock::runnable):
+        (JSC::JSWebAssemblyCodeBlock::errorMessage):
+        (JSC::JSWebAssemblyCodeBlock::callees):
+        * wasm/js/JSWebAssemblyHelpers.h:
+        (JSC::createSourceBufferFromValue):
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::finishCreation):
+        (JSC::JSWebAssemblyInstance::visitChildren):
+        (JSC::JSWebAssemblyInstance::addUnitializedCodeBlock):
+        (JSC::JSWebAssemblyInstance::finalizeCreation):
+        (JSC::JSWebAssemblyInstance::create):
+        (JSC::JSWebAssemblyInstance::setMemory): Deleted.
+        * wasm/js/JSWebAssemblyInstance.h:
+        (JSC::JSWebAssemblyInstance::codeBlock):
+        (JSC::JSWebAssemblyInstance::initialized):
+        (JSC::JSWebAssemblyInstance::module):
+        (JSC::JSWebAssemblyInstance::importFunction):
+        (JSC::JSWebAssemblyInstance::setMemory):
+        (JSC::JSWebAssemblyInstance::table):
+        (JSC::JSWebAssemblyInstance::importFunctions):
+        (JSC::JSWebAssemblyInstance::setImportFunction): Deleted.
+        (JSC::JSWebAssemblyInstance::setTable): Deleted.
+        * wasm/js/JSWebAssemblyModule.cpp:
+        (JSC::JSWebAssemblyModule::createStub):
+        (JSC::JSWebAssemblyModule::JSWebAssemblyModule):
+        (JSC::JSWebAssemblyModule::finishCreation):
+        (JSC::JSWebAssemblyModule::setCodeBlock):
+        (JSC::JSWebAssemblyModule::buildCodeBlock): Deleted.
+        (JSC::JSWebAssemblyModule::create): Deleted.
+        (JSC::JSWebAssemblyModule::codeBlock): Deleted.
+        * wasm/js/JSWebAssemblyModule.h:
+        (JSC::JSWebAssemblyModule::moduleInformation):
+        (JSC::JSWebAssemblyModule::codeBlock):
+        (JSC::JSWebAssemblyModule::source):
+        (JSC::JSWebAssemblyModule::takeReservedMemory): Deleted.
+        (JSC::JSWebAssemblyModule::codeBlockFor): Deleted.
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance):
+        (JSC::WebAssemblyInstanceConstructor::createInstance): Deleted.
+        * wasm/js/WebAssemblyModuleConstructor.cpp:
+        (JSC::WebAssemblyModuleConstructor::createModule):
+        * wasm/js/WebAssemblyModulePrototype.cpp:
+        (JSC::webAssemblyModuleProtoImports):
+        (JSC::webAssemblyModuleProtoExports):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::finishCreation):
+        (JSC::WebAssemblyModuleRecord::link):
+        (JSC::WebAssemblyModuleRecord::evaluate):
+        * wasm/js/WebAssemblyModuleRecord.h:
+
</ins><span class="cx"> 2017-03-28  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: add fallback to use pinned register to load/store state
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -1321,11 +1321,17 @@
</span><span class="cx">                 52C952B919A28A1C0069B386 /* TypeProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */; };
</span><span class="cx">                 52F6C35D1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */; };
</span><span class="cx">                 52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                530FB3021E7A0B6E003C19DD /* WasmWorklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 530FB3011E7A0B6E003C19DD /* WasmWorklist.h */; };
+                530FB3041E7A1146003C19DD /* WasmWorklist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 530FB3031E7A1146003C19DD /* WasmWorklist.cpp */; };
</ins><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><span class="cx">                 533B15DF1DC7F463004D500A /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><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><ins>+                534638711E70CF3D00F12AC1 /* JSRunLoopTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 534638701E70CF3D00F12AC1 /* JSRunLoopTimer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                534638731E70D01500F12AC1 /* JSRunLoopTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 534638721E70D01500F12AC1 /* JSRunLoopTimer.cpp */; };
+                534638751E70DDEC00F12AC1 /* PromiseDeferredTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 534638741E70DDEC00F12AC1 /* PromiseDeferredTimer.h */; };
+                534638771E71E06E00F12AC1 /* PromiseDeferredTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 534638761E71E06E00F12AC1 /* PromiseDeferredTimer.cpp */; };
</ins><span class="cx">                 53486BB71C1795C300F6F3AF /* JSTypedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 53486BB61C1795C300F6F3AF /* JSTypedArray.h */; settings = {ATTRIBUTES = (Public, ); }; };
</span><span class="cx">                 53486BBB1C18E84500F6F3AF /* JSTypedArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */; };
</span><span class="cx">                 534902851C7276B70012BCB8 /* TypedArrayCTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 534902821C7242C80012BCB8 /* TypedArrayCTest.cpp */; };
</span><span class="lines">@@ -1359,6 +1365,7 @@
</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="cx">                 53F6BF6D1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                53F8D2001E8387D400D21116 /* WasmPlanInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F8D1FF1E8387D400D21116 /* WasmPlanInlines.h */; };
</ins><span class="cx">                 53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
</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="lines">@@ -2238,8 +2245,6 @@
</span><span class="cx">                 C2CF39C116E15A8100DD69BE /* JSAPIWrapperObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = C2CF39BF16E15A8100DD69BE /* JSAPIWrapperObject.mm */; };
</span><span class="cx">                 C2CF39C216E15A8100DD69BE /* JSAPIWrapperObject.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CF39C016E15A8100DD69BE /* JSAPIWrapperObject.h */; };
</span><span class="cx">                 C2DA778318E259990066FCB6 /* HeapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C2DA778218E259990066FCB6 /* HeapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2E526BB1590EF000054E48D /* HeapTimer.cpp */; };
-                C2E526BE1590EF000054E48D /* HeapTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E526BC1590EF000054E48D /* HeapTimer.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx">                 C2F0F2D116BAEEE900187C19 /* StructureRareData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F0F2D016BAEEE900187C19 /* StructureRareData.cpp */; };
</span><span class="cx">                 C2FCAE1017A9C24E0034C735 /* BytecodeBasicBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FCAE0C17A9C24E0034C735 /* BytecodeBasicBlock.cpp */; };
</span><span class="cx">                 C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FCAE0D17A9C24E0034C735 /* BytecodeBasicBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -3810,11 +3815,17 @@
</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">                 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyWrapperFunction.cpp; path = js/WebAssemblyWrapperFunction.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyWrapperFunction.h; path = js/WebAssemblyWrapperFunction.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                530FB3011E7A0B6E003C19DD /* WasmWorklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmWorklist.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                530FB3031E7A1146003C19DD /* WasmWorklist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmWorklist.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><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><span class="cx">                 533B15DE1DC7F463004D500A /* WasmOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOps.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><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><ins>+                534638701E70CF3D00F12AC1 /* JSRunLoopTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRunLoopTimer.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                534638721E70D01500F12AC1 /* JSRunLoopTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSRunLoopTimer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                534638741E70DDEC00F12AC1 /* PromiseDeferredTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PromiseDeferredTimer.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                534638761E71E06E00F12AC1 /* PromiseDeferredTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PromiseDeferredTimer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><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="cx">                 53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArray.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 534902821C7242C80012BCB8 /* TypedArrayCTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypedArrayCTest.cpp; path = API/tests/TypedArrayCTest.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3854,6 +3865,7 @@
</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="cx">                 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InternalFunctionAllocationProfile.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                53F8D1FF1E8387D400D21116 /* WasmPlanInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmPlanInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</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="lines">@@ -4798,8 +4810,6 @@
</span><span class="cx">                 C2CF39BF16E15A8100DD69BE /* JSAPIWrapperObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JSAPIWrapperObject.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C2CF39C016E15A8100DD69BE /* JSAPIWrapperObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAPIWrapperObject.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C2DA778218E259990066FCB6 /* HeapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                C2E526BB1590EF000054E48D /* HeapTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapTimer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
-                C2E526BC1590EF000054E48D /* HeapTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapTimer.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 C2F0F2D016BAEEE900187C19 /* StructureRareData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureRareData.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C2FCAE0C17A9C24E0034C735 /* BytecodeBasicBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BytecodeBasicBlock.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C2FCAE0D17A9C24E0034C735 /* BytecodeBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeBasicBlock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5919,8 +5929,6 @@
</span><span class="cx">                                 A54C2AAF1C6544D100A18D78 /* HeapSnapshot.h */,
</span><span class="cx">                                 A5311C341C77CEAC00E6B1B6 /* HeapSnapshotBuilder.cpp */,
</span><span class="cx">                                 A5311C351C77CEAC00E6B1B6 /* HeapSnapshotBuilder.h */,
</span><del>-                                C2E526BB1590EF000054E48D /* HeapTimer.cpp */,
-                                C2E526BC1590EF000054E48D /* HeapTimer.h */,
</del><span class="cx">                                 0FADE6721D4D23BC00768457 /* HeapUtil.h */,
</span><span class="cx">                                 C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */,
</span><span class="cx">                                 C25F8BCC157544A900245B71 /* IncrementalSweeper.h */,
</span><span class="lines">@@ -6288,11 +6296,14 @@
</span><span class="cx">                                 53F40E8C1D5901F20099A1B6 /* WasmParser.h */,
</span><span class="cx">                                 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */,
</span><span class="cx">                                 531374BC1D5CE67600AF7A0B /* WasmPlan.h */,
</span><ins>+                                53F8D1FF1E8387D400D21116 /* WasmPlanInlines.h */,
</ins><span class="cx">                                 53F40E841D58F9770099A1B6 /* WasmSections.h */,
</span><span class="cx">                                 AD7438BE1E04579200FD0C2A /* WasmSignature.cpp */,
</span><span class="cx">                                 AD7438BF1E04579200FD0C2A /* WasmSignature.h */,
</span><span class="cx">                                 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */,
</span><span class="cx">                                 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */,
</span><ins>+                                530FB3031E7A1146003C19DD /* WasmWorklist.cpp */,
+                                530FB3011E7A0B6E003C19DD /* WasmWorklist.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">@@ -6449,6 +6460,8 @@
</span><span class="cx">                                 14A1563010966365006FA260 /* DateInstanceCache.h */,
</span><span class="cx">                                 BCD203470E17135E002C7E82 /* DatePrototype.cpp */,
</span><span class="cx">                                 BCD203480E17135E002C7E82 /* DatePrototype.h */,
</span><ins>+                                534638761E71E06E00F12AC1 /* PromiseDeferredTimer.cpp */,
+                                534638741E70DDEC00F12AC1 /* PromiseDeferredTimer.h */,
</ins><span class="cx">                                 169948EDE68D4054B01EF797 /* DefinePropertyAttributes.h */,
</span><span class="cx">                                 0FE0500F1AA9091100D33B33 /* DirectArguments.cpp */,
</span><span class="cx">                                 0FE050101AA9091100D33B33 /* DirectArguments.h */,
</span><span class="lines">@@ -6837,6 +6850,8 @@
</span><span class="cx">                                 0F7C39FC1C8F659500480151 /* RegExpObjectInlines.h */,
</span><span class="cx">                                 BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */,
</span><span class="cx">                                 BCD202C00E1706A7002C7E82 /* RegExpPrototype.h */,
</span><ins>+                                534638721E70D01500F12AC1 /* JSRunLoopTimer.cpp */,
+                                534638701E70CF3D00F12AC1 /* JSRunLoopTimer.h */,
</ins><span class="cx">                                 70B0A9D01A9B66200001306A /* RuntimeFlags.h */,
</span><span class="cx">                                 527773DD1AAF83AC00BDE7E8 /* RuntimeType.cpp */,
</span><span class="cx">                                 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */,
</span><span class="lines">@@ -8130,6 +8145,7 @@
</span><span class="cx">                                 0FEC85061BDACDAC0080FF74 /* B3CheckSpecial.h in Headers */,
</span><span class="cx">                                 0FEC85081BDACDAC0080FF74 /* B3CheckValue.h in Headers */,
</span><span class="cx">                                 0FEC850A1BDACDAC0080FF74 /* B3Common.h in Headers */,
</span><ins>+                                530FB3021E7A0B6E003C19DD /* WasmWorklist.h in Headers */,
</ins><span class="cx">                                 0FEC850C1BDACDAC0080FF74 /* B3Commutativity.h in Headers */,
</span><span class="cx">                                 0F338E0C1BF0276C0013C88F /* B3Compilation.h in Headers */,
</span><span class="cx">                                 7919B7801E03559C005BEED8 /* B3Compile.h in Headers */,
</span><span class="lines">@@ -8250,6 +8266,7 @@
</span><span class="cx">                                 BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */,
</span><span class="cx">                                 0F64B27A1A7957B2006E4E66 /* CallEdge.h in Headers */,
</span><span class="cx">                                 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */,
</span><ins>+                                534638751E70DDEC00F12AC1 /* PromiseDeferredTimer.h in Headers */,
</ins><span class="cx">                                 62EC9BB71B7EB07C00303AD1 /* CallFrameShuffleData.h in Headers */,
</span><span class="cx">                                 0FF4B4BD1E88449A00DBBE86 /* AirRegLiveness.h in Headers */,
</span><span class="cx">                                 62D755D71B84FB4A001801FA /* CallFrameShuffler.h in Headers */,
</span><span class="lines">@@ -8537,6 +8554,7 @@
</span><span class="cx">                                 E3FF75331D9CEA1800C7E16D /* DOMJITGetterSetter.h in Headers */,
</span><span class="cx">                                 E35CA1541DBC3A5C00F83516 /* DOMJITHeapRange.h in Headers */,
</span><span class="cx">                                 E3C08E3C1DA41B810039478F /* DOMJITPatchpoint.h in Headers */,
</span><ins>+                                534638711E70CF3D00F12AC1 /* JSRunLoopTimer.h in Headers */,
</ins><span class="cx">                                 FE6F56DE1E64EAD600D17801 /* VMTraps.h in Headers */,
</span><span class="cx">                                 E37AD83C1DA4928600F3D412 /* DOMJITPatchpointParams.h in Headers */,
</span><span class="cx">                                 E37AD83D1DA4928600F3D412 /* DOMJITReg.h in Headers */,
</span><span class="lines">@@ -8707,7 +8725,6 @@
</span><span class="cx">                                 A5398FAB1C750DA40060A963 /* HeapProfiler.h in Headers */,
</span><span class="cx">                                 A54C2AB11C6544F200A18D78 /* HeapSnapshot.h in Headers */,
</span><span class="cx">                                 A5311C361C77CEC500E6B1B6 /* HeapSnapshotBuilder.h in Headers */,
</span><del>-                                C2E526BE1590EF000054E48D /* HeapTimer.h in Headers */,
</del><span class="cx">                                 0FD0E5EA1E43D34D0006AB08 /* GCConductor.h in Headers */,
</span><span class="cx">                                 0FADE6731D4D23BE00768457 /* HeapUtil.h in Headers */,
</span><span class="cx">                                 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */,
</span><span class="lines">@@ -9157,6 +9174,7 @@
</span><span class="cx">                                 BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */,
</span><span class="cx">                                 A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */,
</span><span class="cx">                                 BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */,
</span><ins>+                                53F8D2001E8387D400D21116 /* WasmPlanInlines.h in Headers */,
</ins><span class="cx">                                 BCD202D60E170708002C7E82 /* RegExpConstructor.lut.h in Headers */,
</span><span class="cx">                                 0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */,
</span><span class="cx">                                 A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */,
</span><span class="lines">@@ -9977,6 +9995,7 @@
</span><span class="cx">                                 0FEC850F1BDACDAC0080FF74 /* B3Const64Value.cpp in Sources */,
</span><span class="cx">                                 0FF4B4CA1E889D7B00DBBE86 /* B3VariableLiveness.cpp in Sources */,
</span><span class="cx">                                 0FEC85111BDACDAC0080FF74 /* B3ConstDoubleValue.cpp in Sources */,
</span><ins>+                                530FB3041E7A1146003C19DD /* WasmWorklist.cpp in Sources */,
</ins><span class="cx">                                 43422A621C158E6A00E2EB98 /* B3ConstFloatValue.cpp in Sources */,
</span><span class="cx">                                 0F338DF51BE93D550013C88F /* B3ConstrainedValue.cpp in Sources */,
</span><span class="cx">                                 0F338E0D1BF0276C0013C88F /* B3DataSection.cpp in Sources */,
</span><span class="lines">@@ -10270,6 +10289,7 @@
</span><span class="cx">                                 14AD91171DCA97FD0014F9FE /* EvalCodeBlock.cpp in Sources */,
</span><span class="cx">                                 147341E21DC2CE9600AA29BA /* EvalExecutable.cpp in Sources */,
</span><span class="cx">                                 A54982031891D0B00081E5B8 /* EventLoop.cpp in Sources */,
</span><ins>+                                534638731E70D01500F12AC1 /* JSRunLoopTimer.cpp in Sources */,
</ins><span class="cx">                                 FE1C0FFF1B194FD100B53FCA /* Exception.cpp in Sources */,
</span><span class="cx">                                 FE80C19B1D776A98008510C0 /* ExceptionEventLocation.cpp in Sources */,
</span><span class="cx">                                 0F12DE0F1979D5FD0006FF4E /* ExceptionFuzz.cpp in Sources */,
</span><span class="lines">@@ -10347,7 +10367,6 @@
</span><span class="cx">                                 A5398FAC1C750DA60060A963 /* HeapProfiler.cpp in Sources */,
</span><span class="cx">                                 A54C2AB01C6544EE00A18D78 /* HeapSnapshot.cpp in Sources */,
</span><span class="cx">                                 A5311C371C77CECA00E6B1B6 /* HeapSnapshotBuilder.cpp in Sources */,
</span><del>-                                C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */,
</del><span class="cx">                                 0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */,
</span><span class="cx">                                 DC2143081CA32E58000A8869 /* ICStats.cpp in Sources */,
</span><span class="cx">                                 147F39CE107EC37600427A48 /* Identifier.cpp in Sources */,
</span><span class="lines">@@ -10672,6 +10691,7 @@
</span><span class="cx">                                 992ABCF91BEA9BD2006403A0 /* RemoteAutomationTarget.cpp in Sources */,
</span><span class="cx">                                 992F56B41E4E84A40035953B /* RemoteConnectionToTargetCocoa.mm in Sources */,
</span><span class="cx">                                 998ED6741BED70AC00DD8017 /* RemoteControllableTarget.cpp in Sources */,
</span><ins>+                                534638771E71E06E00F12AC1 /* PromiseDeferredTimer.cpp in Sources */,
</ins><span class="cx">                                 A594558F18245EFD00CC3843 /* RemoteInspectionTarget.cpp in Sources */,
</span><span class="cx">                                 995566861E4E8B0F00AAE13C /* RemoteInspector.cpp in Sources */,
</span><span class="cx">                                 992F56B51E4E84A80035953B /* RemoteInspectorCocoa.mm in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCActivityCallbackh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/GCActivityCallback.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCActivityCallback.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/heap/GCActivityCallback.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -28,7 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include &quot;HeapTimer.h&quot;
</del><ins>+#include &quot;JSRunLoopTimer.h&quot;
</ins><span class="cx"> #include &lt;wtf/RefPtr.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #if USE(CF)
</span><span class="lines">@@ -40,8 +40,9 @@
</span><span class="cx"> class FullGCActivityCallback;
</span><span class="cx"> class Heap;
</span><span class="cx"> 
</span><del>-class JS_EXPORT_PRIVATE GCActivityCallback : public HeapTimer {
</del><ins>+class JS_EXPORT_PRIVATE GCActivityCallback : public JSRunLoopTimer {
</ins><span class="cx"> public:
</span><ins>+    using Base = JSRunLoopTimer;
</ins><span class="cx">     static RefPtr&lt;FullGCActivityCallback&gt; createFullTimer(Heap*);
</span><span class="cx">     static RefPtr&lt;GCActivityCallback&gt; createEdenTimer(Heap*);
</span><span class="cx"> 
</span><span class="lines">@@ -70,7 +71,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(CF)
</span><span class="cx">     GCActivityCallback(VM* vm)
</span><del>-        : HeapTimer(vm)
</del><ins>+        : Base(vm)
</ins><span class="cx">         , m_enabled(true)
</span><span class="cx">         , m_delay(s_decade)
</span><span class="cx">     {
</span><span class="lines">@@ -77,7 +78,7 @@
</span><span class="cx">     }
</span><span class="cx"> #elif USE(GLIB)
</span><span class="cx">     GCActivityCallback(VM* vm)
</span><del>-        : HeapTimer(vm)
</del><ins>+        : Base(vm)
</ins><span class="cx">         , m_enabled(true)
</span><span class="cx">         , m_delay(s_decade)
</span><span class="cx">     {
</span><span class="lines">@@ -84,7 +85,7 @@
</span><span class="cx">     }
</span><span class="cx"> #else
</span><span class="cx">     GCActivityCallback(VM* vm)
</span><del>-        : HeapTimer(vm)
</del><ins>+        : Base(vm)
</ins><span class="cx">         , m_enabled(true)
</span><span class="cx">     {
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapTimercpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/HeapTimer.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapTimer.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/heap/HeapTimer.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -1,199 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012, 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;HeapTimer.h&quot;
-
-#include &quot;GCActivityCallback.h&quot;
-#include &quot;IncrementalSweeper.h&quot;
-#include &quot;JSObject.h&quot;
-#include &quot;JSString.h&quot;
-#include &quot;JSCInlines.h&quot;
-#include &lt;wtf/MainThread.h&gt;
-#include &lt;wtf/Threading.h&gt;
-
-#if USE(GLIB)
-#include &lt;glib.h&gt;
-#endif
-
-namespace JSC {
-
-#if USE(CF)
-    
-const CFTimeInterval HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10;
-
-HeapTimer::HeapTimer(VM* vm)
-    : m_vm(vm)
-    , m_apiLock(&amp;vm-&gt;apiLock())
-{
-    setRunLoop(vm-&gt;heap.runLoop());
-}
-
-void HeapTimer::setRunLoop(CFRunLoopRef runLoop)
-{
-    if (m_runLoop) {
-        CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
-        CFRunLoopTimerInvalidate(m_timer.get());
-        m_runLoop.clear();
-        m_timer.clear();
-    }
-    
-    if (runLoop) {
-        m_runLoop = runLoop;
-        memset(&amp;m_context, 0, sizeof(CFRunLoopTimerContext));
-        m_context.info = this;
-        m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, s_decade, s_decade, 0, 0, HeapTimer::timerDidFire, &amp;m_context));
-        CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
-    }
-}
-
-HeapTimer::~HeapTimer()
-{
-    setRunLoop(0);
-}
-
-void HeapTimer::timerDidFire(CFRunLoopTimerRef, void* contextPtr)
-{
-    HeapTimer* timer = static_cast&lt;HeapTimer*&gt;(contextPtr);
-    timer-&gt;m_apiLock-&gt;lock();
-
-    RefPtr&lt;VM&gt; vm = timer-&gt;m_apiLock-&gt;vm();
-    if (!vm) {
-        // The VM has been destroyed, so we should just give up.
-        timer-&gt;m_apiLock-&gt;unlock();
-        return;
-    }
-
-    {
-        JSLockHolder locker(vm.get());
-        timer-&gt;doWork();
-    }
-
-    timer-&gt;m_apiLock-&gt;unlock();
-}
-
-void HeapTimer::scheduleTimer(double intervalInSeconds)
-{
-    CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + intervalInSeconds);
-    m_isScheduled = true;
-}
-
-void HeapTimer::cancelTimer()
-{
-    CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
-    m_isScheduled = false;
-}
-
-#elif USE(GLIB)
-
-const long HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10;
-
-static GSourceFuncs heapTimerSourceFunctions = {
-    nullptr, // prepare
-    nullptr, // check
-    // dispatch
-    [](GSource*, GSourceFunc callback, gpointer userData) -&gt; gboolean
-    {
-        return callback(userData);
-    },
-    nullptr, // finalize
-    nullptr, // closure_callback
-    nullptr, // closure_marshall
-};
-
-HeapTimer::HeapTimer(VM* vm)
-    : m_vm(vm)
-    , m_apiLock(&amp;vm-&gt;apiLock())
-    , m_timer(adoptGRef(g_source_new(&amp;heapTimerSourceFunctions, sizeof(GSource))))
-{
-    g_source_set_name(m_timer.get(), &quot;[JavaScriptCore] HeapTimer&quot;);
-    g_source_set_callback(m_timer.get(), [](gpointer userData) -&gt; gboolean {
-        auto&amp; heapTimer = *static_cast&lt;HeapTimer*&gt;(userData);
-        g_source_set_ready_time(heapTimer.m_timer.get(), g_get_monotonic_time() + HeapTimer::s_decade * G_USEC_PER_SEC);
-        heapTimer.timerDidFire();
-        return G_SOURCE_CONTINUE;
-    }, this, nullptr);
-    g_source_attach(m_timer.get(), g_main_context_get_thread_default());
-}
-
-HeapTimer::~HeapTimer()
-{
-    g_source_destroy(m_timer.get());
-}
-
-void HeapTimer::timerDidFire()
-{
-    m_apiLock-&gt;lock();
-
-    if (!m_apiLock-&gt;vm()) {
-        // The VM has been destroyed, so we should just give up.
-        m_apiLock-&gt;unlock();
-        return;
-    }
-
-    {
-        JSLockHolder locker(m_vm);
-        doWork();
-    }
-
-    m_apiLock-&gt;unlock();
-}
-
-void HeapTimer::scheduleTimer(double intervalInSeconds)
-{
-    g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + intervalInSeconds * G_USEC_PER_SEC);
-    m_isScheduled = true;
-}
-
-void HeapTimer::cancelTimer()
-{
-    g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + s_decade * G_USEC_PER_SEC);
-    m_isScheduled = false;
-}
-#else
-HeapTimer::HeapTimer(VM* vm)
-    : m_vm(vm)
-{
-}
-
-HeapTimer::~HeapTimer()
-{
-}
-
-void HeapTimer::invalidate()
-{
-}
-
-void HeapTimer::scheduleTimer(double)
-{
-}
-
-void HeapTimer::cancelTimer()
-{
-}
-#endif
-    
-
-} // namespace JSC
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapTimerh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/HeapTimer.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapTimer.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/heap/HeapTimer.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -1,89 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012, 2015-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
-
-#include &lt;wtf/Lock.h&gt;
-#include &lt;wtf/RefPtr.h&gt;
-#include &lt;wtf/RetainPtr.h&gt;
-#include &lt;wtf/ThreadSafeRefCounted.h&gt;
-#include &lt;wtf/Threading.h&gt;
-
-#if USE(CF)
-#include &lt;CoreFoundation/CoreFoundation.h&gt;
-#endif
-
-#if USE(GLIB)
-#include &lt;wtf/glib/GRefPtr.h&gt;
-#endif
-
-namespace JSC {
-
-class JSLock;
-class VM;
-
-class HeapTimer : public ThreadSafeRefCounted&lt;HeapTimer&gt; {
-public:
-    HeapTimer(VM*);
-#if USE(CF)
-    static void timerDidFire(CFRunLoopTimerRef, void*);
-#endif
-    
-    JS_EXPORT_PRIVATE virtual ~HeapTimer();
-    virtual void doWork() = 0;
-
-    void scheduleTimer(double intervalInSeconds);
-    void cancelTimer();
-    bool isScheduled() const { return m_isScheduled; }
-
-#if USE(CF)
-    JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef);
-#endif // USE(CF)
-    
-protected:
-    VM* m_vm;
-
-    RefPtr&lt;JSLock&gt; m_apiLock;
-    bool m_isScheduled { false };
-#if USE(CF)
-    static const CFTimeInterval s_decade;
-
-    RetainPtr&lt;CFRunLoopTimerRef&gt; m_timer;
-    RetainPtr&lt;CFRunLoopRef&gt; m_runLoop;
-    
-    CFRunLoopTimerContext m_context;
-
-    Lock m_shutdownMutex;
-#elif USE(GLIB)
-    static const long s_decade;
-    void timerDidFire();
-    GRefPtr&lt;GSource&gt; m_timer;
-#endif
-    
-private:
-    void invalidate();
-};
-
-} // namespace JSC
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapIncrementalSweepercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -41,11 +41,11 @@
</span><span class="cx"> 
</span><span class="cx"> void IncrementalSweeper::scheduleTimer()
</span><span class="cx"> {
</span><del>-    HeapTimer::scheduleTimer(sweepTimeSlice * sweepTimeMultiplier);
</del><ins>+    Base::scheduleTimer(sweepTimeSlice * sweepTimeMultiplier);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> IncrementalSweeper::IncrementalSweeper(Heap* heap)
</span><del>-    : HeapTimer(heap-&gt;vm())
</del><ins>+    : Base(heap-&gt;vm())
</ins><span class="cx">     , m_currentAllocator(nullptr)
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapIncrementalSweeperh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include &quot;HeapTimer.h&quot;
</del><ins>+#include &quot;JSRunLoopTimer.h&quot;
</ins><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -33,8 +33,9 @@
</span><span class="cx"> class Heap;
</span><span class="cx"> class MarkedAllocator;
</span><span class="cx"> 
</span><del>-class IncrementalSweeper : public HeapTimer {
</del><ins>+class IncrementalSweeper : public JSRunLoopTimer {
</ins><span class="cx"> public:
</span><ins>+    using Base = JSRunLoopTimer;
</ins><span class="cx">     JS_EXPORT_PRIVATE explicit IncrementalSweeper(Heap*);
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void startSweeping();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapStopIfNecessaryTimercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> StopIfNecessaryTimer::StopIfNecessaryTimer(VM* vm)
</span><del>-    : HeapTimer(vm)
</del><ins>+    : Base(vm)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapStopIfNecessaryTimerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -25,14 +25,15 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include &quot;HeapTimer.h&quot;
</del><ins>+#include &quot;JSRunLoopTimer.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class Heap;
</span><span class="cx"> 
</span><del>-class StopIfNecessaryTimer : public HeapTimer {
</del><ins>+class StopIfNecessaryTimer : public JSRunLoopTimer {
</ins><span class="cx"> public:
</span><ins>+    using Base = JSRunLoopTimer;
</ins><span class="cx">     explicit StopIfNecessaryTimer(VM*);
</span><span class="cx">     
</span><span class="cx">     void doWork() override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapStrongInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/StrongInlines.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/StrongInlines.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/heap/StrongInlines.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><ins>+#include &quot;JSCJSValueInlines.h&quot;
</ins><span class="cx"> #include &quot;VM.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -62,6 +62,7 @@
</span><span class="cx"> #include &quot;ObjectConstructor.h&quot;
</span><span class="cx"> #include &quot;ParserError.h&quot;
</span><span class="cx"> #include &quot;ProfilerDatabase.h&quot;
</span><ins>+#include &quot;PromiseDeferredTimer.h&quot;
</ins><span class="cx"> #include &quot;ProtoCallFrame.h&quot;
</span><span class="cx"> #include &quot;ReleaseHeapAccessScope.h&quot;
</span><span class="cx"> #include &quot;SamplingProfiler.h&quot;
</span><span class="lines">@@ -73,8 +74,9 @@
</span><span class="cx"> #include &quot;TestRunnerUtils.h&quot;
</span><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><span class="cx"> #include &quot;WasmFaultSignalHandler.h&quot;
</span><del>-#include &quot;WasmPlan.h&quot;
</del><span class="cx"> #include &quot;WasmMemory.h&quot;
</span><ins>+#include &quot;WasmPlanInlines.h&quot;
+#include &quot;WasmWorklist.h&quot;
</ins><span class="cx"> #include &lt;locale.h&gt;
</span><span class="cx"> #include &lt;math.h&gt;
</span><span class="cx"> #include &lt;stdio.h&gt;
</span><span class="lines">@@ -907,8 +909,8 @@
</span><span class="cx"> const ClassInfo DOMJITFunctionObject::s_info = { &quot;DOMJITFunctionObject&quot;, &amp;Base::s_info, nullptr, CREATE_METHOD_TABLE(DOMJITFunctionObject) };
</span><span class="cx"> const ClassInfo RuntimeArray::s_info = { &quot;RuntimeArray&quot;, &amp;Base::s_info, nullptr, CREATE_METHOD_TABLE(RuntimeArray) };
</span><span class="cx"> const ClassInfo SimpleObject::s_info = { &quot;SimpleObject&quot;, &amp;Base::s_info, nullptr, CREATE_METHOD_TABLE(SimpleObject) };
</span><del>-static bool test262AsyncPassed { false };
-static bool test262AsyncTest { false };
</del><ins>+static unsigned asyncTestPasses { 0 };
+static unsigned asyncTestExpectedPasses { 0 };
</ins><span class="cx"> 
</span><span class="cx"> ElementHandleOwner* Element::handleOwner()
</span><span class="cx"> {
</span><span class="lines">@@ -1077,6 +1079,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*);
</span><ins>+static EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*);
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionTestWasmModuleFunctions(ExecState*);
</span><span class="lines">@@ -1349,6 +1353,9 @@
</span><span class="cx"> 
</span><span class="cx">         addFunction(vm, &quot;maxArguments&quot;, functionMaxArguments, 0);
</span><span class="cx"> 
</span><ins>+        addFunction(vm, &quot;asyncTestStart&quot;, functionAsyncTestStart, 1);
+        addFunction(vm, &quot;asyncTestPassed&quot;, functionAsyncTestPassed, 1);
+
</ins><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx">         addFunction(vm, &quot;testWasmModuleFunctions&quot;, functionTestWasmModuleFunctions, 0);
</span><span class="cx"> #endif
</span><span class="lines">@@ -1732,11 +1739,12 @@
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><del>-    if (test262AsyncTest) {
</del><ins>+    if (asyncTestExpectedPasses) {
</ins><span class="cx">         JSValue value = exec-&gt;argument(0);
</span><del>-        if (value.isString() &amp;&amp; WTF::equal(asString(value)-&gt;value(exec).impl(), &quot;Test262:AsyncTestComplete&quot;))
-            test262AsyncPassed = true;
-        return JSValue::encode(jsUndefined());
</del><ins>+        if (value.isString() &amp;&amp; WTF::equal(asString(value)-&gt;value(exec).impl(), &quot;Test262:AsyncTestComplete&quot;)) {
+            asyncTestPasses++;
+            return JSValue::encode(jsUndefined());
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = 0; i &lt; exec-&gt;argumentCount(); ++i) {
</span><span class="lines">@@ -3049,6 +3057,25 @@
</span><span class="cx">     return JSValue::encode(jsNumber(JSC::maxArguments));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState* exec)
+{
+    VM&amp; vm = exec-&gt;vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue numberOfAsyncPasses = exec-&gt;argument(0);
+    if (!numberOfAsyncPasses.isUInt32())
+        return throwVMError(exec, scope, ASCIILiteral(&quot;Expected first argument to a uint32&quot;));
+
+    asyncTestExpectedPasses += numberOfAsyncPasses.asUInt32();
+    return encodedJSUndefined();
+}
+
+EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*)
+{
+    asyncTestPasses++;
+    return encodedJSUndefined();
+}
+
</ins><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><span class="cx"> static CString valueWithTypeOfWasmValue(ExecState* exec, VM&amp; vm, JSValue value, JSValue wasmValue)
</span><span class="lines">@@ -3159,14 +3186,15 @@
</span><span class="cx">     if (exec-&gt;argumentCount() != functionCount + 2)
</span><span class="cx">         CRASH();
</span><span class="cx"> 
</span><del>-    Wasm::Plan plan(&amp;vm, static_cast&lt;uint8_t*&gt;(source-&gt;vector()), source-&gt;length());
-    plan.run();
-    if (plan.failed()) {
-        dataLogLn(&quot;failed to parse module: &quot;, plan.errorMessage());
</del><ins>+    Ref&lt;Wasm::Plan&gt; plan = adoptRef(*new Wasm::Plan(vm, static_cast&lt;uint8_t*&gt;(source-&gt;vector()), source-&gt;length(), Wasm::Plan::FullCompile, Wasm::Plan::dontFinalize));
+    Wasm::ensureWorklist().enqueue(plan.copyRef());
+    Wasm::ensureWorklist().completePlanSynchronously(plan.get());
+    if (plan-&gt;failed()) {
+        dataLogLn(&quot;failed to parse module: &quot;, plan-&gt;errorMessage());
</ins><span class="cx">         CRASH();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (plan.internalFunctionCount() != functionCount)
</del><ins>+    if (plan-&gt;internalFunctionCount() != functionCount)
</ins><span class="cx">         CRASH();
</span><span class="cx"> 
</span><span class="cx">     MarkedArgumentBuffer callees;
</span><span class="lines">@@ -3173,7 +3201,7 @@
</span><span class="cx">     MarkedArgumentBuffer keepAlive;
</span><span class="cx">     {
</span><span class="cx">         unsigned lastIndex = UINT_MAX;
</span><del>-        plan.initializeCallees(exec-&gt;lexicalGlobalObject(),
</del><ins>+        plan-&gt;initializeCallees(
</ins><span class="cx">             [&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
</span><span class="cx">                 RELEASE_ASSERT(!calleeIndex || (calleeIndex - 1 == lastIndex));
</span><span class="cx">                 callees.append(jsEntrypointCallee);
</span><span class="lines">@@ -3181,7 +3209,7 @@
</span><span class="cx">                 lastIndex = calleeIndex;
</span><span class="cx">             });
</span><span class="cx">     }
</span><del>-    std::unique_ptr&lt;Wasm::ModuleInformation&gt; moduleInformation = plan.takeModuleInformation();
</del><ins>+    std::unique_ptr&lt;Wasm::ModuleInformation&gt; moduleInformation = plan-&gt;takeModuleInformation();
</ins><span class="cx">     RELEASE_ASSERT(!moduleInformation-&gt;memory);
</span><span class="cx"> 
</span><span class="cx">     for (uint32_t i = 0; i &lt; functionCount; ++i) {
</span><span class="lines">@@ -3666,7 +3694,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!strcmp(arg, &quot;--test262-async&quot;)) {
</span><del>-            test262AsyncTest = true;
</del><ins>+            asyncTestExpectedPasses++;
</ins><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -3738,48 +3766,64 @@
</span><span class="cx">     Worker worker(Workers::singleton());
</span><span class="cx">     
</span><span class="cx">     VM&amp; vm = VM::create(LargeHeap).leakRef();
</span><del>-    JSLockHolder locker(&amp;vm);
-
</del><span class="cx">     int result;
</span><del>-    if (options.m_profile &amp;&amp; !vm.m_perBytecodeProfiler)
-        vm.m_perBytecodeProfiler = std::make_unique&lt;Profiler::Database&gt;(vm);
</del><ins>+    bool success;
+    {
+        JSLockHolder locker(vm);
</ins><span class="cx"> 
</span><del>-    GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments);
-    globalObject-&gt;setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
-    bool success = func(vm, globalObject);
-    if (options.m_interactive &amp;&amp; success)
-        runInteractive(globalObject);
</del><ins>+        if (options.m_profile &amp;&amp; !vm.m_perBytecodeProfiler)
+            vm.m_perBytecodeProfiler = std::make_unique&lt;Profiler::Database&gt;(vm);
</ins><span class="cx"> 
</span><del>-    vm.drainMicrotasks();
-    result = success &amp;&amp; (test262AsyncTest == test262AsyncPassed) ? 0 : 3;
</del><ins>+        GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments);
+        globalObject-&gt;setRemoteDebuggingEnabled(options.m_enableRemoteDebugging);
+        success = func(vm, globalObject);
+        if (options.m_interactive &amp;&amp; success)
+            runInteractive(globalObject);
</ins><span class="cx"> 
</span><del>-    if (options.m_exitCode)
-        printf(&quot;jsc exiting %d\n&quot;, result);
</del><ins>+        vm.drainMicrotasks();
+    }
+#if USE(CF)
+    vm.promiseDeferredTimer-&gt;runRunLoop();
+#endif
</ins><span class="cx"> 
</span><ins>+    result = success &amp;&amp; (asyncTestExpectedPasses == asyncTestPasses) ? 0 : 3;
+
+    if (options.m_exitCode) {
+        printf(&quot;jsc exiting %d&quot;, result);
+        if (asyncTestExpectedPasses != asyncTestPasses)
+            printf(&quot; because expected: %d async test passes but got: %d async test passes&quot;, asyncTestExpectedPasses, asyncTestPasses);
+        printf(&quot;\n&quot;);
+    }
+
</ins><span class="cx">     if (options.m_profile) {
</span><ins>+        JSLockHolder locker(vm);
</ins><span class="cx">         if (!vm.m_perBytecodeProfiler-&gt;save(options.m_profilerOutput.utf8().data()))
</span><span class="cx">             fprintf(stderr, &quot;could not save profiler output.\n&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><del>-    if (Options::useExceptionFuzz())
-        printf(&quot;JSC EXCEPTION FUZZ: encountered %u checks.\n&quot;, numberOfExceptionFuzzChecks());
-    bool fireAtEnabled =
-    Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
-    if (Options::useExecutableAllocationFuzz() &amp;&amp; (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
-        printf(&quot;JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n&quot;, numberOfExecutableAllocationFuzzChecks());
-    if (Options::useOSRExitFuzz()) {
-        printf(&quot;JSC OSR EXIT FUZZ: encountered %u static checks.\n&quot;, numberOfStaticOSRExitFuzzChecks());
-        printf(&quot;JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n&quot;, numberOfOSRExitFuzzChecks());
</del><ins>+    {
+        JSLockHolder locker(vm);
+        if (Options::useExceptionFuzz())
+            printf(&quot;JSC EXCEPTION FUZZ: encountered %u checks.\n&quot;, numberOfExceptionFuzzChecks());
+        bool fireAtEnabled =
+        Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter();
+        if (Options::useExecutableAllocationFuzz() &amp;&amp; (!fireAtEnabled || Options::verboseExecutableAllocationFuzz()))
+            printf(&quot;JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n&quot;, numberOfExecutableAllocationFuzzChecks());
+        if (Options::useOSRExitFuzz()) {
+            printf(&quot;JSC OSR EXIT FUZZ: encountered %u static checks.\n&quot;, numberOfStaticOSRExitFuzzChecks());
+            printf(&quot;JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n&quot;, numberOfOSRExitFuzzChecks());
+        }
+
+        
+        auto compileTimeStats = JIT::compileTimeStats();
+        Vector&lt;CString&gt; compileTimeKeys;
+        for (auto&amp; entry : compileTimeStats)
+            compileTimeKeys.append(entry.key);
+        std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
+        for (CString key : compileTimeKeys)
+            printf(&quot;%40s: %.3lf ms\n&quot;, key.data(), compileTimeStats.get(key));
</ins><span class="cx">     }
</span><del>-
-    auto compileTimeStats = JIT::compileTimeStats();
-    Vector&lt;CString&gt; compileTimeKeys;
-    for (auto&amp; entry : compileTimeStats)
-        compileTimeKeys.append(entry.key);
-    std::sort(compileTimeKeys.begin(), compileTimeKeys.end());
-    for (CString key : compileTimeKeys)
-        printf(&quot;%40s: %.3lf ms\n&quot;, key.data(), compileTimeStats.get(key));
</del><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     if (Options::gcAtEnd()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSPromiseDeferredcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;JSObjectInlines.h&quot;
</span><span class="cx"> #include &quot;JSPromise.h&quot;
</span><span class="cx"> #include &quot;JSPromiseConstructor.h&quot;
</span><ins>+#include &quot;PromiseDeferredTimer.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -99,11 +100,15 @@
</span><span class="cx"> void JSPromiseDeferred::resolve(ExecState* exec, JSValue value)
</span><span class="cx"> {
</span><span class="cx">     callFunction(exec, m_resolve.get(), value);
</span><ins>+    bool wasPending = exec-&gt;vm().promiseDeferredTimer-&gt;cancelPendingPromise(this);
+    ASSERT_UNUSED(wasPending, wasPending == m_promiseIsAsyncPending);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSPromiseDeferred::reject(ExecState* exec, JSValue reason)
</span><span class="cx"> {
</span><span class="cx">     callFunction(exec, m_reject.get(), reason);
</span><ins>+    bool wasPending = exec-&gt;vm().promiseDeferredTimer-&gt;cancelPendingPromise(this);
+    ASSERT_UNUSED(wasPending, wasPending == m_promiseIsAsyncPending);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSPromiseDeferred::reject(ExecState* exec, Exception* reason)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSPromiseDeferredh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -56,6 +56,10 @@
</span><span class="cx">     JS_EXPORT_PRIVATE void reject(ExecState*, JSValue);
</span><span class="cx">     JS_EXPORT_PRIVATE void reject(ExecState*, Exception*);
</span><span class="cx"> 
</span><ins>+#ifndef NDEBUG
+    void promiseAsyncPending() { m_promiseIsAsyncPending = true; }
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx">     JSPromiseDeferred(VM&amp;, Structure*);
</span><span class="cx">     void finishCreation(VM&amp;, JSObject*, JSValue, JSValue);
</span><span class="lines">@@ -64,6 +68,10 @@
</span><span class="cx"> private:
</span><span class="cx">     JSPromiseDeferred(VM&amp;);
</span><span class="cx"> 
</span><ins>+#ifndef NDEBUG
+    bool m_promiseIsAsyncPending { false };
+#endif
+
</ins><span class="cx">     WriteBarrier&lt;JSObject&gt; m_promise;
</span><span class="cx">     WriteBarrier&lt;Unknown&gt; m_resolve;
</span><span class="cx">     WriteBarrier&lt;Unknown&gt; m_reject;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSRunLoopTimercppfromrev214502trunkSourceJavaScriptCoreheapHeapTimercpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp (from rev 214502, trunk/Source/JavaScriptCore/heap/HeapTimer.cpp) (0 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -0,0 +1,199 @@
</span><ins>+/*
+ * Copyright (C) 2012, 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;JSRunLoopTimer.h&quot;
+
+#include &quot;GCActivityCallback.h&quot;
+#include &quot;IncrementalSweeper.h&quot;
+#include &quot;JSCInlines.h&quot;
+#include &quot;JSObject.h&quot;
+#include &quot;JSString.h&quot;
+
+#include &lt;wtf/MainThread.h&gt;
+#include &lt;wtf/Threading.h&gt;
+
+#if USE(GLIB)
+#include &lt;glib.h&gt;
+#endif
+
+namespace JSC {
+
+#if USE(CF)
+
+const CFTimeInterval JSRunLoopTimer::s_decade = 60 * 60 * 24 * 365 * 10;
+
+JSRunLoopTimer::JSRunLoopTimer(VM* vm)
+    : m_vm(vm)
+    , m_apiLock(&amp;vm-&gt;apiLock())
+{
+    setRunLoop(vm-&gt;heap.runLoop());
+}
+
+void JSRunLoopTimer::setRunLoop(CFRunLoopRef runLoop)
+{
+    if (m_runLoop) {
+        CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+        CFRunLoopTimerInvalidate(m_timer.get());
+        m_runLoop.clear();
+        m_timer.clear();
+    }
+
+    if (runLoop) {
+        m_runLoop = runLoop;
+        memset(&amp;m_context, 0, sizeof(CFRunLoopTimerContext));
+        m_context.info = this;
+        m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + s_decade, s_decade, 0, 0, JSRunLoopTimer::timerDidFire, &amp;m_context));
+        CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
+    }
+}
+
+JSRunLoopTimer::~JSRunLoopTimer()
+{
+    setRunLoop(0);
+}
+
+void JSRunLoopTimer::timerDidFire(CFRunLoopTimerRef, void* contextPtr)
+{
+    JSRunLoopTimer* timer = static_cast&lt;JSRunLoopTimer*&gt;(contextPtr);
+    timer-&gt;m_apiLock-&gt;lock();
+
+    RefPtr&lt;VM&gt; vm = timer-&gt;m_apiLock-&gt;vm();
+    if (!vm) {
+        // The VM has been destroyed, so we should just give up.
+        timer-&gt;m_apiLock-&gt;unlock();
+        return;
+    }
+
+    {
+        JSLockHolder locker(vm.get());
+        timer-&gt;doWork();
+    }
+
+    timer-&gt;m_apiLock-&gt;unlock();
+}
+
+void JSRunLoopTimer::scheduleTimer(double intervalInSeconds)
+{
+    CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + intervalInSeconds);
+    m_isScheduled = true;
+}
+
+void JSRunLoopTimer::cancelTimer()
+{
+    CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
+    m_isScheduled = false;
+}
+
+#elif USE(GLIB)
+
+const long JSRunLoopTimer::s_decade = 60 * 60 * 24 * 365 * 10;
+
+static GSourceFuncs JSRunLoopTimerSourceFunctions = {
+    nullptr, // prepare
+    nullptr, // check
+    // dispatch
+    [](GSource*, GSourceFunc callback, gpointer userData) -&gt; gboolean
+    {
+        return callback(userData);
+    },
+    nullptr, // finalize
+    nullptr, // closure_callback
+    nullptr, // closure_marshall
+};
+
+JSRunLoopTimer::JSRunLoopTimer(VM* vm)
+    : m_vm(vm)
+    , m_apiLock(&amp;vm-&gt;apiLock())
+    , m_timer(adoptGRef(g_source_new(&amp;JSRunLoopTimerSourceFunctions, sizeof(GSource))))
+{
+    g_source_set_name(m_timer.get(), &quot;[JavaScriptCore] JSRunLoopTimer&quot;);
+    g_source_set_callback(m_timer.get(), [](gpointer userData) -&gt; gboolean {
+        auto&amp; runLoopTimer = *static_cast&lt;JSRunLoopTimer*&gt;(userData);
+        g_source_set_ready_time(runLoopTimer.m_timer.get(), g_get_monotonic_time() + JSRunLoopTimer::s_decade * G_USEC_PER_SEC);
+        runLoopTimer.timerDidFire();
+        return G_SOURCE_CONTINUE;
+    }, this, nullptr);
+    g_source_attach(m_timer.get(), g_main_context_get_thread_default());
+}
+
+JSRunLoopTimer::~JSRunLoopTimer()
+{
+    g_source_destroy(m_timer.get());
+}
+
+void JSRunLoopTimer::timerDidFire()
+{
+    m_apiLock-&gt;lock();
+
+    if (!m_apiLock-&gt;vm()) {
+        // The VM has been destroyed, so we should just give up.
+        m_apiLock-&gt;unlock();
+        return;
+    }
+
+    {
+        JSLockHolder locker(m_vm);
+        doWork();
+    }
+
+    m_apiLock-&gt;unlock();
+}
+
+void JSRunLoopTimer::scheduleTimer(double intervalInSeconds)
+{
+    g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + intervalInSeconds * G_USEC_PER_SEC);
+    m_isScheduled = true;
+}
+
+void JSRunLoopTimer::cancelTimer()
+{
+    g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + s_decade * G_USEC_PER_SEC);
+    m_isScheduled = false;
+}
+#else
+JSRunLoopTimer::JSRunLoopTimer(VM* vm)
+    : m_vm(vm)
+{
+}
+
+JSRunLoopTimer::~JSRunLoopTimer()
+{
+}
+
+void JSRunLoopTimer::invalidate()
+{
+}
+
+void JSRunLoopTimer::scheduleTimer(double)
+{
+}
+
+void JSRunLoopTimer::cancelTimer()
+{
+}
+#endif
+    
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSRunLoopTimerhfromrev214502trunkSourceJavaScriptCoreheapHeapTimerh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.h (from rev 214502, trunk/Source/JavaScriptCore/heap/HeapTimer.h) (0 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -0,0 +1,89 @@
</span><ins>+/*
+ * Copyright (C) 2012, 2015-2017 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
+
+#include &lt;wtf/Lock.h&gt;
+#include &lt;wtf/RefPtr.h&gt;
+#include &lt;wtf/RetainPtr.h&gt;
+#include &lt;wtf/ThreadSafeRefCounted.h&gt;
+#include &lt;wtf/Threading.h&gt;
+
+#if USE(CF)
+#include &lt;CoreFoundation/CoreFoundation.h&gt;
+#endif
+
+#if USE(GLIB)
+#include &lt;wtf/glib/GRefPtr.h&gt;
+#endif
+
+namespace JSC {
+
+class JSLock;
+class VM;
+
+class JSRunLoopTimer : public ThreadSafeRefCounted&lt;JSRunLoopTimer&gt; {
+public:
+    JSRunLoopTimer(VM*);
+#if USE(CF)
+    static void timerDidFire(CFRunLoopTimerRef, void*);
+#endif
+
+    JS_EXPORT_PRIVATE virtual ~JSRunLoopTimer();
+    virtual void doWork() = 0;
+
+    void scheduleTimer(double intervalInSeconds);
+    void cancelTimer();
+    bool isScheduled() const { return m_isScheduled; }
+
+#if USE(CF)
+    JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef);
+#endif // USE(CF)
+
+protected:
+    VM* m_vm;
+
+    RefPtr&lt;JSLock&gt; m_apiLock;
+    bool m_isScheduled { false };
+#if USE(CF)
+    static const CFTimeInterval s_decade;
+
+    RetainPtr&lt;CFRunLoopTimerRef&gt; m_timer;
+    RetainPtr&lt;CFRunLoopRef&gt; m_runLoop;
+
+    CFRunLoopTimerContext m_context;
+
+    Lock m_shutdownMutex;
+#elif USE(GLIB)
+    static const long s_decade;
+    void timerDidFire();
+    GRefPtr&lt;GSource&gt; m_timer;
+#endif
+    
+private:
+    void invalidate();
+};
+    
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -252,6 +252,7 @@
</span><span class="cx">     v(unsigned, numberOfFTLCompilerThreads, computeNumberOfWorkerThreads(8, 2) - 1, Normal, nullptr) \
</span><span class="cx">     v(int32, priorityDeltaOfDFGCompilerThreads, computePriorityDeltaOfWorkerThreads(-1, 0), Normal, nullptr) \
</span><span class="cx">     v(int32, priorityDeltaOfFTLCompilerThreads, computePriorityDeltaOfWorkerThreads(-2, 0), Normal, nullptr) \
</span><ins>+    v(int32, priorityDeltaOfWasmCompilerThreads, computePriorityDeltaOfWorkerThreads(-1, 0), Normal, nullptr) \
</ins><span class="cx">     \
</span><span class="cx">     v(bool, useProfiler, false, Normal, nullptr) \
</span><span class="cx">     v(bool, disassembleBaselineForProfiler, true, Normal, nullptr) \
</span><span class="lines">@@ -428,6 +429,9 @@
</span><span class="cx">     v(bool, useCodeCache, true, Normal, &quot;If false, the unlinked byte code cache will not be used.&quot;) \
</span><span class="cx">     \
</span><span class="cx">     v(bool, useWebAssembly, true, Normal, &quot;Expose the WebAssembly global object.&quot;) \
</span><ins>+    \
+    v(bool, failToCompileWebAssemblyCode, false, Normal, &quot;If true, no Wasm::Plan will sucessfully compile a function.&quot;) \
+    \
</ins><span class="cx">     v(bool, simulateWebAssemblyLowMemory, false, Normal, &quot;If true, the Memory object won't mmap the full 'maximum' range and instead will allocate the minimum required amount.&quot;) \
</span><span class="cx">     v(bool, useWebAssemblyFastMemory, true, Normal, &quot;If true, we will try to use a 32-bit address space with a signal handler to bounds check wasm memory.&quot;) \
</span><span class="cx">     v(bool, useWebAssemblyFastTLS, true, Normal, &quot;If true, we will try to use fast thread-local storage if available on the current platform.&quot;)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimePromiseDeferredTimercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/PromiseDeferredTimer.cpp (0 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/PromiseDeferredTimer.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/PromiseDeferredTimer.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -0,0 +1,139 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;PromiseDeferredTimer.h&quot;
+
+#include &quot;JSPromiseDeferred.h&quot;
+#include &quot;StrongInlines.h&quot;
+#include &quot;VM.h&quot;
+
+#include &lt;wtf/Locker.h&gt;
+
+namespace JSC {
+
+static const bool verbose = false;
+
+PromiseDeferredTimer::PromiseDeferredTimer(VM&amp; vm)
+    : Base(&amp;vm)
+{
+}
+
+void PromiseDeferredTimer::doWork()
+{
+    ASSERT(m_vm-&gt;currentThreadIsHoldingAPILock());
+    LockHolder locker(m_taskLock);
+    cancelTimer();
+    if (!m_runTasks)
+        return;
+
+    while (!m_tasks.isEmpty()) {
+        JSPromiseDeferred* ticket;
+        Task task;
+        std::tie(ticket, task) = m_tasks.takeLast();
+        dataLogLnIf(verbose, &quot;Doing work on promise: &quot;, RawPointer(ticket));
+
+        // We may have already canceled these promises.
+        if (m_pendingPromises.contains(ticket)) {
+            task();
+            m_vm-&gt;drainMicrotasks();
+        }
+
+        auto waitingTasks = m_blockedTasks.take(ticket);
+        for (const Task&amp; unblockedTask : waitingTasks) {
+            unblockedTask();
+            m_vm-&gt;drainMicrotasks();
+        }
+    }
+
+#if USE(CF)
+    if (m_pendingPromises.isEmpty() &amp;&amp; m_shouldStopRunLoopWhenAllPromisesFinish)
+        CFRunLoopStop(m_runLoop.get());
+#endif
+}
+
+#if USE(CF)
+void PromiseDeferredTimer::runRunLoop()
+{
+    ASSERT(!m_vm-&gt;currentThreadIsHoldingAPILock());
+    ASSERT(CFRunLoopGetCurrent() == m_runLoop.get());
+    m_shouldStopRunLoopWhenAllPromisesFinish = true;
+    if (m_pendingPromises.size())
+        CFRunLoopRun();
+}
+#endif
+
+void PromiseDeferredTimer::addPendingPromise(JSPromiseDeferred* ticket, Vector&lt;Strong&lt;JSCell&gt;&gt;&amp;&amp; dependencies)
+{
+    ASSERT(m_vm-&gt;currentThreadIsHoldingAPILock());
+    for (unsigned i = 0; i &lt; dependencies.size(); ++i)
+        ASSERT(dependencies[i].get() != ticket);
+
+    auto result = m_pendingPromises.add(ticket, Vector&lt;Strong&lt;JSCell&gt;&gt;());
+    if (result.isNewEntry) {
+        dataLogLnIf(verbose, &quot;Adding new pending promise: &quot;, RawPointer(ticket));
+        dependencies.append(Strong&lt;JSCell&gt;(*m_vm, ticket));
+        result.iterator-&gt;value = WTFMove(dependencies);
+    } else {
+        dataLogLnIf(verbose, &quot;Adding new dependencies for promise: &quot;, RawPointer(ticket));
+        result.iterator-&gt;value.appendVector(dependencies);
+    }
+
+#ifndef NDEBUG
+    ticket-&gt;promiseAsyncPending();
+#endif
+}
+
+bool PromiseDeferredTimer::cancelPendingPromise(JSPromiseDeferred* ticket)
+{
+    ASSERT(m_vm-&gt;currentThreadIsHoldingAPILock());
+    bool result = m_pendingPromises.remove(ticket);
+
+    if (result)
+        dataLogLnIf(verbose, &quot;Canceling promise: &quot;, RawPointer(ticket));
+
+    auto blockedTasks = m_blockedTasks.take(ticket);
+    for (const Task&amp; task : blockedTasks)
+        task();
+    return result;
+}
+
+void PromiseDeferredTimer::scheduleWorkSoon(JSPromiseDeferred* ticket, Task&amp;&amp; task)
+{
+    LockHolder locker(m_taskLock);
+    m_tasks.append(std::make_tuple(ticket, WTFMove(task)));
+    if (!isScheduled())
+        scheduleTimer(0);
+}
+
+void PromiseDeferredTimer::scheduleBlockedTask(JSPromiseDeferred* blockingTicket, Task&amp;&amp; task)
+{
+    ASSERT(m_vm-&gt;currentThreadIsHoldingAPILock());
+    ASSERT(m_pendingPromises.contains(blockingTicket));
+    auto result = m_blockedTasks.add(blockingTicket, Vector&lt;Task&gt;());
+    result.iterator-&gt;value.append(WTFMove(task));
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimePromiseDeferredTimerhfromrev214502trunkSourceJavaScriptCoreheapHeapTimerh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/runtime/PromiseDeferredTimer.h (from rev 214502, trunk/Source/JavaScriptCore/heap/HeapTimer.h) (0 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/PromiseDeferredTimer.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/PromiseDeferredTimer.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -0,0 +1,79 @@
</span><ins>+/*
+ * Copyright (C) 2017 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
+
+#include &quot;JSRunLoopTimer.h&quot;
+#include &quot;Strong.h&quot;
+#include &quot;WriteBarrier.h&quot;
+
+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/Lock.h&gt;
+#include &lt;wtf/SharedTask.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC {
+
+class JSPromiseDeferred;
+class VM;
+class JSCell;
+
+class PromiseDeferredTimer : public JSRunLoopTimer {
+public:
+    using Base = JSRunLoopTimer;
+
+    PromiseDeferredTimer(VM&amp;);
+
+    void doWork() override;
+
+    void addPendingPromise(JSPromiseDeferred*, Vector&lt;Strong&lt;JSCell&gt;&gt;&amp;&amp; dependencies);
+    // JSPromiseDeferred should handle canceling when the promise is resolved or rejected.
+    bool cancelPendingPromise(JSPromiseDeferred*);
+
+    typedef std::function&lt;void()&gt; Task;
+    void scheduleWorkSoon(JSPromiseDeferred*, Task&amp;&amp;);
+
+    // Blocked tasks should only be registered while holding the JS API lock. If we didn't require holding the
+    // JS API lock then there might be a race where the promise you are waiting on is run before your task is
+    // registered.
+    void scheduleBlockedTask(JSPromiseDeferred*, Task&amp;&amp;);
+
+    void stopRunningTasks() { m_runTasks = false; }
+#if USE(CF)
+    JS_EXPORT_PRIVATE void runRunLoop();
+#endif
+
+private:
+    HashMap&lt;JSPromiseDeferred*, Vector&lt;Strong&lt;JSCell&gt;&gt;&gt; m_pendingPromises;
+    Lock m_taskLock;
+    bool m_runTasks { true };
+#if USE(CF)
+    bool m_shouldStopRunLoopWhenAllPromisesFinish { false };
+#endif
+    Vector&lt;std::tuple&lt;JSPromiseDeferred*, Task&gt;&gt; m_tasks;
+    HashMap&lt;JSPromiseDeferred*, Vector&lt;Task&gt;&gt; m_blockedTasks;
+};
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -85,6 +85,7 @@
</span><span class="cx"> #include &quot;Parser.h&quot;
</span><span class="cx"> #include &quot;ProfilerDatabase.h&quot;
</span><span class="cx"> #include &quot;ProgramCodeBlock.h&quot;
</span><ins>+#include &quot;PromiseDeferredTimer.h&quot;
</ins><span class="cx"> #include &quot;PropertyMapHashTable.h&quot;
</span><span class="cx"> #include &quot;RegExpCache.h&quot;
</span><span class="cx"> #include &quot;RegExpObject.h&quot;
</span><span class="lines">@@ -103,6 +104,7 @@
</span><span class="cx"> #include &quot;UnlinkedCodeBlock.h&quot;
</span><span class="cx"> #include &quot;VMEntryScope.h&quot;
</span><span class="cx"> #include &quot;VMInspector.h&quot;
</span><ins>+#include &quot;WasmWorklist.h&quot;
</ins><span class="cx"> #include &quot;Watchdog.h&quot;
</span><span class="cx"> #include &quot;WeakGCMapInlines.h&quot;
</span><span class="cx"> #include &quot;WeakMapData.h&quot;
</span><span class="lines">@@ -177,6 +179,7 @@
</span><span class="cx">     , clientData(0)
</span><span class="cx">     , topVMEntryFrame(nullptr)
</span><span class="cx">     , topCallFrame(CallFrame::noCaller())
</span><ins>+    , promiseDeferredTimer(std::make_unique&lt;PromiseDeferredTimer&gt;(*this))
</ins><span class="cx">     , m_atomicStringTable(vmType == Default ? wtfThreadData().atomicStringTable() : new AtomicStringTable)
</span><span class="cx">     , propertyNames(nullptr)
</span><span class="cx">     , emptyList(new ArgList)
</span><span class="lines">@@ -355,6 +358,11 @@
</span><span class="cx"> 
</span><span class="cx"> VM::~VM()
</span><span class="cx"> {
</span><ins>+    promiseDeferredTimer-&gt;stopRunningTasks();
+#if ENABLE(WEBASSEMBLY)
+    if (Wasm::existingWorklistOrNull())
+        Wasm::ensureWorklist().stopAllPlansForVM(*this);
+#endif
</ins><span class="cx">     if (UNLIKELY(m_watchdog))
</span><span class="cx">         m_watchdog-&gt;willDestroyVM(this);
</span><span class="cx">     m_traps.willDestroyVM();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -106,6 +106,7 @@
</span><span class="cx"> class JSWebAssemblyInstance;
</span><span class="cx"> class LLIntOffsetsExtractor;
</span><span class="cx"> class NativeExecutable;
</span><ins>+class PromiseDeferredTimer;
</ins><span class="cx"> class RegExpCache;
</span><span class="cx"> class Register;
</span><span class="cx"> class RegisterAtOffsetList;
</span><span class="lines">@@ -379,6 +380,7 @@
</span><span class="cx">     std::once_flag m_wasmSignatureInformationOnceFlag;
</span><span class="cx">     std::unique_ptr&lt;Wasm::SignatureInformation&gt; m_wasmSignatureInformation;
</span><span class="cx"> #endif
</span><ins>+    std::unique_ptr&lt;PromiseDeferredTimer&gt; promiseDeferredTimer;
</ins><span class="cx">     
</span><span class="cx">     JSCell* currentlyDestructingCallbackObject;
</span><span class="cx">     const ClassInfo* currentlyDestructingCallbackObjectClassInfo;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmJSWebAssemblycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/JSWebAssembly.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/JSWebAssembly.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/JSWebAssembly.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -33,10 +33,17 @@
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSPromiseDeferred.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyHelpers.h&quot;
</span><ins>+#include &quot;JSWebAssemblyInstance.h&quot;
+#include &quot;JSWebAssemblyModule.h&quot;
</ins><span class="cx"> #include &quot;ObjectConstructor.h&quot;
</span><ins>+#include &quot;PromiseDeferredTimer.h&quot;
+#include &quot;StrongInlines.h&quot;
</ins><span class="cx"> #include &quot;WasmPlan.h&quot;
</span><ins>+#include &quot;WasmWorklist.h&quot;
</ins><span class="cx"> #include &quot;WebAssemblyModuleConstructor.h&quot;
</span><span class="cx"> 
</span><ins>+using JSC::Wasm::Plan;
+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSWebAssembly);
</span><span class="lines">@@ -45,45 +52,161 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState*);
</span><span class="cx"> 
</span><ins>+static EncodedJSValue reject(ExecState* exec, CatchScope&amp; catchScope, JSPromiseDeferred* promise)
+{
+    Exception* exception = catchScope.exception();
+    ASSERT(exception);
+    catchScope.clearException();
+    promise-&gt;reject(exec, exception-&gt;value());
+    return JSValue::encode(promise-&gt;promise());
+}
+
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><del>-    auto catchScope = DECLARE_CATCH_SCOPE(vm);
</del><ins>+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    auto* globalObject = exec-&gt;lexicalGlobalObject();
</ins><span class="cx"> 
</span><del>-    JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, exec-&gt;lexicalGlobalObject());
-    RETURN_IF_EXCEPTION(catchScope, encodedJSValue());
</del><ins>+    JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx"> 
</span><del>-    // FIXME: Make this truly asynchronous:
-    // https://bugs.webkit.org/show_bug.cgi?id=166016
-    JSValue module = WebAssemblyModuleConstructor::createModule(exec, exec-&gt;argument(0), exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyModuleStructure());
-    if (Exception* exception = catchScope.exception()) {
-        catchScope.clearException();
-        promise-&gt;reject(exec, exception-&gt;value());
-        return JSValue::encode(promise-&gt;promise());
-    }
</del><ins>+    RefPtr&lt;ArrayBuffer&gt; source = createSourceBufferFromValue(vm, exec, exec-&gt;argument(0));
+    RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx"> 
</span><del>-    promise-&gt;resolve(exec, module);
</del><ins>+    Vector&lt;Strong&lt;JSCell&gt;&gt; dependencies;
+    dependencies.append(Strong&lt;JSCell&gt;(vm, globalObject));
+    vm.promiseDeferredTimer-&gt;addPendingPromise(promise, WTFMove(dependencies));
+
+    Ref&lt;Plan&gt; plan = adoptRef(*new Plan(vm, *source, Plan::Validation, [source, promise, globalObject] (Plan&amp; p) mutable {
+        RefPtr&lt;Plan&gt; plan = makeRef(p);
+        plan-&gt;vm().promiseDeferredTimer-&gt;scheduleWorkSoon(promise, [source, promise, globalObject, plan = WTFMove(plan)] () mutable {
+            VM&amp; vm = plan-&gt;vm();
+            auto scope = DECLARE_CATCH_SCOPE(vm);
+            ExecState* exec = globalObject-&gt;globalExec();
+            JSValue module = JSWebAssemblyModule::createStub(vm, exec, globalObject-&gt;WebAssemblyModuleStructure(), WTFMove(source), WTFMove(plan));
+            if (scope.exception()) {
+                reject(exec, scope, promise);
+                return;
+            }
+
+            promise-&gt;resolve(exec, module);
+        });
+    }));
+
+    Wasm::ensureWorklist().enqueue(WTFMove(plan));
</ins><span class="cx">     return JSValue::encode(promise-&gt;promise());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+enum class Resolve { WithInstance, WithModuleAndInstance };
+static void resolve(VM&amp; vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAssemblyInstance* instance, JSWebAssemblyModule* module, Resolve entries)
+{
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    instance-&gt;finalizeCreation(vm, exec);
+    if (scope.exception()) {
+        reject(exec, scope, promise);
+        return;
+    }
+
+    if (entries == Resolve::WithInstance)
+        promise-&gt;resolve(exec, instance);
+    else {
+        JSObject* result = constructEmptyObject(exec);
+        result-&gt;putDirect(vm, Identifier::fromString(&amp;vm, ASCIILiteral(&quot;module&quot;)), module);
+        result-&gt;putDirect(vm, Identifier::fromString(&amp;vm, ASCIILiteral(&quot;instance&quot;)), instance);
+        promise-&gt;resolve(exec, result);
+    }
+}
+
+static void instantiate(VM&amp; vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAssemblyModule* module, JSObject* importObject, Resolve entries)
+{
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    // In order to avoid potentially recompiling a module. We first gather all the import/memory information prior to compiling code.
+    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyInstanceStructure());
+    if (scope.exception()) {
+        reject(exec, scope, promise);
+        return;
+    }
+
+    // There are three possible cases:
+    // 1) The instance already has an initialized CodeBlock, so we have no more work to do.
+    // 2) The instance has no CodeBlock, so we need to make one and compile the code for it.
+    // 3) The instance already has an uninitialized CodeBlock, so someone else is compiling code and we just need to wait for them.
+
+    if (instance-&gt;initialized()) {
+        resolve(vm, exec, promise, instance, module, entries);
+        return;
+    }
+
+    Vector&lt;Strong&lt;JSCell&gt;&gt; dependencies;
+    // The instance keeps the module alive.
+    dependencies.append(Strong&lt;JSCell&gt;(vm, instance));
+    vm.promiseDeferredTimer-&gt;addPendingPromise(promise, WTFMove(dependencies));
+
+    if (instance-&gt;codeBlock()) {
+        vm.promiseDeferredTimer-&gt;scheduleBlockedTask(instance-&gt;codeBlock()-&gt;plan().pendingPromise(), [&amp;vm, promise, instance, module, entries] () {
+            auto* globalObject = instance-&gt;globalObject();
+            ExecState* exec = globalObject-&gt;globalExec();
+            resolve(vm, exec, promise, instance, module, entries);
+        });
+        return;
+    }
+    ASSERT(!instance-&gt;codeBlock());
+
+    // FIXME: This re-parses the module header, which shouldn't be necessary.
+    // https://bugs.webkit.org/show_bug.cgi?id=170205
+    Ref&lt;Plan&gt; plan = adoptRef(*new Plan(vm, module-&gt;source(), Plan::FullCompile, [promise, instance, module, entries] (Plan&amp; p) {
+        RefPtr&lt;Plan&gt; plan = makeRef(p);
+        plan-&gt;vm().promiseDeferredTimer-&gt;scheduleWorkSoon(promise, [promise, instance, module, entries, plan = WTFMove(plan)] () {
+            VM&amp; vm = plan-&gt;vm();
+            ExecState* exec = instance-&gt;globalObject()-&gt;globalExec();
+            resolve(vm, exec, promise, instance, module, entries);
+        });
+    }));
+
+    instance-&gt;addUnitializedCodeBlock(vm, plan.copyRef());
+    plan-&gt;setModeAndPromise(instance-&gt;memoryMode(), promise);
+    Wasm::ensureWorklist().enqueue(WTFMove(plan));
+}
+
+static void compileAndInstantiate(VM&amp; vm, ExecState* exec, JSPromiseDeferred* promise, JSValue buffer, JSObject* importObject)
+{
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    RefPtr&lt;ArrayBuffer&gt; source = createSourceBufferFromValue(vm, exec, buffer);
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto* globalObject = exec-&gt;lexicalGlobalObject();
+
+    Vector&lt;Strong&lt;JSCell&gt;&gt; dependencies;
+    dependencies.append(Strong&lt;JSCell&gt;(vm, importObject));
+    vm.promiseDeferredTimer-&gt;addPendingPromise(promise, WTFMove(dependencies));
+
+    Ref&lt;Plan&gt; plan = adoptRef(*new Plan(vm, *source, Plan::Validation, [source, promise, importObject, globalObject] (Plan&amp; p) mutable {
+        RefPtr&lt;Plan&gt; plan = makeRef(p);
+        plan-&gt;vm().promiseDeferredTimer-&gt;scheduleWorkSoon(promise, [source, promise, importObject, globalObject, plan = WTFMove(plan)] () mutable {
+            VM&amp; vm = plan-&gt;vm();
+            auto scope = DECLARE_CATCH_SCOPE(vm);
+            ExecState* exec = globalObject-&gt;globalExec();
+            JSWebAssemblyModule* module = JSWebAssemblyModule::createStub(vm, exec, globalObject-&gt;WebAssemblyModuleStructure(), WTFMove(source), plan.copyRef());
+            if (scope.exception()) {
+                reject(exec, scope, promise);
+                return;
+            }
+
+            instantiate(vm, exec, promise, module, importObject, Resolve::WithModuleAndInstance);
+        });
+    }));
+
+    Wasm::ensureWorklist().enqueue(WTFMove(plan));
+}
+
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     auto catchScope = DECLARE_CATCH_SCOPE(vm);
</span><span class="cx"> 
</span><del>-    // FIXME: Make this API truly asynchronous: https://bugs.webkit.org/show_bug.cgi?id=169187
-
</del><span class="cx">     JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, exec-&gt;lexicalGlobalObject());
</span><span class="cx">     RETURN_IF_EXCEPTION(catchScope, encodedJSValue());
</span><span class="cx"> 
</span><del>-    auto reject = [&amp;] () {
-        Exception* exception = catchScope.exception();
-        ASSERT(exception);
-        catchScope.clearException();
-        promise-&gt;reject(exec, exception-&gt;value());
-        return JSValue::encode(promise-&gt;promise());
-    };
-
</del><span class="cx">     JSValue importArgument = exec-&gt;argument(1);
</span><span class="cx">     JSObject* importObject = importArgument.getObject();
</span><span class="cx">     if (!importArgument.isUndefined() &amp;&amp; !importObject) {
</span><span class="lines">@@ -93,30 +216,11 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JSValue firstArgument = exec-&gt;argument(0);
</span><del>-    JSValue module;
-    bool firstArgumentIsModule = false;
-    if (firstArgument.inherits(vm, JSWebAssemblyModule::info())) {
-        firstArgumentIsModule = true;
-        module = firstArgument;
-    } else {
-        module = WebAssemblyModuleConstructor::createModule(exec, firstArgument, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyModuleStructure());
-        if (catchScope.exception())
-            return reject();
-    }
</del><ins>+    if (auto* module = jsDynamicCast&lt;JSWebAssemblyModule*&gt;(vm, firstArgument))
+        instantiate(vm, exec, promise, module, importObject, Resolve::WithInstance);
+    else
+        compileAndInstantiate(vm, exec, promise, firstArgument, importObject);
</ins><span class="cx"> 
</span><del>-    JSWebAssemblyInstance* instance = WebAssemblyInstanceConstructor::createInstance(exec, jsCast&lt;JSWebAssemblyModule*&gt;(module), importObject, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyInstanceStructure());
-    if (catchScope.exception())
-        return reject();
-
-    if (firstArgumentIsModule)
-        promise-&gt;resolve(exec, instance);
-    else {
-        JSObject* result = constructEmptyObject(exec);
-        result-&gt;putDirect(vm, Identifier::fromString(&amp;vm, ASCIILiteral(&quot;module&quot;)), module);
-        result-&gt;putDirect(vm, Identifier::fromString(&amp;vm, ASCIILiteral(&quot;instance&quot;)), instance);
-        promise-&gt;resolve(exec, result);
-    }
-
</del><span class="cx">     return JSValue::encode(promise-&gt;promise());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -129,7 +233,7 @@
</span><span class="cx">     size_t byteSize;
</span><span class="cx">     uint8_t* base = getWasmBufferFromValue(exec, exec-&gt;argument(0), byteOffset, byteSize);
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><del>-    Wasm::Plan plan(&amp;vm, base + byteOffset, byteSize);
</del><ins>+    Wasm::Plan plan(vm, base + byteOffset, byteSize, Plan::Validation, Plan::dontFinalize);
</ins><span class="cx">     // FIXME: We might want to throw an OOM exception here if we detect that something will OOM.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=166015
</span><span class="cx">     return JSValue::encode(jsBoolean(plan.parseAndValidateModule()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -157,7 +157,7 @@
</span><span class="cx">             return fail(__VA_ARGS__);             \
</span><span class="cx">     } while (0)
</span><span class="cx"> 
</span><del>-    B3IRGenerator(VM&amp;, const ModuleInformation&amp;, Procedure&amp;, WasmInternalFunction*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;);
</del><ins>+    B3IRGenerator(VM&amp;, const ModuleInformation&amp;, Procedure&amp;, WasmInternalFunction*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, MemoryMode);
</ins><span class="cx"> 
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN addArguments(const Signature*);
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN addLocal(Type, uint32_t);
</span><span class="lines">@@ -225,6 +225,7 @@
</span><span class="cx"> 
</span><span class="cx">     VM&amp; m_vm;
</span><span class="cx">     const ModuleInformation&amp; m_info;
</span><ins>+    MemoryMode m_mode;
</ins><span class="cx">     Procedure&amp; m_proc;
</span><span class="cx">     BasicBlock* m_currentBlock;
</span><span class="cx">     Vector&lt;Variable*&gt; m_locals;
</span><span class="lines">@@ -290,9 +291,10 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-B3IRGenerator::B3IRGenerator(VM&amp; vm, const ModuleInformation&amp; info, Procedure&amp; procedure, WasmInternalFunction* compilation, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls)
</del><ins>+B3IRGenerator::B3IRGenerator(VM&amp; vm, const ModuleInformation&amp; info, Procedure&amp; procedure, WasmInternalFunction* compilation, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, MemoryMode mode)
</ins><span class="cx">     : m_vm(vm)
</span><span class="cx">     , m_info(info)
</span><ins>+    , m_mode(mode)
</ins><span class="cx">     , m_proc(procedure)
</span><span class="cx">     , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls)
</span><span class="cx"> {
</span><span class="lines">@@ -520,7 +522,7 @@
</span><span class="cx"> inline Value* B3IRGenerator::emitCheckAndPreparePointer(ExpressionType pointer, uint32_t offset, uint32_t sizeOfOperation)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_memoryBaseGPR);
</span><del>-    if (m_info.memory.mode() == MemoryMode::BoundsChecking) {
</del><ins>+    if (m_mode == MemoryMode::BoundsChecking) {
</ins><span class="cx">         ASSERT(m_memorySizeGPR);
</span><span class="cx">         ASSERT(sizeOfOperation + offset &gt; offset);
</span><span class="cx">         m_currentBlock-&gt;appendNew&lt;WasmBoundsCheckValue&gt;(m_proc, Origin(), pointer, m_memorySizeGPR, sizeOfOperation + offset - 1);
</span><span class="lines">@@ -556,7 +558,7 @@
</span><span class="cx"> 
</span><span class="cx"> inline B3::Kind B3IRGenerator::memoryKind(B3::Opcode memoryOp)
</span><span class="cx"> {
</span><del>-    if (m_info.memory.mode() == MemoryMode::Signaling)
</del><ins>+    if (m_mode == MemoryMode::Signaling)
</ins><span class="cx">         return trapping(memoryOp);
</span><span class="cx">     return memoryOp;
</span><span class="cx"> }
</span><span class="lines">@@ -1277,7 +1279,7 @@
</span><span class="cx">     jit.ret();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp; vm, CompilationContext&amp; compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const ModuleInformation&amp; info, const Vector&lt;SignatureIndex&gt;&amp; moduleSignatureIndicesToUniquedSignatureIndices, unsigned optLevel)
</del><ins>+Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp; vm, CompilationContext&amp; compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp; unlinkedWasmToWasmCalls, const ModuleInformation&amp; info, const Vector&lt;SignatureIndex&gt;&amp; moduleSignatureIndicesToUniquedSignatureIndices, MemoryMode mode, unsigned optLevel)
</ins><span class="cx"> {
</span><span class="cx">     auto result = std::make_unique&lt;WasmInternalFunction&gt;();
</span><span class="cx"> 
</span><span class="lines">@@ -1285,7 +1287,7 @@
</span><span class="cx">     compilationContext.wasmEntrypointJIT = std::make_unique&lt;CCallHelpers&gt;(&amp;vm);
</span><span class="cx"> 
</span><span class="cx">     Procedure procedure;
</span><del>-    B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls);
</del><ins>+    B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls, mode);
</ins><span class="cx">     FunctionParser&lt;B3IRGenerator&gt; parser(&amp;vm, context, functionStart, functionLength, signature, info, moduleSignatureIndicesToUniquedSignatureIndices);
</span><span class="cx">     WASM_FAIL_IF_HELPER_FAILS(parser.parse());
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmB3IRGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><span class="cx"> #include &quot;WasmFormat.h&quot;
</span><ins>+#include &quot;WasmMemory.h&quot;
</ins><span class="cx"> #include &lt;wtf/Expected.h&gt;
</span><span class="cx"> 
</span><span class="cx"> extern &quot;C&quot; void dumpProcedure(void*);
</span><span class="lines">@@ -47,7 +48,7 @@
</span><span class="cx">     CCallHelpers::Call jsEntrypointToWasmEntrypointCall;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp;, CompilationContext&amp;, const uint8_t*, size_t, const Signature*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ModuleInformation&amp;, const Vector&lt;SignatureIndex&gt;&amp;, unsigned optLevel = 1);
</del><ins>+Expected&lt;std::unique_ptr&lt;WasmInternalFunction&gt;, String&gt; parseAndCompile(VM&amp;, CompilationContext&amp;, const uint8_t*, size_t, const Signature*, Vector&lt;UnlinkedWasmToWasmCall&gt;&amp;, const ModuleInformation&amp;, const Vector&lt;SignatureIndex&gt;&amp;, MemoryMode, unsigned optLevel = 1);
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFormat.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmFormat.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -102,14 +102,14 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> struct Import {
</span><del>-    Identifier module;
-    Identifier field;
</del><ins>+    String module;
+    String field;
</ins><span class="cx">     ExternalKind kind;
</span><span class="cx">     unsigned kindIndex; // Index in the vector of the corresponding kind.
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct Export {
</span><del>-    Identifier field;
</del><ins>+    String field;
</ins><span class="cx">     ExternalKind kind;
</span><span class="cx">     unsigned kindIndex; // Index in the vector of the corresponding kind.
</span><span class="cx"> };
</span><span class="lines">@@ -260,6 +260,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
</span><ins>+    uint32_t internalFunctionCount() const { return internalFunctionSignatureIndices.size(); }
</ins><span class="cx"> 
</span><span class="cx">     ~ModuleInformation();
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmFunctionParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(numberOfLocals), &quot;can't get Function's number of locals in group &quot;, i);
</span><span class="cx">         WASM_PARSER_FAIL_IF(numberOfLocals == std::numeric_limits&lt;uint32_t&gt;::max(), &quot;Function section's &quot;, i, &quot;th local group count is too big &quot;, numberOfLocals);
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseValueType(typeOfLocal), &quot;can't get Function local's type in group &quot;, i);
</span><del>-        WASM_PARSER_FAIL_IF(!m_context.addLocal(typeOfLocal, numberOfLocals), &quot;can't add &quot;, numberOfLocals, &quot; Function locals from group &quot;, i);
</del><ins>+        WASM_TRY_ADD_TO_CONTEXT(addLocal(typeOfLocal, numberOfLocals));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     WASM_FAIL_IF_HELPER_FAILS(parseBody());
</span><span class="lines">@@ -267,7 +267,7 @@
</span><span class="cx">         uint32_t index;
</span><span class="cx">         ExpressionType result;
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(index), &quot;can't get index for get_local&quot;);
</span><del>-        WASM_PARSER_FAIL_IF(!m_context.getLocal(index, result), &quot;can't get_local at index&quot;, index);
</del><ins>+        WASM_TRY_ADD_TO_CONTEXT(getLocal(index, result));
</ins><span class="cx">         m_expressionStack.append(result);
</span><span class="cx">         return { };
</span><span class="cx">     }
</span><span class="lines">@@ -304,7 +304,7 @@
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(index), &quot;can't get set_global's index&quot;);
</span><span class="cx">         WASM_TRY_POP_EXPRESSION_STACK_INTO(value, &quot;set_global value&quot;);
</span><span class="cx">         WASM_TRY_ADD_TO_CONTEXT(setGlobal(index, value));
</span><del>-        return m_context.setGlobal(index, value);
</del><ins>+        return { };
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case Call: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemory.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemory.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx"> namespace Wasm {
</span><span class="cx"> 
</span><span class="cx"> // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693
</span><del>-enum class MemoryMode {
</del><ins>+enum class MemoryMode : uint8_t {
</ins><span class="cx">     BoundsChecking,
</span><span class="cx">     Signaling,
</span><span class="cx">     NumberOfMemoryModes
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryInformationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -88,7 +88,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MemoryInformation::MemoryInformation(VM&amp; vm, PageCount initial, PageCount maximum, std::optional&lt;MemoryMode&gt; recompileMode, bool isImport)
</del><ins>+MemoryInformation::MemoryInformation(PageCount initial, PageCount maximum, bool isImport)
</ins><span class="cx">     : m_initial(initial)
</span><span class="cx">     , m_maximum(maximum)
</span><span class="cx">     , m_isImport(isImport)
</span><span class="lines">@@ -96,28 +96,6 @@
</span><span class="cx">     RELEASE_ASSERT(!!m_initial);
</span><span class="cx">     RELEASE_ASSERT(!m_maximum || m_maximum &gt;= m_initial);
</span><span class="cx">     ASSERT(!!*this);
</span><del>-
-    if (!recompileMode) {
-        if (!isImport) {
-            if (maximum &amp;&amp; maximum.bytes() == 0) {
-                m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::BoundsChecking);
-                RELEASE_ASSERT(m_reservedMemory);
-                RELEASE_ASSERT(m_reservedMemory-&gt;maximum());
-                RELEASE_ASSERT(m_reservedMemory-&gt;maximum().bytes() == 0);
-                m_mode = m_reservedMemory-&gt;mode();
-                return;
-            }
-
-            m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::Signaling);
-            if (m_reservedMemory) {
-                ASSERT(!!*m_reservedMemory);
-                m_mode = m_reservedMemory-&gt;mode();
-                return;
-            }
-        }
-        m_mode = Memory::lastAllocatedMode();
-    } else
-        m_mode = *recompileMode;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::Wasm
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmMemoryInformationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -67,22 +67,17 @@
</span><span class="cx">         ASSERT(!*this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MemoryInformation(VM&amp;, PageCount initial, PageCount maximum, std::optional&lt;MemoryMode&gt;, bool isImport);
</del><ins>+    MemoryInformation(PageCount initial, PageCount maximum, bool isImport);
</ins><span class="cx"> 
</span><span class="cx">     PageCount initial() const { return m_initial; }
</span><span class="cx">     PageCount maximum() const { return m_maximum; }
</span><del>-    bool hasReservedMemory() const { return m_reservedMemory; }
-    RefPtr&lt;Memory&gt; takeReservedMemory() { ASSERT(hasReservedMemory()); return m_reservedMemory.release(); }
-    MemoryMode mode() const { return m_mode; }
</del><span class="cx">     bool isImport() const { return m_isImport; }
</span><span class="cx"> 
</span><span class="cx">     explicit operator bool() const { return !!m_initial; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    RefPtr&lt;Memory&gt; m_reservedMemory;
</del><span class="cx">     PageCount m_initial { };
</span><span class="cx">     PageCount m_maximum { };
</span><del>-    MemoryMode m_mode { MemoryMode::BoundsChecking };
</del><span class="cx">     bool m_isImport { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -162,11 +162,11 @@
</span><span class="cx"> 
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(moduleLen), &quot;can't get &quot;, importNumber, &quot;th Import's module name length&quot;);
</span><span class="cx">         WASM_PARSER_FAIL_IF(!consumeUTF8String(moduleString, moduleLen), &quot;can't get &quot;, importNumber, &quot;th Import's module name of length &quot;, moduleLen);
</span><del>-        imp.module = Identifier::fromString(m_vm, moduleString);
</del><ins>+        imp.module = moduleString;
</ins><span class="cx"> 
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), &quot;can't get &quot;, importNumber, &quot;th Import's field name length in module '&quot;, moduleString, &quot;'&quot;);
</span><span class="cx">         WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), &quot;can't get &quot;, importNumber, &quot;th Import's field name of length &quot;, moduleLen, &quot; in module '&quot;, moduleString, &quot;'&quot;);
</span><del>-        imp.field = Identifier::fromString(m_vm, fieldString);
</del><ins>+        imp.field = fieldString;
</ins><span class="cx"> 
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseExternalKind(imp.kind), &quot;can't get &quot;, importNumber, &quot;th Import's kind in module '&quot;, moduleString, &quot;' field '&quot;, fieldString, &quot;'&quot;);
</span><span class="cx">         switch (imp.kind) {
</span><span class="lines">@@ -316,7 +316,7 @@
</span><span class="cx">     ASSERT(initialPageCount);
</span><span class="cx">     ASSERT(!maximumPageCount || maximumPageCount &gt;= initialPageCount);
</span><span class="cx"> 
</span><del>-    m_result.module-&gt;memory = MemoryInformation(*m_vm, initialPageCount, maximumPageCount, m_mode, isImport);
</del><ins>+    m_result.module-&gt;memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
</ins><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -376,7 +376,7 @@
</span><span class="cx">         WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), &quot;can't get &quot;, exportNumber, &quot;th Export's field name of length &quot;, fieldLen);
</span><span class="cx">         WASM_PARSER_FAIL_IF(exportNames.contains(fieldString), &quot;duplicate export: '&quot;, fieldString, &quot;'&quot;);
</span><span class="cx">         exportNames.add(fieldString);
</span><del>-        exp.field = Identifier::fromString(m_vm, fieldString);
</del><ins>+        exp.field = fieldString;
</ins><span class="cx"> 
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseExternalKind(exp.kind), &quot;can't get &quot;, exportNumber, &quot;th Export's kind, named '&quot;, fieldString, &quot;'&quot;);
</span><span class="cx">         WASM_PARSER_FAIL_IF(!parseVarUInt32(exp.kindIndex), &quot;can't get &quot;, exportNumber, &quot;th Export's kind index, named '&quot;, fieldString, &quot;'&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmModuleParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -44,9 +44,9 @@
</span><span class="cx"> class ModuleParser : public Parser&lt;ModuleParserResult&gt; {
</span><span class="cx"> public:
</span><span class="cx"> 
</span><del>-    ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional&lt;MemoryMode&gt; mode)
</del><ins>+
+    ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength)
</ins><span class="cx">         : Parser(vm, sourceBuffer, sourceLength)
</span><del>-        , m_mode(mode)
</del><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -66,7 +66,6 @@
</span><span class="cx">     PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&amp;, uint64_t&amp;, Type&amp; initExprType);
</span><span class="cx"> 
</span><span class="cx">     ModuleParserResult m_result;
</span><del>-    std::optional&lt;MemoryMode&gt; m_mode { std::nullopt };
</del><span class="cx">     bool m_hasTable { false };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -42,7 +42,6 @@
</span><span class="cx"> #include &lt;wtf/DataLog.h&gt;
</span><span class="cx"> #include &lt;wtf/Locker.h&gt;
</span><span class="cx"> #include &lt;wtf/MonotonicTime.h&gt;
</span><del>-#include &lt;wtf/NumberOfCores.h&gt;
</del><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> #include &lt;wtf/SystemTracing.h&gt;
</span><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><span class="lines">@@ -50,30 +49,65 @@
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><span class="cx"> static const bool verbose = false;
</span><del>-    
-Plan::Plan(VM* vm, Vector&lt;uint8_t&gt; source)
-    : Plan(vm, source.data(), source.size())
</del><ins>+
+Plan::Plan(VM&amp; vm, ArrayBuffer&amp; source, AsyncWork work, CompletionTask&amp;&amp; task)
+    : Plan(vm, reinterpret_cast&lt;uint8_t*&gt;(source.data()), source.byteLength(), work, WTFMove(task))
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Plan::Plan(VM* vm, const uint8_t* source, size_t sourceLength)
</del><ins>+Plan::Plan(VM&amp; vm, Vector&lt;uint8_t&gt;&amp; source, AsyncWork work, CompletionTask&amp;&amp; task)
+    : Plan(vm, source.data(), source.size(), work, WTFMove(task))
+{
+}
+
+Plan::Plan(VM&amp; vm, const uint8_t* source, size_t sourceLength, AsyncWork work, CompletionTask&amp;&amp; task)
</ins><span class="cx">     : m_vm(vm)
</span><ins>+    , m_completionTask(task)
</ins><span class="cx">     , m_source(source)
</span><span class="cx">     , m_sourceLength(sourceLength)
</span><ins>+    , m_asyncWork(work)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Plan::parseAndValidateModule(std::optional&lt;MemoryMode&gt; recompileMode)
</del><ins>+const char* Plan::stateString(State state)
</ins><span class="cx"> {
</span><ins>+    switch (state) {
+    case State::Initial: return &quot;Initial&quot;;
+    case State::Validated: return &quot;Validated&quot;;
+    case State::Prepared: return &quot;Prepared&quot;;
+    case State::Compiled: return &quot;Compiled&quot;;
+    case State::Completed: return &quot;Completed&quot;;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void Plan::moveToState(State state)
+{
+    ASSERT(state &gt; m_state);
+    dataLogLnIf(verbose, &quot;moving to state: &quot;, stateString(state), &quot; from state: &quot;, stateString(m_state));
+    m_state = state;
+}
+
+void Plan::fail(const AbstractLocker&amp; locker, String&amp;&amp; errorMessage)
+{
+    dataLogLnIf(verbose, &quot;failing with message: &quot;, errorMessage);
+    m_errorMessage = WTFMove(errorMessage);
+    complete(locker);
+}
+
+bool Plan::parseAndValidateModule()
+{
+    ASSERT(m_state == State::Initial);
+    dataLogLnIf(verbose, &quot;starting validation&quot;);
</ins><span class="cx">     MonotonicTime startTime;
</span><span class="cx">     if (verbose || Options::reportCompileTimes())
</span><span class="cx">         startTime = MonotonicTime::now();
</span><span class="cx"> 
</span><span class="cx">     {
</span><del>-        ModuleParser moduleParser(m_vm, m_source, m_sourceLength, recompileMode);
</del><ins>+        ModuleParser moduleParser(&amp;m_vm, m_source, m_sourceLength);
</ins><span class="cx">         auto parseResult = moduleParser.parse();
</span><span class="cx">         if (!parseResult) {
</span><del>-            m_errorMessage = parseResult.error();
</del><ins>+            fail(holdLock(m_lock), WTFMove(parseResult.error()));
</ins><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx">         m_moduleInformation = WTFMove(parseResult-&gt;module);
</span><span class="lines">@@ -82,15 +116,14 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     for (unsigned functionIndex = 0; functionIndex &lt; m_functionLocationInBinary.size(); ++functionIndex) {
</span><del>-        if (verbose)
-            dataLogLn(&quot;Processing function starting at: &quot;, m_functionLocationInBinary[functionIndex].start, &quot; and ending at: &quot;, m_functionLocationInBinary[functionIndex].end);
</del><ins>+        dataLogLnIf(verbose, &quot;Processing function starting at: &quot;, m_functionLocationInBinary[functionIndex].start, &quot; and ending at: &quot;, m_functionLocationInBinary[functionIndex].end);
</ins><span class="cx">         const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start;
</span><span class="cx">         size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start;
</span><span class="cx">         ASSERT(functionLength &lt;= m_sourceLength);
</span><span class="cx">         SignatureIndex signatureIndex = m_moduleInformation-&gt;internalFunctionSignatureIndices[functionIndex];
</span><del>-        const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
</del><ins>+        const Signature* signature = SignatureInformation::get(&amp;m_vm, signatureIndex);
</ins><span class="cx"> 
</span><del>-        auto validationResult = validateFunction(m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices);
</del><ins>+        auto validationResult = validateFunction(&amp;m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices);
</ins><span class="cx">         if (!validationResult) {
</span><span class="cx">             if (verbose) {
</span><span class="cx">                 for (unsigned i = 0; i &lt; functionLength; ++i)
</span><span class="lines">@@ -97,7 +130,7 @@
</span><span class="cx">                     dataLog(RawPointer(reinterpret_cast&lt;void*&gt;(functionStart[i])), &quot;, &quot;);
</span><span class="cx">                 dataLogLn();
</span><span class="cx">             }
</span><del>-            m_errorMessage = makeString(validationResult.error(), &quot;, in function at index &quot;, String::number(functionIndex)); // FIXME make this an Expected.
</del><ins>+            fail(holdLock(m_lock), makeString(validationResult.error(), &quot;, in function at index &quot;, String::number(functionIndex))); // FIXME make this an Expected.
</ins><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -104,23 +137,20 @@
</span><span class="cx"> 
</span><span class="cx">     if (verbose || Options::reportCompileTimes())
</span><span class="cx">         dataLogLn(&quot;Took &quot;, (MonotonicTime::now() - startTime).microseconds(), &quot; us to validate module&quot;);
</span><ins>+    if (m_asyncWork == Validation)
+        complete(holdLock(m_lock));
+    else
+        moveToState(State::Validated);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// We are creating a bunch of threads that touch the main thread's stack. This will make ASAN unhappy.
-// The reason this is OK is that we guarantee that the main thread doesn't continue until all threads
-// that could touch its stack are done executing.
-SUPPRESS_ASAN 
-void Plan::run(std::optional&lt;MemoryMode&gt; recompileMode)
</del><ins>+void Plan::prepare()
</ins><span class="cx"> {
</span><del>-    if (!parseAndValidateModule(recompileMode))
-        return;
</del><ins>+    ASSERT(m_state == State::Validated);
+    dataLogLnIf(verbose, &quot;Starting preparation&quot;);
</ins><span class="cx"> 
</span><span class="cx">     TraceScope traceScope(WebAssemblyCompileStart, WebAssemblyCompileEnd);
</span><span class="cx"> 
</span><del>-    if (recompileMode)
-        ASSERT(m_moduleInformation-&gt;memory.mode() == recompileMode);
-
</del><span class="cx">     auto tryReserveCapacity = [this] (auto&amp; vector, size_t size, const char* what) {
</span><span class="cx">         if (UNLIKELY(!vector.tryReserveCapacity(size))) {
</span><span class="cx">             StringBuilder builder;
</span><span class="lines">@@ -127,7 +157,7 @@
</span><span class="cx">             builder.appendLiteral(&quot;Failed allocating enough space for &quot;);
</span><span class="cx">             builder.appendNumber(size);
</span><span class="cx">             builder.append(what);
</span><del>-            m_errorMessage = builder.toString();
</del><ins>+            fail(holdLock(m_lock), builder.toString());
</ins><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx">         return true;
</span><span class="lines">@@ -148,128 +178,149 @@
</span><span class="cx">         if (import-&gt;kind != ExternalKind::Function)
</span><span class="cx">             continue;
</span><span class="cx">         unsigned importFunctionIndex = m_wasmExitStubs.size();
</span><del>-        if (verbose)
-            dataLogLn(&quot;Processing import function number &quot;, importFunctionIndex, &quot;: &quot;, import-&gt;module, &quot;: &quot;, import-&gt;field);
</del><ins>+        dataLogLnIf(verbose, &quot;Processing import function number &quot;, importFunctionIndex, &quot;: &quot;, import-&gt;module, &quot;: &quot;, import-&gt;field);
</ins><span class="cx">         SignatureIndex signatureIndex = m_moduleInformation-&gt;importFunctionSignatureIndices.at(import-&gt;kindIndex);
</span><del>-        m_wasmExitStubs.uncheckedAppend(exitStubGenerator(m_vm, m_callLinkInfos, signatureIndex, importFunctionIndex));
</del><ins>+        m_wasmExitStubs.uncheckedAppend(exitStubGenerator(&amp;m_vm, m_callLinkInfos, signatureIndex, importFunctionIndex));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_currentIndex = 0;
</del><ins>+    moveToState(State::Prepared);
+}
</ins><span class="cx"> 
</span><del>-    auto doWork = [this] {
-        while (true) {
-            uint32_t functionIndex;
-            {
-                auto locker = holdLock(m_lock);
-                if (m_currentIndex &gt;= m_functionLocationInBinary.size())
-                    return;
-                functionIndex = m_currentIndex;
-                ++m_currentIndex;
-            }
</del><ins>+// We don't have a semaphore class... and this does kinda interesting things.
+class Plan::ThreadCountHolder {
+public:
+    ThreadCountHolder(Plan&amp; plan)
+        : m_plan(plan)
+    {
+        LockHolder locker(m_plan.m_lock);
+        m_plan.m_numberOfActiveThreads++;
+    }
</ins><span class="cx"> 
</span><del>-            const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start;
-            size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start;
-            ASSERT(functionLength &lt;= m_sourceLength);
-            SignatureIndex signatureIndex = m_moduleInformation-&gt;internalFunctionSignatureIndices[functionIndex];
-            const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
-            unsigned functionIndexSpace = m_wasmExitStubs.size() + functionIndex;
-            ASSERT_UNUSED(functionIndexSpace, m_moduleInformation-&gt;signatureIndexFromFunctionIndexSpace(functionIndexSpace) == signatureIndex);
-            ASSERT(validateFunction(m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices));
</del><ins>+    ~ThreadCountHolder()
+    {
+        LockHolder locker(m_plan.m_lock);
+        m_plan.m_numberOfActiveThreads--;
</ins><span class="cx"> 
</span><del>-            m_unlinkedWasmToWasmCalls[functionIndex] = Vector&lt;UnlinkedWasmToWasmCall&gt;();
-            auto parseAndCompileResult = parseAndCompile(*m_vm, m_compilationContexts[functionIndex], functionStart, functionLength, signature, m_unlinkedWasmToWasmCalls[functionIndex], *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices);
</del><ins>+        if (!m_plan.m_numberOfActiveThreads)
+            m_plan.complete(locker);
+    }
</ins><span class="cx"> 
</span><del>-            if (UNLIKELY(!parseAndCompileResult)) {
-                auto locker = holdLock(m_lock);
-                if (!m_errorMessage) {
-                    // Multiple compiles could fail simultaneously. We arbitrarily choose the first.
-                    m_errorMessage = makeString(parseAndCompileResult.error(), &quot;, in function at index &quot;, String::number(functionIndex)); // FIXME make this an Expected.
-                }
-                m_currentIndex = m_functionLocationInBinary.size();
</del><ins>+    Plan&amp; m_plan;
+};
</ins><span class="cx"> 
</span><del>-                // We will terminate on the next execution.
-                continue; 
-            }
</del><ins>+void Plan::compileFunctions()
+{
+    ASSERT(m_state &gt;= State::Prepared);
+    dataLogLnIf(verbose, &quot;Starting compilation&quot;);
</ins><span class="cx"> 
</span><del>-            m_wasmInternalFunctions[functionIndex] = WTFMove(*parseAndCompileResult);
</del><ins>+    if (m_state &gt;= State::Compiled)
+        return;
+    ThreadCountHolder holder(*this);
+    while (true) {
+        uint32_t functionIndex;
+        {
+            auto locker = holdLock(m_lock);
+            if (m_currentIndex &gt;= m_functionLocationInBinary.size())
+                return;
+            functionIndex = m_currentIndex;
+            ++m_currentIndex;
+            if (m_currentIndex == m_functionLocationInBinary.size())
+                moveToState(State::Compiled);
</ins><span class="cx">         }
</span><del>-    };
</del><span class="cx"> 
</span><del>-    MonotonicTime startTime;
-    if (verbose || Options::reportCompileTimes())
-        startTime = MonotonicTime::now();
</del><ins>+        const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start;
+        size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start;
+        ASSERT(functionLength &lt;= m_sourceLength);
+        SignatureIndex signatureIndex = m_moduleInformation-&gt;internalFunctionSignatureIndices[functionIndex];
+        const Signature* signature = SignatureInformation::get(&amp;m_vm, signatureIndex);
+        unsigned functionIndexSpace = m_wasmExitStubs.size() + functionIndex;
+        ASSERT_UNUSED(functionIndexSpace, m_moduleInformation-&gt;signatureIndexFromFunctionIndexSpace(functionIndexSpace) == signatureIndex);
+        ASSERT(validateFunction(&amp;m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices));
</ins><span class="cx"> 
</span><del>-    uint32_t threadCount = Options::useConcurrentJIT() ? WTF::numberOfProcessorCores() : 1;
-    uint32_t numWorkerThreads = threadCount - 1;
-    Vector&lt;ThreadIdentifier&gt; threads;
-    threads.reserveCapacity(numWorkerThreads);
-    for (uint32_t i = 0; i &lt; numWorkerThreads; i++)
-        threads.uncheckedAppend(createThread(&quot;jsc.wasm-b3-compilation.thread&quot;, doWork));
</del><ins>+        m_unlinkedWasmToWasmCalls[functionIndex] = Vector&lt;UnlinkedWasmToWasmCall&gt;();
+        auto parseAndCompileResult = parseAndCompile(m_vm, m_compilationContexts[functionIndex], functionStart, functionLength, signature, m_unlinkedWasmToWasmCalls[functionIndex], *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices, m_mode);
</ins><span class="cx"> 
</span><del>-    doWork(); // Let the main thread do some work too.
</del><ins>+        if (UNLIKELY(!parseAndCompileResult)) {
+            auto locker = holdLock(m_lock);
+            if (!m_errorMessage) {
+                // Multiple compiles could fail simultaneously. We arbitrarily choose the first.
+                fail(locker, makeString(parseAndCompileResult.error(), &quot;, in function at index &quot;, String::number(functionIndex))); // FIXME make this an Expected.
+            }
+            m_currentIndex = m_functionLocationInBinary.size();
+            return;
+        }
</ins><span class="cx"> 
</span><del>-    for (uint32_t i = 0; i &lt; numWorkerThreads; i++)
-        waitForThreadCompletion(threads[i]);
</del><ins>+        m_wasmInternalFunctions[functionIndex] = WTFMove(*parseAndCompileResult);
+    }
+}
</ins><span class="cx"> 
</span><del>-    for (uint32_t functionIndex = 0; functionIndex &lt; m_functionLocationInBinary.size(); functionIndex++) {
-        {
-            CompilationContext&amp; context = m_compilationContexts[functionIndex];
-            SignatureIndex signatureIndex = m_moduleInformation-&gt;internalFunctionSignatureIndices[functionIndex];
-            String signatureDescription = SignatureInformation::get(m_vm, signatureIndex)-&gt;toString();
</del><ins>+void Plan::complete(const AbstractLocker&amp;)
+{
+    ASSERT(m_state != State::Compiled || m_currentIndex &gt;= m_functionLocationInBinary.size());
+    dataLogLnIf(verbose, &quot;Starting Completion&quot;);
+
+    if (m_state == State::Compiled) {
+        for (uint32_t functionIndex = 0; functionIndex &lt; m_functionLocationInBinary.size(); functionIndex++) {
</ins><span class="cx">             {
</span><del>-                LinkBuffer linkBuffer(*m_vm, *context.wasmEntrypointJIT, nullptr);
-                m_wasmInternalFunctions[functionIndex]-&gt;wasmEntrypoint.compilation =
</del><ins>+                CompilationContext&amp; context = m_compilationContexts[functionIndex];
+                SignatureIndex signatureIndex = m_moduleInformation-&gt;internalFunctionSignatureIndices[functionIndex];
+                String signatureDescription = SignatureInformation::get(&amp;m_vm, signatureIndex)-&gt;toString();
+                {
+                    LinkBuffer linkBuffer(m_vm, *context.wasmEntrypointJIT, nullptr);
+                    m_wasmInternalFunctions[functionIndex]-&gt;wasmEntrypoint.compilation =
</ins><span class="cx">                     std::make_unique&lt;B3::Compilation&gt;(FINALIZE_CODE(linkBuffer, (&quot;WebAssembly function[%i] %s&quot;, functionIndex, signatureDescription.ascii().data())), WTFMove(context.wasmEntrypointByproducts));
</span><del>-            }
</del><ins>+                }
</ins><span class="cx"> 
</span><del>-            {
-                LinkBuffer linkBuffer(*m_vm, *context.jsEntrypointJIT, nullptr);
-                linkBuffer.link(context.jsEntrypointToWasmEntrypointCall, FunctionPtr(m_wasmInternalFunctions[functionIndex]-&gt;wasmEntrypoint.compilation-&gt;code().executableAddress()));
</del><ins>+                {
+                    LinkBuffer linkBuffer(m_vm, *context.jsEntrypointJIT, nullptr);
+                    linkBuffer.link(context.jsEntrypointToWasmEntrypointCall, FunctionPtr(m_wasmInternalFunctions[functionIndex]-&gt;wasmEntrypoint.compilation-&gt;code().executableAddress()));
</ins><span class="cx"> 
</span><del>-                m_wasmInternalFunctions[functionIndex]-&gt;jsToWasmEntrypoint.compilation =
</del><ins>+                    m_wasmInternalFunctions[functionIndex]-&gt;jsToWasmEntrypoint.compilation =
</ins><span class="cx">                     std::make_unique&lt;B3::Compilation&gt;(FINALIZE_CODE(linkBuffer, (&quot;JavaScript-&gt;WebAssembly entrypoint[%i] %s&quot;, functionIndex, signatureDescription.ascii().data())), WTFMove(context.jsEntrypointByproducts));
</span><ins>+                }
</ins><span class="cx">             }
</span><ins>+
</ins><span class="cx">         }
</span><del>-    }
</del><span class="cx"> 
</span><del>-    if (verbose || Options::reportCompileTimes()) {
-        dataLogLn(&quot;Took &quot;, (MonotonicTime::now() - startTime).microseconds(),
-            &quot; us to compile and link the module&quot;);
-    }
-
-    // Patch the call sites for each WebAssembly function.
-    for (auto&amp; unlinked : m_unlinkedWasmToWasmCalls) {
-        for (auto&amp; call : unlinked) {
-            void* executableAddress;
-            if (m_moduleInformation-&gt;isImportedFunctionFromFunctionIndexSpace(call.functionIndex)) {
-                // FIXME imports could have been linked in B3, instead of generating a patchpoint. This condition should be replaced by a RELEASE_ASSERT. https://bugs.webkit.org/show_bug.cgi?id=166462
-                executableAddress = call.target == UnlinkedWasmToWasmCall::Target::ToJs
</del><ins>+        for (auto&amp; unlinked : m_unlinkedWasmToWasmCalls) {
+            for (auto&amp; call : unlinked) {
+                void* executableAddress;
+                if (m_moduleInformation-&gt;isImportedFunctionFromFunctionIndexSpace(call.functionIndex)) {
+                    // FIXME imports could have been linked in B3, instead of generating a patchpoint. This condition should be replaced by a RELEASE_ASSERT. https://bugs.webkit.org/show_bug.cgi?id=166462
+                    executableAddress = call.target == UnlinkedWasmToWasmCall::Target::ToJs
</ins><span class="cx">                     ? m_wasmExitStubs.at(call.functionIndex).wasmToJs.code().executableAddress()
</span><span class="cx">                     : m_wasmExitStubs.at(call.functionIndex).wasmToWasm.code().executableAddress();
</span><del>-            } else {
-                ASSERT(call.target != UnlinkedWasmToWasmCall::Target::ToJs);
-                executableAddress = m_wasmInternalFunctions.at(call.functionIndex - m_wasmExitStubs.size())-&gt;wasmEntrypoint.compilation-&gt;code().executableAddress();
</del><ins>+                } else {
+                    ASSERT(call.target != UnlinkedWasmToWasmCall::Target::ToJs);
+                    executableAddress = m_wasmInternalFunctions.at(call.functionIndex - m_wasmExitStubs.size())-&gt;wasmEntrypoint.compilation-&gt;code().executableAddress();
+                }
+                MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(executableAddress));
</ins><span class="cx">             }
</span><del>-            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(executableAddress));
</del><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_failed = false;
</del><ins>+    if (m_state != State::Completed) {
+        moveToState(State::Completed);
+        m_completionTask(*this);
+        m_completed.notifyAll();
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Plan::initializeCallees(JSGlobalObject* globalObject, std::function&lt;void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)&gt; callback)
</del><ins>+void Plan::waitForCompletion()
</ins><span class="cx"> {
</span><del>-    ASSERT(!failed());
-    for (unsigned internalFunctionIndex = 0; internalFunctionIndex &lt; m_wasmInternalFunctions.size(); ++internalFunctionIndex) {
-        WasmInternalFunction* function = m_wasmInternalFunctions[internalFunctionIndex].get();
</del><ins>+    LockHolder locker(m_lock);
+    if (m_state != State::Completed) {
+        // FIXME: We should have a wait conditionally so we don't have to hold the lock to complete / fail.
+        m_completed.wait(m_lock);
+    }
+}
</ins><span class="cx"> 
</span><del>-        JSWebAssemblyCallee* jsEntrypointCallee = JSWebAssemblyCallee::create(globalObject-&gt;vm(), WTFMove(function-&gt;jsToWasmEntrypoint));
-        MacroAssembler::repatchPointer(function-&gt;jsToWasmCalleeMoveLocation, jsEntrypointCallee);
-
-        JSWebAssemblyCallee* wasmEntrypointCallee = JSWebAssemblyCallee::create(globalObject-&gt;vm(), WTFMove(function-&gt;wasmEntrypoint));
-        MacroAssembler::repatchPointer(function-&gt;wasmCalleeMoveLocation, wasmEntrypointCallee);
-
-        callback(internalFunctionIndex, jsEntrypointCallee, wasmEntrypointCallee);
</del><ins>+void Plan::cancel()
+{
+    LockHolder locker(m_lock);
+    if (m_state != State::Completed) {
+        m_currentIndex = m_functionLocationInBinary.size();
+        fail(locker, ASCIILiteral(&quot;WebAssembly Plan was canceled. If you see this error message please file a bug at bugs.webkit.org!&quot;));
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlanh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPlan.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlan.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -40,61 +40,96 @@
</span><span class="cx"> class CallLinkInfo;
</span><span class="cx"> class JSGlobalObject;
</span><span class="cx"> class JSWebAssemblyCallee;
</span><ins>+class JSPromiseDeferred;
</ins><span class="cx"> 
</span><span class="cx"> namespace Wasm {
</span><span class="cx"> 
</span><del>-class Plan {
</del><ins>+class Plan : public ThreadSafeRefCounted&lt;Plan&gt; {
</ins><span class="cx"> public:
</span><del>-    JS_EXPORT_PRIVATE Plan(VM*, Vector&lt;uint8_t&gt;);
-    JS_EXPORT_PRIVATE Plan(VM*, const uint8_t*, size_t);
</del><ins>+    static void dontFinalize(Plan&amp;) { }
+    typedef std::function&lt;void(Plan&amp;)&gt; CompletionTask;
+    enum AsyncWork : uint8_t { FullCompile, Validation };
+    // Note: CompletionTask should not hold a reference to the Plan otherwise there will be a reference cycle.
+    Plan(VM&amp;, ArrayBuffer&amp;, AsyncWork, CompletionTask&amp;&amp;);
+    JS_EXPORT_PRIVATE Plan(VM&amp;, Vector&lt;uint8_t&gt;&amp;, AsyncWork, CompletionTask&amp;&amp;);
+    JS_EXPORT_PRIVATE Plan(VM&amp;, const uint8_t*, size_t, AsyncWork, CompletionTask&amp;&amp;);
</ins><span class="cx">     JS_EXPORT_PRIVATE ~Plan();
</span><span class="cx"> 
</span><del>-    bool parseAndValidateModule(std::optional&lt;MemoryMode&gt; = std::nullopt);
</del><ins>+    bool parseAndValidateModule();
</ins><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE void run(std::optional&lt;MemoryMode&gt; = std::nullopt);
</del><ins>+    JS_EXPORT_PRIVATE void prepare();
+    void compileFunctions();
</ins><span class="cx"> 
</span><del>-    JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function&lt;void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)&gt;);
</del><ins>+    template&lt;typename Functor&gt;
+    void initializeCallees(const Functor&amp;);
</ins><span class="cx"> 
</span><del>-    bool WARN_UNUSED_RETURN failed() const { return m_failed; }
-    const String&amp; errorMessage() const
-    {
-        RELEASE_ASSERT(failed());
-        return m_errorMessage;
-    }
-
</del><span class="cx">     Vector&lt;Export&gt;&amp; exports() const
</span><span class="cx">     {
</span><del>-        RELEASE_ASSERT(!failed());
</del><ins>+        RELEASE_ASSERT(!failed() &amp;&amp; !hasWork());
</ins><span class="cx">         return m_moduleInformation-&gt;exports;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     size_t internalFunctionCount() const
</span><span class="cx">     {
</span><del>-        RELEASE_ASSERT(!failed());
-        return m_wasmInternalFunctions.size();
</del><ins>+        RELEASE_ASSERT(!failed() &amp;&amp; !hasWork());
+        return m_functionLocationInBinary.size();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;ModuleInformation&gt;&amp;&amp; takeModuleInformation()
</span><span class="cx">     {
</span><del>-        RELEASE_ASSERT(!failed());
</del><ins>+        RELEASE_ASSERT(!failed() &amp;&amp; !hasWork());
</ins><span class="cx">         return WTFMove(m_moduleInformation);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Bag&lt;CallLinkInfo&gt;&amp;&amp; takeCallLinkInfos()
</span><span class="cx">     {
</span><del>-        RELEASE_ASSERT(!failed());
</del><ins>+        RELEASE_ASSERT(!failed() &amp;&amp; !hasWork());
</ins><span class="cx">         return WTFMove(m_callLinkInfos);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;WasmExitStubs&gt;&amp;&amp; takeWasmExitStubs()
</span><span class="cx">     {
</span><del>-        RELEASE_ASSERT(!failed());
</del><ins>+        RELEASE_ASSERT(!failed() &amp;&amp; !hasWork());
</ins><span class="cx">         return WTFMove(m_wasmExitStubs);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MemoryMode mode() const { return m_moduleInformation-&gt;memory.mode(); }
</del><ins>+    void setModeAndPromise(MemoryMode mode, JSPromiseDeferred* promise)
+    {
+        m_mode = mode;
+        m_pendingPromise = promise;
+    }
+    MemoryMode mode() const { return m_mode; }
+    JSPromiseDeferred* pendingPromise() { return m_pendingPromise; }
+    VM&amp; vm() const { return m_vm; }
</ins><span class="cx"> 
</span><ins>+    enum class State : uint8_t {
+        Initial,
+        Validated,
+        Prepared,
+        Compiled,
+        Completed // We should only move to Completed if we are holding the lock.
+    };
+
+    const String&amp; errorMessage() const { return m_errorMessage; }
+
+    bool WARN_UNUSED_RETURN failed() const { return !errorMessage().isNull(); }
+    bool hasWork() const { return m_state &lt; State::Compiled; }
+    bool hasBeenPrepared() const { return m_state &gt;= State::Prepared; }
+
+    void waitForCompletion();
+    void cancel();
+
</ins><span class="cx"> private:
</span><ins>+    class ThreadCountHolder;
+    friend class ThreadCountHolder;
+
+    void complete(const AbstractLocker&amp;);
+
+    void moveToState(State);
+    void fail(const AbstractLocker&amp;, String&amp;&amp; errorMessage);
+
+    const char* stateString(State);
+
</ins><span class="cx">     std::unique_ptr&lt;ModuleInformation&gt; m_moduleInformation;
</span><span class="cx">     Vector&lt;FunctionLocationInBinary&gt; m_functionLocationInBinary;
</span><span class="cx">     Vector&lt;SignatureIndex&gt; m_moduleSignatureIndicesToUniquedSignatureIndices;
</span><span class="lines">@@ -103,16 +138,24 @@
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;WasmInternalFunction&gt;&gt; m_wasmInternalFunctions;
</span><span class="cx">     Vector&lt;CompilationContext&gt; m_compilationContexts;
</span><span class="cx"> 
</span><del>-    VM* m_vm;
</del><ins>+    VM&amp; m_vm;
+    JSPromiseDeferred* m_pendingPromise { nullptr };
+    CompletionTask m_completionTask;
+
</ins><span class="cx">     Vector&lt;Vector&lt;UnlinkedWasmToWasmCall&gt;&gt; m_unlinkedWasmToWasmCalls;
</span><span class="cx">     const uint8_t* m_source;
</span><span class="cx">     const size_t m_sourceLength;
</span><del>-    bool m_failed { true };
</del><span class="cx">     String m_errorMessage;
</span><del>-    uint32_t m_currentIndex;
</del><ins>+    MemoryMode m_mode { MemoryMode::BoundsChecking };
</ins><span class="cx">     Lock m_lock;
</span><ins>+    Condition m_completed;
+    State m_state { State::Initial };
+    const AsyncWork m_asyncWork;
+    uint8_t m_numberOfActiveThreads { 0 };
+    uint32_t m_currentIndex { 0 };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> } } // namespace JSC::Wasm
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEBASSEMBLY)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPlanInlineshfromrev214502trunkSourceJavaScriptCorewasmWasmB3IRGeneratorh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/wasm/WasmPlanInlines.h (from rev 214502, trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h) (0 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPlanInlines.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WasmPlanInlines.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;JSWebAssemblyCallee.h&quot;
+#include &quot;WasmPlan.h&quot;
+
+namespace JSC { namespace Wasm {
+
+template&lt;typename Functor&gt;
+void Plan::initializeCallees(const Functor&amp; callback)
+{
+    ASSERT(!failed());
+    for (unsigned internalFunctionIndex = 0; internalFunctionIndex &lt; m_wasmInternalFunctions.size(); ++internalFunctionIndex) {
+        WasmInternalFunction* function = m_wasmInternalFunctions[internalFunctionIndex].get();
+
+        JSWebAssemblyCallee* jsEntrypointCallee = JSWebAssemblyCallee::create(m_vm, WTFMove(function-&gt;jsToWasmEntrypoint));
+        MacroAssembler::repatchPointer(function-&gt;jsToWasmCalleeMoveLocation, jsEntrypointCallee);
+
+        JSWebAssemblyCallee* wasmEntrypointCallee = JSWebAssemblyCallee::create(m_vm, WTFMove(function-&gt;wasmEntrypoint));
+        MacroAssembler::repatchPointer(function-&gt;wasmCalleeMoveLocation, wasmEntrypointCallee);
+
+        callback(internalFunctionIndex, jsEntrypointCallee, wasmEntrypointCallee);
+    }
+}
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -271,7 +271,7 @@
</span><span class="cx">         if (target.signature() == Void)
</span><span class="cx">             return { };
</span><span class="cx"> 
</span><del>-        WASM_VALIDATOR_FAIL_IF(expressionStack.isEmpty(), &quot;branch to block on empty expression stack&quot;);
</del><ins>+        WASM_VALIDATOR_FAIL_IF(expressionStack.isEmpty(), target.type() == BlockType::TopLevel ? &quot;branch out of function&quot; : &quot;branch to block&quot;, &quot; on empty expression stack, but expected &quot;, target.signature());
</ins><span class="cx">         WASM_VALIDATOR_FAIL_IF(target.signature() != expressionStack.last(), &quot;branch's stack type doesn't match block's type&quot;);
</span><span class="cx"> 
</span><span class="cx">         return { };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmWorklistcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/WasmWorklist.cpp (0 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmWorklist.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WasmWorklist.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -0,0 +1,275 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;WasmWorklist.h&quot;
+
+#if ENABLE(WEBASSEMBLY)
+
+#include &quot;WasmPlan.h&quot;
+
+#include &lt;wtf/NumberOfCores.h&gt;
+
+namespace JSC { namespace Wasm {
+
+static const bool verbose = false;
+
+const char* Worklist::priorityString(Priority priority)
+{
+    switch (priority) {
+    case Priority::Preparation: return &quot;Preparation&quot;;
+    case Priority::Shutdown: return &quot;Shutdown&quot;;
+    case Priority::Compilation: return &quot;Compilation&quot;;
+    case Priority::Synchronous: return &quot;Synchronous&quot;;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+// The Thread class is designed to prevent threads from blocking when there is still work
+// in the queue. Wasm's Plans have some phases, Validiation, Preparation, and Completion,
+// that can only be done by one thread, and another phase, Compilation, that can be done
+// many threads. In order to stop a thread from wasting time we remove any plan that is
+// is currently in a single threaded state from the work queue so other plans can run.
+class Worklist::Thread final : public AutomaticThread {
+public:
+    using Base = AutomaticThread;
+    Thread(const AbstractLocker&amp; locker, Worklist&amp; work)
+        : Base(locker, work.m_lock, work.m_planEnqueued)
+        , worklist(work)
+    {
+
+    }
+
+protected:
+    PollResult poll(const AbstractLocker&amp;) override
+    {
+        auto&amp; queue = worklist.m_queue;
+        synchronize.notifyAll();
+
+        while (!queue.empty()) {
+
+            Priority priority = queue.top().priority;
+            if (priority == Worklist::Priority::Shutdown)
+                return PollResult::Stop;
+
+            element = queue.top();
+            // Only one thread should validate/prepare.
+            if (!queue.top().plan-&gt;hasBeenPrepared()) {
+                queue.pop();
+                return PollResult::Work;
+            }
+
+            if (element.plan-&gt;hasWork())
+                return PollResult::Work;
+
+            // There must be a another thread linking this plan so we can deque and see if there is other work.
+            queue.pop();
+            element = QueueElement();
+        }
+        return PollResult::Wait;
+    }
+
+    WorkResult work() override
+    {
+        auto complete = [&amp;] () {
+            element = QueueElement();
+            return WorkResult::Continue;
+        };
+
+        Plan* plan = element.plan.get();
+        ASSERT(plan);
+        if (!plan-&gt;hasBeenPrepared()) {
+            plan-&gt;parseAndValidateModule();
+            if (!plan-&gt;hasWork())
+                return complete();
+            
+            plan-&gt;prepare();
+
+            LockHolder locker(*worklist.m_lock);
+            element.setToNextPriority();
+            worklist.m_queue.push(element);
+            worklist.m_planEnqueued-&gt;notifyAll(locker);
+        }
+
+        // FIXME: this should check in occasionally to see if there are new, higher priority e.g. synchronous, plans that need to be run.
+        // https://bugs.webkit.org/show_bug.cgi?id=170204
+        plan-&gt;compileFunctions();
+        ASSERT(!plan-&gt;hasWork());
+
+        {
+            LockHolder locker(*worklist.m_lock);
+            auto queue = worklist.m_queue;
+            // Another thread may have removed our plan from the queue already.
+            if (!queue.empty() &amp;&amp; queue.top().plan == element.plan)
+                queue.pop();
+        }
+
+        return complete();
+    }
+
+public:
+    Condition synchronize;
+    Worklist&amp; worklist;
+    // We can only modify element when holding the lock. A synchronous compile might look at each thread's tasks in order to boost the priority.
+    QueueElement element;
+};
+
+void Worklist::QueueElement::setToNextPriority()
+{
+    switch (priority) {
+    case Priority::Preparation:
+        priority = Priority::Compilation;
+        return;
+    case Priority::Synchronous:
+        return;
+    default:
+        break;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+enum class IterateResult { UpdateAndBreak, DropAndContinue, Continue };
+
+template&lt;typename Functor&gt;
+void Worklist::iterate(const AbstractLocker&amp;, const Functor&amp; func)
+{
+    // std::priority_queue does not have an iterator or decrease_key... :( While this is gross, this function
+    // shouldn't be called very often and the queue should be small.
+    // FIXME: we should have our own PriorityQueue that doesn't suck.
+    // https://bugs.webkit.org/show_bug.cgi?id=170145
+    std::vector&lt;QueueElement&gt; elements;
+    while (!m_queue.empty()) {
+        QueueElement element = m_queue.top();
+        m_queue.pop();
+        IterateResult result = func(element);
+        if (result == IterateResult::UpdateAndBreak) {
+            elements.push_back(element);
+            break;
+        }
+
+        if (result == IterateResult::Continue)
+            elements.push_back(element);
+        continue;
+    }
+    
+    for (auto element : elements)
+        m_queue.push(element);
+}
+
+void Worklist::enqueue(Ref&lt;Plan&gt; plan)
+{
+    LockHolder locker(*m_lock);
+
+    if (!ASSERT_DISABLED) {
+        iterate(locker, [&amp;] (QueueElement&amp; element) {
+            ASSERT_UNUSED(element, element.plan.get() != &amp;plan.get());
+            return IterateResult::Continue;
+        });
+    }
+
+    // If we don't have a promise it must be synchronous so we should boost the priority.
+    Priority priority = plan-&gt;pendingPromise() ? Priority::Preparation : Priority::Synchronous;
+    dataLogLnIf(verbose, &quot;Enqueuing plan with priority: &quot;, priorityString(priority));
+    m_queue.push({ priority, nextTicket(),  WTFMove(plan) });
+    m_planEnqueued-&gt;notifyOne(locker);
+}
+
+void Worklist::completePlanSynchronously(Plan&amp; plan)
+{
+    {
+        LockHolder locker(*m_lock);
+        iterate(locker, [&amp;] (QueueElement&amp; element) {
+            if (element.plan == &amp;plan) {
+                element.priority = Priority::Synchronous;
+                return IterateResult::UpdateAndBreak;
+            }
+            return IterateResult::Continue;
+        });
+
+        for (auto&amp; thread : m_threads) {
+            if (thread-&gt;element.plan == &amp;plan)
+                thread-&gt;element.priority = Priority::Synchronous;
+        }
+    }
+
+    plan.waitForCompletion();
+}
+
+void Worklist::stopAllPlansForVM(VM&amp; vm)
+{
+    LockHolder locker(*m_lock);
+    iterate(locker, [&amp;] (QueueElement&amp; element) {
+        if (&amp;element.plan-&gt;vm() == &amp;vm) {
+            element.plan-&gt;cancel();
+            return IterateResult::DropAndContinue;
+        }
+        return IterateResult::Continue;
+    });
+
+    for (auto&amp; thread : m_threads) {
+        if (thread-&gt;element.plan &amp;&amp; &amp;thread-&gt;element.plan-&gt;vm() == &amp;vm) {
+            // We don't have to worry about the deadlocking since the thread can't block without clearing the plan and must hold the lock to do so.
+            thread-&gt;element.plan-&gt;cancel();
+            thread-&gt;synchronize.wait(*m_lock);
+        }
+    }
+}
+
+Worklist::Worklist()
+    : m_lock(Box&lt;Lock&gt;::create())
+    , m_planEnqueued(AutomaticThreadCondition::create())
+{
+    unsigned numberOfCompilationThreads = Options::useConcurrentJIT() ? WTF::numberOfProcessorCores() : 1;
+    m_threads.reserveCapacity(numberOfCompilationThreads);
+    LockHolder locker(*m_lock);
+    for (unsigned i = 0; i &lt; numberOfCompilationThreads; i++)
+        m_threads.uncheckedAppend(std::make_unique&lt;Worklist::Thread&gt;(locker, *this));
+}
+
+Worklist::~Worklist()
+{
+    {
+        LockHolder locker(*m_lock);
+        m_queue.push({ Priority::Shutdown, nextTicket(), nullptr });
+        m_planEnqueued-&gt;notifyAll(locker);
+    }
+    for (unsigned i = 0; i &lt; m_threads.size(); ++i)
+        m_threads[i]-&gt;join();
+}
+
+static Worklist* globalWorklist;
+
+Worklist* existingWorklistOrNull() { return globalWorklist; }
+Worklist&amp; ensureWorklist()
+{
+    static std::once_flag initializeWorklist;
+    std::call_once(initializeWorklist, [] {
+        globalWorklist = new Worklist();
+    });
+    return *globalWorklist;
+}
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmWorklisth"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/wasm/WasmWorklist.h (0 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmWorklist.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/wasm/WasmWorklist.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -0,0 +1,110 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;VM.h&quot;
+
+#include &lt;queue&gt;
+
+#include &lt;wtf/AutomaticThread.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC {
+
+class JSPromiseDeferred;
+
+namespace Wasm {
+
+class Plan;
+
+class Worklist {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    Worklist();
+    ~Worklist();
+
+    JS_EXPORT_PRIVATE void enqueue(Ref&lt;Plan&gt;);
+    void stopAllPlansForVM(VM&amp;);
+
+    JS_EXPORT_PRIVATE void completePlanSynchronously(Plan&amp;);
+
+    void activatePlan(JSPromiseDeferred*, Plan*);
+    void deactivePlan(JSPromiseDeferred*, Plan*);
+
+private:
+    class Thread;
+    friend class Thread;
+
+    typedef uint64_t Ticket;
+    Ticket nextTicket() { return m_lastGrantedTicket++; }
+
+    enum class Priority {
+        Shutdown,
+        Synchronous,
+        Compilation,
+        Preparation
+    };
+    const char* priorityString(Priority);
+
+    struct QueueElement {
+        Priority priority;
+        Ticket ticket;
+        RefPtr&lt;Plan&gt; plan;
+
+        void setToNextPriority();
+    };
+
+    struct Comparator {
+        bool operator()(const QueueElement&amp; left, const QueueElement&amp; right) const
+        {
+            if (left.priority == right.priority)
+                return left.ticket &gt; right.ticket;
+            return left.priority &gt; right.priority;
+        }
+    };
+
+    template&lt;typename Functor&gt;
+    void iterate(const AbstractLocker&amp;, const Functor&amp;);
+
+    Box&lt;Lock&gt; m_lock;
+    RefPtr&lt;AutomaticThreadCondition&gt; m_planEnqueued;
+    // Technically, this could overflow but that's unlikely. Even if it did, we will just compile things of the same
+    // Priority it the wrong order, which isn't wrong, just suboptimal.
+    Ticket m_lastGrantedTicket { 0 };
+    // FIXME: This should use WTF::Vector but WTF::Vector does not support random access iterator.
+    std::priority_queue&lt;QueueElement, std::vector&lt;QueueElement&gt;, Comparator&gt; m_queue;
+    HashMap&lt;JSPromiseDeferred*, Plan*&gt; m_activePlans;
+    Vector&lt;std::unique_ptr&lt;Thread&gt;&gt; m_threads;
+};
+
+Worklist* existingWorklistOrNull();
+JS_EXPORT_PRIVATE Worklist&amp; ensureWorklist();
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyCalleeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -60,8 +60,8 @@
</span><span class="cx">     RegisterAtOffsetList* calleeSaveRegisters() { return &amp;m_entrypoint.calleeSaveRegisters; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    void finishCreation(VM&amp;, Wasm::Entrypoint&amp;&amp;);
-    JSWebAssemblyCallee(VM&amp;);
</del><ins>+    JS_EXPORT_PRIVATE void finishCreation(VM&amp;, Wasm::Entrypoint&amp;&amp;);
+    JS_EXPORT_PRIVATE JSWebAssemblyCallee(VM&amp;);
</ins><span class="cx"> 
</span><span class="cx">     Wasm::Entrypoint m_entrypoint;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -29,31 +29,67 @@
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;JSWebAssemblyLinkError.h&quot;
</ins><span class="cx"> #include &quot;JSWebAssemblyMemory.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyModule.h&quot;
</span><ins>+#include &quot;WasmPlanInlines.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSWebAssemblyCodeBlock::s_info = { &quot;WebAssemblyCodeBlock&quot;, nullptr, 0, CREATE_METHOD_TABLE(JSWebAssemblyCodeBlock) };
</span><span class="cx"> 
</span><del>-JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM&amp; vm, JSWebAssemblyModule* owner, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; wasmExitStubs, Wasm::MemoryMode mode, unsigned calleeCount)
</del><ins>+JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM&amp; vm, JSWebAssemblyModule* owner,  Wasm::MemoryMode mode, Ref&lt;Wasm::Plan&gt;&amp;&amp; plan, unsigned calleeCount)
</ins><span class="cx">     : Base(vm, vm.webAssemblyCodeBlockStructure.get())
</span><del>-    , m_callLinkInfos(WTFMove(callLinkInfos))
-    , m_wasmExitStubs(WTFMove(wasmExitStubs))
</del><ins>+    , m_plan(WTFMove(plan))
</ins><span class="cx">     , m_mode(mode)
</span><span class="cx">     , m_calleeCount(calleeCount)
</span><span class="cx"> {
</span><span class="cx">     m_module.set(vm, this, owner);
</span><ins>+    ASSERT(!module()-&gt;codeBlock(mode));
+    module()-&gt;setCodeBlock(vm, mode, this);
+
</ins><span class="cx">     memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier&lt;JSWebAssemblyCallee&gt;) * 2);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSWebAssemblyCodeBlock::initialize()
+{
+    if (initialized())
+        return;
+
+    VM&amp; vm = plan().vm();
+    ASSERT(vm.currentThreadIsHoldingAPILock());
+    RELEASE_ASSERT(!plan().hasWork());
+
+    if (plan().failed()) {
+        m_errorMessage = plan().errorMessage();
+        m_plan = nullptr;
+        return;
+    }
+
+    RELEASE_ASSERT(plan().mode() == mode());
+    ASSERT(plan().internalFunctionCount() == m_calleeCount);
+
+    m_callLinkInfos = plan().takeCallLinkInfos();
+    m_wasmExitStubs = plan().takeWasmExitStubs();
+
+    plan().initializeCallees([&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
+        setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee);
+        setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee);
+    });
+
+    m_plan = nullptr;
+}
+
</ins><span class="cx"> void JSWebAssemblyCodeBlock::destroy(JSCell* cell)
</span><span class="cx"> {
</span><span class="cx">     static_cast&lt;JSWebAssemblyCodeBlock*&gt;(cell)-&gt;JSWebAssemblyCodeBlock::~JSWebAssemblyCodeBlock();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool JSWebAssemblyCodeBlock::isSafeToRun(JSWebAssemblyMemory* memory)
</del><ins>+bool JSWebAssemblyCodeBlock::isSafeToRun(JSWebAssemblyMemory* memory) const
</ins><span class="cx"> {
</span><ins>+    if (!runnable())
+        return false;
+
</ins><span class="cx">     Wasm::MemoryMode codeMode = mode();
</span><span class="cx">     Wasm::MemoryMode memoryMode = memory-&gt;memory().mode();
</span><span class="cx">     switch (codeMode) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyCallee.h&quot;
</span><ins>+#include &quot;PromiseDeferredTimer.h&quot;
</ins><span class="cx"> #include &quot;UnconditionalFinalizer.h&quot;
</span><span class="cx"> #include &quot;WasmFormat.h&quot;
</span><span class="cx"> #include &lt;wtf/Bag.h&gt;
</span><span class="lines">@@ -39,14 +40,18 @@
</span><span class="cx"> class JSWebAssemblyModule;
</span><span class="cx"> class JSWebAssemblyMemory;
</span><span class="cx"> 
</span><ins>+namespace Wasm {
+class Plan;
+}
+
</ins><span class="cx"> class JSWebAssemblyCodeBlock : public JSCell {
</span><span class="cx"> public:
</span><span class="cx">     typedef JSCell Base;
</span><span class="cx">     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyCodeBlock* create(VM&amp; vm, JSWebAssemblyModule* owner, Bag&lt;CallLinkInfo&gt;&amp;&amp; callLinkInfos, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp; exitStubs, Wasm::MemoryMode mode, unsigned calleeCount)
</del><ins>+    static JSWebAssemblyCodeBlock* create(VM&amp; vm, JSWebAssemblyModule* owner, Wasm::MemoryMode mode, Ref&lt;Wasm::Plan&gt;&amp;&amp; plan, unsigned calleeCount)
</ins><span class="cx">     {
</span><del>-        auto* result = new (NotNull, allocateCell&lt;JSWebAssemblyCodeBlock&gt;(vm.heap, allocationSize(calleeCount))) JSWebAssemblyCodeBlock(vm, owner, std::forward&lt;Bag&lt;CallLinkInfo&gt;&gt;(callLinkInfos), std::forward&lt;Vector&lt;Wasm::WasmExitStubs&gt;&gt;(exitStubs), mode, calleeCount);
</del><ins>+        auto* result = new (NotNull, allocateCell&lt;JSWebAssemblyCodeBlock&gt;(vm.heap, allocationSize(calleeCount))) JSWebAssemblyCodeBlock(vm, owner, mode, WTFMove(plan), calleeCount);
</ins><span class="cx">         result-&gt;finishCreation(vm);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="lines">@@ -59,8 +64,17 @@
</span><span class="cx">     unsigned functionImportCount() const { return m_wasmExitStubs.size(); }
</span><span class="cx">     Wasm::MemoryMode mode() const { return m_mode; }
</span><span class="cx">     JSWebAssemblyModule* module() const { return m_module.get(); }
</span><del>-    bool isSafeToRun(JSWebAssemblyMemory*);
</del><span class="cx"> 
</span><ins>+    // Don't call intialize directly, this should be called for you, as needed, by JSWebAssemblyInstance::finalizeCreation.
+    void initialize();
+    bool initialized() const { return !m_plan; }
+
+    Wasm::Plan&amp; plan() const { ASSERT(!initialized()); return *m_plan; }
+
+    bool runnable() const { return initialized() &amp;&amp; !m_errorMessage; }
+    String&amp; errorMessage() { ASSERT(!runnable()); return m_errorMessage; }
+    bool isSafeToRun(JSWebAssemblyMemory*) const;
+
</ins><span class="cx">     JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)
</span><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(functionIndexSpace &gt;= functionImportCount());
</span><span class="lines">@@ -89,10 +103,7 @@
</span><span class="cx">         callees()[calleeIndex + m_calleeCount].set(vm, this, callee);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    WriteBarrier&lt;JSWebAssemblyCallee&gt;* callees()
-    {
-        return bitwise_cast&lt;WriteBarrier&lt;JSWebAssemblyCallee&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + offsetOfCallees());
-    }
</del><ins>+    WriteBarrier&lt;JSWebAssemblyCallee&gt;* callees() { return bitwise_cast&lt;WriteBarrier&lt;JSWebAssemblyCallee&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + offsetOfCallees()); }
</ins><span class="cx"> 
</span><span class="cx">     void* wasmToJsCallStubForImport(unsigned importIndex)
</span><span class="cx">     {
</span><span class="lines">@@ -101,7 +112,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    JSWebAssemblyCodeBlock(VM&amp;, JSWebAssemblyModule*, Bag&lt;CallLinkInfo&gt;&amp;&amp;, Vector&lt;Wasm::WasmExitStubs&gt;&amp;&amp;, Wasm::MemoryMode, unsigned calleeCount);
</del><ins>+    JSWebAssemblyCodeBlock(VM&amp;, JSWebAssemblyModule*, Wasm::MemoryMode, Ref&lt;Wasm::Plan&gt;&amp;&amp;, unsigned calleeCount);
</ins><span class="cx">     DECLARE_EXPORT_INFO;
</span><span class="cx">     static const bool needsDestruction = true;
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="lines">@@ -125,6 +136,9 @@
</span><span class="cx">     UnconditionalFinalizer m_unconditionalFinalizer;
</span><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><span class="cx">     Vector&lt;Wasm::WasmExitStubs&gt; m_wasmExitStubs;
</span><ins>+    // The plan that is compiling this code block.
+    RefPtr&lt;Wasm::Plan&gt; m_plan;
+    String m_errorMessage;
</ins><span class="cx">     Wasm::MemoryMode m_mode;
</span><span class="cx">     unsigned m_calleeCount;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -73,6 +73,22 @@
</span><span class="cx">     return arrayBufferView ? static_cast&lt;uint8_t*&gt;(arrayBufferView-&gt;vector()) : static_cast&lt;uint8_t*&gt;(arrayBuffer-&gt;impl()-&gt;data());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE RefPtr&lt;ArrayBuffer&gt; createSourceBufferFromValue(VM&amp; vm, ExecState* exec, JSValue value)
+{
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    size_t byteOffset;
+    size_t byteSize;
+    uint8_t* data = getWasmBufferFromValue(exec, value, byteOffset, byteSize);
+    RETURN_IF_EXCEPTION(throwScope, nullptr);
+
+    auto buffer = ArrayBuffer::tryCreate(data + byteOffset, byteSize);
+    if (buffer)
+        return buffer;
+
+    throwException(exec, throwScope, createOutOfMemoryError(exec));
+    return nullptr;
+}
+
</ins><span class="cx"> ALWAYS_INLINE bool isWebAssemblyHostFunction(VM&amp; vm, JSObject* object, WebAssemblyFunction*&amp; wasmFunction, WebAssemblyWrapperFunction*&amp; wasmWrapperFunction)
</span><span class="cx"> {
</span><span class="cx">     if (object-&gt;inherits(vm, WebAssemblyFunction::info())) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstancecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -32,33 +32,18 @@
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSModuleEnvironment.h&quot;
</span><span class="cx"> #include &quot;JSModuleNamespaceObject.h&quot;
</span><ins>+#include &quot;JSWebAssemblyHelpers.h&quot;
+#include &quot;JSWebAssemblyLinkError.h&quot;
</ins><span class="cx"> #include &quot;JSWebAssemblyMemory.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyModule.h&quot;
</span><ins>+#include &quot;WebAssemblyModuleRecord.h&quot;
</ins><span class="cx"> #include &quot;WebAssemblyToJSCallee.h&quot;
</span><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-void JSWebAssemblyInstance::setMemory(VM&amp; vm, ExecState* exec, JSWebAssemblyMemory* memory)
-{
-    auto scope = DECLARE_THROW_SCOPE(vm);
-    // We create stub memories even for modules that should eventually get a memory so we want to avoid recompling there.
-    if (memory-&gt;memory()) {
-        auto codeBlock = m_codeBlock-&gt;module()-&gt;codeBlock(vm, exec, memory);
-        RETURN_IF_EXCEPTION(scope,);
-        m_codeBlock.set(vm, this, codeBlock);
-    }
-    m_memory.set(vm, this, memory);
-}
</del><ins>+const ClassInfo JSWebAssemblyInstance::s_info = { &quot;WebAssembly.Instance&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyInstance) };
</ins><span class="cx"> 
</span><del>-JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM&amp; vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
-{
-    // FIXME: These objects could be pretty big we should try to throw OOM here.
-    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyInstance&gt;(vm.heap, allocationSize(module-&gt;moduleInformation().importFunctionSignatureIndices.size()))) JSWebAssemblyInstance(vm, structure, module-&gt;moduleInformation().importFunctionSignatureIndices.size());
-    instance-&gt;finishCreation(vm, module, moduleNamespaceObject);
-    return instance;
-}
-
</del><span class="cx"> Structure* JSWebAssemblyInstance::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span><span class="cx"> {
</span><span class="cx">     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
</span><span class="lines">@@ -76,11 +61,11 @@
</span><span class="cx">     Base::finishCreation(vm);
</span><span class="cx">     ASSERT(inherits(vm, info()));
</span><span class="cx"> 
</span><ins>+    m_module.set(vm, this, module);
</ins><span class="cx">     const size_t extraMemorySize = module-&gt;moduleInformation().globals.size() * sizeof(Register);
</span><span class="cx">     m_globals = MallocPtr&lt;uint64_t&gt;::malloc(extraMemorySize);
</span><span class="cx">     heap()-&gt;reportExtraMemoryAllocated(extraMemorySize);
</span><span class="cx"> 
</span><del>-    m_codeBlock.set(vm, this, module-&gt;codeBlock());
</del><span class="cx">     m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
</span><span class="cx">     m_callee.set(vm, this, module-&gt;callee());
</span><span class="cx">     putDirect(vm, Identifier::fromString(&amp;vm, &quot;exports&quot;), moduleNamespaceObject, None);
</span><span class="lines">@@ -97,6 +82,7 @@
</span><span class="cx">     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
</span><span class="cx"> 
</span><span class="cx">     Base::visitChildren(thisObject, visitor);
</span><ins>+    visitor.append(thisObject-&gt;m_module);
</ins><span class="cx">     visitor.append(thisObject-&gt;m_codeBlock);
</span><span class="cx">     visitor.append(thisObject-&gt;m_moduleNamespaceObject);
</span><span class="cx">     visitor.append(thisObject-&gt;m_memory);
</span><span class="lines">@@ -104,11 +90,272 @@
</span><span class="cx">     visitor.append(thisObject-&gt;m_callee);
</span><span class="cx">     visitor.reportExtraMemoryVisited(thisObject-&gt;module()-&gt;moduleInformation().globals.size());
</span><span class="cx">     for (unsigned i = 0; i &lt; thisObject-&gt;m_numImportFunctions; ++i)
</span><del>-        visitor.append(*thisObject-&gt;importFunction(i));
</del><ins>+        visitor.append(thisObject-&gt;importFunctions()[i]);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-const ClassInfo JSWebAssemblyInstance::s_info = { &quot;WebAssembly.Instance&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyInstance) };
</del><ins>+void JSWebAssemblyInstance::addUnitializedCodeBlock(VM&amp; vm, Ref&lt;Wasm::Plan&gt; plan)
+{
+    auto* codeBlock = JSWebAssemblyCodeBlock::create(vm, module(), memoryMode(), WTFMove(plan), module()-&gt;moduleInformation().internalFunctionCount());
+    m_codeBlock.set(vm, this, codeBlock);
+    ASSERT(!codeBlock-&gt;initialized());
+}
</ins><span class="cx"> 
</span><ins>+void JSWebAssemblyInstance::finalizeCreation(VM&amp; vm, ExecState* exec)
+{
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    codeBlock()-&gt;initialize();
+
+    if (!codeBlock()-&gt;runnable()) {
+        throwException(exec, scope, JSWebAssemblyLinkError::create(exec, vm, globalObject()-&gt;WebAssemblyLinkErrorStructure(), codeBlock()-&gt;errorMessage()));
+        return;
+    }
+    RELEASE_ASSERT(codeBlock()-&gt;isSafeToRun(memory()));
+
+    auto* moduleRecord = jsCast&lt;WebAssemblyModuleRecord*&gt;(m_moduleNamespaceObject-&gt;moduleRecord());
+    moduleRecord-&gt;link(exec, module(), this);
+    RETURN_IF_EXCEPTION(scope, void());
+
+    JSValue startResult = moduleRecord-&gt;evaluate(exec);
+    UNUSED_PARAM(startResult);
+    RETURN_IF_EXCEPTION(scope, void());
+}
+
+JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM&amp; vm, ExecState* exec, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure)
+{
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto* globalObject = exec-&gt;lexicalGlobalObject();
+
+    const Wasm::ModuleInformation&amp; moduleInformation = jsModule-&gt;moduleInformation();
+
+    auto exception = [&amp;] (JSObject* error) {
+        throwException(exec, throwScope, error);
+        return nullptr;
+    };
+
+    // If the list of module.imports is not empty and Type(importObject) is not Object, a TypeError is thrown.
+    if (moduleInformation.imports.size() &amp;&amp; !importObject)
+        return exception(createTypeError(exec, ASCIILiteral(&quot;can't make WebAssembly.Instance because there is no imports Object and the WebAssembly.Module requires imports&quot;)));
+
+    Identifier moduleKey = Identifier::fromUid(PrivateName(PrivateName::Description, &quot;WebAssemblyInstance&quot;));
+    WebAssemblyModuleRecord* moduleRecord = WebAssemblyModuleRecord::create(exec, vm, globalObject-&gt;webAssemblyModuleRecordStructure(), moduleKey, moduleInformation);
+    RETURN_IF_EXCEPTION(throwScope, nullptr);
+
+    JSModuleNamespaceObject* moduleNamespace = moduleRecord-&gt;getModuleNamespace(exec);
+    // FIXME: These objects could be pretty big we should try to throw OOM here.
+    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyInstance&gt;(vm.heap, allocationSize(moduleInformation.importFunctionCount()))) JSWebAssemblyInstance(vm, instanceStructure, moduleInformation.importFunctionCount());
+    instance-&gt;finishCreation(vm, jsModule, moduleNamespace);
+    RETURN_IF_EXCEPTION(throwScope, nullptr);
+
+    // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
+    // Let imports be an initially-empty list of external values.
+    unsigned numImportFunctions = 0;
+    unsigned numImportGlobals = 0;
+
+    bool hasMemoryImport = false;
+    bool hasTableImport = false;
+    // For each import i in module.imports:
+    for (auto&amp; import : moduleInformation.imports) {
+        // 1. Let o be the resultant value of performing Get(importObject, i.module_name).
+        JSValue importModuleValue = importObject-&gt;get(exec, Identifier::fromString(&amp;vm, import.module));
+        RETURN_IF_EXCEPTION(throwScope, nullptr);
+        // 2. If Type(o) is not Object, throw a TypeError.
+        if (!importModuleValue.isObject())
+            return exception(createTypeError(exec, ASCIILiteral(&quot;import must be an object&quot;), defaultSourceAppender, runtimeTypeForValue(importModuleValue)));
+
+        // 3. Let v be the value of performing Get(o, i.item_name)
+        JSObject* object = jsCast&lt;JSObject*&gt;(importModuleValue);
+        JSValue value = object-&gt;get(exec, Identifier::fromString(&amp;vm, import.field));
+        RETURN_IF_EXCEPTION(throwScope, nullptr);
+
+        switch (import.kind) {
+        case Wasm::ExternalKind::Function: {
+            // 4. If i is a function import:
+            // i. If IsCallable(v) is false, throw a WebAssembly.LinkError.
+            if (!value.isFunction())
+                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;import function must be callable&quot;)));
+
+            JSObject* function = jsCast&lt;JSObject*&gt;(value);
+            // ii. If v is an Exported Function Exotic Object:
+            WebAssemblyFunction* wasmFunction;
+            WebAssemblyWrapperFunction* wasmWrapperFunction;
+            if (isWebAssemblyHostFunction(vm, function, wasmFunction, wasmWrapperFunction)) {
+                // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError.
+                Wasm::SignatureIndex importedSignatureIndex;
+                if (wasmFunction)
+                    importedSignatureIndex = wasmFunction-&gt;signatureIndex();
+                else {
+                    importedSignatureIndex = wasmWrapperFunction-&gt;signatureIndex();
+                    // b. Let closure be v.[[Closure]].
+                    function = wasmWrapperFunction-&gt;function();
+                }
+                Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
+                if (importedSignatureIndex != expectedSignatureIndex)
+                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;imported function's signature doesn't match the provided WebAssembly function's signature&quot;)));
+            }
+            // iii. Otherwise:
+            // a. Let closure be a new host function of the given signature which calls v by coercing WebAssembly arguments to JavaScript arguments via ToJSValue and returns the result, if any, by coercing via ToWebAssemblyValue.
+            // Note: done as part of Plan compilation.
+            // iv. Append v to funcs.
+            // Note: adding the JSCell to the instance list fulfills closure requirements b. above (the WebAssembly.Instance wil be kept alive) and v. below (the JSFunction).
+
+            ASSERT(numImportFunctions == import.kindIndex);
+            instance-&gt;importFunctions()[numImportFunctions++].set(vm, instance, function);
+            // v. Append closure to imports.
+            break;
+        }
+        case Wasm::ExternalKind::Table: {
+            RELEASE_ASSERT(!hasTableImport); // This should be guaranteed by a validation failure.
+            // 7. Otherwise (i is a table import):
+            hasTableImport = true;
+            JSWebAssemblyTable* table = jsDynamicCast&lt;JSWebAssemblyTable*&gt;(vm, value);
+            // i. If v is not a WebAssembly.Table object, throw a WebAssembly.LinkError.
+            if (!table)
+                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Table import is not an instance of WebAssembly.Table&quot;)));
+
+            uint32_t expectedInitial = moduleInformation.tableInformation.initial();
+            uint32_t actualInitial = table-&gt;size();
+            if (actualInitial &lt; expectedInitial)
+                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Table import provided an 'initial' that is too small&quot;)));
+
+            if (std::optional&lt;uint32_t&gt; expectedMaximum = moduleInformation.tableInformation.maximum()) {
+                std::optional&lt;uint32_t&gt; actualMaximum = table-&gt;maximum();
+                if (!actualMaximum)
+                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Table import does not have a 'maximum' but the module requires that it does&quot;)));
+                if (*actualMaximum &gt; *expectedMaximum)
+                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Imported Table's 'maximum' is larger than the module's expected 'maximum'&quot;)));
+            }
+
+            // ii. Append v to tables.
+            // iii. Append v.[[Table]] to imports.
+            instance-&gt;m_table.set(vm, instance, table);
+            break;
+        }
+
+        case Wasm::ExternalKind::Memory: {
+            // 6. If i is a memory import:
+            RELEASE_ASSERT(!hasMemoryImport); // This should be guaranteed by a validation failure.
+            RELEASE_ASSERT(moduleInformation.memory);
+            hasMemoryImport = true;
+            JSWebAssemblyMemory* memory = jsDynamicCast&lt;JSWebAssemblyMemory*&gt;(vm, value);
+            // i. If v is not a WebAssembly.Memory object, throw a WebAssembly.LinkError.
+            if (!memory)
+                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import is not an instance of WebAssembly.Memory&quot;)));
+
+            Wasm::PageCount declaredInitial = moduleInformation.memory.initial();
+            Wasm::PageCount importedInitial = memory-&gt;memory().initial();
+            if (importedInitial &lt; declaredInitial)
+                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import provided an 'initial' that is smaller than the module's declared 'initial' import memory size&quot;)));
+
+            if (Wasm::PageCount declaredMaximum = moduleInformation.memory.maximum()) {
+                Wasm::PageCount importedMaximum = memory-&gt;memory().maximum();
+                if (!importedMaximum)
+                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import did not have a 'maximum' but the module requires that it does&quot;)));
+
+                if (importedMaximum &gt; declaredMaximum)
+                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import provided a 'maximum' that is larger than the module's declared 'maximum' import memory size&quot;)));
+            }
+
+            // ii. Append v to memories.
+            // iii. Append v.[[Memory]] to imports.
+            ASSERT(!instance-&gt;m_memory);
+            instance-&gt;m_memory.set(vm, instance, memory);
+            RETURN_IF_EXCEPTION(throwScope, nullptr);
+            break;
+        }
+        case Wasm::ExternalKind::Global: {
+            // 5. If i is a global import:
+            // i. If i is not an immutable global, throw a TypeError.
+            ASSERT(moduleInformation.globals[import.kindIndex].mutability == Wasm::Global::Immutable);
+            // ii. If the global_type of i is i64 or Type(v) is not Number, throw a WebAssembly.LinkError.
+            if (moduleInformation.globals[import.kindIndex].type == Wasm::I64)
+                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;imported global cannot be an i64&quot;)));
+            if (!value.isNumber())
+                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;imported global must be a number&quot;)));
+            // iii. Append ToWebAssemblyValue(v) to imports.
+            ASSERT(numImportGlobals == import.kindIndex);
+            switch (moduleInformation.globals[import.kindIndex].type) {
+            case Wasm::I32:
+                instance-&gt;setGlobal(numImportGlobals++, value.toInt32(exec));
+                break;
+            case Wasm::F32:
+                instance-&gt;setGlobal(numImportGlobals++, bitwise_cast&lt;uint32_t&gt;(value.toFloat(exec)));
+                break;
+            case Wasm::F64:
+                instance-&gt;setGlobal(numImportGlobals++, bitwise_cast&lt;uint64_t&gt;(value.asNumber()));
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
+            ASSERT(!throwScope.exception());
+            break;
+        }
+        }
+    }
+
+    {
+        if (!!moduleInformation.memory &amp;&amp; moduleInformation.memory.isImport()) {
+            // We should either have a Memory import or we should have thrown an exception.
+            RELEASE_ASSERT(hasMemoryImport);
+        }
+
+        if (moduleInformation.memory &amp;&amp; !hasMemoryImport) {
+            RELEASE_ASSERT(!moduleInformation.memory.isImport());
+            // We create a memory when it's a memory definition.
+            RefPtr&lt;Wasm::Memory&gt; memory = Wasm::Memory::create(vm, moduleInformation.memory.initial(), moduleInformation.memory.maximum());
+            if (!memory)
+                return exception(createOutOfMemoryError(exec));
+
+            instance-&gt;m_memory.set(vm, instance,
+                JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), memory.releaseNonNull()));
+            RETURN_IF_EXCEPTION(throwScope, nullptr);
+        }
+    }
+
+    {
+        if (!!moduleInformation.tableInformation &amp;&amp; moduleInformation.tableInformation.isImport()) {
+            // We should either have a Table import or we should have thrown an exception.
+            RELEASE_ASSERT(hasTableImport);
+        }
+
+        if (!!moduleInformation.tableInformation &amp;&amp; !hasTableImport) {
+            RELEASE_ASSERT(!moduleInformation.tableInformation.isImport());
+            // We create a Table when it's a Table definition.
+            JSWebAssemblyTable* table = JSWebAssemblyTable::create(exec, vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyTableStructure(),
+                moduleInformation.tableInformation.initial(), moduleInformation.tableInformation.maximum());
+            // We should always be able to allocate a JSWebAssemblyTable we've defined.
+            // If it's defined to be too large, we should have thrown a validation error.
+            ASSERT(!throwScope.exception());
+            ASSERT(table);
+            instance-&gt;m_table.set(vm, instance, table);
+        }
+    }
+    
+    if (!instance-&gt;memory()) {
+        // Make sure we have a dummy memory, so that wasm -&gt; wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers.
+        instance-&gt;m_memory.set(vm, instance, JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), adoptRef(*(new Wasm::Memory()))));
+    }
+    
+    // Globals
+    {
+        ASSERT(numImportGlobals == moduleInformation.firstInternalGlobal);
+        for (size_t globalIndex = numImportGlobals; globalIndex &lt; moduleInformation.globals.size(); ++globalIndex) {
+            const auto&amp; global = moduleInformation.globals[globalIndex];
+            ASSERT(global.initializationType != Wasm::Global::IsImport);
+            if (global.initializationType == Wasm::Global::FromGlobalImport) {
+                ASSERT(global.initialBitsOrImportNumber &lt; numImportGlobals);
+                instance-&gt;setGlobal(globalIndex, instance-&gt;loadI64Global(global.initialBitsOrImportNumber));
+            } else
+                instance-&gt;setGlobal(globalIndex, global.initialBitsOrImportNumber);
+        }
+    }
+
+    ASSERT(!instance-&gt;codeBlock());
+    instance-&gt;m_codeBlock.setMayBeNull(vm, instance, jsModule-&gt;codeBlock(instance-&gt;memoryMode()));
+
+    return instance;
+}
+
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(WEBASSEMBLY)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyInstanceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -39,51 +39,34 @@
</span><span class="cx"> class JSWebAssemblyModule;
</span><span class="cx"> class WebAssemblyToJSCallee;
</span><span class="cx"> 
</span><ins>+namespace Wasm {
+class Plan;
+}
+
+
</ins><span class="cx"> class JSWebAssemblyInstance : public JSDestructibleObject {
</span><span class="cx"> public:
</span><span class="cx">     typedef JSDestructibleObject Base;
</span><span class="cx"> 
</span><del>-
-    static JSWebAssemblyInstance* create(VM&amp;, Structure*, JSWebAssemblyModule*, JSModuleNamespaceObject*);
</del><ins>+    static JSWebAssemblyInstance* create(VM&amp;, ExecState*, JSWebAssemblyModule*, JSObject* importObject, Structure*);
</ins><span class="cx">     static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><del>-    JSWebAssemblyModule* module() const
-    {
-        ASSERT(m_codeBlock);
-        return m_codeBlock-&gt;module();
-    }
</del><ins>+    JSWebAssemblyCodeBlock* codeBlock() const { return m_codeBlock.get(); }
+    bool initialized() const { return codeBlock() &amp;&amp; codeBlock()-&gt;initialized(); }
+    void addUnitializedCodeBlock(VM&amp;, Ref&lt;Wasm::Plan&gt;);
+    void finalizeCreation(VM&amp;, ExecState*);
</ins><span class="cx"> 
</span><del>-    JSWebAssemblyCodeBlock* codeBlock() const
-    {
-        ASSERT(m_codeBlock);
-        return m_codeBlock.get();
-    }
</del><ins>+    JSWebAssemblyModule* module() const { return m_module.get(); }
</ins><span class="cx"> 
</span><del>-    WriteBarrier&lt;JSObject&gt;* importFunction(unsigned idx)
-    {
-        RELEASE_ASSERT(idx &lt; m_numImportFunctions);
-        return &amp;importFunctions()[idx];
-    }
</del><ins>+    JSObject* importFunction(unsigned idx) { RELEASE_ASSERT(idx &lt; m_numImportFunctions); return importFunctions()[idx].get(); }
</ins><span class="cx"> 
</span><del>-    WriteBarrier&lt;JSObject&gt;* importFunctions()
-    {
-        return bitwise_cast&lt;WriteBarrier&lt;JSObject&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + offsetOfImportFunctions());
-    }
-
-    void setImportFunction(VM&amp; vm, JSObject* value, unsigned idx)
-    {
-        importFunction(idx)-&gt;set(vm, this, value);
-    }
-
</del><span class="cx">     JSWebAssemblyMemory* memory() { return m_memory.get(); }
</span><del>-    // Calling this might trigger a recompile.
-    void setMemory(VM&amp;, ExecState*, JSWebAssemblyMemory*);
</del><ins>+    void setMemory(VM&amp; vm, JSWebAssemblyMemory* value) { ASSERT(!memory()); m_memory.set(vm, this, value); }
</ins><span class="cx">     Wasm::MemoryMode memoryMode() { return memory()-&gt;memory().mode(); }
</span><span class="cx"> 
</span><span class="cx">     JSWebAssemblyTable* table() { return m_table.get(); }
</span><del>-    void setTable(VM&amp; vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }
</del><span class="cx"> 
</span><span class="cx">     int32_t loadI32Global(unsigned i) const { return m_globals.get()[i]; }
</span><span class="cx">     int64_t loadI64Global(unsigned i) const { return m_globals.get()[i]; }
</span><span class="lines">@@ -91,11 +74,6 @@
</span><span class="cx">     double loadF64Global(unsigned i) const { return bitwise_cast&lt;double&gt;(loadI64Global(i)); }
</span><span class="cx">     void setGlobal(unsigned i, int64_t bits) { m_globals.get()[i] = bits; }
</span><span class="cx"> 
</span><del>-    static size_t offsetOfImportFunction(unsigned idx)
-    {
-        return offsetOfImportFunctions() + sizeof(WriteBarrier&lt;JSCell&gt;) * idx;
-    }
-
</del><span class="cx">     static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_memory); }
</span><span class="cx">     static ptrdiff_t offsetOfTable() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_table); }
</span><span class="cx">     static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_callee); }
</span><span class="lines">@@ -115,6 +93,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    WriteBarrier&lt;JSObject&gt;* importFunctions() { return bitwise_cast&lt;WriteBarrier&lt;JSObject&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + offsetOfImportFunctions()); }
+
+    WriteBarrier&lt;JSWebAssemblyModule&gt; m_module;
</ins><span class="cx">     WriteBarrier&lt;JSWebAssemblyCodeBlock&gt; m_codeBlock;
</span><span class="cx">     WriteBarrier&lt;JSModuleNamespaceObject&gt; m_moduleNamespaceObject;
</span><span class="cx">     WriteBarrier&lt;JSWebAssemblyMemory&gt; m_memory;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModulecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -43,98 +43,60 @@
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo JSWebAssemblyModule::s_info = { &quot;WebAssembly.Module&quot;, &amp;Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
</span><span class="cx"> 
</span><del>-JSWebAssemblyCodeBlock* JSWebAssemblyModule::buildCodeBlock(VM&amp; vm, ExecState* exec, Wasm::Plan&amp; plan, std::optional&lt;Wasm::MemoryMode&gt; mode)
</del><ins>+JSWebAssemblyModule* JSWebAssemblyModule::createStub(VM&amp; vm, ExecState* exec, Structure* structure, RefPtr&lt;ArrayBuffer&gt;&amp;&amp; source, RefPtr&lt;Wasm::Plan&gt;&amp;&amp; plan)
</ins><span class="cx"> {
</span><ins>+    ASSERT(!plan-&gt;hasWork());
</ins><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><del>-    // On failure, a new WebAssembly.CompileError is thrown.
-    plan.run(mode);
-    if (plan.failed()) {
-        throwException(exec, scope, createJSWebAssemblyCompileError(exec, vm, plan.errorMessage()));
</del><ins>+    if (plan-&gt;failed()) {
+        throwException(exec, scope, JSWebAssemblyCompileError::create(exec, vm, structure-&gt;globalObject()-&gt;WebAssemblyCompileErrorStructure(), plan-&gt;errorMessage()));
</ins><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><del>-    if (mode)
-        ASSERT(*mode == plan.mode());
</del><span class="cx"> 
</span><del>-    unsigned calleeCount = plan.internalFunctionCount();
-    auto* codeBlock = JSWebAssemblyCodeBlock::create(vm, this, plan.takeCallLinkInfos(), plan.takeWasmExitStubs(), plan.mode(), calleeCount);
-
-    plan.initializeCallees(exec-&gt;jsCallee()-&gt;globalObject(),
-        [&amp;] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) {
-            codeBlock-&gt;setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee);
-            codeBlock-&gt;setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee);
-        });
-    return codeBlock;
</del><ins>+    auto* module = new (NotNull, allocateCell&lt;JSWebAssemblyModule&gt;(vm.heap)) JSWebAssemblyModule(vm, structure, WTFMove(source));
+    module-&gt;finishCreation(vm, WTFMove(plan));
+    return module;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSWebAssemblyModule* JSWebAssemblyModule::create(VM&amp; vm, ExecState* exec, Structure* structure, uint8_t* source, size_t byteSize)
-{
-    auto* instance = new (NotNull, allocateCell&lt;JSWebAssemblyModule&gt;(vm.heap)) JSWebAssemblyModule(vm, structure);
-
-    instance-&gt;finishCreation(vm, exec, source, byteSize);
-    return instance;
-}
-
</del><span class="cx"> Structure* JSWebAssemblyModule::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span><span class="cx"> {
</span><span class="cx">     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSWebAssemblyModule::JSWebAssemblyModule(VM&amp; vm, Structure* structure)
</del><ins>+JSWebAssemblyModule::JSWebAssemblyModule(VM&amp; vm, Structure* structure, RefPtr&lt;ArrayBuffer&gt;&amp;&amp; source)
</ins><span class="cx">     : Base(vm, structure)
</span><ins>+    , m_sourceBuffer(source.releaseNonNull())
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSWebAssemblyCodeBlock* JSWebAssemblyModule::codeBlock(VM&amp; vm, ExecState* exec, JSWebAssemblyMemory* memory)
</del><ins>+void JSWebAssemblyModule::finishCreation(VM&amp; vm, RefPtr&lt;Wasm::Plan&gt;&amp;&amp; plan)
</ins><span class="cx"> {
</span><del>-    Wasm::MemoryMode mode = memory-&gt;memory().mode();
</del><ins>+    Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
</ins><span class="cx"> 
</span><del>-    for (unsigned i = 0; i &lt; Wasm::NumberOfMemoryModes; ++i) {
-        if (m_codeBlocks[i] &amp;&amp; m_codeBlocks[i]-&gt;isSafeToRun(memory))
-            return m_codeBlocks[i].get();
</del><ins>+    std::unique_ptr&lt;Wasm::ModuleInformation&gt; moduleInformation = plan-&gt;takeModuleInformation();
+    for (auto&amp; exp : moduleInformation-&gt;exports) {
+        ASSERT(exp.field.isSafeToSendToAnotherThread());
+        exp.field = AtomicString(exp.field);
</ins><span class="cx">     }
</span><del>-
-    ASSERT(!codeBlockFor(mode));
-    auto scope = DECLARE_THROW_SCOPE(vm);
-    // We don't have a code block for this mode, we need to recompile...
-    Wasm::Plan plan(&amp;vm, static_cast&lt;uint8_t*&gt;(m_sourceBuffer-&gt;data()), m_sourceBuffer-&gt;byteLength());
-
-    auto* codeBlock = buildCodeBlock(vm, exec, plan, mode);
-    RETURN_IF_EXCEPTION(scope, nullptr);
-
-    ASSERT(plan.exports().size() == m_exportSymbolTable-&gt;size());
-    if (!ASSERT_DISABLED) {
-        for (auto&amp; exp : plan.exports())
-            ASSERT_UNUSED(exp, m_exportSymbolTable-&gt;contains(exp.field.impl()));
</del><ins>+    for (auto&amp; imp : moduleInformation-&gt;imports) {
+        ASSERT(imp.field.isSafeToSendToAnotherThread());
+        imp.field = AtomicString(imp.field);
+        ASSERT(imp.module.isSafeToSendToAnotherThread());
+        imp.module = AtomicString(imp.module);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ASSERT(mode == codeBlock-&gt;mode());
-    codeBlockFor(mode).set(vm, this, codeBlock);
-    return codeBlock;
-}
</del><ins>+    m_moduleInformation = WTFMove(moduleInformation);
</ins><span class="cx"> 
</span><del>-void JSWebAssemblyModule::finishCreation(VM&amp; vm, ExecState* exec, uint8_t* source, size_t byteSize)
-{
-    Base::finishCreation(vm);
-    ASSERT(inherits(vm, info()));
-
-    auto scope = DECLARE_THROW_SCOPE(vm);
-    Wasm::Plan plan(&amp;vm, source, byteSize);
-
-    auto* codeBlock = buildCodeBlock(vm, exec, plan);
-    RETURN_IF_EXCEPTION(scope,);
-
</del><span class="cx">     // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module.
</span><span class="cx">     SymbolTable* exportSymbolTable = SymbolTable::create(vm);
</span><del>-    for (auto&amp; exp : plan.exports()) {
</del><ins>+    for (auto&amp; exp : m_moduleInformation-&gt;exports) {
</ins><span class="cx">         auto offset = exportSymbolTable-&gt;takeNextScopeOffset(NoLockingNecessary);
</span><del>-        exportSymbolTable-&gt;set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset)));
</del><ins>+        ASSERT(exp.field.impl()-&gt;isAtomic());
+        exportSymbolTable-&gt;set(NoLockingNecessary, static_cast&lt;AtomicStringImpl*&gt;(exp.field.impl()), SymbolTableEntry(VarOffset(offset)));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_sourceBuffer = ArrayBuffer::create(source, byteSize);
-    m_moduleInformation = plan.takeModuleInformation();
</del><span class="cx">     m_exportSymbolTable.set(vm, this, exportSymbolTable);
</span><span class="cx">     m_callee.set(vm, this, WebAssemblyToJSCallee::create(vm, vm.webAssemblyToJSCalleeStructure.get(), this));
</span><del>-    codeBlockFor(codeBlock-&gt;mode()).set(vm, this, codeBlock);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSWebAssemblyModule::destroy(JSCell* cell)
</span><span class="lines">@@ -142,6 +104,11 @@
</span><span class="cx">     static_cast&lt;JSWebAssemblyModule*&gt;(cell)-&gt;JSWebAssemblyModule::~JSWebAssemblyModule();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JSWebAssemblyModule::setCodeBlock(VM&amp; vm, Wasm::MemoryMode mode, JSWebAssemblyCodeBlock* codeBlock)
+{
+    m_codeBlocks[static_cast&lt;size_t&gt;(mode)].set(vm, this, codeBlock);
+}
+
</ins><span class="cx"> void JSWebAssemblyModule::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><span class="cx">     JSWebAssemblyModule* thisObject = jsCast&lt;JSWebAssemblyModule*&gt;(cell);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSWebAssemblyModuleh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -49,13 +49,12 @@
</span><span class="cx"> public:
</span><span class="cx">     typedef JSDestructibleObject Base;
</span><span class="cx"> 
</span><del>-    static JSWebAssemblyModule* create(VM&amp;, ExecState*, Structure*, uint8_t* source, size_t byteSize);
</del><ins>+    static JSWebAssemblyModule* createStub(VM&amp;, ExecState*, Structure*, RefPtr&lt;ArrayBuffer&gt;&amp;&amp; source, RefPtr&lt;Wasm::Plan&gt;&amp;&amp;);
</ins><span class="cx">     static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue);
</span><span class="cx"> 
</span><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><span class="cx">     const Wasm::ModuleInformation&amp; moduleInformation() const { return *m_moduleInformation.get(); }
</span><del>-    RefPtr&lt;Wasm::Memory&gt; takeReservedMemory() { return m_moduleInformation-&gt;memory.takeReservedMemory(); }
</del><span class="cx">     SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); }
</span><span class="cx">     Wasm::SignatureIndex signatureIndexFromFunctionIndexSpace(unsigned functionIndexSpace) const
</span><span class="cx">     {
</span><span class="lines">@@ -63,22 +62,22 @@
</span><span class="cx">     }
</span><span class="cx">     WebAssemblyToJSCallee* callee() const { return m_callee.get(); }
</span><span class="cx"> 
</span><del>-    // Returns the code block that this module was originally compiled expecting to use. This won't need to recompile.
-    JSWebAssemblyCodeBlock* codeBlock() { return codeBlockFor(m_moduleInformation-&gt;memory.mode()).get(); }
-    // Returns the appropriate code block for the given memory, possibly triggering a recompile.
-    JSWebAssemblyCodeBlock* codeBlock(VM&amp;, ExecState*, JSWebAssemblyMemory*);
</del><ins>+    JSWebAssemblyCodeBlock* codeBlock(Wasm::MemoryMode mode) { return m_codeBlocks[static_cast&lt;size_t&gt;(mode)].get(); }
</ins><span class="cx"> 
</span><ins>+    ArrayBuffer&amp; source() const { return m_sourceBuffer.get(); }
+
</ins><span class="cx"> private:
</span><del>-    WriteBarrier&lt;JSWebAssemblyCodeBlock&gt;&amp; codeBlockFor(Wasm::MemoryMode mode) { return m_codeBlocks[static_cast&lt;size_t&gt;(mode)]; }
-    JSWebAssemblyCodeBlock* buildCodeBlock(VM&amp;, ExecState*, Wasm::Plan&amp;, std::optional&lt;Wasm::MemoryMode&gt; mode = std::nullopt);
</del><ins>+    friend class JSWebAssemblyCodeBlock;
</ins><span class="cx"> 
</span><del>-    JSWebAssemblyModule(VM&amp;, Structure*);
-    void finishCreation(VM&amp;, ExecState*, uint8_t* source, size_t byteSize);
</del><ins>+    void setCodeBlock(VM&amp;, Wasm::MemoryMode, JSWebAssemblyCodeBlock*);
+
+    JSWebAssemblyModule(VM&amp;, Structure*, RefPtr&lt;ArrayBuffer&gt;&amp;&amp;);
+    void finishCreation(VM&amp;, RefPtr&lt;Wasm::Plan&gt;&amp;&amp;);
</ins><span class="cx">     static void destroy(JSCell*);
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><del>-    RefPtr&lt;ArrayBuffer&gt; m_sourceBuffer;
-    std::unique_ptr&lt;Wasm::ModuleInformation&gt; m_moduleInformation;
</del><ins>+    Ref&lt;ArrayBuffer&gt; m_sourceBuffer;
+    std::unique_ptr&lt;const Wasm::ModuleInformation&gt; m_moduleInformation;
</ins><span class="cx">     WriteBarrier&lt;SymbolTable&gt; m_exportSymbolTable;
</span><span class="cx">     WriteBarrier&lt;JSWebAssemblyCodeBlock&gt; m_codeBlocks[Wasm::NumberOfMemoryModes];
</span><span class="cx">     WriteBarrier&lt;WebAssemblyToJSCallee&gt; m_callee;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyInstanceConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -37,6 +37,8 @@
</span><span class="cx"> #include &quot;JSWebAssemblyLinkError.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyMemory.h&quot;
</span><span class="cx"> #include &quot;JSWebAssemblyModule.h&quot;
</span><ins>+#include &quot;WasmPlan.h&quot;
+#include &quot;WasmWorklist.h&quot;
</ins><span class="cx"> #include &quot;WebAssemblyFunction.h&quot;
</span><span class="cx"> #include &quot;WebAssemblyInstancePrototype.h&quot;
</span><span class="cx"> #include &quot;WebAssemblyModuleRecord.h&quot;
</span><span class="lines">@@ -45,8 +47,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-static const bool verbose = false;
-
</del><span class="cx"> const ClassInfo WebAssemblyInstanceConstructor::s_info = { &quot;Function&quot;, &amp;Base::s_info, &amp;constructorTableWebAssemblyInstance, CREATE_METHOD_TABLE(WebAssemblyInstanceConstructor) };
</span><span class="cx"> 
</span><span class="cx"> /* Source for WebAssemblyInstanceConstructor.lut.h
</span><span class="lines">@@ -54,269 +54,52 @@
</span><span class="cx">  @end
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+using Wasm::Plan;
+
</ins><span class="cx"> static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     auto&amp; vm = exec-&gt;vm();
</span><del>-    auto throwScope = DECLARE_THROW_SCOPE(vm);
</del><ins>+    auto scope = DECLARE_THROW_SCOPE(vm);
</ins><span class="cx"> 
</span><span class="cx">     // If moduleObject is not a WebAssembly.Module instance, a TypeError is thrown.
</span><del>-    JSWebAssemblyModule* jsModule = jsDynamicCast&lt;JSWebAssemblyModule*&gt;(vm, exec-&gt;argument(0));
-    if (!jsModule)
-        return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, ASCIILiteral(&quot;first argument to WebAssembly.Instance must be a WebAssembly.Module&quot;), defaultSourceAppender, runtimeTypeForValue(exec-&gt;argument(0)))));
</del><ins>+    JSWebAssemblyModule* module = jsDynamicCast&lt;JSWebAssemblyModule*&gt;(vm, exec-&gt;argument(0));
+    if (!module)
+        return JSValue::encode(throwException(exec, scope, createTypeError(exec, ASCIILiteral(&quot;first argument to WebAssembly.Instance must be a WebAssembly.Module&quot;), defaultSourceAppender, runtimeTypeForValue(exec-&gt;argument(0)))));
</ins><span class="cx"> 
</span><span class="cx">     // If the importObject parameter is not undefined and Type(importObject) is not Object, a TypeError is thrown.
</span><span class="cx">     JSValue importArgument = exec-&gt;argument(1);
</span><span class="cx">     JSObject* importObject = importArgument.getObject();
</span><span class="cx">     if (!importArgument.isUndefined() &amp;&amp; !importObject)
</span><del>-        return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, ASCIILiteral(&quot;second argument to WebAssembly.Instance must be undefined or an Object&quot;), defaultSourceAppender, runtimeTypeForValue(importArgument))));
</del><ins>+        return JSValue::encode(throwException(exec, scope, createTypeError(exec, ASCIILiteral(&quot;second argument to WebAssembly.Instance must be undefined or an Object&quot;), defaultSourceAppender, runtimeTypeForValue(importArgument))));
</ins><span class="cx">     
</span><span class="cx">     Structure* instanceStructure = InternalFunction::createSubclassStructure(exec, exec-&gt;newTarget(), exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyInstanceStructure());
</span><del>-    RETURN_IF_EXCEPTION(throwScope, { });
</del><ins>+    RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx"> 
</span><del>-    throwScope.release();
-    return JSValue::encode(WebAssemblyInstanceConstructor::createInstance(exec, jsModule, importObject, instanceStructure));
-}
</del><ins>+    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, instanceStructure);
+    RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx"> 
</span><del>-JSWebAssemblyInstance* WebAssemblyInstanceConstructor::createInstance(ExecState* exec, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure)
-{
-    auto&amp; vm = exec-&gt;vm();
-    auto throwScope = DECLARE_THROW_SCOPE(vm);
-    auto* globalObject = exec-&gt;lexicalGlobalObject();
</del><ins>+    // There are three possible cases:
+    // 1) The instance already has an initialized CodeBlock (runnable), so we just need to finalizeCreation.
+    // 2) The instance has no CodeBlock, so we need to make one and compile the code for it.
+    // 3) The instance already has an uninitialized CodeBlock, so we need to wait for the compilation to finish.
</ins><span class="cx"> 
</span><del>-    const Wasm::ModuleInformation&amp; moduleInformation = jsModule-&gt;moduleInformation();
</del><ins>+    if (!instance-&gt;initialized()) {
+        if (instance-&gt;codeBlock())
+            Wasm::ensureWorklist().completePlanSynchronously(instance-&gt;codeBlock()-&gt;plan());
+        else {
+            Ref&lt;Wasm::Plan&gt; plan = adoptRef(*new Plan(vm, module-&gt;source(), Plan::FullCompile, Plan::dontFinalize));
+            plan-&gt;setModeAndPromise(instance-&gt;memoryMode(), nullptr);
+            instance-&gt;addUnitializedCodeBlock(vm, plan.copyRef());
</ins><span class="cx"> 
</span><del>-    auto exception = [&amp;] (JSObject* error) {
-        throwException(exec, throwScope, error);
-        return nullptr;
-    };
-
-    // If the list of module.imports is not empty and Type(importObject) is not Object, a TypeError is thrown.
-    if (moduleInformation.imports.size() &amp;&amp; !importObject)
-        return exception(createTypeError(exec, ASCIILiteral(&quot;can't make WebAssembly.Instance because there is no imports Object and the WebAssembly.Module requires imports&quot;)));
-
-    Identifier moduleKey = Identifier::fromUid(PrivateName(PrivateName::Description, &quot;WebAssemblyInstance&quot;));
-    WebAssemblyModuleRecord* moduleRecord = WebAssemblyModuleRecord::create(exec, vm, globalObject-&gt;webAssemblyModuleRecordStructure(), moduleKey, moduleInformation);
-    RETURN_IF_EXCEPTION(throwScope, nullptr);
-
-
-    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord-&gt;getModuleNamespace(exec));
-    RETURN_IF_EXCEPTION(throwScope, nullptr);
-
-    // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
-    // Let imports be an initially-empty list of external values.
-    unsigned numImportFunctions = 0;
-    unsigned numImportGlobals = 0;
-
-    bool hasMemoryImport = false;
-    bool hasTableImport = false;
-    // For each import i in module.imports:
-    for (auto&amp; import : moduleInformation.imports) {
-        // 1. Let o be the resultant value of performing Get(importObject, i.module_name).
-        JSValue importModuleValue = importObject-&gt;get(exec, import.module);
-        RETURN_IF_EXCEPTION(throwScope, nullptr);
-        // 2. If Type(o) is not Object, throw a TypeError.
-        if (!importModuleValue.isObject())
-            return exception(createTypeError(exec, ASCIILiteral(&quot;import must be an object&quot;), defaultSourceAppender, runtimeTypeForValue(importModuleValue)));
-
-        // 3. Let v be the value of performing Get(o, i.item_name)
-        JSObject* object = jsCast&lt;JSObject*&gt;(importModuleValue);
-        JSValue value = object-&gt;get(exec, import.field);
-        RETURN_IF_EXCEPTION(throwScope, nullptr);
-
-        switch (import.kind) {
-        case Wasm::ExternalKind::Function: {
-            // 4. If i is a function import:
-            // i. If IsCallable(v) is false, throw a WebAssembly.LinkError.
-            if (!value.isFunction())
-                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;import function must be callable&quot;)));
-
-            JSObject* function = jsCast&lt;JSObject*&gt;(value);
-            // ii. If v is an Exported Function Exotic Object:
-            WebAssemblyFunction* wasmFunction;
-            WebAssemblyWrapperFunction* wasmWrapperFunction;
-            if (isWebAssemblyHostFunction(vm, function, wasmFunction, wasmWrapperFunction)) {
-                // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError.
-                Wasm::SignatureIndex importedSignatureIndex;
-                if (wasmFunction)
-                    importedSignatureIndex = wasmFunction-&gt;signatureIndex();
-                else {
-                    importedSignatureIndex = wasmWrapperFunction-&gt;signatureIndex();
-                    // b. Let closure be v.[[Closure]].
-                    function = wasmWrapperFunction-&gt;function();
-                }
-                Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
-                if (importedSignatureIndex != expectedSignatureIndex)
-                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;imported function's signature doesn't match the provided WebAssembly function's signature&quot;)));
-            }
-            // iii. Otherwise:
-            // a. Let closure be a new host function of the given signature which calls v by coercing WebAssembly arguments to JavaScript arguments via ToJSValue and returns the result, if any, by coercing via ToWebAssemblyValue.
-            // Note: done as part of Plan compilation.
-            // iv. Append v to funcs.
-            // Note: adding the JSCell to the instance list fulfills closure requirements b. above (the WebAssembly.Instance wil be kept alive) and v. below (the JSFunction).
-
-            ASSERT(numImportFunctions == import.kindIndex);
-            instance-&gt;setImportFunction(vm, function, numImportFunctions++);
-            // v. Append closure to imports.
-            break;
</del><ins>+            auto&amp; worklist = Wasm::ensureWorklist();
+            worklist.enqueue(plan.copyRef());
+            worklist.completePlanSynchronously(plan.get());
</ins><span class="cx">         }
</span><del>-        case Wasm::ExternalKind::Table: {
-            RELEASE_ASSERT(!hasTableImport); // This should be guaranteed by a validation failure.
-            // 7. Otherwise (i is a table import):
-            hasTableImport = true;
-            JSWebAssemblyTable* table = jsDynamicCast&lt;JSWebAssemblyTable*&gt;(vm, value);
-            // i. If v is not a WebAssembly.Table object, throw a WebAssembly.LinkError.
-            if (!table)
-                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Table import is not an instance of WebAssembly.Table&quot;)));
-
-            uint32_t declaredInitial = moduleInformation.tableInformation.initial();
-            uint32_t importedInitial = table-&gt;size();
-            if (importedInitial &lt; declaredInitial)
-                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Table import provided an 'initial' that is too small&quot;)));
-
-            if (std::optional&lt;uint32_t&gt; declaredMaximum = moduleInformation.tableInformation.maximum()) {
-                std::optional&lt;uint32_t&gt; importedMaximum = table-&gt;maximum();
-                if (!importedMaximum)
-                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Table import does not have a 'maximum' but the module requires that it does&quot;)));
-                if (*importedMaximum &gt; *declaredMaximum)
-                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Imported Table's 'maximum' is larger than the module's expected 'maximum'&quot;)));
-            }
-
-            // ii. Append v to tables.
-            // iii. Append v.[[Table]] to imports.
-            instance-&gt;setTable(vm, table);
-            break;
-        }
-        case Wasm::ExternalKind::Memory: {
-            // 6. If i is a memory import:
-            RELEASE_ASSERT(!hasMemoryImport); // This should be guaranteed by a validation failure.
-            RELEASE_ASSERT(moduleInformation.memory);
-            hasMemoryImport = true;
-            JSWebAssemblyMemory* memory = jsDynamicCast&lt;JSWebAssemblyMemory*&gt;(vm, value);
-            // i. If v is not a WebAssembly.Memory object, throw a WebAssembly.LinkError.
-            if (!memory)
-                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import is not an instance of WebAssembly.Memory&quot;)));
-
-            Wasm::PageCount declaredInitial = moduleInformation.memory.initial();
-            Wasm::PageCount importedInitial = memory-&gt;memory().initial();
-            if (importedInitial &lt; declaredInitial)
-                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import provided an 'initial' that is smaller than the module's declared 'initial' import memory size&quot;)));
-
-            if (Wasm::PageCount declaredMaximum = moduleInformation.memory.maximum()) {
-                Wasm::PageCount importedMaximum = memory-&gt;memory().maximum();
-                if (!importedMaximum)
-                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import did not have a 'maximum' but the module requires that it does&quot;)));
-
-                if (importedMaximum &gt; declaredMaximum)
-                    return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;Memory import provided a 'maximum' that is larger than the module's declared 'maximum' import memory size&quot;)));
-            }
-
-            // ii. Append v to memories.
-            // iii. Append v.[[Memory]] to imports.
-            instance-&gt;setMemory(vm, exec, memory);
-            RETURN_IF_EXCEPTION(throwScope, nullptr);
-            break;
-        }
-        case Wasm::ExternalKind::Global: {
-            // 5. If i is a global import:
-            // i. If i is not an immutable global, throw a TypeError.
-            ASSERT(moduleInformation.globals[import.kindIndex].mutability == Wasm::Global::Immutable);
-            // ii. If the global_type of i is i64 or Type(v) is not Number, throw a WebAssembly.LinkError.
-            if (moduleInformation.globals[import.kindIndex].type == Wasm::I64)
-                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;imported global cannot be an i64&quot;)));
-            if (!value.isNumber())
-                return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral(&quot;imported global must be a number&quot;)));
-            // iii. Append ToWebAssemblyValue(v) to imports.
-            ASSERT(numImportGlobals == import.kindIndex);
-            switch (moduleInformation.globals[import.kindIndex].type) {
-            case Wasm::I32:
-                instance-&gt;setGlobal(numImportGlobals++, value.toInt32(exec));
-                break;
-            case Wasm::F32:
-                instance-&gt;setGlobal(numImportGlobals++, bitwise_cast&lt;uint32_t&gt;(value.toFloat(exec)));
-                break;
-            case Wasm::F64:
-                instance-&gt;setGlobal(numImportGlobals++, bitwise_cast&lt;uint64_t&gt;(value.asNumber()));
-                break;
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-            }
-            ASSERT(!throwScope.exception());
-            break;
-        }
-        }
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    {
-        if (!!moduleInformation.memory &amp;&amp; moduleInformation.memory.isImport()) {
-            // We should either have a Memory import or we should have thrown an exception.
-            RELEASE_ASSERT(hasMemoryImport);
-        }
-
-        if (moduleInformation.memory &amp;&amp; !hasMemoryImport) {
-            RELEASE_ASSERT(!moduleInformation.memory.isImport());
-            // We create a memory when it's a memory definition.
-            RefPtr&lt;Wasm::Memory&gt; memory;
-            if (moduleInformation.memory.hasReservedMemory())
-                memory = jsModule-&gt;takeReservedMemory();
-            else {
-                memory = Wasm::Memory::create(vm, moduleInformation.memory.initial(), moduleInformation.memory.maximum());
-                if (!memory)
-                    return exception(createOutOfMemoryError(exec));
-            }
-            instance-&gt;setMemory(vm, exec,
-                JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), memory.releaseNonNull()));
-            RETURN_IF_EXCEPTION(throwScope, nullptr);
-        }
-    }
-
-    {
-        if (!!moduleInformation.tableInformation &amp;&amp; moduleInformation.tableInformation.isImport()) {
-            // We should either have a Table import or we should have thrown an exception.
-            RELEASE_ASSERT(hasTableImport);
-        }
-
-        if (!!moduleInformation.tableInformation &amp;&amp; !hasTableImport) {
-            RELEASE_ASSERT(!moduleInformation.tableInformation.isImport());
-            // We create a Table when it's a Table definition.
-            JSWebAssemblyTable* table = JSWebAssemblyTable::create(exec, vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyTableStructure(),
-                moduleInformation.tableInformation.initial(), moduleInformation.tableInformation.maximum());
-            // We should always be able to allocate a JSWebAssemblyTable we've defined.
-            // If it's defined to be too large, we should have thrown a validation error.
-            ASSERT(!throwScope.exception());
-            ASSERT(table); 
-            instance-&gt;setTable(vm, table);
-        }
-    }
-
-    if (!instance-&gt;memory()) {
-        // Make sure we have a dummy memory, so that wasm -&gt; wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers.
-        instance-&gt;setMemory(vm, exec, JSWebAssemblyMemory::create(vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyMemoryStructure(), adoptRef(*(new Wasm::Memory()))));
-    }
-
-    // Globals
-    {
-        ASSERT(numImportGlobals == moduleInformation.firstInternalGlobal);
-        for (size_t globalIndex = numImportGlobals; globalIndex &lt; moduleInformation.globals.size(); ++globalIndex) {
-            const auto&amp; global = moduleInformation.globals[globalIndex];
-            ASSERT(global.initializationType != Wasm::Global::IsImport);
-            if (global.initializationType == Wasm::Global::FromGlobalImport) {
-                ASSERT(global.initialBitsOrImportNumber &lt; numImportGlobals);
-                instance-&gt;setGlobal(globalIndex, instance-&gt;loadI64Global(global.initialBitsOrImportNumber));
-            } else
-                instance-&gt;setGlobal(globalIndex, global.initialBitsOrImportNumber);
-        }
-    }
-
-    moduleRecord-&gt;link(exec, instance);
-    RETURN_IF_EXCEPTION(throwScope, nullptr);
-
-    if (verbose)
-        moduleRecord-&gt;dump();
-    JSValue startResult = moduleRecord-&gt;evaluate(exec);
-    UNUSED_PARAM(startResult);
-    RETURN_IF_EXCEPTION(throwScope, nullptr);
-
-    return instance;
</del><ins>+    instance-&gt;finalizeCreation(vm, exec);
+    RETURN_IF_EXCEPTION(scope, { });
+    return JSValue::encode(instance);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyInstance(ExecState* exec)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -75,13 +75,13 @@
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><del>-    size_t byteOffset;
-    size_t byteSize;
-    uint8_t* base = getWasmBufferFromValue(exec, buffer, byteOffset, byteSize);
</del><ins>+    RefPtr&lt;ArrayBuffer&gt; source = createSourceBufferFromValue(vm, exec, buffer);
</ins><span class="cx">     RETURN_IF_EXCEPTION(scope, { });
</span><span class="cx"> 
</span><del>-    scope.release();
-    return JSWebAssemblyModule::create(vm, exec, structure, base + byteOffset, byteSize);
</del><ins>+    RefPtr&lt;Wasm::Plan&gt; plan = adoptRef(new Wasm::Plan(vm, *source, Wasm::Plan::Validation, Wasm::Plan::dontFinalize));
+    if (!plan-&gt;parseAndValidateModule())
+        return throwException(exec, scope, JSWebAssemblyCompileError::create(exec, vm, exec-&gt;lexicalGlobalObject()-&gt;WebAssemblyCompileErrorStructure(), plan-&gt;errorMessage()));
+    return JSWebAssemblyModule::createStub(vm, exec, structure, WTFMove(source), WTFMove(plan));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebAssemblyModuleConstructor* WebAssemblyModuleConstructor::create(VM&amp; vm, Structure* structure, WebAssemblyModulePrototype* thisPrototype)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModulePrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModulePrototype.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModulePrototype.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModulePrototype.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -110,8 +110,8 @@
</span><span class="cx">         for (const Wasm::Import&amp; imp : imports) {
</span><span class="cx">             JSObject* obj = constructEmptyObject(exec);
</span><span class="cx">             RETURN_IF_EXCEPTION(throwScope, { });
</span><del>-            obj-&gt;putDirect(vm, module, jsString(exec, imp.module.string()));
-            obj-&gt;putDirect(vm, name, jsString(exec, imp.field.string()));
</del><ins>+            obj-&gt;putDirect(vm, module, jsString(exec, imp.module));
+            obj-&gt;putDirect(vm, name, jsString(exec, imp.field));
</ins><span class="cx">             obj-&gt;putDirect(vm, kind, jsString(exec, String(makeString(imp.kind))));
</span><span class="cx">             result-&gt;push(exec, obj);
</span><span class="cx">             RETURN_IF_EXCEPTION(throwScope, { });
</span><span class="lines">@@ -141,7 +141,7 @@
</span><span class="cx">         for (const Wasm::Export&amp; exp : exports) {
</span><span class="cx">             JSObject* obj = constructEmptyObject(exec);
</span><span class="cx">             RETURN_IF_EXCEPTION(throwScope, { });
</span><del>-            obj-&gt;putDirect(vm, name, jsString(exec, exp.field.string()));
</del><ins>+            obj-&gt;putDirect(vm, name, jsString(exec, exp.field));
</ins><span class="cx">             obj-&gt;putDirect(vm, kind, jsString(exec, String(makeString(exp.kind))));
</span><span class="cx">             result-&gt;push(exec, obj);
</span><span class="cx">             RETURN_IF_EXCEPTION(throwScope, { });
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -73,8 +73,10 @@
</span><span class="cx"> {
</span><span class="cx">     Base::finishCreation(exec, vm);
</span><span class="cx">     ASSERT(inherits(vm, info()));
</span><del>-    for (const auto&amp; exp : moduleInformation.exports)
-        addExportEntry(ExportEntry::createLocal(exp.field, exp.field));
</del><ins>+    for (const auto&amp; exp : moduleInformation.exports) {
+        Identifier field = Identifier::fromString(&amp;vm, exp.field);
+        addExportEntry(ExportEntry::createLocal(field, field));
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebAssemblyModuleRecord::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="lines">@@ -85,7 +87,7 @@
</span><span class="cx">     visitor.append(thisObject-&gt;m_startFunction);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyInstance* instance)
</del><ins>+void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module, JSWebAssemblyInstance* instance)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -92,7 +94,6 @@
</span><span class="cx">     UNUSED_PARAM(scope);
</span><span class="cx">     auto* globalObject = exec-&gt;lexicalGlobalObject();
</span><span class="cx"> 
</span><del>-    JSWebAssemblyModule* module = instance-&gt;module();
</del><span class="cx">     JSWebAssemblyCodeBlock* codeBlock = instance-&gt;codeBlock();
</span><span class="cx">     const Wasm::ModuleInformation&amp; moduleInformation = module-&gt;moduleInformation();
</span><span class="cx"> 
</span><span class="lines">@@ -112,7 +113,7 @@
</span><span class="cx">             //   ii. (Note: At most one wrapper is created for any closure, so func is unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.)
</span><span class="cx">             if (exp.kindIndex &lt; functionImportCount) {
</span><span class="cx">                 unsigned functionIndex = exp.kindIndex;
</span><del>-                JSObject* functionImport = instance-&gt;importFunction(functionIndex)-&gt;get();
</del><ins>+                JSObject* functionImport = instance-&gt;importFunction(functionIndex);
</ins><span class="cx">                 if (isWebAssemblyHostFunction(vm, functionImport))
</span><span class="cx">                     exportedValue = functionImport;
</span><span class="cx">                 else {
</span><span class="lines">@@ -128,7 +129,7 @@
</span><span class="cx">                 JSWebAssemblyCallee* wasmEntrypointCallee = codeBlock-&gt;wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
</span><span class="cx">                 Wasm::SignatureIndex signatureIndex = module-&gt;signatureIndexFromFunctionIndexSpace(exp.kindIndex);
</span><span class="cx">                 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&amp;vm, signatureIndex);
</span><del>-                WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature-&gt;argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
</del><ins>+                WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature-&gt;argumentCount(), exp.field, instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
</ins><span class="cx">                 exportedValue = function;
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="lines">@@ -179,7 +180,7 @@
</span><span class="cx">         bool shouldThrowReadOnlyError = false;
</span><span class="cx">         bool ignoreReadOnlyErrors = true;
</span><span class="cx">         bool putResult = false;
</span><del>-        symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, exp.field, exportedValue, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
</del><ins>+        symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, Identifier::fromString(&amp;vm, exp.field), exportedValue, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
</ins><span class="cx">         RELEASE_ASSERT(putResult);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -192,7 +193,7 @@
</span><span class="cx">         ASSERT(!signature-&gt;argumentCount());
</span><span class="cx">         ASSERT(signature-&gt;returnType() == Wasm::Void);
</span><span class="cx">         if (startFunctionIndexSpace &lt; codeBlock-&gt;functionImportCount()) {
</span><del>-            JSObject* startFunction = instance-&gt;importFunction(startFunctionIndexSpace)-&gt;get();
</del><ins>+            JSObject* startFunction = instance-&gt;importFunction(startFunctionIndexSpace);
</ins><span class="cx">             m_startFunction.set(vm, this, startFunction);
</span><span class="cx">         } else {
</span><span class="cx">             JSWebAssemblyCallee* jsEntrypointCallee = codeBlock-&gt;jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
</span><span class="lines">@@ -251,7 +252,7 @@
</span><span class="cx">                 uint32_t functionIndex = element.functionIndices[i];
</span><span class="cx">                 Wasm::SignatureIndex signatureIndex = module-&gt;signatureIndexFromFunctionIndexSpace(functionIndex);
</span><span class="cx">                 if (functionIndex &lt; codeBlock-&gt;functionImportCount()) {
</span><del>-                    JSObject* functionImport = jsCast&lt;JSObject*&gt;(m_instance-&gt;importFunction(functionIndex)-&gt;get());
</del><ins>+                    JSObject* functionImport = jsCast&lt;JSObject*&gt;(m_instance-&gt;importFunction(functionIndex));
</ins><span class="cx">                     if (isWebAssemblyHostFunction(vm, functionImport)) {
</span><span class="cx">                         WebAssemblyFunction* wasmFunction = jsDynamicCast&lt;WebAssemblyFunction*&gt;(vm, functionImport);
</span><span class="cx">                         // If we ever import a WebAssemblyWrapperFunction, we set the import as the unwrapped value.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyModuleRecordh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h (214503 => 214504)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h        2017-03-28 23:11:35 UTC (rev 214503)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h        2017-03-28 23:12:11 UTC (rev 214504)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class JSWebAssemblyInstance;
</span><ins>+class JSWebAssemblyModule;
</ins><span class="cx"> class WebAssemblyFunction;
</span><span class="cx"> 
</span><span class="cx"> // Based on the WebAssembly.Instance specification
</span><span class="lines">@@ -47,7 +48,7 @@
</span><span class="cx">     static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue);
</span><span class="cx">     static WebAssemblyModuleRecord* create(ExecState*, VM&amp;, Structure*, const Identifier&amp;, const Wasm::ModuleInformation&amp;);
</span><span class="cx"> 
</span><del>-    void link(ExecState*, JSWebAssemblyInstance*);
</del><ins>+    void link(ExecState*, JSWebAssemblyModule*, JSWebAssemblyInstance*);
</ins><span class="cx">     JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);
</span><span class="cx"> 
</span><span class="cx"> private:
</span></span></pre>
</div>
</div>

</body>
</html>