Changeset 214504 in webkit
- Timestamp:
- Mar 28, 2017 4:12:11 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 45 edited
- 2 copied
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r214484 r214504 1 2017-03-28 Keith Miller <keith_miller@apple.com> 2 3 WebAssembly: Make WebAssembly.instantiate/compile truly asynchronous 4 https://bugs.webkit.org/show_bug.cgi?id=169187 5 6 Reviewed by Saam Barati. 7 8 * wasm/assert.js: 9 * wasm/js-api/Module-compile.js: 10 (async.testPromiseAPI): 11 * wasm/js-api/web-assembly-compile-parallel.js: Added. 12 (async.throwExn): 13 (async.test): 14 * wasm/js-api/web-assembly-instantiate-parallel.js: Added. 15 (async.test): 16 * wasm/js-api/web-assembly-instantiate.js: 17 (assert.eq.async.test): 18 (assert.eq): 19 (assert.asyncTest.async.test): 20 (assert.asyncTest): 21 (assert.truthy.async.test): Deleted. 22 (assert.truthy): Deleted. 23 1 24 2017-03-28 JF Bastien <jfbastien@apple.com> 2 25 -
trunk/JSTests/wasm/assert.js
r214438 r214504 145 145 _instanceof as instanceof, 146 146 }; 147 148 const asyncTestImpl = (promise, thenFunc, catchFunc) => { 149 asyncTestStart(1); 150 promise.then(thenFunc).catch(catchFunc); 151 }; 152 153 const printExn = (e) => { 154 print("Failed: ", e); 155 print(e.stack); 156 }; 157 158 export const asyncTest = (promise) => asyncTestImpl(promise, asyncTestPassed, printExn); 159 export const asyncTestEq = (promise, expected) => { 160 const thenCheck = (value) => { 161 if (value === expected) 162 return asyncTestPassed(); 163 print("Failed: got ", value, " but expected ", expected); 164 165 } 166 asyncTestImpl(promise, thenCheck, printExn); 167 }; -
trunk/JSTests/wasm/js-api/Module-compile.js
r211410 r214504 2 2 import Builder from '../Builder.js'; 3 3 4 let done = false;5 4 async function testPromiseAPI() { 6 5 { … … 15 14 .End(); 16 15 17 let threw = false;18 16 try { 19 17 await WebAssembly.compile(builder.WebAssembly().get()); 20 18 } catch(e) { 21 threw = true;22 19 assert.truthy(e instanceof WebAssembly.CompileError); 23 assert.truthy(e.message === "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())')");20 assert.truthy(e.message === "WebAssembly.Module doesn't parse at byte 34 / 43: Memory section cannot exist if an Import has a memory"); 24 21 } 25 assert.truthy(threw);26 22 } 27 23 28 24 { 29 let threw = false;30 25 try { 31 26 await WebAssembly.compile(); 32 27 } catch(e) { 33 threw = true;34 28 assert.truthy(e instanceof TypeError); 35 29 assert.eq(e.message, "first argument must be an ArrayBufferView or an ArrayBuffer (evaluating 'WebAssembly.compile()')"); 36 30 } 37 assert.truthy(threw);38 31 } 39 32 40 33 { 41 let threw = false;42 34 try { 43 35 await WebAssembly.compile(20); 44 36 } catch(e) { 45 threw = true;46 37 assert.truthy(e instanceof TypeError); 47 38 assert.eq(e.message, "first argument must be an ArrayBufferView or an ArrayBuffer (evaluating 'WebAssembly.compile(20)')"); 48 39 } 49 assert.truthy(threw);50 40 } 51 41 … … 62 52 assert.truthy(module instanceof WebAssembly.Module); 63 53 } 64 65 done = true;66 54 } 67 55 68 testPromiseAPI(); 69 drainMicrotasks(); 70 assert.truthy(done); 56 assert.asyncTest(testPromiseAPI()); -
trunk/JSTests/wasm/js-api/web-assembly-instantiate.js
r213506 r214504 20 20 const bin = builder.WebAssembly().get(); 21 21 22 let done = false;23 22 async function test() { 24 23 let {module, instance} = await WebAssembly.instantiate(bin); … … 26 25 assert.truthy(instance instanceof WebAssembly.Instance); 27 26 assert.eq(instance.exports.foo(20), 1); 28 done = true;29 27 } 30 28 31 test(); 32 drainMicrotasks(); 33 assert.truthy(done); 29 assert.asyncTest(test()); 34 30 } 35 31 … … 49 45 const bin = builder.WebAssembly().get(); 50 46 51 let done = false;52 47 async function test() { 53 48 try { … … 56 51 assert.eq(e.message, "second argument to WebAssembly.instantiate must be undefined or an Object (evaluating 'WebAssembly.instantiate(bin, null)')"); 57 52 } 58 done = true;59 53 } 60 54 61 test(); 62 drainMicrotasks(); 63 assert.truthy(done); 55 assert.asyncTest(test()); 64 56 } 65 57 … … 79 71 const bin = builder.WebAssembly().get(); 80 72 81 let done = false;82 73 async function test() { 83 74 try { … … 85 76 } catch(e) { 86 77 assert.truthy(e instanceof WebAssembly.CompileError); 87 assert.eq(e.message, "WebAssembly.Module doesn't validate: control flow returns with unexpected type, in function at index 0 (evaluating 'WebAssembly.instantiate(bin)')");78 assert.eq(e.message, "WebAssembly.Module doesn't validate: control flow returns with unexpected type, in function at index 0"); 88 79 } 89 done = true;90 80 } 91 81 92 test(); 93 drainMicrotasks(); 94 assert.truthy(done); 82 assert.asyncTest(test()); 95 83 } 96 84 … … 111 99 const bin = builder.WebAssembly().get(); 112 100 113 let done = false;114 101 async function test() { 115 102 try { 116 103 let {module, instance} = await WebAssembly.instantiate(bin, {imp: {memory: 20}}); 117 104 } catch(e) { 118 assert.eq(e.message, "Memory import is not an instance of WebAssembly.Memory (evaluating 'WebAssembly.instantiate(bin, {imp: {memory: 20}})')");105 assert.eq(e.message, "Memory import is not an instance of WebAssembly.Memory"); 119 106 } 120 done = true;121 107 } 122 108 123 test(); 124 drainMicrotasks(); 125 assert.truthy(done); 109 assert.asyncTest(test()); 126 110 } 127 111 … … 142 126 const bin = builder.WebAssembly().get(); 143 127 144 let done = false;145 128 async function test() { 146 129 try { … … 148 131 let instance = await WebAssembly.instantiate(bin, {imp: {memory: 20}}); 149 132 } catch(e) { 150 assert.eq(e.message, "Memory import is not an instance of WebAssembly.Memory (evaluating 'WebAssembly.instantiate(bin, {imp: {memory: 20}})')");133 assert.eq(e.message, "Memory import is not an instance of WebAssembly.Memory"); 151 134 } 152 done = true;153 135 } 154 136 155 test(); 156 drainMicrotasks(); 157 assert.truthy(done); 137 assert.asyncTest(test()); 158 138 } 159 139 … … 173 153 const bin = builder.WebAssembly().get(); 174 154 175 let done = false;176 155 async function test() { 177 156 let module = new WebAssembly.Module(bin); … … 179 158 assert.truthy(instance instanceof WebAssembly.Instance); 180 159 assert.eq(instance.exports.foo(20), 1); 181 done = true;182 160 } 183 161 184 test(); 185 drainMicrotasks(); 186 assert.truthy(done); 162 assert.asyncTest(test()); 187 163 } 188 164 … … 203 179 const bin = builder.WebAssembly().get(); 204 180 205 let done = false;206 181 async function test() { 207 182 try { … … 211 186 assert.eq(e.message, "first argument must be an ArrayBufferView or an ArrayBuffer (evaluating 'WebAssembly.instantiate(25)')"); 212 187 } 213 done = true;214 188 } 215 189 216 test(); 217 drainMicrotasks(); 218 assert.truthy(done); 190 assert.asyncTest(test()); 219 191 } -
trunk/Source/JavaScriptCore/CMakeLists.txt
r214410 r214504 504 504 heap/HeapSnapshot.cpp 505 505 heap/HeapSnapshotBuilder.cpp 506 heap/HeapTimer.cpp507 506 heap/IncrementalSweeper.cpp 508 507 heap/JITStubRoutineSet.cpp … … 803 802 runtime/JSPropertyNameIterator.cpp 804 803 runtime/JSProxy.cpp 804 runtime/JSRunLoopTimer.cpp 805 805 runtime/JSScope.cpp 806 806 runtime/JSScriptFetcher.cpp … … 852 852 runtime/Options.cpp 853 853 runtime/ProgramExecutable.cpp 854 runtime/PromiseDeferredTimer.cpp 854 855 runtime/PropertyDescriptor.cpp 855 856 runtime/PropertySlot.cpp … … 945 946 wasm/WasmSignature.cpp 946 947 wasm/WasmValidate.cpp 948 wasm/WasmWorklist.cpp 947 949 948 950 wasm/js/JSWebAssemblyCallee.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r214498 r214504 1 2017-03-28 Keith Miller <keith_miller@apple.com> 2 3 WebAssembly: Make WebAssembly.instantiate/compile truly asynchronous 4 https://bugs.webkit.org/show_bug.cgi?id=169187 5 6 Reviewed by Saam Barati. 7 8 This patch allows WebAssembly compilations to happen asynchronously. 9 To do so, it refactors how much of the compilation happens and adds 10 new infrastructure for async promises. 11 12 First, there is a new class, PromiseDeferredTimer that lives on 13 the VM. PromiseDeferredTimer will manage the life-cycle of async 14 pending promises and any dependencies that promise 15 needs. PromiseDeferredTimer automagically releases the pending 16 promise and dependencies once the JSPromiseDeferred is resolved or 17 rejected. Additionally, PromiseDeferredTimer provides a mechanism 18 to poll the run-loop whenever the async task needs to synchronize 19 with the JS thread. Normally, that will be whenever the async task 20 finishes. In the case of Web Assembly we also use this feature for 21 the compile + instantiate case, where we might have more work 22 after the first async task completes (more on that later). 23 24 The next class is Wasm::Worklist, which is used to manage Wasm 25 compilation tasks. The worklist class works similarly to the 26 DFG/FTL Worklists. It has a pool of threads that it manages. One 27 interesting aspect of Wasm Worklist is that it can synchronously 28 compile a plan that is already potentially running 29 asynchronously. This can occur if a user calls 30 WebAssembly.instantiate() then new WebAssembly.instantiate() on 31 the same module. In that case the Wasm Worklist will bump the 32 priority of the running pending Plan and block the JS thread. 33 34 This patch also makes some of the Wasm Plan code cleaner. Since we 35 now defer all compilation to instantiation time, we no longer need 36 to guess at which memory we are going to get. Also, Wasm Plans now 37 track the work they have done with a state enum. 38 39 Finally, this patch makes renamed HeapTimer to JSRunLoopTimer. It 40 also adds changes test262AsyncTest to a more generic testing 41 infrastructure. Now, in addition to the old functionality, you can 42 call asyncTest() with the number of tests you expect. When the jsc 43 CLI exits, it will guarantee that asyncTestPassed() is called that 44 many times. 45 46 * CMakeLists.txt: 47 * JavaScriptCore.xcodeproj/project.pbxproj: 48 * heap/GCActivityCallback.h: 49 * heap/IncrementalSweeper.cpp: 50 (JSC::IncrementalSweeper::scheduleTimer): 51 (JSC::IncrementalSweeper::IncrementalSweeper): 52 * heap/IncrementalSweeper.h: 53 * heap/StopIfNecessaryTimer.cpp: 54 (JSC::StopIfNecessaryTimer::StopIfNecessaryTimer): 55 * heap/StopIfNecessaryTimer.h: 56 * heap/StrongInlines.h: 57 * jsc.cpp: 58 (GlobalObject::finishCreation): 59 (printInternal): 60 (functionAsyncTestStart): 61 (functionAsyncTestPassed): 62 (functionTestWasmModuleFunctions): 63 (CommandLine::parseArguments): 64 (runJSC): 65 * runtime/JSPromiseDeferred.cpp: 66 (JSC::JSPromiseDeferred::resolve): 67 (JSC::JSPromiseDeferred::reject): 68 * runtime/JSPromiseDeferred.h: 69 (JSC::JSPromiseDeferred::promiseAsyncPending): 70 * runtime/JSRunLoopTimer.cpp: Renamed from Source/JavaScriptCore/heap/HeapTimer.cpp. 71 (JSC::JSRunLoopTimer::JSRunLoopTimer): 72 (JSC::JSRunLoopTimer::setRunLoop): 73 (JSC::JSRunLoopTimer::~JSRunLoopTimer): 74 (JSC::JSRunLoopTimer::timerDidFire): 75 (JSC::JSRunLoopTimer::scheduleTimer): 76 (JSC::JSRunLoopTimer::cancelTimer): 77 (JSC::JSRunLoopTimer::invalidate): 78 * runtime/JSRunLoopTimer.h: Copied from Source/JavaScriptCore/heap/HeapTimer.h. 79 * runtime/Options.h: 80 * runtime/PromiseDeferredTimer.cpp: Added. 81 (JSC::PromiseDeferredTimer::PromiseDeferredTimer): 82 (JSC::PromiseDeferredTimer::doWork): 83 (JSC::PromiseDeferredTimer::runRunLoop): 84 (JSC::PromiseDeferredTimer::addPendingPromise): 85 (JSC::PromiseDeferredTimer::cancelPendingPromise): 86 (JSC::PromiseDeferredTimer::scheduleWorkSoon): 87 (JSC::PromiseDeferredTimer::scheduleBlockedTask): 88 * runtime/PromiseDeferredTimer.h: Renamed from Source/JavaScriptCore/heap/HeapTimer.h. 89 (JSC::PromiseDeferredTimer::stopRunningTasks): 90 * runtime/VM.cpp: 91 (JSC::VM::VM): 92 (JSC::VM::~VM): 93 * runtime/VM.h: 94 * wasm/JSWebAssembly.cpp: 95 (JSC::reject): 96 (JSC::webAssemblyCompileFunc): 97 (JSC::resolve): 98 (JSC::instantiate): 99 (JSC::compileAndInstantiate): 100 (JSC::webAssemblyInstantiateFunc): 101 (JSC::webAssemblyValidateFunc): 102 * wasm/WasmB3IRGenerator.cpp: 103 (JSC::Wasm::B3IRGenerator::B3IRGenerator): 104 (JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer): 105 (JSC::Wasm::B3IRGenerator::memoryKind): 106 (JSC::Wasm::parseAndCompile): 107 * wasm/WasmB3IRGenerator.h: 108 * wasm/WasmFormat.h: 109 (JSC::Wasm::ModuleInformation::internalFunctionCount): 110 * wasm/WasmFunctionParser.h: 111 * wasm/WasmMemory.h: 112 * wasm/WasmMemoryInformation.cpp: 113 (JSC::Wasm::MemoryInformation::MemoryInformation): 114 * wasm/WasmMemoryInformation.h: 115 (JSC::Wasm::MemoryInformation::maximum): 116 (JSC::Wasm::MemoryInformation::hasReservedMemory): Deleted. 117 (JSC::Wasm::MemoryInformation::takeReservedMemory): Deleted. 118 (JSC::Wasm::MemoryInformation::mode): Deleted. 119 * wasm/WasmModuleParser.cpp: 120 * wasm/WasmModuleParser.h: 121 (JSC::Wasm::ModuleParser::ModuleParser): 122 * wasm/WasmPlan.cpp: 123 (JSC::Wasm::Plan::Plan): 124 (JSC::Wasm::Plan::stateString): 125 (JSC::Wasm::Plan::moveToState): 126 (JSC::Wasm::Plan::fail): 127 (JSC::Wasm::Plan::parseAndValidateModule): 128 (JSC::Wasm::Plan::prepare): 129 (JSC::Wasm::Plan::ThreadCountHolder::ThreadCountHolder): 130 (JSC::Wasm::Plan::ThreadCountHolder::~ThreadCountHolder): 131 (JSC::Wasm::Plan::compileFunctions): 132 (JSC::Wasm::Plan::complete): 133 (JSC::Wasm::Plan::waitForCompletion): 134 (JSC::Wasm::Plan::cancel): 135 (JSC::Wasm::Plan::run): Deleted. 136 (JSC::Wasm::Plan::initializeCallees): Deleted. 137 * wasm/WasmPlan.h: 138 (JSC::Wasm::Plan::dontFinalize): 139 (JSC::Wasm::Plan::exports): 140 (JSC::Wasm::Plan::internalFunctionCount): 141 (JSC::Wasm::Plan::takeModuleInformation): 142 (JSC::Wasm::Plan::takeCallLinkInfos): 143 (JSC::Wasm::Plan::takeWasmExitStubs): 144 (JSC::Wasm::Plan::setModeAndPromise): 145 (JSC::Wasm::Plan::mode): 146 (JSC::Wasm::Plan::pendingPromise): 147 (JSC::Wasm::Plan::vm): 148 (JSC::Wasm::Plan::errorMessage): 149 (JSC::Wasm::Plan::failed): 150 (JSC::Wasm::Plan::hasWork): 151 (JSC::Wasm::Plan::hasBeenPrepared): 152 * wasm/WasmPlanInlines.h: Copied from Source/JavaScriptCore/wasm/WasmB3IRGenerator.h. 153 (JSC::Wasm::Plan::initializeCallees): 154 * wasm/WasmValidate.cpp: 155 * wasm/WasmWorklist.cpp: Added. 156 (JSC::Wasm::Worklist::priorityString): 157 (JSC::Wasm::Worklist::QueueElement::setToNextPriority): 158 (JSC::Wasm::Worklist::iterate): 159 (JSC::Wasm::Worklist::enqueue): 160 (JSC::Wasm::Worklist::completePlanSynchronously): 161 (JSC::Wasm::Worklist::stopAllPlansForVM): 162 (JSC::Wasm::Worklist::Worklist): 163 (JSC::Wasm::Worklist::~Worklist): 164 (JSC::Wasm::existingWorklistOrNull): 165 (JSC::Wasm::ensureWorklist): 166 * wasm/WasmWorklist.h: Added. 167 (JSC::Wasm::Worklist::nextTicket): 168 (JSC::Wasm::Worklist::Comparator::operator()): 169 * wasm/js/JSWebAssemblyCallee.h: 170 * wasm/js/JSWebAssemblyCodeBlock.cpp: 171 (JSC::JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock): 172 (JSC::JSWebAssemblyCodeBlock::initialize): 173 (JSC::JSWebAssemblyCodeBlock::isSafeToRun): 174 * wasm/js/JSWebAssemblyCodeBlock.h: 175 (JSC::JSWebAssemblyCodeBlock::create): 176 (JSC::JSWebAssemblyCodeBlock::initialized): 177 (JSC::JSWebAssemblyCodeBlock::plan): 178 (JSC::JSWebAssemblyCodeBlock::runnable): 179 (JSC::JSWebAssemblyCodeBlock::errorMessage): 180 (JSC::JSWebAssemblyCodeBlock::callees): 181 * wasm/js/JSWebAssemblyHelpers.h: 182 (JSC::createSourceBufferFromValue): 183 * wasm/js/JSWebAssemblyInstance.cpp: 184 (JSC::JSWebAssemblyInstance::finishCreation): 185 (JSC::JSWebAssemblyInstance::visitChildren): 186 (JSC::JSWebAssemblyInstance::addUnitializedCodeBlock): 187 (JSC::JSWebAssemblyInstance::finalizeCreation): 188 (JSC::JSWebAssemblyInstance::create): 189 (JSC::JSWebAssemblyInstance::setMemory): Deleted. 190 * wasm/js/JSWebAssemblyInstance.h: 191 (JSC::JSWebAssemblyInstance::codeBlock): 192 (JSC::JSWebAssemblyInstance::initialized): 193 (JSC::JSWebAssemblyInstance::module): 194 (JSC::JSWebAssemblyInstance::importFunction): 195 (JSC::JSWebAssemblyInstance::setMemory): 196 (JSC::JSWebAssemblyInstance::table): 197 (JSC::JSWebAssemblyInstance::importFunctions): 198 (JSC::JSWebAssemblyInstance::setImportFunction): Deleted. 199 (JSC::JSWebAssemblyInstance::setTable): Deleted. 200 * wasm/js/JSWebAssemblyModule.cpp: 201 (JSC::JSWebAssemblyModule::createStub): 202 (JSC::JSWebAssemblyModule::JSWebAssemblyModule): 203 (JSC::JSWebAssemblyModule::finishCreation): 204 (JSC::JSWebAssemblyModule::setCodeBlock): 205 (JSC::JSWebAssemblyModule::buildCodeBlock): Deleted. 206 (JSC::JSWebAssemblyModule::create): Deleted. 207 (JSC::JSWebAssemblyModule::codeBlock): Deleted. 208 * wasm/js/JSWebAssemblyModule.h: 209 (JSC::JSWebAssemblyModule::moduleInformation): 210 (JSC::JSWebAssemblyModule::codeBlock): 211 (JSC::JSWebAssemblyModule::source): 212 (JSC::JSWebAssemblyModule::takeReservedMemory): Deleted. 213 (JSC::JSWebAssemblyModule::codeBlockFor): Deleted. 214 * wasm/js/WebAssemblyInstanceConstructor.cpp: 215 (JSC::constructJSWebAssemblyInstance): 216 (JSC::WebAssemblyInstanceConstructor::createInstance): Deleted. 217 * wasm/js/WebAssemblyModuleConstructor.cpp: 218 (JSC::WebAssemblyModuleConstructor::createModule): 219 * wasm/js/WebAssemblyModulePrototype.cpp: 220 (JSC::webAssemblyModuleProtoImports): 221 (JSC::webAssemblyModuleProtoExports): 222 * wasm/js/WebAssemblyModuleRecord.cpp: 223 (JSC::WebAssemblyModuleRecord::finishCreation): 224 (JSC::WebAssemblyModuleRecord::link): 225 (JSC::WebAssemblyModuleRecord::evaluate): 226 * wasm/js/WebAssemblyModuleRecord.h: 227 1 228 2017-03-28 Yusuke Suzuki <utatane.tea@gmail.com> 2 229 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r214465 r214504 1322 1322 52F6C35D1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */; }; 1323 1323 52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1324 530FB3021E7A0B6E003C19DD /* WasmWorklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 530FB3011E7A0B6E003C19DD /* WasmWorklist.h */; }; 1325 530FB3041E7A1146003C19DD /* WasmWorklist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 530FB3031E7A1146003C19DD /* WasmWorklist.cpp */; }; 1324 1326 531374BD1D5CE67600AF7A0B /* WasmPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WasmPlan.h */; }; 1325 1327 531374BF1D5CE95000AF7A0B /* WasmPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */; }; … … 1327 1329 5341FC701DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5341FC6F1DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp */; }; 1328 1330 5341FC721DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */; }; 1331 534638711E70CF3D00F12AC1 /* JSRunLoopTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 534638701E70CF3D00F12AC1 /* JSRunLoopTimer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1332 534638731E70D01500F12AC1 /* JSRunLoopTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 534638721E70D01500F12AC1 /* JSRunLoopTimer.cpp */; }; 1333 534638751E70DDEC00F12AC1 /* PromiseDeferredTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 534638741E70DDEC00F12AC1 /* PromiseDeferredTimer.h */; }; 1334 534638771E71E06E00F12AC1 /* PromiseDeferredTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 534638761E71E06E00F12AC1 /* PromiseDeferredTimer.cpp */; }; 1329 1335 53486BB71C1795C300F6F3AF /* JSTypedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 53486BB61C1795C300F6F3AF /* JSTypedArray.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1330 1336 53486BBB1C18E84500F6F3AF /* JSTypedArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */; }; … … 1360 1366 53F40E971D5A7BEC0099A1B6 /* WasmModuleParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */; }; 1361 1367 53F6BF6D1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1368 53F8D2001E8387D400D21116 /* WasmPlanInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F8D1FF1E8387D400D21116 /* WasmPlanInlines.h */; }; 1362 1369 53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1363 1370 53FA2AE31CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */; }; … … 2239 2246 C2CF39C216E15A8100DD69BE /* JSAPIWrapperObject.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CF39C016E15A8100DD69BE /* JSAPIWrapperObject.h */; }; 2240 2247 C2DA778318E259990066FCB6 /* HeapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C2DA778218E259990066FCB6 /* HeapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 2241 C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2E526BB1590EF000054E48D /* HeapTimer.cpp */; };2242 C2E526BE1590EF000054E48D /* HeapTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E526BC1590EF000054E48D /* HeapTimer.h */; settings = {ATTRIBUTES = (Private, ); }; };2243 2248 C2F0F2D116BAEEE900187C19 /* StructureRareData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F0F2D016BAEEE900187C19 /* StructureRareData.cpp */; }; 2244 2249 C2FCAE1017A9C24E0034C735 /* BytecodeBasicBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FCAE0C17A9C24E0034C735 /* BytecodeBasicBlock.cpp */; }; … … 3811 3816 52F6C35B1E71EB080081F4CC /* WebAssemblyWrapperFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyWrapperFunction.cpp; path = js/WebAssemblyWrapperFunction.cpp; sourceTree = "<group>"; }; 3812 3817 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyWrapperFunction.h; path = js/WebAssemblyWrapperFunction.h; sourceTree = "<group>"; }; 3818 530FB3011E7A0B6E003C19DD /* WasmWorklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmWorklist.h; sourceTree = "<group>"; }; 3819 530FB3031E7A1146003C19DD /* WasmWorklist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmWorklist.cpp; sourceTree = "<group>"; }; 3813 3820 531374BC1D5CE67600AF7A0B /* WasmPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmPlan.h; sourceTree = "<group>"; }; 3814 3821 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmPlan.cpp; sourceTree = "<group>"; }; … … 3816 3823 5341FC6F1DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3WasmBoundsCheckValue.cpp; path = b3/B3WasmBoundsCheckValue.cpp; sourceTree = "<group>"; }; 3817 3824 5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3WasmBoundsCheckValue.h; path = b3/B3WasmBoundsCheckValue.h; sourceTree = "<group>"; }; 3825 534638701E70CF3D00F12AC1 /* JSRunLoopTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRunLoopTimer.h; sourceTree = "<group>"; }; 3826 534638721E70D01500F12AC1 /* JSRunLoopTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSRunLoopTimer.cpp; sourceTree = "<group>"; }; 3827 534638741E70DDEC00F12AC1 /* PromiseDeferredTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PromiseDeferredTimer.h; sourceTree = "<group>"; }; 3828 534638761E71E06E00F12AC1 /* PromiseDeferredTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PromiseDeferredTimer.cpp; sourceTree = "<group>"; }; 3818 3829 53486BB61C1795C300F6F3AF /* JSTypedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArray.h; sourceTree = "<group>"; }; 3819 3830 53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArray.cpp; sourceTree = "<group>"; }; … … 3855 3866 53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmModuleParser.cpp; sourceTree = "<group>"; }; 3856 3867 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InternalFunctionAllocationProfile.h; sourceTree = "<group>"; }; 3868 53F8D1FF1E8387D400D21116 /* WasmPlanInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmPlanInlines.h; sourceTree = "<group>"; }; 3857 3869 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.h; sourceTree = "<group>"; }; 3858 3870 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; }; … … 4799 4811 C2CF39C016E15A8100DD69BE /* JSAPIWrapperObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAPIWrapperObject.h; sourceTree = "<group>"; }; 4800 4812 C2DA778218E259990066FCB6 /* HeapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapInlines.h; sourceTree = "<group>"; }; 4801 C2E526BB1590EF000054E48D /* HeapTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapTimer.cpp; sourceTree = "<group>"; };4802 C2E526BC1590EF000054E48D /* HeapTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapTimer.h; sourceTree = "<group>"; };4803 4813 C2F0F2D016BAEEE900187C19 /* StructureRareData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureRareData.cpp; sourceTree = "<group>"; }; 4804 4814 C2FCAE0C17A9C24E0034C735 /* BytecodeBasicBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BytecodeBasicBlock.cpp; sourceTree = "<group>"; }; … … 5920 5930 A5311C341C77CEAC00E6B1B6 /* HeapSnapshotBuilder.cpp */, 5921 5931 A5311C351C77CEAC00E6B1B6 /* HeapSnapshotBuilder.h */, 5922 C2E526BB1590EF000054E48D /* HeapTimer.cpp */,5923 C2E526BC1590EF000054E48D /* HeapTimer.h */,5924 5932 0FADE6721D4D23BC00768457 /* HeapUtil.h */, 5925 5933 C25F8BCB157544A900245B71 /* IncrementalSweeper.cpp */, … … 6289 6297 531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */, 6290 6298 531374BC1D5CE67600AF7A0B /* WasmPlan.h */, 6299 53F8D1FF1E8387D400D21116 /* WasmPlanInlines.h */, 6291 6300 53F40E841D58F9770099A1B6 /* WasmSections.h */, 6292 6301 AD7438BE1E04579200FD0C2A /* WasmSignature.cpp */, … … 6294 6303 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */, 6295 6304 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */, 6305 530FB3031E7A1146003C19DD /* WasmWorklist.cpp */, 6306 530FB3011E7A0B6E003C19DD /* WasmWorklist.h */, 6296 6307 ); 6297 6308 path = wasm; … … 6450 6461 BCD203470E17135E002C7E82 /* DatePrototype.cpp */, 6451 6462 BCD203480E17135E002C7E82 /* DatePrototype.h */, 6463 534638761E71E06E00F12AC1 /* PromiseDeferredTimer.cpp */, 6464 534638741E70DDEC00F12AC1 /* PromiseDeferredTimer.h */, 6452 6465 169948EDE68D4054B01EF797 /* DefinePropertyAttributes.h */, 6453 6466 0FE0500F1AA9091100D33B33 /* DirectArguments.cpp */, … … 6838 6851 BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */, 6839 6852 BCD202C00E1706A7002C7E82 /* RegExpPrototype.h */, 6853 534638721E70D01500F12AC1 /* JSRunLoopTimer.cpp */, 6854 534638701E70CF3D00F12AC1 /* JSRunLoopTimer.h */, 6840 6855 70B0A9D01A9B66200001306A /* RuntimeFlags.h */, 6841 6856 527773DD1AAF83AC00BDE7E8 /* RuntimeType.cpp */, … … 8131 8146 0FEC85081BDACDAC0080FF74 /* B3CheckValue.h in Headers */, 8132 8147 0FEC850A1BDACDAC0080FF74 /* B3Common.h in Headers */, 8148 530FB3021E7A0B6E003C19DD /* WasmWorklist.h in Headers */, 8133 8149 0FEC850C1BDACDAC0080FF74 /* B3Commutativity.h in Headers */, 8134 8150 0F338E0C1BF0276C0013C88F /* B3Compilation.h in Headers */, … … 8251 8267 0F64B27A1A7957B2006E4E66 /* CallEdge.h in Headers */, 8252 8268 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */, 8269 534638751E70DDEC00F12AC1 /* PromiseDeferredTimer.h in Headers */, 8253 8270 62EC9BB71B7EB07C00303AD1 /* CallFrameShuffleData.h in Headers */, 8254 8271 0FF4B4BD1E88449A00DBBE86 /* AirRegLiveness.h in Headers */, … … 8538 8555 E35CA1541DBC3A5C00F83516 /* DOMJITHeapRange.h in Headers */, 8539 8556 E3C08E3C1DA41B810039478F /* DOMJITPatchpoint.h in Headers */, 8557 534638711E70CF3D00F12AC1 /* JSRunLoopTimer.h in Headers */, 8540 8558 FE6F56DE1E64EAD600D17801 /* VMTraps.h in Headers */, 8541 8559 E37AD83C1DA4928600F3D412 /* DOMJITPatchpointParams.h in Headers */, … … 8708 8726 A54C2AB11C6544F200A18D78 /* HeapSnapshot.h in Headers */, 8709 8727 A5311C361C77CEC500E6B1B6 /* HeapSnapshotBuilder.h in Headers */, 8710 C2E526BE1590EF000054E48D /* HeapTimer.h in Headers */,8711 8728 0FD0E5EA1E43D34D0006AB08 /* GCConductor.h in Headers */, 8712 8729 0FADE6731D4D23BE00768457 /* HeapUtil.h in Headers */, … … 9158 9175 A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */, 9159 9176 BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */, 9177 53F8D2001E8387D400D21116 /* WasmPlanInlines.h in Headers */, 9160 9178 BCD202D60E170708002C7E82 /* RegExpConstructor.lut.h in Headers */, 9161 9179 0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */, … … 9978 9996 0FF4B4CA1E889D7B00DBBE86 /* B3VariableLiveness.cpp in Sources */, 9979 9997 0FEC85111BDACDAC0080FF74 /* B3ConstDoubleValue.cpp in Sources */, 9998 530FB3041E7A1146003C19DD /* WasmWorklist.cpp in Sources */, 9980 9999 43422A621C158E6A00E2EB98 /* B3ConstFloatValue.cpp in Sources */, 9981 10000 0F338DF51BE93D550013C88F /* B3ConstrainedValue.cpp in Sources */, … … 10271 10290 147341E21DC2CE9600AA29BA /* EvalExecutable.cpp in Sources */, 10272 10291 A54982031891D0B00081E5B8 /* EventLoop.cpp in Sources */, 10292 534638731E70D01500F12AC1 /* JSRunLoopTimer.cpp in Sources */, 10273 10293 FE1C0FFF1B194FD100B53FCA /* Exception.cpp in Sources */, 10274 10294 FE80C19B1D776A98008510C0 /* ExceptionEventLocation.cpp in Sources */, … … 10348 10368 A54C2AB01C6544EE00A18D78 /* HeapSnapshot.cpp in Sources */, 10349 10369 A5311C371C77CECA00E6B1B6 /* HeapSnapshotBuilder.cpp in Sources */, 10350 C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */,10351 10370 0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */, 10352 10371 DC2143081CA32E58000A8869 /* ICStats.cpp in Sources */, … … 10673 10692 992F56B41E4E84A40035953B /* RemoteConnectionToTargetCocoa.mm in Sources */, 10674 10693 998ED6741BED70AC00DD8017 /* RemoteControllableTarget.cpp in Sources */, 10694 534638771E71E06E00F12AC1 /* PromiseDeferredTimer.cpp in Sources */, 10675 10695 A594558F18245EFD00CC3843 /* RemoteInspectionTarget.cpp in Sources */, 10676 10696 995566861E4E8B0F00AAE13C /* RemoteInspector.cpp in Sources */, -
trunk/Source/JavaScriptCore/heap/GCActivityCallback.h
r212541 r214504 29 29 #pragma once 30 30 31 #include " HeapTimer.h"31 #include "JSRunLoopTimer.h" 32 32 #include <wtf/RefPtr.h> 33 33 … … 41 41 class Heap; 42 42 43 class JS_EXPORT_PRIVATE GCActivityCallback : public HeapTimer {43 class JS_EXPORT_PRIVATE GCActivityCallback : public JSRunLoopTimer { 44 44 public: 45 using Base = JSRunLoopTimer; 45 46 static RefPtr<FullGCActivityCallback> createFullTimer(Heap*); 46 47 static RefPtr<GCActivityCallback> createEdenTimer(Heap*); … … 71 72 #if USE(CF) 72 73 GCActivityCallback(VM* vm) 73 : HeapTimer(vm)74 : Base(vm) 74 75 , m_enabled(true) 75 76 , m_delay(s_decade) … … 78 79 #elif USE(GLIB) 79 80 GCActivityCallback(VM* vm) 80 : HeapTimer(vm)81 : Base(vm) 81 82 , m_enabled(true) 82 83 , m_delay(s_decade) … … 85 86 #else 86 87 GCActivityCallback(VM* vm) 87 : HeapTimer(vm)88 : Base(vm) 88 89 , m_enabled(true) 89 90 { -
trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
r212778 r214504 42 42 void IncrementalSweeper::scheduleTimer() 43 43 { 44 HeapTimer::scheduleTimer(sweepTimeSlice * sweepTimeMultiplier);44 Base::scheduleTimer(sweepTimeSlice * sweepTimeMultiplier); 45 45 } 46 46 47 47 IncrementalSweeper::IncrementalSweeper(Heap* heap) 48 : HeapTimer(heap->vm())48 : Base(heap->vm()) 49 49 , m_currentAllocator(nullptr) 50 50 { -
trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h
r212778 r214504 26 26 #pragma once 27 27 28 #include " HeapTimer.h"28 #include "JSRunLoopTimer.h" 29 29 #include <wtf/Vector.h> 30 30 … … 34 34 class MarkedAllocator; 35 35 36 class IncrementalSweeper : public HeapTimer {36 class IncrementalSweeper : public JSRunLoopTimer { 37 37 public: 38 using Base = JSRunLoopTimer; 38 39 JS_EXPORT_PRIVATE explicit IncrementalSweeper(Heap*); 39 40 -
trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp
r208306 r214504 32 32 33 33 StopIfNecessaryTimer::StopIfNecessaryTimer(VM* vm) 34 : HeapTimer(vm)34 : Base(vm) 35 35 { 36 36 } -
trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h
r208306 r214504 26 26 #pragma once 27 27 28 #include " HeapTimer.h"28 #include "JSRunLoopTimer.h" 29 29 30 30 namespace JSC { … … 32 32 class Heap; 33 33 34 class StopIfNecessaryTimer : public HeapTimer {34 class StopIfNecessaryTimer : public JSRunLoopTimer { 35 35 public: 36 using Base = JSRunLoopTimer; 36 37 explicit StopIfNecessaryTimer(VM*); 37 38 -
trunk/Source/JavaScriptCore/heap/StrongInlines.h
r206525 r214504 26 26 #pragma once 27 27 28 #include "JSCJSValueInlines.h" 28 29 #include "VM.h" 29 30 -
trunk/Source/JavaScriptCore/jsc.cpp
r214289 r214504 63 63 #include "ParserError.h" 64 64 #include "ProfilerDatabase.h" 65 #include "PromiseDeferredTimer.h" 65 66 #include "ProtoCallFrame.h" 66 67 #include "ReleaseHeapAccessScope.h" … … 74 75 #include "TypeProfilerLog.h" 75 76 #include "WasmFaultSignalHandler.h" 76 #include "WasmPlan.h"77 77 #include "WasmMemory.h" 78 #include "WasmPlanInlines.h" 79 #include "WasmWorklist.h" 78 80 #include <locale.h> 79 81 #include <math.h> … … 908 910 const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, nullptr, CREATE_METHOD_TABLE(RuntimeArray) }; 909 911 const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, nullptr, CREATE_METHOD_TABLE(SimpleObject) }; 910 static bool test262AsyncPassed { false};911 static bool test262AsyncTest { false};912 static unsigned asyncTestPasses { 0 }; 913 static unsigned asyncTestExpectedPasses { 0 }; 912 914 913 915 ElementHandleOwner* Element::handleOwner() … … 1078 1080 1079 1081 static EncodedJSValue JSC_HOST_CALL functionMaxArguments(ExecState*); 1082 static EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState*); 1083 static EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*); 1080 1084 1081 1085 #if ENABLE(WEBASSEMBLY) … … 1349 1353 1350 1354 addFunction(vm, "maxArguments", functionMaxArguments, 0); 1355 1356 addFunction(vm, "asyncTestStart", functionAsyncTestStart, 1); 1357 addFunction(vm, "asyncTestPassed", functionAsyncTestPassed, 1); 1351 1358 1352 1359 #if ENABLE(WEBASSEMBLY) … … 1733 1740 auto scope = DECLARE_THROW_SCOPE(vm); 1734 1741 1735 if ( test262AsyncTest) {1742 if (asyncTestExpectedPasses) { 1736 1743 JSValue value = exec->argument(0); 1737 if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete")) 1738 test262AsyncPassed = true; 1739 return JSValue::encode(jsUndefined()); 1744 if (value.isString() && WTF::equal(asString(value)->value(exec).impl(), "Test262:AsyncTestComplete")) { 1745 asyncTestPasses++; 1746 return JSValue::encode(jsUndefined()); 1747 } 1740 1748 } 1741 1749 … … 3050 3058 } 3051 3059 3060 EncodedJSValue JSC_HOST_CALL functionAsyncTestStart(ExecState* exec) 3061 { 3062 VM& vm = exec->vm(); 3063 auto scope = DECLARE_THROW_SCOPE(vm); 3064 3065 JSValue numberOfAsyncPasses = exec->argument(0); 3066 if (!numberOfAsyncPasses.isUInt32()) 3067 return throwVMError(exec, scope, ASCIILiteral("Expected first argument to a uint32")); 3068 3069 asyncTestExpectedPasses += numberOfAsyncPasses.asUInt32(); 3070 return encodedJSUndefined(); 3071 } 3072 3073 EncodedJSValue JSC_HOST_CALL functionAsyncTestPassed(ExecState*) 3074 { 3075 asyncTestPasses++; 3076 return encodedJSUndefined(); 3077 } 3078 3052 3079 #if ENABLE(WEBASSEMBLY) 3053 3080 … … 3160 3187 CRASH(); 3161 3188 3162 Wasm::Plan plan(&vm, static_cast<uint8_t*>(source->vector()), source->length()); 3163 plan.run(); 3164 if (plan.failed()) { 3165 dataLogLn("failed to parse module: ", plan.errorMessage()); 3189 Ref<Wasm::Plan> plan = adoptRef(*new Wasm::Plan(vm, static_cast<uint8_t*>(source->vector()), source->length(), Wasm::Plan::FullCompile, Wasm::Plan::dontFinalize)); 3190 Wasm::ensureWorklist().enqueue(plan.copyRef()); 3191 Wasm::ensureWorklist().completePlanSynchronously(plan.get()); 3192 if (plan->failed()) { 3193 dataLogLn("failed to parse module: ", plan->errorMessage()); 3166 3194 CRASH(); 3167 3195 } 3168 3196 3169 if (plan .internalFunctionCount() != functionCount)3197 if (plan->internalFunctionCount() != functionCount) 3170 3198 CRASH(); 3171 3199 … … 3174 3202 { 3175 3203 unsigned lastIndex = UINT_MAX; 3176 plan .initializeCallees(exec->lexicalGlobalObject(),3204 plan->initializeCallees( 3177 3205 [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) { 3178 3206 RELEASE_ASSERT(!calleeIndex || (calleeIndex - 1 == lastIndex)); … … 3182 3210 }); 3183 3211 } 3184 std::unique_ptr<Wasm::ModuleInformation> moduleInformation = plan .takeModuleInformation();3212 std::unique_ptr<Wasm::ModuleInformation> moduleInformation = plan->takeModuleInformation(); 3185 3213 RELEASE_ASSERT(!moduleInformation->memory); 3186 3214 … … 3667 3695 3668 3696 if (!strcmp(arg, "--test262-async")) { 3669 test262AsyncTest = true;3697 asyncTestExpectedPasses++; 3670 3698 continue; 3671 3699 } … … 3739 3767 3740 3768 VM& vm = VM::create(LargeHeap).leakRef(); 3741 JSLockHolder locker(&vm);3742 3743 3769 int result; 3744 if (options.m_profile && !vm.m_perBytecodeProfiler) 3745 vm.m_perBytecodeProfiler = std::make_unique<Profiler::Database>(vm); 3746 3747 GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments); 3748 globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging); 3749 bool success = func(vm, globalObject); 3750 if (options.m_interactive && success) 3751 runInteractive(globalObject); 3752 3753 vm.drainMicrotasks(); 3754 result = success && (test262AsyncTest == test262AsyncPassed) ? 0 : 3; 3755 3756 if (options.m_exitCode) 3757 printf("jsc exiting %d\n", result); 3770 bool success; 3771 { 3772 JSLockHolder locker(vm); 3773 3774 if (options.m_profile && !vm.m_perBytecodeProfiler) 3775 vm.m_perBytecodeProfiler = std::make_unique<Profiler::Database>(vm); 3776 3777 GlobalObject* globalObject = GlobalObject::create(vm, GlobalObject::createStructure(vm, jsNull()), options.m_arguments); 3778 globalObject->setRemoteDebuggingEnabled(options.m_enableRemoteDebugging); 3779 success = func(vm, globalObject); 3780 if (options.m_interactive && success) 3781 runInteractive(globalObject); 3782 3783 vm.drainMicrotasks(); 3784 } 3785 #if USE(CF) 3786 vm.promiseDeferredTimer->runRunLoop(); 3787 #endif 3788 3789 result = success && (asyncTestExpectedPasses == asyncTestPasses) ? 0 : 3; 3790 3791 if (options.m_exitCode) { 3792 printf("jsc exiting %d", result); 3793 if (asyncTestExpectedPasses != asyncTestPasses) 3794 printf(" because expected: %d async test passes but got: %d async test passes", asyncTestExpectedPasses, asyncTestPasses); 3795 printf("\n"); 3796 } 3758 3797 3759 3798 if (options.m_profile) { 3799 JSLockHolder locker(vm); 3760 3800 if (!vm.m_perBytecodeProfiler->save(options.m_profilerOutput.utf8().data())) 3761 3801 fprintf(stderr, "could not save profiler output.\n"); … … 3763 3803 3764 3804 #if ENABLE(JIT) 3765 if (Options::useExceptionFuzz()) 3766 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks()); 3767 bool fireAtEnabled = 3768 Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter(); 3769 if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz())) 3770 printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks()); 3771 if (Options::useOSRExitFuzz()) { 3772 printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks()); 3773 printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks()); 3774 } 3775 3776 auto compileTimeStats = JIT::compileTimeStats(); 3777 Vector<CString> compileTimeKeys; 3778 for (auto& entry : compileTimeStats) 3779 compileTimeKeys.append(entry.key); 3780 std::sort(compileTimeKeys.begin(), compileTimeKeys.end()); 3781 for (CString key : compileTimeKeys) 3782 printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key)); 3805 { 3806 JSLockHolder locker(vm); 3807 if (Options::useExceptionFuzz()) 3808 printf("JSC EXCEPTION FUZZ: encountered %u checks.\n", numberOfExceptionFuzzChecks()); 3809 bool fireAtEnabled = 3810 Options::fireExecutableAllocationFuzzAt() || Options::fireExecutableAllocationFuzzAtOrAfter(); 3811 if (Options::useExecutableAllocationFuzz() && (!fireAtEnabled || Options::verboseExecutableAllocationFuzz())) 3812 printf("JSC EXECUTABLE ALLOCATION FUZZ: encountered %u checks.\n", numberOfExecutableAllocationFuzzChecks()); 3813 if (Options::useOSRExitFuzz()) { 3814 printf("JSC OSR EXIT FUZZ: encountered %u static checks.\n", numberOfStaticOSRExitFuzzChecks()); 3815 printf("JSC OSR EXIT FUZZ: encountered %u dynamic checks.\n", numberOfOSRExitFuzzChecks()); 3816 } 3817 3818 3819 auto compileTimeStats = JIT::compileTimeStats(); 3820 Vector<CString> compileTimeKeys; 3821 for (auto& entry : compileTimeStats) 3822 compileTimeKeys.append(entry.key); 3823 std::sort(compileTimeKeys.begin(), compileTimeKeys.end()); 3824 for (CString key : compileTimeKeys) 3825 printf("%40s: %.3lf ms\n", key.data(), compileTimeStats.get(key)); 3826 } 3783 3827 #endif 3784 3828 -
trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp
r214218 r214504 34 34 #include "JSPromise.h" 35 35 #include "JSPromiseConstructor.h" 36 #include "PromiseDeferredTimer.h" 36 37 37 38 namespace JSC { … … 100 101 { 101 102 callFunction(exec, m_resolve.get(), value); 103 bool wasPending = exec->vm().promiseDeferredTimer->cancelPendingPromise(this); 104 ASSERT_UNUSED(wasPending, wasPending == m_promiseIsAsyncPending); 102 105 } 103 106 … … 105 108 { 106 109 callFunction(exec, m_reject.get(), reason); 110 bool wasPending = exec->vm().promiseDeferredTimer->cancelPendingPromise(this); 111 ASSERT_UNUSED(wasPending, wasPending == m_promiseIsAsyncPending); 107 112 } 108 113 -
trunk/Source/JavaScriptCore/runtime/JSPromiseDeferred.h
r214218 r214504 57 57 JS_EXPORT_PRIVATE void reject(ExecState*, Exception*); 58 58 59 #ifndef NDEBUG 60 void promiseAsyncPending() { m_promiseIsAsyncPending = true; } 61 #endif 62 59 63 protected: 60 64 JSPromiseDeferred(VM&, Structure*); … … 64 68 private: 65 69 JSPromiseDeferred(VM&); 70 71 #ifndef NDEBUG 72 bool m_promiseIsAsyncPending { false }; 73 #endif 66 74 67 75 WriteBarrier<JSObject> m_promise; -
trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.cpp
r214502 r214504 21 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 25 26 26 #include "config.h" 27 #include " HeapTimer.h"27 #include "JSRunLoopTimer.h" 28 28 29 29 #include "GCActivityCallback.h" 30 30 #include "IncrementalSweeper.h" 31 #include "JSCInlines.h" 31 32 #include "JSObject.h" 32 33 #include "JSString.h" 33 #include "JSCInlines.h" 34 34 35 #include <wtf/MainThread.h> 35 36 #include <wtf/Threading.h> … … 42 43 43 44 #if USE(CF) 44 45 const CFTimeInterval HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10;46 45 47 HeapTimer::HeapTimer(VM* vm) 46 const CFTimeInterval JSRunLoopTimer::s_decade = 60 * 60 * 24 * 365 * 10; 47 48 JSRunLoopTimer::JSRunLoopTimer(VM* vm) 48 49 : m_vm(vm) 49 50 , m_apiLock(&vm->apiLock()) … … 52 53 } 53 54 54 void HeapTimer::setRunLoop(CFRunLoopRef runLoop)55 void JSRunLoopTimer::setRunLoop(CFRunLoopRef runLoop) 55 56 { 56 57 if (m_runLoop) { … … 60 61 m_timer.clear(); 61 62 } 62 63 63 64 if (runLoop) { 64 65 m_runLoop = runLoop; 65 66 memset(&m_context, 0, sizeof(CFRunLoopTimerContext)); 66 67 m_context.info = this; 67 m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, s_decade, s_decade, 0, 0, HeapTimer::timerDidFire, &m_context));68 m_timer = adoptCF(CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + s_decade, s_decade, 0, 0, JSRunLoopTimer::timerDidFire, &m_context)); 68 69 CFRunLoopAddTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes); 69 70 } 70 71 } 71 72 72 HeapTimer::~HeapTimer()73 JSRunLoopTimer::~JSRunLoopTimer() 73 74 { 74 75 setRunLoop(0); 75 76 } 76 77 77 void HeapTimer::timerDidFire(CFRunLoopTimerRef, void* contextPtr)78 void JSRunLoopTimer::timerDidFire(CFRunLoopTimerRef, void* contextPtr) 78 79 { 79 HeapTimer* timer = static_cast<HeapTimer*>(contextPtr);80 JSRunLoopTimer* timer = static_cast<JSRunLoopTimer*>(contextPtr); 80 81 timer->m_apiLock->lock(); 81 82 … … 95 96 } 96 97 97 void HeapTimer::scheduleTimer(double intervalInSeconds)98 void JSRunLoopTimer::scheduleTimer(double intervalInSeconds) 98 99 { 99 100 CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + intervalInSeconds); … … 101 102 } 102 103 103 void HeapTimer::cancelTimer()104 void JSRunLoopTimer::cancelTimer() 104 105 { 105 106 CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade); … … 109 110 #elif USE(GLIB) 110 111 111 const long HeapTimer::s_decade = 60 * 60 * 24 * 365 * 10;112 const long JSRunLoopTimer::s_decade = 60 * 60 * 24 * 365 * 10; 112 113 113 static GSourceFuncs heapTimerSourceFunctions = {114 static GSourceFuncs JSRunLoopTimerSourceFunctions = { 114 115 nullptr, // prepare 115 116 nullptr, // check … … 124 125 }; 125 126 126 HeapTimer::HeapTimer(VM* vm)127 JSRunLoopTimer::JSRunLoopTimer(VM* vm) 127 128 : m_vm(vm) 128 129 , m_apiLock(&vm->apiLock()) 129 , m_timer(adoptGRef(g_source_new(& heapTimerSourceFunctions, sizeof(GSource))))130 , m_timer(adoptGRef(g_source_new(&JSRunLoopTimerSourceFunctions, sizeof(GSource)))) 130 131 { 131 g_source_set_name(m_timer.get(), "[JavaScriptCore] HeapTimer");132 g_source_set_name(m_timer.get(), "[JavaScriptCore] JSRunLoopTimer"); 132 133 g_source_set_callback(m_timer.get(), [](gpointer userData) -> gboolean { 133 auto& heapTimer = *static_cast<HeapTimer*>(userData);134 g_source_set_ready_time( heapTimer.m_timer.get(), g_get_monotonic_time() + HeapTimer::s_decade * G_USEC_PER_SEC);135 heapTimer.timerDidFire();134 auto& runLoopTimer = *static_cast<JSRunLoopTimer*>(userData); 135 g_source_set_ready_time(runLoopTimer.m_timer.get(), g_get_monotonic_time() + JSRunLoopTimer::s_decade * G_USEC_PER_SEC); 136 runLoopTimer.timerDidFire(); 136 137 return G_SOURCE_CONTINUE; 137 138 }, this, nullptr); … … 139 140 } 140 141 141 HeapTimer::~HeapTimer()142 JSRunLoopTimer::~JSRunLoopTimer() 142 143 { 143 144 g_source_destroy(m_timer.get()); 144 145 } 145 146 146 void HeapTimer::timerDidFire()147 void JSRunLoopTimer::timerDidFire() 147 148 { 148 149 m_apiLock->lock(); … … 162 163 } 163 164 164 void HeapTimer::scheduleTimer(double intervalInSeconds)165 void JSRunLoopTimer::scheduleTimer(double intervalInSeconds) 165 166 { 166 167 g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + intervalInSeconds * G_USEC_PER_SEC); … … 168 169 } 169 170 170 void HeapTimer::cancelTimer()171 void JSRunLoopTimer::cancelTimer() 171 172 { 172 173 g_source_set_ready_time(m_timer.get(), g_get_monotonic_time() + s_decade * G_USEC_PER_SEC); … … 174 175 } 175 176 #else 176 HeapTimer::HeapTimer(VM* vm)177 JSRunLoopTimer::JSRunLoopTimer(VM* vm) 177 178 : m_vm(vm) 178 179 { 179 180 } 180 181 181 HeapTimer::~HeapTimer()182 JSRunLoopTimer::~JSRunLoopTimer() 182 183 { 183 184 } 184 185 185 void HeapTimer::invalidate()186 void JSRunLoopTimer::invalidate() 186 187 { 187 188 } 188 189 189 void HeapTimer::scheduleTimer(double)190 void JSRunLoopTimer::scheduleTimer(double) 190 191 { 191 192 } 192 193 193 void HeapTimer::cancelTimer()194 void JSRunLoopTimer::cancelTimer() 194 195 { 195 196 } 196 197 #endif 197 198 198 199 199 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSRunLoopTimer.h
r214502 r214504 1 1 /* 2 * Copyright (C) 2012, 2015-201 6Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2015-2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 21 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 25 … … 45 45 class VM; 46 46 47 class HeapTimer : public ThreadSafeRefCounted<HeapTimer> {47 class JSRunLoopTimer : public ThreadSafeRefCounted<JSRunLoopTimer> { 48 48 public: 49 HeapTimer(VM*);49 JSRunLoopTimer(VM*); 50 50 #if USE(CF) 51 51 static void timerDidFire(CFRunLoopTimerRef, void*); 52 52 #endif 53 54 JS_EXPORT_PRIVATE virtual ~ HeapTimer();53 54 JS_EXPORT_PRIVATE virtual ~JSRunLoopTimer(); 55 55 virtual void doWork() = 0; 56 56 … … 62 62 JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef); 63 63 #endif // USE(CF) 64 64 65 65 protected: 66 66 VM* m_vm; … … 73 73 RetainPtr<CFRunLoopTimerRef> m_timer; 74 74 RetainPtr<CFRunLoopRef> m_runLoop; 75 75 76 76 CFRunLoopTimerContext m_context; 77 77 … … 86 86 void invalidate(); 87 87 }; 88 88 89 89 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/Options.h
r214384 r214504 253 253 v(int32, priorityDeltaOfDFGCompilerThreads, computePriorityDeltaOfWorkerThreads(-1, 0), Normal, nullptr) \ 254 254 v(int32, priorityDeltaOfFTLCompilerThreads, computePriorityDeltaOfWorkerThreads(-2, 0), Normal, nullptr) \ 255 v(int32, priorityDeltaOfWasmCompilerThreads, computePriorityDeltaOfWorkerThreads(-1, 0), Normal, nullptr) \ 255 256 \ 256 257 v(bool, useProfiler, false, Normal, nullptr) \ … … 429 430 \ 430 431 v(bool, useWebAssembly, true, Normal, "Expose the WebAssembly global object.") \ 432 \ 433 v(bool, failToCompileWebAssemblyCode, false, Normal, "If true, no Wasm::Plan will sucessfully compile a function.") \ 434 \ 431 435 v(bool, simulateWebAssemblyLowMemory, false, Normal, "If true, the Memory object won't mmap the full 'maximum' range and instead will allocate the minimum required amount.") \ 432 436 v(bool, useWebAssemblyFastMemory, true, Normal, "If true, we will try to use a 32-bit address space with a signal handler to bounds check wasm memory.") \ -
trunk/Source/JavaScriptCore/runtime/PromiseDeferredTimer.h
r214502 r214504 1 1 /* 2 * Copyright (C) 201 2, 2015-2016Apple Inc. All rights reserved.2 * Copyright (C) 2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 21 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 25 26 26 #pragma once 27 27 28 #include "JSRunLoopTimer.h" 29 #include "Strong.h" 30 #include "WriteBarrier.h" 31 32 #include <wtf/HashMap.h> 28 33 #include <wtf/Lock.h> 29 #include <wtf/RefPtr.h> 30 #include <wtf/RetainPtr.h> 31 #include <wtf/ThreadSafeRefCounted.h> 32 #include <wtf/Threading.h> 33 34 #if USE(CF) 35 #include <CoreFoundation/CoreFoundation.h> 36 #endif 37 38 #if USE(GLIB) 39 #include <wtf/glib/GRefPtr.h> 40 #endif 34 #include <wtf/SharedTask.h> 35 #include <wtf/Vector.h> 41 36 42 37 namespace JSC { 43 38 44 class JS Lock;39 class JSPromiseDeferred; 45 40 class VM; 41 class JSCell; 46 42 47 class HeapTimer : public ThreadSafeRefCounted<HeapTimer>{43 class PromiseDeferredTimer : public JSRunLoopTimer { 48 44 public: 49 HeapTimer(VM*); 45 using Base = JSRunLoopTimer; 46 47 PromiseDeferredTimer(VM&); 48 49 void doWork() override; 50 51 void addPendingPromise(JSPromiseDeferred*, Vector<Strong<JSCell>>&& dependencies); 52 // JSPromiseDeferred should handle canceling when the promise is resolved or rejected. 53 bool cancelPendingPromise(JSPromiseDeferred*); 54 55 typedef std::function<void()> Task; 56 void scheduleWorkSoon(JSPromiseDeferred*, Task&&); 57 58 // Blocked tasks should only be registered while holding the JS API lock. If we didn't require holding the 59 // JS API lock then there might be a race where the promise you are waiting on is run before your task is 60 // registered. 61 void scheduleBlockedTask(JSPromiseDeferred*, Task&&); 62 63 void stopRunningTasks() { m_runTasks = false; } 50 64 #if USE(CF) 51 static void timerDidFire(CFRunLoopTimerRef, void*);65 JS_EXPORT_PRIVATE void runRunLoop(); 52 66 #endif 53 54 JS_EXPORT_PRIVATE virtual ~HeapTimer();55 virtual void doWork() = 0;56 67 57 void scheduleTimer(double intervalInSeconds); 58 void cancelTimer();59 bool isScheduled() const { return m_isScheduled; }60 68 private: 69 HashMap<JSPromiseDeferred*, Vector<Strong<JSCell>>> m_pendingPromises; 70 Lock m_taskLock; 71 bool m_runTasks { true }; 61 72 #if USE(CF) 62 JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef); 63 #endif // USE(CF) 64 65 protected: 66 VM* m_vm; 67 68 RefPtr<JSLock> m_apiLock; 69 bool m_isScheduled { false }; 70 #if USE(CF) 71 static const CFTimeInterval s_decade; 72 73 RetainPtr<CFRunLoopTimerRef> m_timer; 74 RetainPtr<CFRunLoopRef> m_runLoop; 75 76 CFRunLoopTimerContext m_context; 77 78 Lock m_shutdownMutex; 79 #elif USE(GLIB) 80 static const long s_decade; 81 void timerDidFire(); 82 GRefPtr<GSource> m_timer; 73 bool m_shouldStopRunLoopWhenAllPromisesFinish { false }; 83 74 #endif 84 85 private: 86 void invalidate(); 75 Vector<std::tuple<JSPromiseDeferred*, Task>> m_tasks; 76 HashMap<JSPromiseDeferred*, Vector<Task>> m_blockedTasks; 87 77 }; 88 78 -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r214498 r214504 86 86 #include "ProfilerDatabase.h" 87 87 #include "ProgramCodeBlock.h" 88 #include "PromiseDeferredTimer.h" 88 89 #include "PropertyMapHashTable.h" 89 90 #include "RegExpCache.h" … … 104 105 #include "VMEntryScope.h" 105 106 #include "VMInspector.h" 107 #include "WasmWorklist.h" 106 108 #include "Watchdog.h" 107 109 #include "WeakGCMapInlines.h" … … 178 180 , topVMEntryFrame(nullptr) 179 181 , topCallFrame(CallFrame::noCaller()) 182 , promiseDeferredTimer(std::make_unique<PromiseDeferredTimer>(*this)) 180 183 , m_atomicStringTable(vmType == Default ? wtfThreadData().atomicStringTable() : new AtomicStringTable) 181 184 , propertyNames(nullptr) … … 356 359 VM::~VM() 357 360 { 361 promiseDeferredTimer->stopRunningTasks(); 362 #if ENABLE(WEBASSEMBLY) 363 if (Wasm::existingWorklistOrNull()) 364 Wasm::ensureWorklist().stopAllPlansForVM(*this); 365 #endif 358 366 if (UNLIKELY(m_watchdog)) 359 367 m_watchdog->willDestroyVM(this); -
trunk/Source/JavaScriptCore/runtime/VM.h
r214498 r214504 107 107 class LLIntOffsetsExtractor; 108 108 class NativeExecutable; 109 class PromiseDeferredTimer; 109 110 class RegExpCache; 110 111 class Register; … … 380 381 std::unique_ptr<Wasm::SignatureInformation> m_wasmSignatureInformation; 381 382 #endif 383 std::unique_ptr<PromiseDeferredTimer> promiseDeferredTimer; 382 384 383 385 JSCell* currentlyDestructingCallbackObject; -
trunk/Source/JavaScriptCore/wasm/JSWebAssembly.cpp
r213506 r214504 34 34 #include "JSPromiseDeferred.h" 35 35 #include "JSWebAssemblyHelpers.h" 36 #include "JSWebAssemblyInstance.h" 37 #include "JSWebAssemblyModule.h" 36 38 #include "ObjectConstructor.h" 39 #include "PromiseDeferredTimer.h" 40 #include "StrongInlines.h" 37 41 #include "WasmPlan.h" 42 #include "WasmWorklist.h" 38 43 #include "WebAssemblyModuleConstructor.h" 44 45 using JSC::Wasm::Plan; 39 46 40 47 namespace JSC { … … 46 53 EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState*); 47 54 55 static EncodedJSValue reject(ExecState* exec, CatchScope& catchScope, JSPromiseDeferred* promise) 56 { 57 Exception* exception = catchScope.exception(); 58 ASSERT(exception); 59 catchScope.clearException(); 60 promise->reject(exec, exception->value()); 61 return JSValue::encode(promise->promise()); 62 } 63 48 64 EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec) 65 { 66 VM& vm = exec->vm(); 67 auto scope = DECLARE_CATCH_SCOPE(vm); 68 auto* globalObject = exec->lexicalGlobalObject(); 69 70 JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject); 71 RETURN_IF_EXCEPTION(scope, { }); 72 73 RefPtr<ArrayBuffer> source = createSourceBufferFromValue(vm, exec, exec->argument(0)); 74 RETURN_IF_EXCEPTION(scope, { }); 75 76 Vector<Strong<JSCell>> dependencies; 77 dependencies.append(Strong<JSCell>(vm, globalObject)); 78 vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies)); 79 80 Ref<Plan> plan = adoptRef(*new Plan(vm, *source, Plan::Validation, [source, promise, globalObject] (Plan& p) mutable { 81 RefPtr<Plan> plan = makeRef(p); 82 plan->vm().promiseDeferredTimer->scheduleWorkSoon(promise, [source, promise, globalObject, plan = WTFMove(plan)] () mutable { 83 VM& vm = plan->vm(); 84 auto scope = DECLARE_CATCH_SCOPE(vm); 85 ExecState* exec = globalObject->globalExec(); 86 JSValue module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(source), WTFMove(plan)); 87 if (scope.exception()) { 88 reject(exec, scope, promise); 89 return; 90 } 91 92 promise->resolve(exec, module); 93 }); 94 })); 95 96 Wasm::ensureWorklist().enqueue(WTFMove(plan)); 97 return JSValue::encode(promise->promise()); 98 } 99 100 enum class Resolve { WithInstance, WithModuleAndInstance }; 101 static void resolve(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAssemblyInstance* instance, JSWebAssemblyModule* module, Resolve entries) 102 { 103 auto scope = DECLARE_CATCH_SCOPE(vm); 104 instance->finalizeCreation(vm, exec); 105 if (scope.exception()) { 106 reject(exec, scope, promise); 107 return; 108 } 109 110 if (entries == Resolve::WithInstance) 111 promise->resolve(exec, instance); 112 else { 113 JSObject* result = constructEmptyObject(exec); 114 result->putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("module")), module); 115 result->putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("instance")), instance); 116 promise->resolve(exec, result); 117 } 118 } 119 120 static void instantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAssemblyModule* module, JSObject* importObject, Resolve entries) 121 { 122 auto scope = DECLARE_CATCH_SCOPE(vm); 123 // In order to avoid potentially recompiling a module. We first gather all the import/memory information prior to compiling code. 124 JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, exec->lexicalGlobalObject()->WebAssemblyInstanceStructure()); 125 if (scope.exception()) { 126 reject(exec, scope, promise); 127 return; 128 } 129 130 // There are three possible cases: 131 // 1) The instance already has an initialized CodeBlock, so we have no more work to do. 132 // 2) The instance has no CodeBlock, so we need to make one and compile the code for it. 133 // 3) The instance already has an uninitialized CodeBlock, so someone else is compiling code and we just need to wait for them. 134 135 if (instance->initialized()) { 136 resolve(vm, exec, promise, instance, module, entries); 137 return; 138 } 139 140 Vector<Strong<JSCell>> dependencies; 141 // The instance keeps the module alive. 142 dependencies.append(Strong<JSCell>(vm, instance)); 143 vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies)); 144 145 if (instance->codeBlock()) { 146 vm.promiseDeferredTimer->scheduleBlockedTask(instance->codeBlock()->plan().pendingPromise(), [&vm, promise, instance, module, entries] () { 147 auto* globalObject = instance->globalObject(); 148 ExecState* exec = globalObject->globalExec(); 149 resolve(vm, exec, promise, instance, module, entries); 150 }); 151 return; 152 } 153 ASSERT(!instance->codeBlock()); 154 155 // FIXME: This re-parses the module header, which shouldn't be necessary. 156 // https://bugs.webkit.org/show_bug.cgi?id=170205 157 Ref<Plan> plan = adoptRef(*new Plan(vm, module->source(), Plan::FullCompile, [promise, instance, module, entries] (Plan& p) { 158 RefPtr<Plan> plan = makeRef(p); 159 plan->vm().promiseDeferredTimer->scheduleWorkSoon(promise, [promise, instance, module, entries, plan = WTFMove(plan)] () { 160 VM& vm = plan->vm(); 161 ExecState* exec = instance->globalObject()->globalExec(); 162 resolve(vm, exec, promise, instance, module, entries); 163 }); 164 })); 165 166 instance->addUnitializedCodeBlock(vm, plan.copyRef()); 167 plan->setModeAndPromise(instance->memoryMode(), promise); 168 Wasm::ensureWorklist().enqueue(WTFMove(plan)); 169 } 170 171 static void compileAndInstantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSValue buffer, JSObject* importObject) 172 { 173 auto scope = DECLARE_THROW_SCOPE(vm); 174 RefPtr<ArrayBuffer> source = createSourceBufferFromValue(vm, exec, buffer); 175 RETURN_IF_EXCEPTION(scope, void()); 176 177 auto* globalObject = exec->lexicalGlobalObject(); 178 179 Vector<Strong<JSCell>> dependencies; 180 dependencies.append(Strong<JSCell>(vm, importObject)); 181 vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies)); 182 183 Ref<Plan> plan = adoptRef(*new Plan(vm, *source, Plan::Validation, [source, promise, importObject, globalObject] (Plan& p) mutable { 184 RefPtr<Plan> plan = makeRef(p); 185 plan->vm().promiseDeferredTimer->scheduleWorkSoon(promise, [source, promise, importObject, globalObject, plan = WTFMove(plan)] () mutable { 186 VM& vm = plan->vm(); 187 auto scope = DECLARE_CATCH_SCOPE(vm); 188 ExecState* exec = globalObject->globalExec(); 189 JSWebAssemblyModule* module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(source), plan.copyRef()); 190 if (scope.exception()) { 191 reject(exec, scope, promise); 192 return; 193 } 194 195 instantiate(vm, exec, promise, module, importObject, Resolve::WithModuleAndInstance); 196 }); 197 })); 198 199 Wasm::ensureWorklist().enqueue(WTFMove(plan)); 200 } 201 202 EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState* exec) 49 203 { 50 204 VM& vm = exec->vm(); … … 53 207 JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, exec->lexicalGlobalObject()); 54 208 RETURN_IF_EXCEPTION(catchScope, encodedJSValue()); 55 56 // FIXME: Make this truly asynchronous:57 // https://bugs.webkit.org/show_bug.cgi?id=16601658 JSValue module = WebAssemblyModuleConstructor::createModule(exec, exec->argument(0), exec->lexicalGlobalObject()->WebAssemblyModuleStructure());59 if (Exception* exception = catchScope.exception()) {60 catchScope.clearException();61 promise->reject(exec, exception->value());62 return JSValue::encode(promise->promise());63 }64 65 promise->resolve(exec, module);66 return JSValue::encode(promise->promise());67 }68 69 EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState* exec)70 {71 VM& vm = exec->vm();72 auto catchScope = DECLARE_CATCH_SCOPE(vm);73 74 // FIXME: Make this API truly asynchronous: https://bugs.webkit.org/show_bug.cgi?id=16918775 76 JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, exec->lexicalGlobalObject());77 RETURN_IF_EXCEPTION(catchScope, encodedJSValue());78 79 auto reject = [&] () {80 Exception* exception = catchScope.exception();81 ASSERT(exception);82 catchScope.clearException();83 promise->reject(exec, exception->value());84 return JSValue::encode(promise->promise());85 };86 209 87 210 JSValue importArgument = exec->argument(1); … … 94 217 95 218 JSValue firstArgument = exec->argument(0); 96 JSValue module; 97 bool firstArgumentIsModule = false; 98 if (firstArgument.inherits(vm, JSWebAssemblyModule::info())) { 99 firstArgumentIsModule = true; 100 module = firstArgument; 101 } else { 102 module = WebAssemblyModuleConstructor::createModule(exec, firstArgument, exec->lexicalGlobalObject()->WebAssemblyModuleStructure()); 103 if (catchScope.exception()) 104 return reject(); 105 } 106 107 JSWebAssemblyInstance* instance = WebAssemblyInstanceConstructor::createInstance(exec, jsCast<JSWebAssemblyModule*>(module), importObject, exec->lexicalGlobalObject()->WebAssemblyInstanceStructure()); 108 if (catchScope.exception()) 109 return reject(); 110 111 if (firstArgumentIsModule) 112 promise->resolve(exec, instance); 113 else { 114 JSObject* result = constructEmptyObject(exec); 115 result->putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("module")), module); 116 result->putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("instance")), instance); 117 promise->resolve(exec, result); 118 } 219 if (auto* module = jsDynamicCast<JSWebAssemblyModule*>(vm, firstArgument)) 220 instantiate(vm, exec, promise, module, importObject, Resolve::WithInstance); 221 else 222 compileAndInstantiate(vm, exec, promise, firstArgument, importObject); 119 223 120 224 return JSValue::encode(promise->promise()); … … 130 234 uint8_t* base = getWasmBufferFromValue(exec, exec->argument(0), byteOffset, byteSize); 131 235 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 132 Wasm::Plan plan( &vm, base + byteOffset, byteSize);236 Wasm::Plan plan(vm, base + byteOffset, byteSize, Plan::Validation, Plan::dontFinalize); 133 237 // FIXME: We might want to throw an OOM exception here if we detect that something will OOM. 134 238 // https://bugs.webkit.org/show_bug.cgi?id=166015 -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
r214498 r214504 158 158 } while (0) 159 159 160 B3IRGenerator(VM&, const ModuleInformation&, Procedure&, WasmInternalFunction*, Vector<UnlinkedWasmToWasmCall>& );160 B3IRGenerator(VM&, const ModuleInformation&, Procedure&, WasmInternalFunction*, Vector<UnlinkedWasmToWasmCall>&, MemoryMode); 161 161 162 162 PartialResult WARN_UNUSED_RETURN addArguments(const Signature*); … … 226 226 VM& m_vm; 227 227 const ModuleInformation& m_info; 228 MemoryMode m_mode; 228 229 Procedure& m_proc; 229 230 BasicBlock* m_currentBlock; … … 291 292 } 292 293 293 B3IRGenerator::B3IRGenerator(VM& vm, const ModuleInformation& info, Procedure& procedure, WasmInternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls )294 B3IRGenerator::B3IRGenerator(VM& vm, const ModuleInformation& info, Procedure& procedure, WasmInternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, MemoryMode mode) 294 295 : m_vm(vm) 295 296 , m_info(info) 297 , m_mode(mode) 296 298 , m_proc(procedure) 297 299 , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls) … … 521 523 { 522 524 ASSERT(m_memoryBaseGPR); 523 if (m_ info.memory.mode()== MemoryMode::BoundsChecking) {525 if (m_mode == MemoryMode::BoundsChecking) { 524 526 ASSERT(m_memorySizeGPR); 525 527 ASSERT(sizeOfOperation + offset > offset); … … 557 559 inline B3::Kind B3IRGenerator::memoryKind(B3::Opcode memoryOp) 558 560 { 559 if (m_ info.memory.mode()== MemoryMode::Signaling)561 if (m_mode == MemoryMode::Signaling) 560 562 return trapping(memoryOp); 561 563 return memoryOp; … … 1278 1280 } 1279 1281 1280 Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM& vm, CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ModuleInformation& info, const Vector<SignatureIndex>& moduleSignatureIndicesToUniquedSignatureIndices, unsigned optLevel)1282 Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM& vm, CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ModuleInformation& info, const Vector<SignatureIndex>& moduleSignatureIndicesToUniquedSignatureIndices, MemoryMode mode, unsigned optLevel) 1281 1283 { 1282 1284 auto result = std::make_unique<WasmInternalFunction>(); … … 1286 1288 1287 1289 Procedure procedure; 1288 B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls );1290 B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls, mode); 1289 1291 FunctionParser<B3IRGenerator> parser(&vm, context, functionStart, functionLength, signature, info, moduleSignatureIndicesToUniquedSignatureIndices); 1290 1292 WASM_FAIL_IF_HELPER_FAILS(parser.parse()); -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.h
r210229 r214504 32 32 #include "VM.h" 33 33 #include "WasmFormat.h" 34 #include "WasmMemory.h" 34 35 #include <wtf/Expected.h> 35 36 … … 48 49 }; 49 50 50 Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM&, CompilationContext&, const uint8_t*, size_t, const Signature*, Vector<UnlinkedWasmToWasmCall>&, const ModuleInformation&, const Vector<SignatureIndex>&, unsigned optLevel = 1);51 Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM&, CompilationContext&, const uint8_t*, size_t, const Signature*, Vector<UnlinkedWasmToWasmCall>&, const ModuleInformation&, const Vector<SignatureIndex>&, MemoryMode, unsigned optLevel = 1); 51 52 52 53 } } // namespace JSC::Wasm -
trunk/Source/JavaScriptCore/wasm/WasmFormat.h
r214484 r214504 103 103 104 104 struct Import { 105 Identifiermodule;106 Identifierfield;105 String module; 106 String field; 107 107 ExternalKind kind; 108 108 unsigned kindIndex; // Index in the vector of the corresponding kind. … … 110 110 111 111 struct Export { 112 Identifierfield;112 String field; 113 113 ExternalKind kind; 114 114 unsigned kindIndex; // Index in the vector of the corresponding kind. … … 261 261 262 262 uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); } 263 uint32_t internalFunctionCount() const { return internalFunctionSignatureIndices.size(); } 263 264 264 265 ~ModuleInformation(); -
trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h
r213067 r214504 116 116 WASM_PARSER_FAIL_IF(numberOfLocals == std::numeric_limits<uint32_t>::max(), "Function section's ", i, "th local group count is too big ", numberOfLocals); 117 117 WASM_PARSER_FAIL_IF(!parseValueType(typeOfLocal), "can't get Function local's type in group ", i); 118 WASM_ PARSER_FAIL_IF(!m_context.addLocal(typeOfLocal, numberOfLocals), "can't add ", numberOfLocals, " Function locals from group ", i);118 WASM_TRY_ADD_TO_CONTEXT(addLocal(typeOfLocal, numberOfLocals)); 119 119 } 120 120 … … 268 268 ExpressionType result; 269 269 WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get index for get_local"); 270 WASM_ PARSER_FAIL_IF(!m_context.getLocal(index, result), "can't get_local at index", index);270 WASM_TRY_ADD_TO_CONTEXT(getLocal(index, result)); 271 271 m_expressionStack.append(result); 272 272 return { }; … … 305 305 WASM_TRY_POP_EXPRESSION_STACK_INTO(value, "set_global value"); 306 306 WASM_TRY_ADD_TO_CONTEXT(setGlobal(index, value)); 307 return m_context.setGlobal(index, value);307 return { }; 308 308 } 309 309 -
trunk/Source/JavaScriptCore/wasm/WasmMemory.h
r214380 r214504 46 46 47 47 // FIXME: We should support other modes. see: https://bugs.webkit.org/show_bug.cgi?id=162693 48 enum class MemoryMode {48 enum class MemoryMode : uint8_t { 49 49 BoundsChecking, 50 50 Signaling, -
trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp
r214498 r214504 89 89 } 90 90 91 MemoryInformation::MemoryInformation( VM& vm, PageCount initial, PageCount maximum, std::optional<MemoryMode> recompileMode, bool isImport)91 MemoryInformation::MemoryInformation(PageCount initial, PageCount maximum, bool isImport) 92 92 : m_initial(initial) 93 93 , m_maximum(maximum) … … 97 97 RELEASE_ASSERT(!m_maximum || m_maximum >= m_initial); 98 98 ASSERT(!!*this); 99 100 if (!recompileMode) {101 if (!isImport) {102 if (maximum && maximum.bytes() == 0) {103 m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::BoundsChecking);104 RELEASE_ASSERT(m_reservedMemory);105 RELEASE_ASSERT(m_reservedMemory->maximum());106 RELEASE_ASSERT(m_reservedMemory->maximum().bytes() == 0);107 m_mode = m_reservedMemory->mode();108 return;109 }110 111 m_reservedMemory = Memory::create(vm, initial, maximum, MemoryMode::Signaling);112 if (m_reservedMemory) {113 ASSERT(!!*m_reservedMemory);114 m_mode = m_reservedMemory->mode();115 return;116 }117 }118 m_mode = Memory::lastAllocatedMode();119 } else120 m_mode = *recompileMode;121 99 } 122 100 -
trunk/Source/JavaScriptCore/wasm/WasmMemoryInformation.h
r214498 r214504 68 68 } 69 69 70 MemoryInformation( VM&, PageCount initial, PageCount maximum, std::optional<MemoryMode>, bool isImport);70 MemoryInformation(PageCount initial, PageCount maximum, bool isImport); 71 71 72 72 PageCount initial() const { return m_initial; } 73 73 PageCount maximum() const { return m_maximum; } 74 bool hasReservedMemory() const { return m_reservedMemory; }75 RefPtr<Memory> takeReservedMemory() { ASSERT(hasReservedMemory()); return m_reservedMemory.release(); }76 MemoryMode mode() const { return m_mode; }77 74 bool isImport() const { return m_isImport; } 78 75 … … 80 77 81 78 private: 82 RefPtr<Memory> m_reservedMemory;83 79 PageCount m_initial { }; 84 80 PageCount m_maximum { }; 85 MemoryMode m_mode { MemoryMode::BoundsChecking };86 81 bool m_isImport { false }; 87 82 }; -
trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp
r213465 r214504 163 163 WASM_PARSER_FAIL_IF(!parseVarUInt32(moduleLen), "can't get ", importNumber, "th Import's module name length"); 164 164 WASM_PARSER_FAIL_IF(!consumeUTF8String(moduleString, moduleLen), "can't get ", importNumber, "th Import's module name of length ", moduleLen); 165 imp.module = Identifier::fromString(m_vm, moduleString);165 imp.module = moduleString; 166 166 167 167 WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", importNumber, "th Import's field name length in module '", moduleString, "'"); 168 168 WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", importNumber, "th Import's field name of length ", moduleLen, " in module '", moduleString, "'"); 169 imp.field = Identifier::fromString(m_vm, fieldString);169 imp.field = fieldString; 170 170 171 171 WASM_PARSER_FAIL_IF(!parseExternalKind(imp.kind), "can't get ", importNumber, "th Import's kind in module '", moduleString, "' field '", fieldString, "'"); … … 317 317 ASSERT(!maximumPageCount || maximumPageCount >= initialPageCount); 318 318 319 m_result.module->memory = MemoryInformation( *m_vm, initialPageCount, maximumPageCount, m_mode, isImport);319 m_result.module->memory = MemoryInformation(initialPageCount, maximumPageCount, isImport); 320 320 return { }; 321 321 } … … 377 377 WASM_PARSER_FAIL_IF(exportNames.contains(fieldString), "duplicate export: '", fieldString, "'"); 378 378 exportNames.add(fieldString); 379 exp.field = Identifier::fromString(m_vm, fieldString);379 exp.field = fieldString; 380 380 381 381 WASM_PARSER_FAIL_IF(!parseExternalKind(exp.kind), "can't get ", exportNumber, "th Export's kind, named '", fieldString, "'"); -
trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h
r214380 r214504 45 45 public: 46 46 47 ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength, std::optional<MemoryMode> mode) 47 48 ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength) 48 49 : Parser(vm, sourceBuffer, sourceLength) 49 , m_mode(mode)50 50 { 51 51 } … … 67 67 68 68 ModuleParserResult m_result; 69 std::optional<MemoryMode> m_mode { std::nullopt };70 69 bool m_hasTable { false }; 71 70 }; -
trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp
r214380 r214504 43 43 #include <wtf/Locker.h> 44 44 #include <wtf/MonotonicTime.h> 45 #include <wtf/NumberOfCores.h>46 45 #include <wtf/StdLibExtras.h> 47 46 #include <wtf/SystemTracing.h> … … 51 50 52 51 static const bool verbose = false; 53 54 Plan::Plan(VM* vm, Vector<uint8_t> source) 55 : Plan(vm, source.data(), source.size()) 56 { 57 } 58 59 Plan::Plan(VM* vm, const uint8_t* source, size_t sourceLength) 52 53 Plan::Plan(VM& vm, ArrayBuffer& source, AsyncWork work, CompletionTask&& task) 54 : Plan(vm, reinterpret_cast<uint8_t*>(source.data()), source.byteLength(), work, WTFMove(task)) 55 { 56 } 57 58 Plan::Plan(VM& vm, Vector<uint8_t>& source, AsyncWork work, CompletionTask&& task) 59 : Plan(vm, source.data(), source.size(), work, WTFMove(task)) 60 { 61 } 62 63 Plan::Plan(VM& vm, const uint8_t* source, size_t sourceLength, AsyncWork work, CompletionTask&& task) 60 64 : m_vm(vm) 65 , m_completionTask(task) 61 66 , m_source(source) 62 67 , m_sourceLength(sourceLength) 63 { 64 } 65 66 bool Plan::parseAndValidateModule(std::optional<MemoryMode> recompileMode) 67 { 68 , m_asyncWork(work) 69 { 70 } 71 72 const char* Plan::stateString(State state) 73 { 74 switch (state) { 75 case State::Initial: return "Initial"; 76 case State::Validated: return "Validated"; 77 case State::Prepared: return "Prepared"; 78 case State::Compiled: return "Compiled"; 79 case State::Completed: return "Completed"; 80 } 81 RELEASE_ASSERT_NOT_REACHED(); 82 } 83 84 void Plan::moveToState(State state) 85 { 86 ASSERT(state > m_state); 87 dataLogLnIf(verbose, "moving to state: ", stateString(state), " from state: ", stateString(m_state)); 88 m_state = state; 89 } 90 91 void Plan::fail(const AbstractLocker& locker, String&& errorMessage) 92 { 93 dataLogLnIf(verbose, "failing with message: ", errorMessage); 94 m_errorMessage = WTFMove(errorMessage); 95 complete(locker); 96 } 97 98 bool Plan::parseAndValidateModule() 99 { 100 ASSERT(m_state == State::Initial); 101 dataLogLnIf(verbose, "starting validation"); 68 102 MonotonicTime startTime; 69 103 if (verbose || Options::reportCompileTimes()) … … 71 105 72 106 { 73 ModuleParser moduleParser( m_vm, m_source, m_sourceLength, recompileMode);107 ModuleParser moduleParser(&m_vm, m_source, m_sourceLength); 74 108 auto parseResult = moduleParser.parse(); 75 109 if (!parseResult) { 76 m_errorMessage = parseResult.error();110 fail(holdLock(m_lock), WTFMove(parseResult.error())); 77 111 return false; 78 112 } … … 83 117 84 118 for (unsigned functionIndex = 0; functionIndex < m_functionLocationInBinary.size(); ++functionIndex) { 85 if (verbose) 86 dataLogLn("Processing function starting at: ", m_functionLocationInBinary[functionIndex].start, " and ending at: ", m_functionLocationInBinary[functionIndex].end); 119 dataLogLnIf(verbose, "Processing function starting at: ", m_functionLocationInBinary[functionIndex].start, " and ending at: ", m_functionLocationInBinary[functionIndex].end); 87 120 const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start; 88 121 size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start; 89 122 ASSERT(functionLength <= m_sourceLength); 90 123 SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex]; 91 const Signature* signature = SignatureInformation::get( m_vm, signatureIndex);92 93 auto validationResult = validateFunction( m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices);124 const Signature* signature = SignatureInformation::get(&m_vm, signatureIndex); 125 126 auto validationResult = validateFunction(&m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices); 94 127 if (!validationResult) { 95 128 if (verbose) { … … 98 131 dataLogLn(); 99 132 } 100 m_errorMessage = makeString(validationResult.error(), ", in function at index ", String::number(functionIndex)); // FIXME make this an Expected.133 fail(holdLock(m_lock), makeString(validationResult.error(), ", in function at index ", String::number(functionIndex))); // FIXME make this an Expected. 101 134 return false; 102 135 } … … 105 138 if (verbose || Options::reportCompileTimes()) 106 139 dataLogLn("Took ", (MonotonicTime::now() - startTime).microseconds(), " us to validate module"); 140 if (m_asyncWork == Validation) 141 complete(holdLock(m_lock)); 142 else 143 moveToState(State::Validated); 107 144 return true; 108 145 } 109 146 110 // We are creating a bunch of threads that touch the main thread's stack. This will make ASAN unhappy. 111 // The reason this is OK is that we guarantee that the main thread doesn't continue until all threads 112 // that could touch its stack are done executing. 113 SUPPRESS_ASAN 114 void Plan::run(std::optional<MemoryMode> recompileMode) 115 { 116 if (!parseAndValidateModule(recompileMode)) 117 return; 147 void Plan::prepare() 148 { 149 ASSERT(m_state == State::Validated); 150 dataLogLnIf(verbose, "Starting preparation"); 118 151 119 152 TraceScope traceScope(WebAssemblyCompileStart, WebAssemblyCompileEnd); 120 121 if (recompileMode)122 ASSERT(m_moduleInformation->memory.mode() == recompileMode);123 153 124 154 auto tryReserveCapacity = [this] (auto& vector, size_t size, const char* what) { … … 128 158 builder.appendNumber(size); 129 159 builder.append(what); 130 m_errorMessage = builder.toString();160 fail(holdLock(m_lock), builder.toString()); 131 161 return false; 132 162 } … … 149 179 continue; 150 180 unsigned importFunctionIndex = m_wasmExitStubs.size(); 151 if (verbose) 152 dataLogLn("Processing import function number ", importFunctionIndex, ": ", import->module, ": ", import->field); 181 dataLogLnIf(verbose, "Processing import function number ", importFunctionIndex, ": ", import->module, ": ", import->field); 153 182 SignatureIndex signatureIndex = m_moduleInformation->importFunctionSignatureIndices.at(import->kindIndex); 154 m_wasmExitStubs.uncheckedAppend(exitStubGenerator(m_vm, m_callLinkInfos, signatureIndex, importFunctionIndex)); 155 } 156 157 m_currentIndex = 0; 158 159 auto doWork = [this] { 160 while (true) { 161 uint32_t functionIndex; 183 m_wasmExitStubs.uncheckedAppend(exitStubGenerator(&m_vm, m_callLinkInfos, signatureIndex, importFunctionIndex)); 184 } 185 186 moveToState(State::Prepared); 187 } 188 189 // We don't have a semaphore class... and this does kinda interesting things. 190 class Plan::ThreadCountHolder { 191 public: 192 ThreadCountHolder(Plan& plan) 193 : m_plan(plan) 194 { 195 LockHolder locker(m_plan.m_lock); 196 m_plan.m_numberOfActiveThreads++; 197 } 198 199 ~ThreadCountHolder() 200 { 201 LockHolder locker(m_plan.m_lock); 202 m_plan.m_numberOfActiveThreads--; 203 204 if (!m_plan.m_numberOfActiveThreads) 205 m_plan.complete(locker); 206 } 207 208 Plan& m_plan; 209 }; 210 211 void Plan::compileFunctions() 212 { 213 ASSERT(m_state >= State::Prepared); 214 dataLogLnIf(verbose, "Starting compilation"); 215 216 if (m_state >= State::Compiled) 217 return; 218 ThreadCountHolder holder(*this); 219 while (true) { 220 uint32_t functionIndex; 221 { 222 auto locker = holdLock(m_lock); 223 if (m_currentIndex >= m_functionLocationInBinary.size()) 224 return; 225 functionIndex = m_currentIndex; 226 ++m_currentIndex; 227 if (m_currentIndex == m_functionLocationInBinary.size()) 228 moveToState(State::Compiled); 229 } 230 231 const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start; 232 size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start; 233 ASSERT(functionLength <= m_sourceLength); 234 SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex]; 235 const Signature* signature = SignatureInformation::get(&m_vm, signatureIndex); 236 unsigned functionIndexSpace = m_wasmExitStubs.size() + functionIndex; 237 ASSERT_UNUSED(functionIndexSpace, m_moduleInformation->signatureIndexFromFunctionIndexSpace(functionIndexSpace) == signatureIndex); 238 ASSERT(validateFunction(&m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices)); 239 240 m_unlinkedWasmToWasmCalls[functionIndex] = Vector<UnlinkedWasmToWasmCall>(); 241 auto parseAndCompileResult = parseAndCompile(m_vm, m_compilationContexts[functionIndex], functionStart, functionLength, signature, m_unlinkedWasmToWasmCalls[functionIndex], *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices, m_mode); 242 243 if (UNLIKELY(!parseAndCompileResult)) { 244 auto locker = holdLock(m_lock); 245 if (!m_errorMessage) { 246 // Multiple compiles could fail simultaneously. We arbitrarily choose the first. 247 fail(locker, makeString(parseAndCompileResult.error(), ", in function at index ", String::number(functionIndex))); // FIXME make this an Expected. 248 } 249 m_currentIndex = m_functionLocationInBinary.size(); 250 return; 251 } 252 253 m_wasmInternalFunctions[functionIndex] = WTFMove(*parseAndCompileResult); 254 } 255 } 256 257 void Plan::complete(const AbstractLocker&) 258 { 259 ASSERT(m_state != State::Compiled || m_currentIndex >= m_functionLocationInBinary.size()); 260 dataLogLnIf(verbose, "Starting Completion"); 261 262 if (m_state == State::Compiled) { 263 for (uint32_t functionIndex = 0; functionIndex < m_functionLocationInBinary.size(); functionIndex++) { 162 264 { 163 auto locker = holdLock(m_lock); 164 if (m_currentIndex >= m_functionLocationInBinary.size()) 165 return; 166 functionIndex = m_currentIndex; 167 ++m_currentIndex; 265 CompilationContext& context = m_compilationContexts[functionIndex]; 266 SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex]; 267 String signatureDescription = SignatureInformation::get(&m_vm, signatureIndex)->toString(); 268 { 269 LinkBuffer linkBuffer(m_vm, *context.wasmEntrypointJIT, nullptr); 270 m_wasmInternalFunctions[functionIndex]->wasmEntrypoint.compilation = 271 std::make_unique<B3::Compilation>(FINALIZE_CODE(linkBuffer, ("WebAssembly function[%i] %s", functionIndex, signatureDescription.ascii().data())), WTFMove(context.wasmEntrypointByproducts)); 272 } 273 274 { 275 LinkBuffer linkBuffer(m_vm, *context.jsEntrypointJIT, nullptr); 276 linkBuffer.link(context.jsEntrypointToWasmEntrypointCall, FunctionPtr(m_wasmInternalFunctions[functionIndex]->wasmEntrypoint.compilation->code().executableAddress())); 277 278 m_wasmInternalFunctions[functionIndex]->jsToWasmEntrypoint.compilation = 279 std::make_unique<B3::Compilation>(FINALIZE_CODE(linkBuffer, ("JavaScript->WebAssembly entrypoint[%i] %s", functionIndex, signatureDescription.ascii().data())), WTFMove(context.jsEntrypointByproducts)); 280 } 168 281 } 169 282 170 const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start; 171 size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start; 172 ASSERT(functionLength <= m_sourceLength); 173 SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex]; 174 const Signature* signature = SignatureInformation::get(m_vm, signatureIndex); 175 unsigned functionIndexSpace = m_wasmExitStubs.size() + functionIndex; 176 ASSERT_UNUSED(functionIndexSpace, m_moduleInformation->signatureIndexFromFunctionIndexSpace(functionIndexSpace) == signatureIndex); 177 ASSERT(validateFunction(m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices)); 178 179 m_unlinkedWasmToWasmCalls[functionIndex] = Vector<UnlinkedWasmToWasmCall>(); 180 auto parseAndCompileResult = parseAndCompile(*m_vm, m_compilationContexts[functionIndex], functionStart, functionLength, signature, m_unlinkedWasmToWasmCalls[functionIndex], *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices); 181 182 if (UNLIKELY(!parseAndCompileResult)) { 183 auto locker = holdLock(m_lock); 184 if (!m_errorMessage) { 185 // Multiple compiles could fail simultaneously. We arbitrarily choose the first. 186 m_errorMessage = makeString(parseAndCompileResult.error(), ", in function at index ", String::number(functionIndex)); // FIXME make this an Expected. 187 } 188 m_currentIndex = m_functionLocationInBinary.size(); 189 190 // We will terminate on the next execution. 191 continue; 192 } 193 194 m_wasmInternalFunctions[functionIndex] = WTFMove(*parseAndCompileResult); 195 } 196 }; 197 198 MonotonicTime startTime; 199 if (verbose || Options::reportCompileTimes()) 200 startTime = MonotonicTime::now(); 201 202 uint32_t threadCount = Options::useConcurrentJIT() ? WTF::numberOfProcessorCores() : 1; 203 uint32_t numWorkerThreads = threadCount - 1; 204 Vector<ThreadIdentifier> threads; 205 threads.reserveCapacity(numWorkerThreads); 206 for (uint32_t i = 0; i < numWorkerThreads; i++) 207 threads.uncheckedAppend(createThread("jsc.wasm-b3-compilation.thread", doWork)); 208 209 doWork(); // Let the main thread do some work too. 210 211 for (uint32_t i = 0; i < numWorkerThreads; i++) 212 waitForThreadCompletion(threads[i]); 213 214 for (uint32_t functionIndex = 0; functionIndex < m_functionLocationInBinary.size(); functionIndex++) { 215 { 216 CompilationContext& context = m_compilationContexts[functionIndex]; 217 SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex]; 218 String signatureDescription = SignatureInformation::get(m_vm, signatureIndex)->toString(); 219 { 220 LinkBuffer linkBuffer(*m_vm, *context.wasmEntrypointJIT, nullptr); 221 m_wasmInternalFunctions[functionIndex]->wasmEntrypoint.compilation = 222 std::make_unique<B3::Compilation>(FINALIZE_CODE(linkBuffer, ("WebAssembly function[%i] %s", functionIndex, signatureDescription.ascii().data())), WTFMove(context.wasmEntrypointByproducts)); 223 } 224 225 { 226 LinkBuffer linkBuffer(*m_vm, *context.jsEntrypointJIT, nullptr); 227 linkBuffer.link(context.jsEntrypointToWasmEntrypointCall, FunctionPtr(m_wasmInternalFunctions[functionIndex]->wasmEntrypoint.compilation->code().executableAddress())); 228 229 m_wasmInternalFunctions[functionIndex]->jsToWasmEntrypoint.compilation = 230 std::make_unique<B3::Compilation>(FINALIZE_CODE(linkBuffer, ("JavaScript->WebAssembly entrypoint[%i] %s", functionIndex, signatureDescription.ascii().data())), WTFMove(context.jsEntrypointByproducts)); 231 } 232 } 233 } 234 235 if (verbose || Options::reportCompileTimes()) { 236 dataLogLn("Took ", (MonotonicTime::now() - startTime).microseconds(), 237 " us to compile and link the module"); 238 } 239 240 // Patch the call sites for each WebAssembly function. 241 for (auto& unlinked : m_unlinkedWasmToWasmCalls) { 242 for (auto& call : unlinked) { 243 void* executableAddress; 244 if (m_moduleInformation->isImportedFunctionFromFunctionIndexSpace(call.functionIndex)) { 245 // 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 246 executableAddress = call.target == UnlinkedWasmToWasmCall::Target::ToJs 283 } 284 285 for (auto& unlinked : m_unlinkedWasmToWasmCalls) { 286 for (auto& call : unlinked) { 287 void* executableAddress; 288 if (m_moduleInformation->isImportedFunctionFromFunctionIndexSpace(call.functionIndex)) { 289 // 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 290 executableAddress = call.target == UnlinkedWasmToWasmCall::Target::ToJs 247 291 ? m_wasmExitStubs.at(call.functionIndex).wasmToJs.code().executableAddress() 248 292 : m_wasmExitStubs.at(call.functionIndex).wasmToWasm.code().executableAddress(); 249 } else { 250 ASSERT(call.target != UnlinkedWasmToWasmCall::Target::ToJs); 251 executableAddress = m_wasmInternalFunctions.at(call.functionIndex - m_wasmExitStubs.size())->wasmEntrypoint.compilation->code().executableAddress(); 293 } else { 294 ASSERT(call.target != UnlinkedWasmToWasmCall::Target::ToJs); 295 executableAddress = m_wasmInternalFunctions.at(call.functionIndex - m_wasmExitStubs.size())->wasmEntrypoint.compilation->code().executableAddress(); 296 } 297 MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(executableAddress)); 252 298 } 253 MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(executableAddress)); 254 } 255 } 256 257 m_failed = false; 258 } 259 260 void Plan::initializeCallees(JSGlobalObject* globalObject, std::function<void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)> callback) 261 { 262 ASSERT(!failed()); 263 for (unsigned internalFunctionIndex = 0; internalFunctionIndex < m_wasmInternalFunctions.size(); ++internalFunctionIndex) { 264 WasmInternalFunction* function = m_wasmInternalFunctions[internalFunctionIndex].get(); 265 266 JSWebAssemblyCallee* jsEntrypointCallee = JSWebAssemblyCallee::create(globalObject->vm(), WTFMove(function->jsToWasmEntrypoint)); 267 MacroAssembler::repatchPointer(function->jsToWasmCalleeMoveLocation, jsEntrypointCallee); 268 269 JSWebAssemblyCallee* wasmEntrypointCallee = JSWebAssemblyCallee::create(globalObject->vm(), WTFMove(function->wasmEntrypoint)); 270 MacroAssembler::repatchPointer(function->wasmCalleeMoveLocation, wasmEntrypointCallee); 271 272 callback(internalFunctionIndex, jsEntrypointCallee, wasmEntrypointCallee); 299 } 300 } 301 302 if (m_state != State::Completed) { 303 moveToState(State::Completed); 304 m_completionTask(*this); 305 m_completed.notifyAll(); 306 } 307 } 308 309 void Plan::waitForCompletion() 310 { 311 LockHolder locker(m_lock); 312 if (m_state != State::Completed) { 313 // FIXME: We should have a wait conditionally so we don't have to hold the lock to complete / fail. 314 m_completed.wait(m_lock); 315 } 316 } 317 318 void Plan::cancel() 319 { 320 LockHolder locker(m_lock); 321 if (m_state != State::Completed) { 322 m_currentIndex = m_functionLocationInBinary.size(); 323 fail(locker, ASCIILiteral("WebAssembly Plan was canceled. If you see this error message please file a bug at bugs.webkit.org!")); 273 324 } 274 325 } -
trunk/Source/JavaScriptCore/wasm/WasmPlan.h
r214380 r214504 1 1 /* 2 * Copyright (C) 2016 Apple Inc. All rights reserved.2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 41 41 class JSGlobalObject; 42 42 class JSWebAssemblyCallee; 43 class JSPromiseDeferred; 43 44 44 45 namespace Wasm { 45 46 46 class Plan {47 class Plan : public ThreadSafeRefCounted<Plan> { 47 48 public: 48 JS_EXPORT_PRIVATE Plan(VM*, Vector<uint8_t>); 49 JS_EXPORT_PRIVATE Plan(VM*, const uint8_t*, size_t); 49 static void dontFinalize(Plan&) { } 50 typedef std::function<void(Plan&)> CompletionTask; 51 enum AsyncWork : uint8_t { FullCompile, Validation }; 52 // Note: CompletionTask should not hold a reference to the Plan otherwise there will be a reference cycle. 53 Plan(VM&, ArrayBuffer&, AsyncWork, CompletionTask&&); 54 JS_EXPORT_PRIVATE Plan(VM&, Vector<uint8_t>&, AsyncWork, CompletionTask&&); 55 JS_EXPORT_PRIVATE Plan(VM&, const uint8_t*, size_t, AsyncWork, CompletionTask&&); 50 56 JS_EXPORT_PRIVATE ~Plan(); 51 57 52 bool parseAndValidateModule( std::optional<MemoryMode> = std::nullopt);58 bool parseAndValidateModule(); 53 59 54 JS_EXPORT_PRIVATE void run(std::optional<MemoryMode> = std::nullopt); 60 JS_EXPORT_PRIVATE void prepare(); 61 void compileFunctions(); 55 62 56 JS_EXPORT_PRIVATE void initializeCallees(JSGlobalObject*, std::function<void(unsigned, JSWebAssemblyCallee*, JSWebAssemblyCallee*)>); 57 58 bool WARN_UNUSED_RETURN failed() const { return m_failed; } 59 const String& errorMessage() const 60 { 61 RELEASE_ASSERT(failed()); 62 return m_errorMessage; 63 } 63 template<typename Functor> 64 void initializeCallees(const Functor&); 64 65 65 66 Vector<Export>& exports() const 66 67 { 67 RELEASE_ASSERT(!failed() );68 RELEASE_ASSERT(!failed() && !hasWork()); 68 69 return m_moduleInformation->exports; 69 70 } … … 71 72 size_t internalFunctionCount() const 72 73 { 73 RELEASE_ASSERT(!failed() );74 return m_ wasmInternalFunctions.size();74 RELEASE_ASSERT(!failed() && !hasWork()); 75 return m_functionLocationInBinary.size(); 75 76 } 76 77 77 78 std::unique_ptr<ModuleInformation>&& takeModuleInformation() 78 79 { 79 RELEASE_ASSERT(!failed() );80 RELEASE_ASSERT(!failed() && !hasWork()); 80 81 return WTFMove(m_moduleInformation); 81 82 } … … 83 84 Bag<CallLinkInfo>&& takeCallLinkInfos() 84 85 { 85 RELEASE_ASSERT(!failed() );86 RELEASE_ASSERT(!failed() && !hasWork()); 86 87 return WTFMove(m_callLinkInfos); 87 88 } … … 89 90 Vector<WasmExitStubs>&& takeWasmExitStubs() 90 91 { 91 RELEASE_ASSERT(!failed() );92 RELEASE_ASSERT(!failed() && !hasWork()); 92 93 return WTFMove(m_wasmExitStubs); 93 94 } 94 95 95 MemoryMode mode() const { return m_moduleInformation->memory.mode(); } 96 void setModeAndPromise(MemoryMode mode, JSPromiseDeferred* promise) 97 { 98 m_mode = mode; 99 m_pendingPromise = promise; 100 } 101 MemoryMode mode() const { return m_mode; } 102 JSPromiseDeferred* pendingPromise() { return m_pendingPromise; } 103 VM& vm() const { return m_vm; } 104 105 enum class State : uint8_t { 106 Initial, 107 Validated, 108 Prepared, 109 Compiled, 110 Completed // We should only move to Completed if we are holding the lock. 111 }; 112 113 const String& errorMessage() const { return m_errorMessage; } 114 115 bool WARN_UNUSED_RETURN failed() const { return !errorMessage().isNull(); } 116 bool hasWork() const { return m_state < State::Compiled; } 117 bool hasBeenPrepared() const { return m_state >= State::Prepared; } 118 119 void waitForCompletion(); 120 void cancel(); 96 121 97 122 private: 123 class ThreadCountHolder; 124 friend class ThreadCountHolder; 125 126 void complete(const AbstractLocker&); 127 128 void moveToState(State); 129 void fail(const AbstractLocker&, String&& errorMessage); 130 131 const char* stateString(State); 132 98 133 std::unique_ptr<ModuleInformation> m_moduleInformation; 99 134 Vector<FunctionLocationInBinary> m_functionLocationInBinary; … … 104 139 Vector<CompilationContext> m_compilationContexts; 105 140 106 VM* m_vm; 141 VM& m_vm; 142 JSPromiseDeferred* m_pendingPromise { nullptr }; 143 CompletionTask m_completionTask; 144 107 145 Vector<Vector<UnlinkedWasmToWasmCall>> m_unlinkedWasmToWasmCalls; 108 146 const uint8_t* m_source; 109 147 const size_t m_sourceLength; 110 bool m_failed { true };111 148 String m_errorMessage; 112 uint32_t m_currentIndex;149 MemoryMode m_mode { MemoryMode::BoundsChecking }; 113 150 Lock m_lock; 151 Condition m_completed; 152 State m_state { State::Initial }; 153 const AsyncWork m_asyncWork; 154 uint8_t m_numberOfActiveThreads { 0 }; 155 uint32_t m_currentIndex { 0 }; 114 156 }; 157 115 158 116 159 } } // namespace JSC::Wasm -
trunk/Source/JavaScriptCore/wasm/WasmPlanInlines.h
r214502 r214504 1 1 /* 2 * Copyright (C) 201 6Apple Inc. All rights reserved.2 * Copyright (C) 2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "B3Compilation.h" 31 #include "CCallHelpers.h" 32 #include "VM.h" 33 #include "WasmFormat.h" 34 #include <wtf/Expected.h> 35 36 extern "C" void dumpProcedure(void*); 30 #include "JSWebAssemblyCallee.h" 31 #include "WasmPlan.h" 37 32 38 33 namespace JSC { namespace Wasm { 39 34 40 class MemoryInformation; 35 template<typename Functor> 36 void Plan::initializeCallees(const Functor& callback) 37 { 38 ASSERT(!failed()); 39 for (unsigned internalFunctionIndex = 0; internalFunctionIndex < m_wasmInternalFunctions.size(); ++internalFunctionIndex) { 40 WasmInternalFunction* function = m_wasmInternalFunctions[internalFunctionIndex].get(); 41 41 42 struct CompilationContext { 43 std::unique_ptr<CCallHelpers> jsEntrypointJIT; 44 std::unique_ptr<B3::OpaqueByproducts> jsEntrypointByproducts; 45 std::unique_ptr<CCallHelpers> wasmEntrypointJIT; 46 std::unique_ptr<B3::OpaqueByproducts> wasmEntrypointByproducts; 47 CCallHelpers::Call jsEntrypointToWasmEntrypointCall; 48 }; 42 JSWebAssemblyCallee* jsEntrypointCallee = JSWebAssemblyCallee::create(m_vm, WTFMove(function->jsToWasmEntrypoint)); 43 MacroAssembler::repatchPointer(function->jsToWasmCalleeMoveLocation, jsEntrypointCallee); 49 44 50 Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM&, CompilationContext&, const uint8_t*, size_t, const Signature*, Vector<UnlinkedWasmToWasmCall>&, const ModuleInformation&, const Vector<SignatureIndex>&, unsigned optLevel = 1); 45 JSWebAssemblyCallee* wasmEntrypointCallee = JSWebAssemblyCallee::create(m_vm, WTFMove(function->wasmEntrypoint)); 46 MacroAssembler::repatchPointer(function->wasmCalleeMoveLocation, wasmEntrypointCallee); 47 48 callback(internalFunctionIndex, jsEntrypointCallee, wasmEntrypointCallee); 49 } 50 } 51 51 52 52 } } // namespace JSC::Wasm -
trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp
r210229 r214504 272 272 return { }; 273 273 274 WASM_VALIDATOR_FAIL_IF(expressionStack.isEmpty(), "branch to block on empty expression stack");274 WASM_VALIDATOR_FAIL_IF(expressionStack.isEmpty(), target.type() == BlockType::TopLevel ? "branch out of function" : "branch to block", " on empty expression stack, but expected ", target.signature()); 275 275 WASM_VALIDATOR_FAIL_IF(target.signature() != expressionStack.last(), "branch's stack type doesn't match block's type"); 276 276 -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCallee.h
r209696 r214504 61 61 62 62 private: 63 void finishCreation(VM&, Wasm::Entrypoint&&);64 JS WebAssemblyCallee(VM&);63 JS_EXPORT_PRIVATE void finishCreation(VM&, Wasm::Entrypoint&&); 64 JS_EXPORT_PRIVATE JSWebAssemblyCallee(VM&); 65 65 66 66 Wasm::Entrypoint m_entrypoint; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp
r214380 r214504 30 30 31 31 #include "JSCInlines.h" 32 #include "JSWebAssemblyLinkError.h" 32 33 #include "JSWebAssemblyMemory.h" 33 34 #include "JSWebAssemblyModule.h" 35 #include "WasmPlanInlines.h" 34 36 35 37 namespace JSC { … … 37 39 const ClassInfo JSWebAssemblyCodeBlock::s_info = { "WebAssemblyCodeBlock", nullptr, 0, CREATE_METHOD_TABLE(JSWebAssemblyCodeBlock) }; 38 40 39 JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& wasmExitStubs, Wasm::MemoryMode mode, unsigned calleeCount)41 JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock(VM& vm, JSWebAssemblyModule* owner, Wasm::MemoryMode mode, Ref<Wasm::Plan>&& plan, unsigned calleeCount) 40 42 : Base(vm, vm.webAssemblyCodeBlockStructure.get()) 41 , m_callLinkInfos(WTFMove(callLinkInfos)) 42 , m_wasmExitStubs(WTFMove(wasmExitStubs)) 43 , m_plan(WTFMove(plan)) 43 44 , m_mode(mode) 44 45 , m_calleeCount(calleeCount) 45 46 { 46 47 m_module.set(vm, this, owner); 48 ASSERT(!module()->codeBlock(mode)); 49 module()->setCodeBlock(vm, mode, this); 50 47 51 memset(callees(), 0, m_calleeCount * sizeof(WriteBarrier<JSWebAssemblyCallee>) * 2); 52 } 53 54 void JSWebAssemblyCodeBlock::initialize() 55 { 56 if (initialized()) 57 return; 58 59 VM& vm = plan().vm(); 60 ASSERT(vm.currentThreadIsHoldingAPILock()); 61 RELEASE_ASSERT(!plan().hasWork()); 62 63 if (plan().failed()) { 64 m_errorMessage = plan().errorMessage(); 65 m_plan = nullptr; 66 return; 67 } 68 69 RELEASE_ASSERT(plan().mode() == mode()); 70 ASSERT(plan().internalFunctionCount() == m_calleeCount); 71 72 m_callLinkInfos = plan().takeCallLinkInfos(); 73 m_wasmExitStubs = plan().takeWasmExitStubs(); 74 75 plan().initializeCallees([&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) { 76 setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee); 77 setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee); 78 }); 79 80 m_plan = nullptr; 48 81 } 49 82 … … 53 86 } 54 87 55 bool JSWebAssemblyCodeBlock::isSafeToRun(JSWebAssemblyMemory* memory) 88 bool JSWebAssemblyCodeBlock::isSafeToRun(JSWebAssemblyMemory* memory) const 56 89 { 90 if (!runnable()) 91 return false; 92 57 93 Wasm::MemoryMode codeMode = mode(); 58 94 Wasm::MemoryMode memoryMode = memory->memory().mode(); -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.h
r214465 r214504 30 30 #include "JSCell.h" 31 31 #include "JSWebAssemblyCallee.h" 32 #include "PromiseDeferredTimer.h" 32 33 #include "UnconditionalFinalizer.h" 33 34 #include "WasmFormat.h" … … 40 41 class JSWebAssemblyMemory; 41 42 43 namespace Wasm { 44 class Plan; 45 } 46 42 47 class JSWebAssemblyCodeBlock : public JSCell { 43 48 public: … … 45 50 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; 46 51 47 static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmExitStubs>&& exitStubs, Wasm::MemoryMode mode, unsigned calleeCount)52 static JSWebAssemblyCodeBlock* create(VM& vm, JSWebAssemblyModule* owner, Wasm::MemoryMode mode, Ref<Wasm::Plan>&& plan, unsigned calleeCount) 48 53 { 49 auto* result = new (NotNull, allocateCell<JSWebAssemblyCodeBlock>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyCodeBlock(vm, owner, std::forward<Bag<CallLinkInfo>>(callLinkInfos), std::forward<Vector<Wasm::WasmExitStubs>>(exitStubs), mode, calleeCount);54 auto* result = new (NotNull, allocateCell<JSWebAssemblyCodeBlock>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyCodeBlock(vm, owner, mode, WTFMove(plan), calleeCount); 50 55 result->finishCreation(vm); 51 56 return result; … … 60 65 Wasm::MemoryMode mode() const { return m_mode; } 61 66 JSWebAssemblyModule* module() const { return m_module.get(); } 62 bool isSafeToRun(JSWebAssemblyMemory*); 67 68 // Don't call intialize directly, this should be called for you, as needed, by JSWebAssemblyInstance::finalizeCreation. 69 void initialize(); 70 bool initialized() const { return !m_plan; } 71 72 Wasm::Plan& plan() const { ASSERT(!initialized()); return *m_plan; } 73 74 bool runnable() const { return initialized() && !m_errorMessage; } 75 String& errorMessage() { ASSERT(!runnable()); return m_errorMessage; } 76 bool isSafeToRun(JSWebAssemblyMemory*) const; 63 77 64 78 JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace) … … 90 104 } 91 105 92 WriteBarrier<JSWebAssemblyCallee>* callees() 93 { 94 return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees()); 95 } 106 WriteBarrier<JSWebAssemblyCallee>* callees() { return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees()); } 96 107 97 108 void* wasmToJsCallStubForImport(unsigned importIndex) … … 102 113 103 114 private: 104 JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Bag<CallLinkInfo>&&, Vector<Wasm::WasmExitStubs>&&, Wasm::MemoryMode, unsigned calleeCount);115 JSWebAssemblyCodeBlock(VM&, JSWebAssemblyModule*, Wasm::MemoryMode, Ref<Wasm::Plan>&&, unsigned calleeCount); 105 116 DECLARE_EXPORT_INFO; 106 117 static const bool needsDestruction = true; … … 126 137 Bag<CallLinkInfo> m_callLinkInfos; 127 138 Vector<Wasm::WasmExitStubs> m_wasmExitStubs; 139 // The plan that is compiling this code block. 140 RefPtr<Wasm::Plan> m_plan; 141 String m_errorMessage; 128 142 Wasm::MemoryMode m_mode; 129 143 unsigned m_calleeCount; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h
r213745 r214504 74 74 } 75 75 76 ALWAYS_INLINE RefPtr<ArrayBuffer> createSourceBufferFromValue(VM& vm, ExecState* exec, JSValue value) 77 { 78 auto throwScope = DECLARE_THROW_SCOPE(vm); 79 size_t byteOffset; 80 size_t byteSize; 81 uint8_t* data = getWasmBufferFromValue(exec, value, byteOffset, byteSize); 82 RETURN_IF_EXCEPTION(throwScope, nullptr); 83 84 auto buffer = ArrayBuffer::tryCreate(data + byteOffset, byteSize); 85 if (buffer) 86 return buffer; 87 88 throwException(exec, throwScope, createOutOfMemoryError(exec)); 89 return nullptr; 90 } 91 76 92 ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSObject* object, WebAssemblyFunction*& wasmFunction, WebAssemblyWrapperFunction*& wasmWrapperFunction) 77 93 { -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
r214498 r214504 33 33 #include "JSModuleEnvironment.h" 34 34 #include "JSModuleNamespaceObject.h" 35 #include "JSWebAssemblyHelpers.h" 36 #include "JSWebAssemblyLinkError.h" 35 37 #include "JSWebAssemblyMemory.h" 36 38 #include "JSWebAssemblyModule.h" 39 #include "WebAssemblyModuleRecord.h" 37 40 #include "WebAssemblyToJSCallee.h" 38 41 #include <wtf/StdLibExtras.h> … … 40 43 namespace JSC { 41 44 42 void JSWebAssemblyInstance::setMemory(VM& vm, ExecState* exec, JSWebAssemblyMemory* memory) 43 { 44 auto scope = DECLARE_THROW_SCOPE(vm); 45 // We create stub memories even for modules that should eventually get a memory so we want to avoid recompling there. 46 if (memory->memory()) { 47 auto codeBlock = m_codeBlock->module()->codeBlock(vm, exec, memory); 48 RETURN_IF_EXCEPTION(scope,); 49 m_codeBlock.set(vm, this, codeBlock); 50 } 51 m_memory.set(vm, this, memory); 52 } 53 54 JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject) 55 { 56 // FIXME: These objects could be pretty big we should try to throw OOM here. 57 auto* instance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap, allocationSize(module->moduleInformation().importFunctionSignatureIndices.size()))) JSWebAssemblyInstance(vm, structure, module->moduleInformation().importFunctionSignatureIndices.size()); 58 instance->finishCreation(vm, module, moduleNamespaceObject); 59 return instance; 60 } 45 const ClassInfo JSWebAssemblyInstance::s_info = { "WebAssembly.Instance", &Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyInstance) }; 61 46 62 47 Structure* JSWebAssemblyInstance::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) … … 77 62 ASSERT(inherits(vm, info())); 78 63 64 m_module.set(vm, this, module); 79 65 const size_t extraMemorySize = module->moduleInformation().globals.size() * sizeof(Register); 80 66 m_globals = MallocPtr<uint64_t>::malloc(extraMemorySize); 81 67 heap()->reportExtraMemoryAllocated(extraMemorySize); 82 68 83 m_codeBlock.set(vm, this, module->codeBlock());84 69 m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject); 85 70 m_callee.set(vm, this, module->callee()); … … 98 83 99 84 Base::visitChildren(thisObject, visitor); 85 visitor.append(thisObject->m_module); 100 86 visitor.append(thisObject->m_codeBlock); 101 87 visitor.append(thisObject->m_moduleNamespaceObject); … … 105 91 visitor.reportExtraMemoryVisited(thisObject->module()->moduleInformation().globals.size()); 106 92 for (unsigned i = 0; i < thisObject->m_numImportFunctions; ++i) 107 visitor.append(*thisObject->importFunction(i)); 108 } 109 110 const ClassInfo JSWebAssemblyInstance::s_info = { "WebAssembly.Instance", &Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyInstance) }; 93 visitor.append(thisObject->importFunctions()[i]); 94 } 95 96 void JSWebAssemblyInstance::addUnitializedCodeBlock(VM& vm, Ref<Wasm::Plan> plan) 97 { 98 auto* codeBlock = JSWebAssemblyCodeBlock::create(vm, module(), memoryMode(), WTFMove(plan), module()->moduleInformation().internalFunctionCount()); 99 m_codeBlock.set(vm, this, codeBlock); 100 ASSERT(!codeBlock->initialized()); 101 } 102 103 void JSWebAssemblyInstance::finalizeCreation(VM& vm, ExecState* exec) 104 { 105 auto scope = DECLARE_THROW_SCOPE(vm); 106 codeBlock()->initialize(); 107 108 if (!codeBlock()->runnable()) { 109 throwException(exec, scope, JSWebAssemblyLinkError::create(exec, vm, globalObject()->WebAssemblyLinkErrorStructure(), codeBlock()->errorMessage())); 110 return; 111 } 112 RELEASE_ASSERT(codeBlock()->isSafeToRun(memory())); 113 114 auto* moduleRecord = jsCast<WebAssemblyModuleRecord*>(m_moduleNamespaceObject->moduleRecord()); 115 moduleRecord->link(exec, module(), this); 116 RETURN_IF_EXCEPTION(scope, void()); 117 118 JSValue startResult = moduleRecord->evaluate(exec); 119 UNUSED_PARAM(startResult); 120 RETURN_IF_EXCEPTION(scope, void()); 121 } 122 123 JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure) 124 { 125 auto throwScope = DECLARE_THROW_SCOPE(vm); 126 auto* globalObject = exec->lexicalGlobalObject(); 127 128 const Wasm::ModuleInformation& moduleInformation = jsModule->moduleInformation(); 129 130 auto exception = [&] (JSObject* error) { 131 throwException(exec, throwScope, error); 132 return nullptr; 133 }; 134 135 // If the list of module.imports is not empty and Type(importObject) is not Object, a TypeError is thrown. 136 if (moduleInformation.imports.size() && !importObject) 137 return exception(createTypeError(exec, ASCIILiteral("can't make WebAssembly.Instance because there is no imports Object and the WebAssembly.Module requires imports"))); 138 139 Identifier moduleKey = Identifier::fromUid(PrivateName(PrivateName::Description, "WebAssemblyInstance")); 140 WebAssemblyModuleRecord* moduleRecord = WebAssemblyModuleRecord::create(exec, vm, globalObject->webAssemblyModuleRecordStructure(), moduleKey, moduleInformation); 141 RETURN_IF_EXCEPTION(throwScope, nullptr); 142 143 JSModuleNamespaceObject* moduleNamespace = moduleRecord->getModuleNamespace(exec); 144 // FIXME: These objects could be pretty big we should try to throw OOM here. 145 auto* instance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap, allocationSize(moduleInformation.importFunctionCount()))) JSWebAssemblyInstance(vm, instanceStructure, moduleInformation.importFunctionCount()); 146 instance->finishCreation(vm, jsModule, moduleNamespace); 147 RETURN_IF_EXCEPTION(throwScope, nullptr); 148 149 // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively. 150 // Let imports be an initially-empty list of external values. 151 unsigned numImportFunctions = 0; 152 unsigned numImportGlobals = 0; 153 154 bool hasMemoryImport = false; 155 bool hasTableImport = false; 156 // For each import i in module.imports: 157 for (auto& import : moduleInformation.imports) { 158 // 1. Let o be the resultant value of performing Get(importObject, i.module_name). 159 JSValue importModuleValue = importObject->get(exec, Identifier::fromString(&vm, import.module)); 160 RETURN_IF_EXCEPTION(throwScope, nullptr); 161 // 2. If Type(o) is not Object, throw a TypeError. 162 if (!importModuleValue.isObject()) 163 return exception(createTypeError(exec, ASCIILiteral("import must be an object"), defaultSourceAppender, runtimeTypeForValue(importModuleValue))); 164 165 // 3. Let v be the value of performing Get(o, i.item_name) 166 JSObject* object = jsCast<JSObject*>(importModuleValue); 167 JSValue value = object->get(exec, Identifier::fromString(&vm, import.field)); 168 RETURN_IF_EXCEPTION(throwScope, nullptr); 169 170 switch (import.kind) { 171 case Wasm::ExternalKind::Function: { 172 // 4. If i is a function import: 173 // i. If IsCallable(v) is false, throw a WebAssembly.LinkError. 174 if (!value.isFunction()) 175 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("import function must be callable"))); 176 177 JSObject* function = jsCast<JSObject*>(value); 178 // ii. If v is an Exported Function Exotic Object: 179 WebAssemblyFunction* wasmFunction; 180 WebAssemblyWrapperFunction* wasmWrapperFunction; 181 if (isWebAssemblyHostFunction(vm, function, wasmFunction, wasmWrapperFunction)) { 182 // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError. 183 Wasm::SignatureIndex importedSignatureIndex; 184 if (wasmFunction) 185 importedSignatureIndex = wasmFunction->signatureIndex(); 186 else { 187 importedSignatureIndex = wasmWrapperFunction->signatureIndex(); 188 // b. Let closure be v.[[Closure]]. 189 function = wasmWrapperFunction->function(); 190 } 191 Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex]; 192 if (importedSignatureIndex != expectedSignatureIndex) 193 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("imported function's signature doesn't match the provided WebAssembly function's signature"))); 194 } 195 // iii. Otherwise: 196 // 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. 197 // Note: done as part of Plan compilation. 198 // iv. Append v to funcs. 199 // 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). 200 201 ASSERT(numImportFunctions == import.kindIndex); 202 instance->importFunctions()[numImportFunctions++].set(vm, instance, function); 203 // v. Append closure to imports. 204 break; 205 } 206 case Wasm::ExternalKind::Table: { 207 RELEASE_ASSERT(!hasTableImport); // This should be guaranteed by a validation failure. 208 // 7. Otherwise (i is a table import): 209 hasTableImport = true; 210 JSWebAssemblyTable* table = jsDynamicCast<JSWebAssemblyTable*>(vm, value); 211 // i. If v is not a WebAssembly.Table object, throw a WebAssembly.LinkError. 212 if (!table) 213 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Table import is not an instance of WebAssembly.Table"))); 214 215 uint32_t expectedInitial = moduleInformation.tableInformation.initial(); 216 uint32_t actualInitial = table->size(); 217 if (actualInitial < expectedInitial) 218 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Table import provided an 'initial' that is too small"))); 219 220 if (std::optional<uint32_t> expectedMaximum = moduleInformation.tableInformation.maximum()) { 221 std::optional<uint32_t> actualMaximum = table->maximum(); 222 if (!actualMaximum) 223 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Table import does not have a 'maximum' but the module requires that it does"))); 224 if (*actualMaximum > *expectedMaximum) 225 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Imported Table's 'maximum' is larger than the module's expected 'maximum'"))); 226 } 227 228 // ii. Append v to tables. 229 // iii. Append v.[[Table]] to imports. 230 instance->m_table.set(vm, instance, table); 231 break; 232 } 233 234 case Wasm::ExternalKind::Memory: { 235 // 6. If i is a memory import: 236 RELEASE_ASSERT(!hasMemoryImport); // This should be guaranteed by a validation failure. 237 RELEASE_ASSERT(moduleInformation.memory); 238 hasMemoryImport = true; 239 JSWebAssemblyMemory* memory = jsDynamicCast<JSWebAssemblyMemory*>(vm, value); 240 // i. If v is not a WebAssembly.Memory object, throw a WebAssembly.LinkError. 241 if (!memory) 242 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import is not an instance of WebAssembly.Memory"))); 243 244 Wasm::PageCount declaredInitial = moduleInformation.memory.initial(); 245 Wasm::PageCount importedInitial = memory->memory().initial(); 246 if (importedInitial < declaredInitial) 247 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import provided an 'initial' that is smaller than the module's declared 'initial' import memory size"))); 248 249 if (Wasm::PageCount declaredMaximum = moduleInformation.memory.maximum()) { 250 Wasm::PageCount importedMaximum = memory->memory().maximum(); 251 if (!importedMaximum) 252 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import did not have a 'maximum' but the module requires that it does"))); 253 254 if (importedMaximum > declaredMaximum) 255 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import provided a 'maximum' that is larger than the module's declared 'maximum' import memory size"))); 256 } 257 258 // ii. Append v to memories. 259 // iii. Append v.[[Memory]] to imports. 260 ASSERT(!instance->m_memory); 261 instance->m_memory.set(vm, instance, memory); 262 RETURN_IF_EXCEPTION(throwScope, nullptr); 263 break; 264 } 265 case Wasm::ExternalKind::Global: { 266 // 5. If i is a global import: 267 // i. If i is not an immutable global, throw a TypeError. 268 ASSERT(moduleInformation.globals[import.kindIndex].mutability == Wasm::Global::Immutable); 269 // ii. If the global_type of i is i64 or Type(v) is not Number, throw a WebAssembly.LinkError. 270 if (moduleInformation.globals[import.kindIndex].type == Wasm::I64) 271 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("imported global cannot be an i64"))); 272 if (!value.isNumber()) 273 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("imported global must be a number"))); 274 // iii. Append ToWebAssemblyValue(v) to imports. 275 ASSERT(numImportGlobals == import.kindIndex); 276 switch (moduleInformation.globals[import.kindIndex].type) { 277 case Wasm::I32: 278 instance->setGlobal(numImportGlobals++, value.toInt32(exec)); 279 break; 280 case Wasm::F32: 281 instance->setGlobal(numImportGlobals++, bitwise_cast<uint32_t>(value.toFloat(exec))); 282 break; 283 case Wasm::F64: 284 instance->setGlobal(numImportGlobals++, bitwise_cast<uint64_t>(value.asNumber())); 285 break; 286 default: 287 RELEASE_ASSERT_NOT_REACHED(); 288 } 289 ASSERT(!throwScope.exception()); 290 break; 291 } 292 } 293 } 294 295 { 296 if (!!moduleInformation.memory && moduleInformation.memory.isImport()) { 297 // We should either have a Memory import or we should have thrown an exception. 298 RELEASE_ASSERT(hasMemoryImport); 299 } 300 301 if (moduleInformation.memory && !hasMemoryImport) { 302 RELEASE_ASSERT(!moduleInformation.memory.isImport()); 303 // We create a memory when it's a memory definition. 304 RefPtr<Wasm::Memory> memory = Wasm::Memory::create(vm, moduleInformation.memory.initial(), moduleInformation.memory.maximum()); 305 if (!memory) 306 return exception(createOutOfMemoryError(exec)); 307 308 instance->m_memory.set(vm, instance, 309 JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), memory.releaseNonNull())); 310 RETURN_IF_EXCEPTION(throwScope, nullptr); 311 } 312 } 313 314 { 315 if (!!moduleInformation.tableInformation && moduleInformation.tableInformation.isImport()) { 316 // We should either have a Table import or we should have thrown an exception. 317 RELEASE_ASSERT(hasTableImport); 318 } 319 320 if (!!moduleInformation.tableInformation && !hasTableImport) { 321 RELEASE_ASSERT(!moduleInformation.tableInformation.isImport()); 322 // We create a Table when it's a Table definition. 323 JSWebAssemblyTable* table = JSWebAssemblyTable::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyTableStructure(), 324 moduleInformation.tableInformation.initial(), moduleInformation.tableInformation.maximum()); 325 // We should always be able to allocate a JSWebAssemblyTable we've defined. 326 // If it's defined to be too large, we should have thrown a validation error. 327 ASSERT(!throwScope.exception()); 328 ASSERT(table); 329 instance->m_table.set(vm, instance, table); 330 } 331 } 332 333 if (!instance->memory()) { 334 // Make sure we have a dummy memory, so that wasm -> wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers. 335 instance->m_memory.set(vm, instance, JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), adoptRef(*(new Wasm::Memory())))); 336 } 337 338 // Globals 339 { 340 ASSERT(numImportGlobals == moduleInformation.firstInternalGlobal); 341 for (size_t globalIndex = numImportGlobals; globalIndex < moduleInformation.globals.size(); ++globalIndex) { 342 const auto& global = moduleInformation.globals[globalIndex]; 343 ASSERT(global.initializationType != Wasm::Global::IsImport); 344 if (global.initializationType == Wasm::Global::FromGlobalImport) { 345 ASSERT(global.initialBitsOrImportNumber < numImportGlobals); 346 instance->setGlobal(globalIndex, instance->loadI64Global(global.initialBitsOrImportNumber)); 347 } else 348 instance->setGlobal(globalIndex, global.initialBitsOrImportNumber); 349 } 350 } 351 352 ASSERT(!instance->codeBlock()); 353 instance->m_codeBlock.setMayBeNull(vm, instance, jsModule->codeBlock(instance->memoryMode())); 354 355 return instance; 356 } 357 111 358 112 359 } // namespace JSC -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
r214498 r214504 40 40 class WebAssemblyToJSCallee; 41 41 42 namespace Wasm { 43 class Plan; 44 } 45 46 42 47 class JSWebAssemblyInstance : public JSDestructibleObject { 43 48 public: 44 49 typedef JSDestructibleObject Base; 45 50 46 47 static JSWebAssemblyInstance* create(VM&, Structure*, JSWebAssemblyModule*, JSModuleNamespaceObject*); 51 static JSWebAssemblyInstance* create(VM&, ExecState*, JSWebAssemblyModule*, JSObject* importObject, Structure*); 48 52 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 49 53 50 54 DECLARE_INFO; 51 55 52 JSWebAssemblyModule* module() const 53 { 54 ASSERT(m_codeBlock); 55 return m_codeBlock->module(); 56 } 56 JSWebAssemblyCodeBlock* codeBlock() const { return m_codeBlock.get(); } 57 bool initialized() const { return codeBlock() && codeBlock()->initialized(); } 58 void addUnitializedCodeBlock(VM&, Ref<Wasm::Plan>); 59 void finalizeCreation(VM&, ExecState*); 57 60 58 JSWebAssemblyCodeBlock* codeBlock() const 59 { 60 ASSERT(m_codeBlock); 61 return m_codeBlock.get(); 62 } 61 JSWebAssemblyModule* module() const { return m_module.get(); } 63 62 64 WriteBarrier<JSObject>* importFunction(unsigned idx) 65 { 66 RELEASE_ASSERT(idx < m_numImportFunctions); 67 return &importFunctions()[idx]; 68 } 69 70 WriteBarrier<JSObject>* importFunctions() 71 { 72 return bitwise_cast<WriteBarrier<JSObject>*>(bitwise_cast<char*>(this) + offsetOfImportFunctions()); 73 } 74 75 void setImportFunction(VM& vm, JSObject* value, unsigned idx) 76 { 77 importFunction(idx)->set(vm, this, value); 78 } 63 JSObject* importFunction(unsigned idx) { RELEASE_ASSERT(idx < m_numImportFunctions); return importFunctions()[idx].get(); } 79 64 80 65 JSWebAssemblyMemory* memory() { return m_memory.get(); } 81 // Calling this might trigger a recompile. 82 void setMemory(VM&, ExecState*, JSWebAssemblyMemory*); 66 void setMemory(VM& vm, JSWebAssemblyMemory* value) { ASSERT(!memory()); m_memory.set(vm, this, value); } 83 67 Wasm::MemoryMode memoryMode() { return memory()->memory().mode(); } 84 68 85 69 JSWebAssemblyTable* table() { return m_table.get(); } 86 void setTable(VM& vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }87 70 88 71 int32_t loadI32Global(unsigned i) const { return m_globals.get()[i]; } … … 91 74 double loadF64Global(unsigned i) const { return bitwise_cast<double>(loadI64Global(i)); } 92 75 void setGlobal(unsigned i, int64_t bits) { m_globals.get()[i] = bits; } 93 94 static size_t offsetOfImportFunction(unsigned idx)95 {96 return offsetOfImportFunctions() + sizeof(WriteBarrier<JSCell>) * idx;97 }98 76 99 77 static ptrdiff_t offsetOfMemory() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_memory); } … … 116 94 117 95 private: 96 WriteBarrier<JSObject>* importFunctions() { return bitwise_cast<WriteBarrier<JSObject>*>(bitwise_cast<char*>(this) + offsetOfImportFunctions()); } 97 98 WriteBarrier<JSWebAssemblyModule> m_module; 118 99 WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlock; 119 100 WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp
r214498 r214504 44 44 const ClassInfo JSWebAssemblyModule::s_info = { "WebAssembly.Module", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) }; 45 45 46 JSWebAssembly CodeBlock* JSWebAssemblyModule::buildCodeBlock(VM& vm, ExecState* exec, Wasm::Plan& plan, std::optional<Wasm::MemoryMode> mode)46 JSWebAssemblyModule* JSWebAssemblyModule::createStub(VM& vm, ExecState* exec, Structure* structure, RefPtr<ArrayBuffer>&& source, RefPtr<Wasm::Plan>&& plan) 47 47 { 48 ASSERT(!plan->hasWork()); 48 49 auto scope = DECLARE_THROW_SCOPE(vm); 49 // On failure, a new WebAssembly.CompileError is thrown. 50 plan.run(mode); 51 if (plan.failed()) { 52 throwException(exec, scope, createJSWebAssemblyCompileError(exec, vm, plan.errorMessage())); 50 if (plan->failed()) { 51 throwException(exec, scope, JSWebAssemblyCompileError::create(exec, vm, structure->globalObject()->WebAssemblyCompileErrorStructure(), plan->errorMessage())); 53 52 return nullptr; 54 53 } 55 if (mode)56 ASSERT(*mode == plan.mode());57 54 58 unsigned calleeCount = plan.internalFunctionCount(); 59 auto* codeBlock = JSWebAssemblyCodeBlock::create(vm, this, plan.takeCallLinkInfos(), plan.takeWasmExitStubs(), plan.mode(), calleeCount); 60 61 plan.initializeCallees(exec->jsCallee()->globalObject(), 62 [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) { 63 codeBlock->setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee); 64 codeBlock->setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee); 65 }); 66 return codeBlock; 67 } 68 69 JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, ExecState* exec, Structure* structure, uint8_t* source, size_t byteSize) 70 { 71 auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure); 72 73 instance->finishCreation(vm, exec, source, byteSize); 74 return instance; 55 auto* module = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure, WTFMove(source)); 56 module->finishCreation(vm, WTFMove(plan)); 57 return module; 75 58 } 76 59 … … 80 63 } 81 64 82 JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure )65 JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, RefPtr<ArrayBuffer>&& source) 83 66 : Base(vm, structure) 67 , m_sourceBuffer(source.releaseNonNull()) 84 68 { 85 69 } 86 70 87 JSWebAssemblyCodeBlock* JSWebAssemblyModule::codeBlock(VM& vm, ExecState* exec, JSWebAssemblyMemory* memory) 88 { 89 Wasm::MemoryMode mode = memory->memory().mode(); 90 91 for (unsigned i = 0; i < Wasm::NumberOfMemoryModes; ++i) { 92 if (m_codeBlocks[i] && m_codeBlocks[i]->isSafeToRun(memory)) 93 return m_codeBlocks[i].get(); 94 } 95 96 ASSERT(!codeBlockFor(mode)); 97 auto scope = DECLARE_THROW_SCOPE(vm); 98 // We don't have a code block for this mode, we need to recompile... 99 Wasm::Plan plan(&vm, static_cast<uint8_t*>(m_sourceBuffer->data()), m_sourceBuffer->byteLength()); 100 101 auto* codeBlock = buildCodeBlock(vm, exec, plan, mode); 102 RETURN_IF_EXCEPTION(scope, nullptr); 103 104 ASSERT(plan.exports().size() == m_exportSymbolTable->size()); 105 if (!ASSERT_DISABLED) { 106 for (auto& exp : plan.exports()) 107 ASSERT_UNUSED(exp, m_exportSymbolTable->contains(exp.field.impl())); 108 } 109 110 ASSERT(mode == codeBlock->mode()); 111 codeBlockFor(mode).set(vm, this, codeBlock); 112 return codeBlock; 113 } 114 115 void JSWebAssemblyModule::finishCreation(VM& vm, ExecState* exec, uint8_t* source, size_t byteSize) 71 void JSWebAssemblyModule::finishCreation(VM& vm, RefPtr<Wasm::Plan>&& plan) 116 72 { 117 73 Base::finishCreation(vm); 118 74 ASSERT(inherits(vm, info())); 119 75 120 auto scope = DECLARE_THROW_SCOPE(vm); 121 Wasm::Plan plan(&vm, source, byteSize); 76 std::unique_ptr<Wasm::ModuleInformation> moduleInformation = plan->takeModuleInformation(); 77 for (auto& exp : moduleInformation->exports) { 78 ASSERT(exp.field.isSafeToSendToAnotherThread()); 79 exp.field = AtomicString(exp.field); 80 } 81 for (auto& imp : moduleInformation->imports) { 82 ASSERT(imp.field.isSafeToSendToAnotherThread()); 83 imp.field = AtomicString(imp.field); 84 ASSERT(imp.module.isSafeToSendToAnotherThread()); 85 imp.module = AtomicString(imp.module); 86 } 122 87 123 auto* codeBlock = buildCodeBlock(vm, exec, plan); 124 RETURN_IF_EXCEPTION(scope,); 88 m_moduleInformation = WTFMove(moduleInformation); 125 89 126 90 // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module. 127 91 SymbolTable* exportSymbolTable = SymbolTable::create(vm); 128 for (auto& exp : plan.exports()) {92 for (auto& exp : m_moduleInformation->exports) { 129 93 auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary); 130 exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset))); 94 ASSERT(exp.field.impl()->isAtomic()); 95 exportSymbolTable->set(NoLockingNecessary, static_cast<AtomicStringImpl*>(exp.field.impl()), SymbolTableEntry(VarOffset(offset))); 131 96 } 132 97 133 m_sourceBuffer = ArrayBuffer::create(source, byteSize);134 m_moduleInformation = plan.takeModuleInformation();135 98 m_exportSymbolTable.set(vm, this, exportSymbolTable); 136 99 m_callee.set(vm, this, WebAssemblyToJSCallee::create(vm, vm.webAssemblyToJSCalleeStructure.get(), this)); 137 codeBlockFor(codeBlock->mode()).set(vm, this, codeBlock);138 100 } 139 101 … … 141 103 { 142 104 static_cast<JSWebAssemblyModule*>(cell)->JSWebAssemblyModule::~JSWebAssemblyModule(); 105 } 106 107 void JSWebAssemblyModule::setCodeBlock(VM& vm, Wasm::MemoryMode mode, JSWebAssemblyCodeBlock* codeBlock) 108 { 109 m_codeBlocks[static_cast<size_t>(mode)].set(vm, this, codeBlock); 143 110 } 144 111 -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h
r214498 r214504 50 50 typedef JSDestructibleObject Base; 51 51 52 static JSWebAssemblyModule* create (VM&, ExecState*, Structure*, uint8_t* source, size_t byteSize);52 static JSWebAssemblyModule* createStub(VM&, ExecState*, Structure*, RefPtr<ArrayBuffer>&& source, RefPtr<Wasm::Plan>&&); 53 53 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 54 54 … … 56 56 57 57 const Wasm::ModuleInformation& moduleInformation() const { return *m_moduleInformation.get(); } 58 RefPtr<Wasm::Memory> takeReservedMemory() { return m_moduleInformation->memory.takeReservedMemory(); }59 58 SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); } 60 59 Wasm::SignatureIndex signatureIndexFromFunctionIndexSpace(unsigned functionIndexSpace) const … … 64 63 WebAssemblyToJSCallee* callee() const { return m_callee.get(); } 65 64 66 // Returns the code block that this module was originally compiled expecting to use. This won't need to recompile. 67 JSWebAssemblyCodeBlock* codeBlock() { return codeBlockFor(m_moduleInformation->memory.mode()).get(); } 68 // Returns the appropriate code block for the given memory, possibly triggering a recompile. 69 JSWebAssemblyCodeBlock* codeBlock(VM&, ExecState*, JSWebAssemblyMemory*); 65 JSWebAssemblyCodeBlock* codeBlock(Wasm::MemoryMode mode) { return m_codeBlocks[static_cast<size_t>(mode)].get(); } 66 67 ArrayBuffer& source() const { return m_sourceBuffer.get(); } 70 68 71 69 private: 72 WriteBarrier<JSWebAssemblyCodeBlock>& codeBlockFor(Wasm::MemoryMode mode) { return m_codeBlocks[static_cast<size_t>(mode)]; } 73 JSWebAssemblyCodeBlock* buildCodeBlock(VM&, ExecState*, Wasm::Plan&, std::optional<Wasm::MemoryMode> mode = std::nullopt); 70 friend class JSWebAssemblyCodeBlock; 74 71 75 JSWebAssemblyModule(VM&, Structure*); 76 void finishCreation(VM&, ExecState*, uint8_t* source, size_t byteSize); 72 void setCodeBlock(VM&, Wasm::MemoryMode, JSWebAssemblyCodeBlock*); 73 74 JSWebAssemblyModule(VM&, Structure*, RefPtr<ArrayBuffer>&&); 75 void finishCreation(VM&, RefPtr<Wasm::Plan>&&); 77 76 static void destroy(JSCell*); 78 77 static void visitChildren(JSCell*, SlotVisitor&); 79 78 80 Ref Ptr<ArrayBuffer> m_sourceBuffer;81 std::unique_ptr< Wasm::ModuleInformation> m_moduleInformation;79 Ref<ArrayBuffer> m_sourceBuffer; 80 std::unique_ptr<const Wasm::ModuleInformation> m_moduleInformation; 82 81 WriteBarrier<SymbolTable> m_exportSymbolTable; 83 82 WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::NumberOfMemoryModes]; -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
r214438 r214504 38 38 #include "JSWebAssemblyMemory.h" 39 39 #include "JSWebAssemblyModule.h" 40 #include "WasmPlan.h" 41 #include "WasmWorklist.h" 40 42 #include "WebAssemblyFunction.h" 41 43 #include "WebAssemblyInstancePrototype.h" … … 46 48 namespace JSC { 47 49 48 static const bool verbose = false;49 50 50 const ClassInfo WebAssemblyInstanceConstructor::s_info = { "Function", &Base::s_info, &constructorTableWebAssemblyInstance, CREATE_METHOD_TABLE(WebAssemblyInstanceConstructor) }; 51 51 … … 55 55 */ 56 56 57 using Wasm::Plan; 58 57 59 static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* exec) 58 60 { 59 61 auto& vm = exec->vm(); 60 auto throwScope = DECLARE_THROW_SCOPE(vm);62 auto scope = DECLARE_THROW_SCOPE(vm); 61 63 62 64 // If moduleObject is not a WebAssembly.Module instance, a TypeError is thrown. 63 JSWebAssemblyModule* jsModule = jsDynamicCast<JSWebAssemblyModule*>(vm, exec->argument(0));64 if (! jsModule)65 return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, ASCIILiteral("first argument to WebAssembly.Instance must be a WebAssembly.Module"), defaultSourceAppender, runtimeTypeForValue(exec->argument(0)))));65 JSWebAssemblyModule* module = jsDynamicCast<JSWebAssemblyModule*>(vm, exec->argument(0)); 66 if (!module) 67 return JSValue::encode(throwException(exec, scope, createTypeError(exec, ASCIILiteral("first argument to WebAssembly.Instance must be a WebAssembly.Module"), defaultSourceAppender, runtimeTypeForValue(exec->argument(0))))); 66 68 67 69 // If the importObject parameter is not undefined and Type(importObject) is not Object, a TypeError is thrown. … … 69 71 JSObject* importObject = importArgument.getObject(); 70 72 if (!importArgument.isUndefined() && !importObject) 71 return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, ASCIILiteral("second argument to WebAssembly.Instance must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument))));73 return JSValue::encode(throwException(exec, scope, createTypeError(exec, ASCIILiteral("second argument to WebAssembly.Instance must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument)))); 72 74 73 75 Structure* instanceStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), exec->lexicalGlobalObject()->WebAssemblyInstanceStructure()); 74 RETURN_IF_EXCEPTION( throwScope, { });76 RETURN_IF_EXCEPTION(scope, { }); 75 77 76 throwScope.release(); 77 return JSValue::encode(WebAssemblyInstanceConstructor::createInstance(exec, jsModule, importObject, instanceStructure)); 78 } 78 JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, instanceStructure); 79 RETURN_IF_EXCEPTION(scope, { }); 79 80 80 JSWebAssemblyInstance* WebAssemblyInstanceConstructor::createInstance(ExecState* exec, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure) 81 { 82 auto& vm = exec->vm(); 83 auto throwScope = DECLARE_THROW_SCOPE(vm); 84 auto* globalObject = exec->lexicalGlobalObject(); 81 // There are three possible cases: 82 // 1) The instance already has an initialized CodeBlock (runnable), so we just need to finalizeCreation. 83 // 2) The instance has no CodeBlock, so we need to make one and compile the code for it. 84 // 3) The instance already has an uninitialized CodeBlock, so we need to wait for the compilation to finish. 85 85 86 const Wasm::ModuleInformation& moduleInformation = jsModule->moduleInformation(); 86 if (!instance->initialized()) { 87 if (instance->codeBlock()) 88 Wasm::ensureWorklist().completePlanSynchronously(instance->codeBlock()->plan()); 89 else { 90 Ref<Wasm::Plan> plan = adoptRef(*new Plan(vm, module->source(), Plan::FullCompile, Plan::dontFinalize)); 91 plan->setModeAndPromise(instance->memoryMode(), nullptr); 92 instance->addUnitializedCodeBlock(vm, plan.copyRef()); 87 93 88 auto exception = [&] (JSObject* error) { 89 throwException(exec, throwScope, error); 90 return nullptr; 91 }; 92 93 // If the list of module.imports is not empty and Type(importObject) is not Object, a TypeError is thrown. 94 if (moduleInformation.imports.size() && !importObject) 95 return exception(createTypeError(exec, ASCIILiteral("can't make WebAssembly.Instance because there is no imports Object and the WebAssembly.Module requires imports"))); 96 97 Identifier moduleKey = Identifier::fromUid(PrivateName(PrivateName::Description, "WebAssemblyInstance")); 98 WebAssemblyModuleRecord* moduleRecord = WebAssemblyModuleRecord::create(exec, vm, globalObject->webAssemblyModuleRecordStructure(), moduleKey, moduleInformation); 99 RETURN_IF_EXCEPTION(throwScope, nullptr); 100 101 102 JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord->getModuleNamespace(exec)); 103 RETURN_IF_EXCEPTION(throwScope, nullptr); 104 105 // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively. 106 // Let imports be an initially-empty list of external values. 107 unsigned numImportFunctions = 0; 108 unsigned numImportGlobals = 0; 109 110 bool hasMemoryImport = false; 111 bool hasTableImport = false; 112 // For each import i in module.imports: 113 for (auto& import : moduleInformation.imports) { 114 // 1. Let o be the resultant value of performing Get(importObject, i.module_name). 115 JSValue importModuleValue = importObject->get(exec, import.module); 116 RETURN_IF_EXCEPTION(throwScope, nullptr); 117 // 2. If Type(o) is not Object, throw a TypeError. 118 if (!importModuleValue.isObject()) 119 return exception(createTypeError(exec, ASCIILiteral("import must be an object"), defaultSourceAppender, runtimeTypeForValue(importModuleValue))); 120 121 // 3. Let v be the value of performing Get(o, i.item_name) 122 JSObject* object = jsCast<JSObject*>(importModuleValue); 123 JSValue value = object->get(exec, import.field); 124 RETURN_IF_EXCEPTION(throwScope, nullptr); 125 126 switch (import.kind) { 127 case Wasm::ExternalKind::Function: { 128 // 4. If i is a function import: 129 // i. If IsCallable(v) is false, throw a WebAssembly.LinkError. 130 if (!value.isFunction()) 131 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("import function must be callable"))); 132 133 JSObject* function = jsCast<JSObject*>(value); 134 // ii. If v is an Exported Function Exotic Object: 135 WebAssemblyFunction* wasmFunction; 136 WebAssemblyWrapperFunction* wasmWrapperFunction; 137 if (isWebAssemblyHostFunction(vm, function, wasmFunction, wasmWrapperFunction)) { 138 // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError. 139 Wasm::SignatureIndex importedSignatureIndex; 140 if (wasmFunction) 141 importedSignatureIndex = wasmFunction->signatureIndex(); 142 else { 143 importedSignatureIndex = wasmWrapperFunction->signatureIndex(); 144 // b. Let closure be v.[[Closure]]. 145 function = wasmWrapperFunction->function(); 146 } 147 Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex]; 148 if (importedSignatureIndex != expectedSignatureIndex) 149 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("imported function's signature doesn't match the provided WebAssembly function's signature"))); 150 } 151 // iii. Otherwise: 152 // 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. 153 // Note: done as part of Plan compilation. 154 // iv. Append v to funcs. 155 // 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). 156 157 ASSERT(numImportFunctions == import.kindIndex); 158 instance->setImportFunction(vm, function, numImportFunctions++); 159 // v. Append closure to imports. 160 break; 161 } 162 case Wasm::ExternalKind::Table: { 163 RELEASE_ASSERT(!hasTableImport); // This should be guaranteed by a validation failure. 164 // 7. Otherwise (i is a table import): 165 hasTableImport = true; 166 JSWebAssemblyTable* table = jsDynamicCast<JSWebAssemblyTable*>(vm, value); 167 // i. If v is not a WebAssembly.Table object, throw a WebAssembly.LinkError. 168 if (!table) 169 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Table import is not an instance of WebAssembly.Table"))); 170 171 uint32_t declaredInitial = moduleInformation.tableInformation.initial(); 172 uint32_t importedInitial = table->size(); 173 if (importedInitial < declaredInitial) 174 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Table import provided an 'initial' that is too small"))); 175 176 if (std::optional<uint32_t> declaredMaximum = moduleInformation.tableInformation.maximum()) { 177 std::optional<uint32_t> importedMaximum = table->maximum(); 178 if (!importedMaximum) 179 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Table import does not have a 'maximum' but the module requires that it does"))); 180 if (*importedMaximum > *declaredMaximum) 181 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Imported Table's 'maximum' is larger than the module's expected 'maximum'"))); 182 } 183 184 // ii. Append v to tables. 185 // iii. Append v.[[Table]] to imports. 186 instance->setTable(vm, table); 187 break; 188 } 189 case Wasm::ExternalKind::Memory: { 190 // 6. If i is a memory import: 191 RELEASE_ASSERT(!hasMemoryImport); // This should be guaranteed by a validation failure. 192 RELEASE_ASSERT(moduleInformation.memory); 193 hasMemoryImport = true; 194 JSWebAssemblyMemory* memory = jsDynamicCast<JSWebAssemblyMemory*>(vm, value); 195 // i. If v is not a WebAssembly.Memory object, throw a WebAssembly.LinkError. 196 if (!memory) 197 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import is not an instance of WebAssembly.Memory"))); 198 199 Wasm::PageCount declaredInitial = moduleInformation.memory.initial(); 200 Wasm::PageCount importedInitial = memory->memory().initial(); 201 if (importedInitial < declaredInitial) 202 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import provided an 'initial' that is smaller than the module's declared 'initial' import memory size"))); 203 204 if (Wasm::PageCount declaredMaximum = moduleInformation.memory.maximum()) { 205 Wasm::PageCount importedMaximum = memory->memory().maximum(); 206 if (!importedMaximum) 207 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import did not have a 'maximum' but the module requires that it does"))); 208 209 if (importedMaximum > declaredMaximum) 210 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("Memory import provided a 'maximum' that is larger than the module's declared 'maximum' import memory size"))); 211 } 212 213 // ii. Append v to memories. 214 // iii. Append v.[[Memory]] to imports. 215 instance->setMemory(vm, exec, memory); 216 RETURN_IF_EXCEPTION(throwScope, nullptr); 217 break; 218 } 219 case Wasm::ExternalKind::Global: { 220 // 5. If i is a global import: 221 // i. If i is not an immutable global, throw a TypeError. 222 ASSERT(moduleInformation.globals[import.kindIndex].mutability == Wasm::Global::Immutable); 223 // ii. If the global_type of i is i64 or Type(v) is not Number, throw a WebAssembly.LinkError. 224 if (moduleInformation.globals[import.kindIndex].type == Wasm::I64) 225 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("imported global cannot be an i64"))); 226 if (!value.isNumber()) 227 return exception(createJSWebAssemblyLinkError(exec, vm, ASCIILiteral("imported global must be a number"))); 228 // iii. Append ToWebAssemblyValue(v) to imports. 229 ASSERT(numImportGlobals == import.kindIndex); 230 switch (moduleInformation.globals[import.kindIndex].type) { 231 case Wasm::I32: 232 instance->setGlobal(numImportGlobals++, value.toInt32(exec)); 233 break; 234 case Wasm::F32: 235 instance->setGlobal(numImportGlobals++, bitwise_cast<uint32_t>(value.toFloat(exec))); 236 break; 237 case Wasm::F64: 238 instance->setGlobal(numImportGlobals++, bitwise_cast<uint64_t>(value.asNumber())); 239 break; 240 default: 241 RELEASE_ASSERT_NOT_REACHED(); 242 } 243 ASSERT(!throwScope.exception()); 244 break; 245 } 94 auto& worklist = Wasm::ensureWorklist(); 95 worklist.enqueue(plan.copyRef()); 96 worklist.completePlanSynchronously(plan.get()); 246 97 } 247 98 } 248 99 249 { 250 if (!!moduleInformation.memory && moduleInformation.memory.isImport()) { 251 // We should either have a Memory import or we should have thrown an exception. 252 RELEASE_ASSERT(hasMemoryImport); 253 } 254 255 if (moduleInformation.memory && !hasMemoryImport) { 256 RELEASE_ASSERT(!moduleInformation.memory.isImport()); 257 // We create a memory when it's a memory definition. 258 RefPtr<Wasm::Memory> memory; 259 if (moduleInformation.memory.hasReservedMemory()) 260 memory = jsModule->takeReservedMemory(); 261 else { 262 memory = Wasm::Memory::create(vm, moduleInformation.memory.initial(), moduleInformation.memory.maximum()); 263 if (!memory) 264 return exception(createOutOfMemoryError(exec)); 265 } 266 instance->setMemory(vm, exec, 267 JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), memory.releaseNonNull())); 268 RETURN_IF_EXCEPTION(throwScope, nullptr); 269 } 270 } 271 272 { 273 if (!!moduleInformation.tableInformation && moduleInformation.tableInformation.isImport()) { 274 // We should either have a Table import or we should have thrown an exception. 275 RELEASE_ASSERT(hasTableImport); 276 } 277 278 if (!!moduleInformation.tableInformation && !hasTableImport) { 279 RELEASE_ASSERT(!moduleInformation.tableInformation.isImport()); 280 // We create a Table when it's a Table definition. 281 JSWebAssemblyTable* table = JSWebAssemblyTable::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyTableStructure(), 282 moduleInformation.tableInformation.initial(), moduleInformation.tableInformation.maximum()); 283 // We should always be able to allocate a JSWebAssemblyTable we've defined. 284 // If it's defined to be too large, we should have thrown a validation error. 285 ASSERT(!throwScope.exception()); 286 ASSERT(table); 287 instance->setTable(vm, table); 288 } 289 } 290 291 if (!instance->memory()) { 292 // Make sure we have a dummy memory, so that wasm -> wasm thunks avoid checking for a nullptr Memory when trying to set pinned registers. 293 instance->setMemory(vm, exec, JSWebAssemblyMemory::create(vm, exec->lexicalGlobalObject()->WebAssemblyMemoryStructure(), adoptRef(*(new Wasm::Memory())))); 294 } 295 296 // Globals 297 { 298 ASSERT(numImportGlobals == moduleInformation.firstInternalGlobal); 299 for (size_t globalIndex = numImportGlobals; globalIndex < moduleInformation.globals.size(); ++globalIndex) { 300 const auto& global = moduleInformation.globals[globalIndex]; 301 ASSERT(global.initializationType != Wasm::Global::IsImport); 302 if (global.initializationType == Wasm::Global::FromGlobalImport) { 303 ASSERT(global.initialBitsOrImportNumber < numImportGlobals); 304 instance->setGlobal(globalIndex, instance->loadI64Global(global.initialBitsOrImportNumber)); 305 } else 306 instance->setGlobal(globalIndex, global.initialBitsOrImportNumber); 307 } 308 } 309 310 moduleRecord->link(exec, instance); 311 RETURN_IF_EXCEPTION(throwScope, nullptr); 312 313 if (verbose) 314 moduleRecord->dump(); 315 JSValue startResult = moduleRecord->evaluate(exec); 316 UNUSED_PARAM(startResult); 317 RETURN_IF_EXCEPTION(throwScope, nullptr); 318 319 return instance; 100 instance->finalizeCreation(vm, exec); 101 RETURN_IF_EXCEPTION(scope, { }); 102 return JSValue::encode(instance); 320 103 } 321 104 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp
r214261 r214504 76 76 auto scope = DECLARE_THROW_SCOPE(vm); 77 77 78 size_t byteOffset; 79 size_t byteSize; 80 uint8_t* base = getWasmBufferFromValue(exec, buffer, byteOffset, byteSize); 78 RefPtr<ArrayBuffer> source = createSourceBufferFromValue(vm, exec, buffer); 81 79 RETURN_IF_EXCEPTION(scope, { }); 82 80 83 scope.release(); 84 return JSWebAssemblyModule::create(vm, exec, structure, base + byteOffset, byteSize); 81 RefPtr<Wasm::Plan> plan = adoptRef(new Wasm::Plan(vm, *source, Wasm::Plan::Validation, Wasm::Plan::dontFinalize)); 82 if (!plan->parseAndValidateModule()) 83 return throwException(exec, scope, JSWebAssemblyCompileError::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyCompileErrorStructure(), plan->errorMessage())); 84 return JSWebAssemblyModule::createStub(vm, exec, structure, WTFMove(source), WTFMove(plan)); 85 85 } 86 86 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModulePrototype.cpp
r214484 r214504 111 111 JSObject* obj = constructEmptyObject(exec); 112 112 RETURN_IF_EXCEPTION(throwScope, { }); 113 obj->putDirect(vm, module, jsString(exec, imp.module .string()));114 obj->putDirect(vm, name, jsString(exec, imp.field .string()));113 obj->putDirect(vm, module, jsString(exec, imp.module)); 114 obj->putDirect(vm, name, jsString(exec, imp.field)); 115 115 obj->putDirect(vm, kind, jsString(exec, String(makeString(imp.kind)))); 116 116 result->push(exec, obj); … … 142 142 JSObject* obj = constructEmptyObject(exec); 143 143 RETURN_IF_EXCEPTION(throwScope, { }); 144 obj->putDirect(vm, name, jsString(exec, exp.field .string()));144 obj->putDirect(vm, name, jsString(exec, exp.field)); 145 145 obj->putDirect(vm, kind, jsString(exec, String(makeString(exp.kind)))); 146 146 result->push(exec, obj); -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
r214261 r214504 74 74 Base::finishCreation(exec, vm); 75 75 ASSERT(inherits(vm, info())); 76 for (const auto& exp : moduleInformation.exports) 77 addExportEntry(ExportEntry::createLocal(exp.field, exp.field)); 76 for (const auto& exp : moduleInformation.exports) { 77 Identifier field = Identifier::fromString(&vm, exp.field); 78 addExportEntry(ExportEntry::createLocal(field, field)); 79 } 78 80 } 79 81 … … 86 88 } 87 89 88 void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssembly Instance* instance)90 void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module, JSWebAssemblyInstance* instance) 89 91 { 90 92 VM& vm = exec->vm(); … … 93 95 auto* globalObject = exec->lexicalGlobalObject(); 94 96 95 JSWebAssemblyModule* module = instance->module();96 97 JSWebAssemblyCodeBlock* codeBlock = instance->codeBlock(); 97 98 const Wasm::ModuleInformation& moduleInformation = module->moduleInformation(); … … 113 114 if (exp.kindIndex < functionImportCount) { 114 115 unsigned functionIndex = exp.kindIndex; 115 JSObject* functionImport = instance->importFunction(functionIndex) ->get();116 JSObject* functionImport = instance->importFunction(functionIndex); 116 117 if (isWebAssemblyHostFunction(vm, functionImport)) 117 118 exportedValue = functionImport; … … 129 130 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex); 130 131 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex); 131 WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), exp.field .string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);132 WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), exp.field, instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex); 132 133 exportedValue = function; 133 134 } … … 180 181 bool ignoreReadOnlyErrors = true; 181 182 bool putResult = false; 182 symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, exp.field, exportedValue, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);183 symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, Identifier::fromString(&vm, exp.field), exportedValue, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult); 183 184 RELEASE_ASSERT(putResult); 184 185 } … … 193 194 ASSERT(signature->returnType() == Wasm::Void); 194 195 if (startFunctionIndexSpace < codeBlock->functionImportCount()) { 195 JSObject* startFunction = instance->importFunction(startFunctionIndexSpace) ->get();196 JSObject* startFunction = instance->importFunction(startFunctionIndexSpace); 196 197 m_startFunction.set(vm, this, startFunction); 197 198 } else { … … 252 253 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex); 253 254 if (functionIndex < codeBlock->functionImportCount()) { 254 JSObject* functionImport = jsCast<JSObject*>(m_instance->importFunction(functionIndex) ->get());255 JSObject* functionImport = jsCast<JSObject*>(m_instance->importFunction(functionIndex)); 255 256 if (isWebAssemblyHostFunction(vm, functionImport)) { 256 257 WebAssemblyFunction* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(vm, functionImport); -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h
r213745 r214504 34 34 35 35 class JSWebAssemblyInstance; 36 class JSWebAssemblyModule; 36 37 class WebAssemblyFunction; 37 38 … … 48 49 static WebAssemblyModuleRecord* create(ExecState*, VM&, Structure*, const Identifier&, const Wasm::ModuleInformation&); 49 50 50 void link(ExecState*, JSWebAssembly Instance*);51 void link(ExecState*, JSWebAssemblyModule*, JSWebAssemblyInstance*); 51 52 JS_EXPORT_PRIVATE JSValue evaluate(ExecState*); 52 53
Note: See TracChangeset
for help on using the changeset viewer.