Changeset 218868 in webkit
- Timestamp:
- Jun 27, 2017 11:42:13 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r218861 r218868 1 2017-06-27 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly: running out of executable memory should throw OoM 4 https://bugs.webkit.org/show_bug.cgi?id=171537 5 <rdar://problem/32963338> 6 7 Reviewed by Saam Barati. 8 9 * wasm.yaml: 10 * wasm/lowExecutableMemory/executable-memory-oom.js: Added. 11 (const.invoke): 12 (failCount.0.catch): 13 (failCount.0.module.undefined.catch): 14 * wasm/lowExecutableMemory/exports-oom.js: Added. 15 (const.type): 16 (const.params): 17 (const.randomProgram): 18 (failCount.0.catch): 19 (failCount.0.module.undefined.catch): 20 * wasm/lowExecutableMemory/imports-oom.js: Added. 21 (const.type): 22 (const.params): 23 (const.randomProgram): 24 (f.imports.push): 25 (failCount.0.catch): 26 (failCount.0.module.undefined.catch): 27 1 28 2017-06-27 Caio Lima <ticaiolima@gmail.com> 2 29 -
trunk/JSTests/wasm.yaml
r218216 r218868 34 34 - path: wasm/stress 35 35 cmd: runWebAssembly unless parseRunCommands 36 - path: wasm/lowExecutableMemory 37 cmd: runWebAssemblyLowExecutableMemory unless parseRunCommands 36 38 37 39 - path: wasm/spec-tests/address.wast.js -
trunk/Source/JavaScriptCore/ChangeLog
r218867 r218868 1 2017-06-27 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly: running out of executable memory should throw OoM 4 https://bugs.webkit.org/show_bug.cgi?id=171537 5 <rdar://problem/32963338> 6 7 Reviewed by Saam Barati. 8 9 Both on first compile with BBQ as well as on tier-up with OMG, 10 running out of X memory shouldn't cause the entire program to 11 terminate. An exception will do when compiling initial code (since 12 we don't have any other fallback at the moment), and refusal to 13 tier up will do as well (it'll just be slower). 14 15 This is useful because programs which generate huge amounts of 16 code simply look like crashes, which developers report to 17 us. Getting a JavaScript exception instead is much clearer. 18 19 * jit/ExecutableAllocator.cpp: 20 (JSC::ExecutableAllocator::allocate): 21 * llint/LLIntSlowPaths.cpp: 22 (JSC::LLInt::shouldJIT): 23 * runtime/Options.h: 24 * wasm/WasmBBQPlan.cpp: 25 (JSC::Wasm::BBQPlan::prepare): 26 (JSC::Wasm::BBQPlan::complete): 27 * wasm/WasmBinding.cpp: 28 (JSC::Wasm::wasmToJs): 29 (JSC::Wasm::wasmToWasm): 30 * wasm/WasmBinding.h: 31 * wasm/WasmOMGPlan.cpp: 32 (JSC::Wasm::OMGPlan::work): 33 * wasm/js/JSWebAssemblyCodeBlock.cpp: 34 (JSC::JSWebAssemblyCodeBlock::JSWebAssemblyCodeBlock): 35 * wasm/js/JSWebAssemblyCodeBlock.h: 36 * wasm/js/JSWebAssemblyInstance.cpp: 37 (JSC::JSWebAssemblyInstance::finalizeCreation): 38 1 39 2017-06-27 Saam Barati <sbarati@apple.com> 2 40 -
trunk/Source/JavaScriptCore/jit/ExecutableAllocator.cpp
r218867 r218868 413 413 size_t bytesAvailable = static_cast<size_t>( 414 414 statistics.bytesReserved * (1 - executablePoolReservationFraction)); 415 if (bytesAllocated > bytesAvailable) 415 if (bytesAllocated > bytesAvailable) { 416 if (Options::logExecutableAllocation()) 417 dataLog("Allocation failed because bytes allocated ", bytesAllocated, " > ", bytesAvailable, " bytes available.\n"); 416 418 return nullptr; 419 } 417 420 } 418 421 -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r218794 r218868 319 319 return false; 320 320 321 // You can modify this to turn off JITting without rebuilding the world. 322 return exec->vm().canUseJIT(); 321 return exec->vm().canUseJIT() && Options::useBaselineJIT(); 323 322 } 324 323 -
trunk/Source/JavaScriptCore/runtime/Options.h
r218861 r218868 113 113 \ 114 114 v(bool, useLLInt, true, Normal, "allows the LLINT to be used if true") \ 115 v(bool, useJIT, true, Normal, "allows the baseline JIT to be used if true") \ 115 v(bool, useJIT, true, Normal, "allows the executable pages to be allocated for JIT and thunks if true") \ 116 v(bool, useBaselineJIT, true, Normal, "allows the baseline JIT to be used if true") \ 116 117 v(bool, useDFGJIT, true, Normal, "allows the DFG JIT to be used if true") \ 117 118 v(bool, useRegExpJIT, true, Normal, "allows the RegExp JIT to be used if true") \ -
trunk/Source/JavaScriptCore/wasm/WasmBBQPlan.cpp
r218619 r218868 176 176 unsigned importFunctionIndex = m_wasmToWasmExitStubs.size(); 177 177 dataLogLnIf(verbose, "Processing import function number ", importFunctionIndex, ": ", makeString(import->module), ": ", makeString(import->field)); 178 m_wasmToWasmExitStubs.uncheckedAppend(wasmToWasm(importFunctionIndex)); 178 auto binding = wasmToWasm(importFunctionIndex); 179 if (UNLIKELY(!binding)) { 180 switch (binding.error()) { 181 case BindingFailure::OutOfMemory: 182 return fail(holdLock(m_lock), makeString("Out of executable memory at import ", String::number(importIndex))); 183 } 184 RELEASE_ASSERT_NOT_REACHED(); 185 } 186 m_wasmToWasmExitStubs.uncheckedAppend(binding.value()); 179 187 } 180 188 … … 289 297 dataLogLnIf(verbose, "Starting Completion"); 290 298 291 if ( m_state == State::Compiled) {299 if (!failed() && m_state == State::Compiled) { 292 300 for (uint32_t functionIndex = 0; functionIndex < m_moduleInformation->functionLocationInBinary.size(); functionIndex++) { 293 301 CompilationContext& context = m_compilationContexts[functionIndex]; 294 302 SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex]; 295 303 { 296 LinkBuffer linkBuffer(*context.wasmEntrypointJIT, nullptr); 304 LinkBuffer linkBuffer(*context.wasmEntrypointJIT, nullptr, JITCompilationCanFail); 305 if (UNLIKELY(linkBuffer.didFailToAllocate())) { 306 Base::fail(locker, makeString("Out of executable memory in function at index ", String::number(functionIndex))); 307 return; 308 } 309 297 310 m_wasmInternalFunctions[functionIndex]->entrypoint.compilation = std::make_unique<B3::Compilation>( 298 311 FINALIZE_CODE(linkBuffer, ("WebAssembly function[%i] %s", functionIndex, SignatureInformation::get(signatureIndex).toString().ascii().data())), … … 301 314 302 315 if (auto jsToWasmInternalFunction = m_jsToWasmInternalFunctions.get(functionIndex)) { 303 LinkBuffer linkBuffer(*context.jsEntrypointJIT, nullptr); 316 LinkBuffer linkBuffer(*context.jsEntrypointJIT, nullptr, JITCompilationCanFail); 317 if (UNLIKELY(linkBuffer.didFailToAllocate())) { 318 Base::fail(locker, makeString("Out of executable memory in function entrypoint at index ", String::number(functionIndex))); 319 return; 320 } 321 304 322 jsToWasmInternalFunction->entrypoint.compilation = std::make_unique<B3::Compilation>( 305 323 FINALIZE_CODE(linkBuffer, ("JavaScript->WebAssembly entrypoint[%i] %s", functionIndex, SignatureInformation::get(signatureIndex).toString().ascii().data())), -
trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp
r218866 r218868 52 52 } 53 53 54 MacroAssemblerCodeRefwasmToJs(VM* vm, Bag<CallLinkInfo>& callLinkInfos, SignatureIndex signatureIndex, unsigned importIndex)54 Expected<MacroAssemblerCodeRef, BindingFailure> wasmToJs(VM* vm, Bag<CallLinkInfo>& callLinkInfos, SignatureIndex signatureIndex, unsigned importIndex) 55 55 { 56 56 // FIXME: This function doesn't properly abstract away the calling convention. … … 120 120 }; 121 121 122 LinkBuffer linkBuffer(jit, GLOBAL_THUNK_ID); 122 LinkBuffer linkBuffer(jit, GLOBAL_THUNK_ID, JITCompilationCanFail); 123 if (UNLIKELY(linkBuffer.didFailToAllocate())) 124 return makeUnexpected(BindingFailure::OutOfMemory); 125 123 126 linkBuffer.link(call, throwBadI64); 124 127 return FINALIZE_CODE(linkBuffer, ("WebAssembly->JavaScript invalid i64 use in import[%i]", importIndex)); … … 304 307 jit.ret(); 305 308 306 LinkBuffer linkBuffer(jit, GLOBAL_THUNK_ID); 309 LinkBuffer linkBuffer(jit, GLOBAL_THUNK_ID, JITCompilationCanFail); 310 if (UNLIKELY(linkBuffer.didFailToAllocate())) 311 return makeUnexpected(BindingFailure::OutOfMemory); 312 307 313 linkBuffer.link(call, callFunc); 308 314 linkBuffer.link(exceptionCall, doUnwinding); … … 601 607 } 602 608 603 LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID); 609 LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, JITCompilationCanFail); 610 if (UNLIKELY(patchBuffer.didFailToAllocate())) 611 return makeUnexpected(BindingFailure::OutOfMemory); 612 604 613 patchBuffer.link(slowCall, FunctionPtr(vm->getCTIStub(linkCallThunkGenerator).code().executableAddress())); 605 614 CodeLocationLabel callReturnLocation(patchBuffer.locationOfNearCall(slowCall)); … … 611 620 } 612 621 613 MacroAssemblerCodeRefwasmToWasm(unsigned importIndex)622 Expected<MacroAssemblerCodeRef, BindingFailure> wasmToWasm(unsigned importIndex) 614 623 { 615 624 const PinnedRegisterInfo& pinnedRegs = PinnedRegisterInfo::get(); … … 654 663 jit.jump(scratch); 655 664 656 LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID); 665 LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, JITCompilationCanFail); 666 if (UNLIKELY(patchBuffer.didFailToAllocate())) 667 return makeUnexpected(BindingFailure::OutOfMemory); 668 657 669 return FINALIZE_CODE(patchBuffer, ("WebAssembly->WebAssembly import[%i]", importIndex)); 658 670 } -
trunk/Source/JavaScriptCore/wasm/WasmBinding.h
r215103 r218868 32 32 #include "WasmFormat.h" 33 33 #include <wtf/Bag.h> 34 #include <wtf/Expected.h> 34 35 35 36 namespace JSC { … … 39 40 namespace Wasm { 40 41 41 MacroAssemblerCodeRef wasmToWasm(unsigned importIndex); 42 MacroAssemblerCodeRef wasmToJs(VM*, Bag<CallLinkInfo>& callLinkInfos, SignatureIndex, unsigned importIndex); 42 enum class BindingFailure { 43 OutOfMemory, 44 }; 45 46 Expected<MacroAssemblerCodeRef, BindingFailure> wasmToWasm(unsigned importIndex); 47 Expected<MacroAssemblerCodeRef, BindingFailure> wasmToJs(VM*, Bag<CallLinkInfo>& callLinkInfos, SignatureIndex, unsigned importIndex); 43 48 44 49 } } // namespace JSC::Wasm -
trunk/Source/JavaScriptCore/wasm/WasmOMGPlan.cpp
r218866 r218868 89 89 90 90 Entrypoint omgEntrypoint; 91 LinkBuffer linkBuffer(*context.wasmEntrypointJIT, nullptr); 91 LinkBuffer linkBuffer(*context.wasmEntrypointJIT, nullptr, JITCompilationCanFail); 92 if (UNLIKELY(linkBuffer.didFailToAllocate())) { 93 Base::fail(holdLock(m_lock), makeString("Out of executable memory while tiering up function at index ", String::number(m_functionIndex))); 94 return; 95 } 96 92 97 omgEntrypoint.compilation = std::make_unique<B3::Compilation>( 93 98 FINALIZE_CODE(linkBuffer, ("WebAssembly OMG function[%i] %s", m_functionIndex, SignatureInformation::get(signatureIndex).toString().ascii().data())), -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.cpp
r217108 r218868 59 59 for (unsigned importIndex = 0; importIndex < m_codeBlock->functionImportCount(); ++importIndex) { 60 60 Wasm::SignatureIndex signatureIndex = moduleInformation.importFunctionSignatureIndices.at(importIndex); 61 m_wasmToJSExitStubs.uncheckedAppend(Wasm::wasmToJs(&vm, m_callLinkInfos, signatureIndex, importIndex)); 61 auto binding = Wasm::wasmToJs(&vm, m_callLinkInfos, signatureIndex, importIndex); 62 if (UNLIKELY(!binding)) { 63 switch (binding.error()) { 64 case Wasm::BindingFailure::OutOfMemory: 65 m_errorMessage = ASCIILiteral("Out of executable memory"); 66 return; 67 } 68 RELEASE_ASSERT_NOT_REACHED(); 69 } 70 m_wasmToJSExitStubs.uncheckedAppend(binding.value()); 62 71 importWasmToJSStub(importIndex) = m_wasmToJSExitStubs[importIndex].code().executableAddress(); 63 72 } -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyCodeBlock.h
r218794 r218868 76 76 Wasm::Callee& jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace) 77 77 { 78 ASSERT(runnable()); 78 79 return m_codeBlock->jsEntrypointCalleeFromFunctionIndexSpace(functionIndexSpace); 79 80 } 80 81 Wasm::WasmEntrypointLoadLocation wasmEntrypointLoadLocationFromFunctionIndexSpace(unsigned functionIndexSpace) 81 82 { 83 ASSERT(runnable()); 82 84 return m_codeBlock->wasmEntrypointLoadLocationFromFunctionIndexSpace(functionIndexSpace); 83 85 } … … 85 87 Wasm::WasmEntrypointLoadLocation wasmToJsCallStubForImport(unsigned importIndex) 86 88 { 89 ASSERT(runnable()); 87 90 return &importWasmToJSStub(importIndex); 88 91 } … … 96 99 97 100 void clearJSCallICs(VM&); 101 102 bool runnable() const { return !m_errorMessage; } 103 104 String errorMessage() 105 { 106 ASSERT(!runnable()); 107 return m_errorMessage; 108 } 98 109 99 110 private: … … 128 139 UnconditionalFinalizer m_unconditionalFinalizer; 129 140 Bag<CallLinkInfo> m_callLinkInfos; 141 String m_errorMessage; 130 142 }; 131 143 -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
r217921 r218868 113 113 } else { 114 114 codeBlock = JSWebAssemblyCodeBlock::create(vm, wasmCodeBlock.copyRef(), m_module.get()); 115 if (UNLIKELY(!codeBlock->runnable())) { 116 throwException(exec, scope, JSWebAssemblyLinkError::create(exec, vm, globalObject()->WebAssemblyLinkErrorStructure(), codeBlock->errorMessage())); 117 return; 118 } 115 119 m_codeBlock.set(vm, this, codeBlock); 116 120 module()->setCodeBlock(vm, memoryMode(), codeBlock); -
trunk/Tools/ChangeLog
r218855 r218868 1 2017-06-27 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly: running out of executable memory should throw OoM 4 https://bugs.webkit.org/show_bug.cgi?id=171537 5 <rdar://problem/32963338> 6 7 Reviewed by Saam Barati. 8 9 * Scripts/run-jsc-stress-tests: add a configuration which runs the 10 tests under limited executable memory and avoids non-WebAssembly 11 code generation so that we more reliably run out of executable 12 memory in WebAssembly. 13 1 14 2017-06-27 Wenson Hsieh <wenson_hsieh@apple.com> 2 15 -
trunk/Tools/Scripts/run-jsc-stress-tests
r218784 r218868 1235 1235 return 1236 1236 end 1237 1238 1237 return if !$jitTests 1239 1238 return if !$isFTLPlatform … … 1247 1246 1248 1247 runWithOutputHandler("default-wasm", noisyOutputHandler, "../spec-harness.js", *FTL_OPTIONS) 1249 runWithOutputHandler("wasm-no-cjit-yes-tls-context", noisyOutputHandler, "../spec-harness.js", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS)) 1250 runWithOutputHandler("wasm-eager-jettison", noisyOutputHandler, "../spec-harness.js", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS) 1251 runWithOutputHandler("wasm-no-call-ic", noisyOutputHandler, "../spec-harness.js", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS) 1252 runWithOutputHandler("wasm-no-tls-context", noisyOutputHandler, "../spec-harness.js", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) 1248 if !$quickMode 1249 runWithOutputHandler("wasm-no-cjit-yes-tls-context", noisyOutputHandler, "../spec-harness.js", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS)) 1250 runWithOutputHandler("wasm-eager-jettison", noisyOutputHandler, "../spec-harness.js", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS) 1251 runWithOutputHandler("wasm-no-call-ic", noisyOutputHandler, "../spec-harness.js", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS) 1252 runWithOutputHandler("wasm-no-tls-context", noisyOutputHandler, "../spec-harness.js", "--useFastTLSForWasmContext=false", *FTL_OPTIONS) 1253 end 1254 end 1255 1256 def runWebAssemblyLowExecutableMemory(*optionalTestSpecificOptions) 1257 return if !$jitTests 1258 return if !$isFTLPlatform 1259 modules = Dir[WASMTESTS_PATH + "*.js"].map { |f| File.basename(f) } 1260 prepareExtraAbsoluteFiles(WASMTESTS_PATH, ["wasm.json"]) 1261 prepareExtraRelativeFiles(modules.map { |f| "../" + f }, $collection) 1262 # Only let WebAssembly get executable memory. 1263 run("default-wasm", "--useConcurrentGC=0" , "--useConcurrentJIT=0", "--jitMemoryReservationSize=15000", "--useBaselineJIT=0", "--useDFGJIT=0", "--useFTLJIT=0", "-m") 1253 1264 end 1254 1265
Note: See TracChangeset
for help on using the changeset viewer.