Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Allow WASM to use up to 4GB
https://bugs.webkit.org/show_bug.cgi?id=229353 rdar://81603447 Reviewed by Yusuke Suzuki. JSTests: The big-wasm-memory/wasm-memory-requested... tests used to simply expect an OOM at 2GB. They now expect success at 4GB, and failure at 4GB+1. The exceptions they expect are now more specific, as previously there was a rounding issue that was causing the specific exceptions not to be thrown (resulting in the generic OOM exception later in the code). Finally I made them only run on 64-bit platforms since we don't support typed arrays >=2GB on 32-bits, and I made them only run in one configuration since they can take a little bit of time. I also added a few new tests, specifically checking our handling of large typed arrays, and especially of indices above INT32_MAX. * stress/big-wasm-memory-grow-no-max.js: (test): * stress/big-wasm-memory-grow.js: (test): * stress/big-wasm-memory.js: (test): * stress/typed-array-always-large.js: Added. (getArrayLength): (getByVal): (putByVal): (test): * stress/typed-array-eventually-large.js: Added. (getArrayLength): (getByVal): (putByVal): (test): * stress/typed-array-large-eventually-oob.js: Added. (getArrayLength): (getByVal): (putByVal): (test): * wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js: * wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js: Source/JavaScriptCore: While increasing MAX_ARRAY_BUFFER_SIZE to 4GB was easy, it was not remotely the only thing required to get this to work: - 4GB is not representable in a uint32_t, so I changed all length of ArrayBuffer/TypedArray/etc.. to being UCPURegister. - This also required changing NewTypedArray in all of LLInt/Baseline/DFG/FTL to accept a non-int32 size. In order to avoid performance regressions, I had to add speculation in the DFG/FTL, which now have two versions of NewTypedArray (one that takes an Int32 and one that takes a StrictInt52) - Similarly, GetArrayLength and GetTypedArrayByteOffset now can either return an Int32 or a larger number. I also had to split them in the DFG/FTL, see GetTypedArrayLengthAsInt52 and GetTypedArrayByteOffsetAsInt52 for examples - In turns, I had to add CheckInBoundsInt52 since CheckInBounds could not accept the result of GetTypedArrayLengthAsInt52 - I modified the runtime functions for GetByVal/PutByVal/DataViewGet/DataViewSet/AtomicsXXX to accept non-Int32 indices, since for {Int8/UInt8/UInt8Clamped}Array, a maximum size of 4GB implies indices > 2B. - I added a "mayBeLargeTypedArray" bit to ArrayProfile/UnlinkedArrayProfile/DFG::ArrayMode to track whether such a non-Int32 index was seen to allow proper speculation and specialization of fast paths in the DFG/FTL. I then updated the runtime functions used by the slow paths to correctly update it. Unfortunately I ran out of time to add all the speculations/update all the fast paths. So the following will have to wait for a follow-up patch: - Accepting large indices in the fast path of GetByVal in the LLInt - Accepting large indices in the fast paths generated by AccessCase/PolymorphicAccess - Accepting large indices in the fast paths generated by the DFG/FTL for each of GetByVal/PutByVal/DataViewGet/DataViewSet/AtomicsXXX The current patch is functional, it will just have dreadful performance if trying to use indices >2B in a {Int8/UInt8/UInt8Clamped}Array. Other minor changes in this patch: - Fixed an undefined behavior in ArrayBuffer::createInternal where memcpy could be called on nullptr (the spec explicitly bans this even when length is 0) - Replaced some repetitive and error-prone bounds checking by calls to WTF::isSumSmallerThanOrEqual, which is clearer, shorter, and reuse CheckedArithmetic facilities to avoid overflow issues. - Fixed a variety of obsolete comments - Added support for branch64(RelationalCondition cond, RegisterID left, Imm64 right) (there was already support for the same but with TrustedImm64) - Made various AbstractMacroAssembler function constexpr as part of the previous point * assembler/AbstractMacroAssembler.cpp: * assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::TrustedImmPtr::TrustedImmPtr): (JSC::AbstractMacroAssembler::TrustedImmPtr::asIntptr): (JSC::AbstractMacroAssembler::TrustedImmPtr::asPtr): (JSC::AbstractMacroAssembler::ImmPtr::ImmPtr): (JSC::AbstractMacroAssembler::ImmPtr::asTrustedImmPtr): (JSC::AbstractMacroAssembler::TrustedImm32::TrustedImm32): (JSC::AbstractMacroAssembler::Imm32::Imm32): (JSC::AbstractMacroAssembler::Imm32::asTrustedImm32 const): (JSC::AbstractMacroAssembler::TrustedImm64::TrustedImm64): (JSC::AbstractMacroAssembler::Imm64::Imm64): (JSC::AbstractMacroAssembler::Imm64::asTrustedImm64 const): (JSC::AbstractMacroAssembler::canBlind): (JSC::AbstractMacroAssembler::shouldBlindForSpecificArch): * assembler/MacroAssembler.h: (JSC::MacroAssembler::branch64): * assembler/MacroAssemblerARM64.h: (JSC::MacroAssemblerARM64::shouldBlindForSpecificArch): (JSC::MacroAssemblerARM64::branch64): * assembler/MacroAssemblerARM64E.h: (JSC::MacroAssemblerARM64E::untagArrayPtrLength64): (JSC::MacroAssemblerARM64E::untagArrayPtrLength32): Deleted. * assembler/MacroAssemblerX86Common.h: (JSC::MacroAssemblerX86Common::canBlind): (JSC::MacroAssemblerX86Common::shouldBlindForSpecificArch): * bytecode/AccessCase.cpp: (JSC::AccessCase::needsScratchFPR const): (JSC::AccessCase::generateWithGuard): * bytecode/ArrayProfile.h: (JSC::ArrayProfile::setMayBeLargeTypedArray): (JSC::ArrayProfile::mayBeLargeTypedArray const): (JSC::UnlinkedArrayProfile::UnlinkedArrayProfile): (JSC::UnlinkedArrayProfile::update): * dfg/DFGAbstractInterpreterInlines.h: (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): * dfg/DFGArgumentsEliminationPhase.cpp: * dfg/DFGArrayMode.cpp: (JSC::DFG::ArrayMode::refine const): * dfg/DFGArrayMode.h: (JSC::DFG::ArrayMode::ArrayMode): (JSC::DFG::ArrayMode::mayBeLargeTypedArray const): (JSC::DFG::ArrayMode::withType const): (JSC::DFG::ArrayMode::withSpeculation const): (JSC::DFG::ArrayMode::withConversion const): (JSC::DFG::ArrayMode::withTypeAndConversion const): (JSC::DFG::ArrayMode::withArrayClassAndSpeculationAndMayBeLargeTypedArray const): (JSC::DFG::ArrayMode::speculationFromProfile): (JSC::DFG::ArrayMode::withSpeculationFromProfile const): (JSC::DFG::ArrayMode::withProfile const): (JSC::DFG::ArrayMode::operator== const): (JSC::DFG::ArrayMode::withArrayClass const): Deleted. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleIntrinsicGetter): * dfg/DFGClobberize.h: (JSC::DFG::clobberize): * dfg/DFGCommon.h: (JSC::DFG::enableInt52): * dfg/DFGConstantFoldingPhase.cpp: (JSC::DFG::ConstantFoldingPhase::foldConstants): * dfg/DFGDoesGC.cpp: (JSC::DFG::doesGC): * dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupNode): (JSC::DFG::FixupPhase::convertToGetArrayLength): (JSC::DFG::FixupPhase::prependGetArrayLength): Deleted. * dfg/DFGGenerationInfo.h: * dfg/DFGHeapLocation.cpp: (WTF::printInternal): * dfg/DFGHeapLocation.h: * dfg/DFGIntegerRangeOptimizationPhase.cpp: * dfg/DFGNode.h: (JSC::DFG::Node::hasStorageChild const): (JSC::DFG::Node::storageChildIndex): (JSC::DFG::Node::hasArrayMode): * dfg/DFGNodeType.h: * dfg/DFGOperations.cpp: (JSC::DFG::putByVal): (JSC::DFG::newTypedArrayWithSize): (JSC::DFG::JSC_DEFINE_JIT_OPERATION): * dfg/DFGOperations.h: * dfg/DFGPredictionPropagationPhase.cpp: * dfg/DFGSSALoweringPhase.cpp: (JSC::DFG::SSALoweringPhase::handleNode): (JSC::DFG::SSALoweringPhase::lowerBoundsCheck): * dfg/DFGSafeToExecute.h: (JSC::DFG::safeToExecute): * dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds): (JSC::DFG::SpeculativeJIT::emitTypedArrayBoundsCheck): (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray): (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray): (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray): (JSC::DFG::SpeculativeJIT::cageTypedArrayStorage): (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffset): (JSC::DFG::SpeculativeJIT::compileGetArrayLength): (JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithSize): (JSC::DFG::SpeculativeJIT::emitNewTypedArrayWithSizeInRegister): (JSC::DFG::SpeculativeJIT::compileNewTypedArray): * dfg/DFGSpeculativeJIT.h: * dfg/DFGSpeculativeJIT32_64.cpp: (JSC::DFG::SpeculativeJIT::compileGetByVal): (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithInt52Size): (JSC::DFG::SpeculativeJIT::compileGetTypedArrayLengthAsInt52): (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffsetAsInt52): (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGTypeCheckHoistingPhase.cpp: (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks): (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks): * dfg/DFGValidate.cpp: * ftl/FTLCapabilities.cpp: (JSC::FTL::canCompile): * ftl/FTLLowerDFGToB3.cpp: (JSC::FTL::DFG::LowerDFGToB3::validateAIState): (JSC::FTL::DFG::LowerDFGToB3::compileNode): (JSC::FTL::DFG::LowerDFGToB3::emitGetTypedArrayByteOffsetExceptSettingResult): (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayByteOffset): (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayByteOffsetAsInt52): (JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength): (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayLengthAsInt52): (JSC::FTL::DFG::LowerDFGToB3::compileCheckInBoundsInt52): (JSC::FTL::DFG::LowerDFGToB3::compilePutByVal): (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray): (JSC::FTL::DFG::LowerDFGToB3::emitNewTypedArrayWithSize): (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq): * ftl/FTLOutput.h: (JSC::FTL::Output::load64NonNegative): * jit/IntrinsicEmitter.cpp: (JSC::IntrinsicGetterAccessCase::emitIntrinsicGetter): * jit/JITOperations.cpp: (JSC::putByVal): (JSC::getByVal): * llint/LLIntOfflineAsmConfig.h: * llint/LLIntSlowPaths.cpp: (JSC::LLInt::getByVal): (JSC::LLInt::LLINT_SLOW_PATH_DECL): * llint/LowLevelInterpreter.asm: * llint/LowLevelInterpreter32_64.asm: * llint/LowLevelInterpreter64.asm: * runtime/ArrayBuffer.cpp: (JSC::SharedArrayBufferContents::SharedArrayBufferContents): (JSC::ArrayBufferContents::ArrayBufferContents): (JSC::ArrayBufferContents::tryAllocate): (JSC::ArrayBuffer::create): (JSC::ArrayBuffer::createAdopted): (JSC::ArrayBuffer::createFromBytes): (JSC::ArrayBuffer::tryCreate): (JSC::ArrayBuffer::createUninitialized): (JSC::ArrayBuffer::tryCreateUninitialized): (JSC::ArrayBuffer::createInternal): (JSC::ArrayBuffer::clampValue): (JSC::ArrayBuffer::clampIndex const): (JSC::ArrayBuffer::sliceWithClampedIndex const): * runtime/ArrayBuffer.h: (JSC::ArrayBufferContents::sizeInBytes const): (JSC::ArrayBuffer::byteLength const): (JSC::ArrayBuffer::gcSizeEstimateInBytes const): * runtime/ArrayBufferView.cpp: (JSC::ArrayBufferView::ArrayBufferView): * runtime/ArrayBufferView.h: (JSC::ArrayBufferView::byteOffset const): (JSC::ArrayBufferView::byteLength const): (JSC::ArrayBufferView::verifyByteOffsetAlignment): (JSC::ArrayBufferView::verifySubRangeLength): (JSC::ArrayBufferView::clampOffsetAndNumElements): (JSC::ArrayBufferView::setImpl): (JSC::ArrayBufferView::setRangeImpl): (JSC::ArrayBufferView::getRangeImpl): (JSC::ArrayBufferView::zeroRangeImpl): (JSC::ArrayBufferView::calculateOffsetAndLength): Deleted. * runtime/AtomicsObject.cpp: * runtime/DataView.cpp: (JSC::DataView::DataView): (JSC::DataView::create): * runtime/DataView.h: * runtime/GenericTypedArrayView.h: * runtime/GenericTypedArrayViewInlines.h: (JSC::GenericTypedArrayView<Adaptor>::GenericTypedArrayView): (JSC::GenericTypedArrayView<Adaptor>::create): (JSC::GenericTypedArrayView<Adaptor>::tryCreate): (JSC::GenericTypedArrayView<Adaptor>::createUninitialized): (JSC::GenericTypedArrayView<Adaptor>::tryCreateUninitialized): (JSC::GenericTypedArrayView<Adaptor>::subarray const): Deleted. * runtime/JSArrayBufferView.cpp: (JSC::JSArrayBufferView::ConstructionContext::ConstructionContext): (JSC::JSArrayBufferView::byteLength const): (JSC::JSArrayBufferView::slowDownAndWasteMemory): (JSC::JSArrayBufferView::possiblySharedImpl): * runtime/JSArrayBufferView.h: (JSC::JSArrayBufferView::sizeOf): (JSC::JSArrayBufferView::ConstructionContext::length const): (JSC::JSArrayBufferView::length const): * runtime/JSArrayBufferViewInlines.h: (JSC::JSArrayBufferView::byteOffsetImpl): (JSC::JSArrayBufferView::byteOffset): (JSC::JSArrayBufferView::byteOffsetConcurrently): * runtime/JSCJSValue.h: * runtime/JSCJSValueInlines.h: (JSC::JSValue::toIndex const): (JSC::JSValue::toTypedArrayIndex const): * runtime/JSDataView.cpp: (JSC::JSDataView::create): (JSC::JSDataView::createUninitialized): (JSC::JSDataView::set): (JSC::JSDataView::setIndex): * runtime/JSDataView.h: * runtime/JSDataViewPrototype.cpp: (JSC::getData): (JSC::setData): * runtime/JSGenericTypedArrayView.h: * runtime/JSGenericTypedArrayViewConstructorInlines.h: (JSC::constructGenericTypedArrayViewWithArguments): (JSC::constructGenericTypedArrayViewImpl): * runtime/JSGenericTypedArrayViewInlines.h: (JSC::JSGenericTypedArrayView<Adaptor>::create): (JSC::JSGenericTypedArrayView<Adaptor>::createWithFastVector): (JSC::JSGenericTypedArrayView<Adaptor>::createUninitialized): (JSC::JSGenericTypedArrayView<Adaptor>::validateRange): (JSC::JSGenericTypedArrayView<Adaptor>::setWithSpecificType): (JSC::JSGenericTypedArrayView<Adaptor>::set): * runtime/JSObject.h: (JSC::JSObject::putByIndexInline): (JSC::JSObject::tryGetIndexQuickly const): (JSC::JSObject::trySetIndexQuickly): (JSC::JSObject::canSetIndexQuickly): Deleted. * runtime/JSObjectInlines.h: (JSC::JSObject::getIndexQuicklyForTypedArray const): (JSC::JSObject::setIndexQuicklyForArrayStorageIndexingType): (JSC::JSObject::trySetIndexQuicklyForTypedArray): (JSC::JSObject::canSetIndexQuicklyForTypedArray const): Deleted. * runtime/Operations.h: (JSC::getByValWithIndex): * wasm/WasmPageCount.h: Source/WebCore: Some parts of WebCore use TypedArrays, and would not build after I made the length() function on typed arrays return UCPURegister instead of uint32_t. Most fixes were trivial, the only exception is SerializedScriptValue.cpp, where I had to increment the version number, as ArrayBuffer (and ArrayBufferViews) now write/read their length in a 64-bit field (and same for the byteOffset of ArrayBufferView). I also had to add a test in PixelBuffer.cpp that the size of the ArrayBuffer it will try to allocate is < INT32_MAX. Otherwise, the test LayoutTests/fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html which checks that very large images are properly rejected without crashing, would timeout. No new tests, as the code is already extensively covered by existing tests, and I implemented no new features. * Modules/webaudio/AudioBuffer.cpp: (WebCore::AudioBuffer::copyFromChannel): (WebCore::AudioBuffer::copyToChannel): * Modules/webaudio/RealtimeAnalyser.cpp: (WebCore::RealtimeAnalyser::getByteFrequencyData): (WebCore::RealtimeAnalyser::getFloatTimeDomainData): (WebCore::RealtimeAnalyser::getByteTimeDomainData): * bindings/js/SerializedScriptValue.cpp: (WebCore::CloneSerializer::dumpArrayBufferView): (WebCore::CloneSerializer::dumpImageBitmap): (WebCore::CloneSerializer::dumpIfTerminal): (WebCore::CloneDeserializer::readArrayBufferImpl): (WebCore::CloneDeserializer::readArrayBuffer): (WebCore::CloneDeserializer::readArrayBufferViewImpl): (WebCore::CloneDeserializer::readArrayBufferView): * bindings/js/SerializedScriptValue.h: (WebCore::SerializedScriptValue::encode const): (WebCore::SerializedScriptValue::decode): * fileapi/NetworkSendQueue.cpp: (WebCore::NetworkSendQueue::enqueue): * platform/graphics/PixelBuffer.cpp: (WebCore::PixelBuffer::tryCreate): * platform/graphics/iso/ISOBox.h: Source/WTF: Made some of CheckedArithmetic constexpr, and added isSumSmallerThanOrEqual since it is a commonly used test in ArrayBuffer and easy to get wrong in terms of overflow. * wtf/CheckedArithmetic.h: (WTF::isInBounds): (WTF::convertSafely): (WTF::isSumSmallerThanOrEqual): LayoutTests: Rebaselined three following tests as different or fewer error messages appear on the console. Also changed currentVersion in serialized-script-value.html from 9 to 10. * fast/canvas/canvas-getImageData-invalid-result-buffer-crash-expected.txt: * fast/storage/serialized-script-value.html: * webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt: * webaudio/OfflineAudioContext/bad-buffer-length-expected.txt: Canonical link: https://commits.webkit.org/243039@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@284230 268f45cc-cd09-0410-ab3c-d52691b4dbfc
- Loading branch information